refactor timeline to use actions

This commit is contained in:
Nolan Lawson 2018-01-27 17:34:08 -08:00
parent c0c7e9fafe
commit de248a9b1f
5 changed files with 111 additions and 83 deletions

View file

@ -0,0 +1,94 @@
import { store } from '../_utils/store'
import { database } from '../_utils/database/database'
import { getTimeline } from '../_utils/mastodon/timelines'
import { toast } from '../_utils/toast'
import { StatusStream } from '../_utils/mastodon/StatusStream'
import { getInstanceInfo } from '../_utils/mastodon/instance'
import { mark, stop } from '../_utils/marks'
import { mergeStatuses } from '../_utils/timelines'
const FETCH_LIMIT = 20
let statusStream
async function fetchStatuses(instanceName, accessToken, timelineName, lastStatusId, online) {
mark('fetchStatuses')
let statuses
if (!online) {
statuses = await database.getTimeline(instanceName, timelineName, lastStatusId, FETCH_LIMIT)
} else {
try {
statuses = await getTimeline(instanceName, accessToken, timelineName, lastStatusId, FETCH_LIMIT)
/* no await */ database.insertStatuses(instanceName, timelineName, statuses)
} catch (e) {
console.error(e)
toast.say('Internet request failed. Showing offline content.')
statuses = await database.getTimeline(instanceName, timelineName, lastStatusId, FETCH_LIMIT)
}
}
stop('fetchStatuses')
return statuses
}
async function addStatuses(instanceName, timelineName, newStatuses) {
mark('addStatuses')
let newStatusIds = newStatuses.map(status => status.id)
let oldStatusIds = store.getForTimeline(instanceName, timelineName, 'statusIds') || []
let merged = mergeStatuses(oldStatusIds, newStatusIds)
store.setForTimeline(instanceName, timelineName, { statusIds: merged })
stop('addStatuses')
}
async function fetchStatusesAndPossiblyFallBack() {
mark('fetchStatusesAndPossiblyFallBack')
let timelineName = store.get('currentTimeline')
let instanceName = store.get('currentInstance')
let accessToken = store.get('accessToken')
let lastStatusId = store.get('lastStatusId')
let online = store.get('online')
let newStatuses = await fetchStatuses(instanceName, accessToken, timelineName, lastStatusId, online)
addStatuses(instanceName, timelineName, newStatuses)
stop('fetchStatusesAndPossiblyFallBack')
}
export function initializeTimeline() {
mark('initializeTimeline')
let instanceName = store.get('currentInstance')
let timeline = store.get('currentTimeline')
requestAnimationFrame(() => {
requestAnimationFrame(() => {
store.setForTimeline(instanceName, timeline, {initialized: true})
})
})
stop('initializeTimeline')
}
export async function setupTimeline() {
mark('addStatuses')
let timelineName = store.get('currentTimeline')
let instanceName = store.get('currentInstance')
let accessToken = store.get('accessToken')
if (!store.get('statusIds').length) {
await fetchStatusesAndPossiblyFallBack()
}
/* no await */ getInstanceInfo(instanceName).then(instanceInfo => database.setInstanceInfo(instanceName, instanceInfo))
let instanceInfo = await database.getInstanceInfo(instanceName)
if (statusStream) {
statusStream.close()
}
statusStream = new StatusStream(instanceInfo.urls.streaming_api, accessToken, timelineName, {
onMessage(message) {
console.log('message', message)
}
})
stop('addStatuses')
}
export async function fetchStatusesOnScrollToBottom() {
let timelineName = store.get('currentTimeline')
let instanceName = store.get('currentInstance')
store.setForTimeline(instanceName, timelineName, { runningUpdate: true })
await fetchStatusesAndPossiblyFallBack()
store.setForTimeline(instanceName, timelineName, { runningUpdate: false })
}

View file

