diff --git a/routes/_actions/timeline.js b/routes/_actions/timeline.js new file mode 100644 index 0000000..829c902 --- /dev/null +++ b/routes/_actions/timeline.js @@ -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 }) +} \ No newline at end of file diff --git a/routes/_components/Layout.html b/routes/_components/Layout.html index 46a6e7b..c7e9692 100644 --- a/routes/_components/Layout.html +++ b/routes/_components/Layout.html @@ -1,3 +1,4 @@ +<:Window bind:online />