@ -1,3 +1,4 @@
<:Window bind:online />
<Nav :page :dynamicPage :dynamicHref :dynamicIcon :dynamicLabel/> <Nav :page :dynamicPage :dynamicHref :dynamicIcon :dynamicLabel/>
{{#if virtual}} {{#if virtual}}
@ -19,6 +20,11 @@
import { store } from '../_utils/store' import { store } from '../_utils/store'
export default { export default {
oncreate() {
this.observe('online', online => {
this.store.set({online: online})
})
},
components: { components: {
VirtualListContainer, VirtualListContainer,
Nav Nav

View file

@ -1,4 +1,3 @@
<:Window bind:online />
<div class="timeline" role="feed" aria-label="{{label}}"> <div class="timeline" role="feed" aria-label="{{label}}">
<VirtualList component="{{StatusListItem}}" <VirtualList component="{{StatusListItem}}"
:makeProps :makeProps
@ -18,41 +17,16 @@
</style> </style>
<script> <script>
import { store } from '../../_utils/store' import { store } from '../../_utils/store'
import { getTimeline } from '../../_utils/mastodon/timelines'
import { getInstanceInfo } from '../../_utils/mastodon/instance'
import StatusListItem from './StatusListItem.html' import StatusListItem from './StatusListItem.html'
import LoadingFooter from './LoadingFooter.html' import LoadingFooter from './LoadingFooter.html'
import VirtualList from '../virtualList/VirtualList.html' import VirtualList from '../virtualList/VirtualList.html'
import { splice, push } from 'svelte-extras'
import { mergeStatuses } from '../../_utils/statuses'
import { mark, stop } from '../../_utils/marks'
import { timelines } from '../../_static/timelines' import { timelines } from '../../_static/timelines'
import { toast } from '../../_utils/toast'
import { database } from '../../_utils/database/database' import { database } from '../../_utils/database/database'
import { StatusStream } from '../../_utils/mastodon/StatusStream' import { initializeTimeline, fetchStatusesOnScrollToBottom, setupTimeline } from '../../_actions/timeline'
const FETCH_LIMIT = 20
export default { export default {
async oncreate() { async oncreate() {
let timeline = this.get('timeline') setupTimeline()
let instanceName = this.store.get('currentInstance')
let accessToken = this.store.get('accessToken')
if (!this.store.get('statusIds').length) {
this.addStatuses(await this.fetchStatusesAndPossiblyFallBack())
}
/* no await */ getInstanceInfo(instanceName).then(instanceInfo => database.setInstanceInfo(instanceName, instanceInfo))
let instanceInfo = await database.getInstanceInfo(instanceName)
this._statusStream = new StatusStream(instanceInfo.urls.streaming_api, accessToken, timeline, {
onMessage(message) {
console.log('message', message)
}
})
},
ondestroy() {
if (this._statusStream) {
this._statusStream.close()
}
}, },
data: () => ({ data: () => ({
StatusListItem: StatusListItem, StatusListItem: StatusListItem,
@ -77,69 +51,17 @@
VirtualList VirtualList
}, },
methods: { methods: {
splice: splice,
push: push,
initialize() { initialize() {
if (this.store.get('initialized') || !this.store.get('statusIds') || !this.store.get('statusIds').length) { if (this.store.get('initialized') || !this.store.get('statusIds') || !this.store.get('statusIds').length) {
return return
} }
let instanceName = this.store.get('currentInstance') initializeTimeline()
let timeline = this.get('timeline')
requestAnimationFrame(() => {
requestAnimationFrame(() => {
this.store.setForTimeline(instanceName, timeline, {initialized: true})
})
})
}, },
async onScrollToBottom() { async onScrollToBottom() {
if (!this.store.get('initialized')) { if (!this.store.get('initialized') || this.store.get('runningUpdate')) {
return return
} }
if (this.store.get('runningUpdate')) { fetchStatusesOnScrollToBottom()
return
}
mark('onScrollToBottom')
let timeline = this.get('timeline')
let instanceName = this.store.get('currentInstance')
this.store.setForTimeline(instanceName, timeline, { runningUpdate: true })
let newStatuses = await this.fetchStatusesAndPossiblyFallBack()
this.store.setForTimeline(instanceName, timeline, { runningUpdate: false })
this.addStatuses(newStatuses)
stop('onScrollToBottom')
},
addStatuses(newStatuses) {
console.log('addStatuses()')
let instanceName = this.store.get('currentInstance')
let timeline = this.get('timeline')
let statusIds = this.store.get('statusIds')
if (!statusIds) {
return
}
/* no await */ database.insertStatuses(instanceName, timeline, newStatuses)
let newStatusIds = newStatuses.map(status => status.id)
let merged = mergeStatuses(statusIds, newStatusIds)
this.store.setForTimeline(instanceName, timeline, { statusIds: merged })
},
async fetchStatusesAndPossiblyFallBack() {
let online = this.get('online')
let instanceName = this.store.get('currentInstance')
let instanceData = this.store.get('currentInstanceData')
let timeline = this.get('timeline')
let lastStatusId = this.store.get('lastStatusId')
let statuses
if (!online) {
statuses = await database.getTimeline(instanceName, timeline, lastStatusId, FETCH_LIMIT)
} else {
try {
statuses = await getTimeline(instanceName, instanceData.access_token, timeline, lastStatusId, FETCH_LIMIT)
/* no await */ database.insertStatuses(instanceName, timeline, statuses)
} catch (e) {
console.error(e)
toast.say('Internet request failed. Showing offline content.')
statuses = await database.getTimeline(instanceName, timeline, lastStatusId, FETCH_LIMIT)
}
}
return statuses
} }
} }
} }

View file

@ -52,6 +52,12 @@ class PinaforeStore extends Store {
timelines[instanceName] = timelineData timelines[instanceName] = timelineData
this.set({timelines: timelines}) this.set({timelines: timelines})
} }
getForTimeline(instanceName, timelineName, key) {
let timelines = this.get('timelines') || {}
let timelineData = timelines[instanceName] || {}
return (timelineData[timelineName] || {})[key]
}
} }
const store = new PinaforeStore({ const store = new PinaforeStore({