diff --git a/components/common/CommonPaginator.vue b/components/common/CommonPaginator.vue index 11cd3f9b..3f24c0bf 100644 --- a/components/common/CommonPaginator.vue +++ b/components/common/CommonPaginator.vue @@ -15,7 +15,7 @@ const { paginator: Paginator<any, any[]> keyProp?: string virtualScroller?: boolean - stream?: WsEvents + stream?: Promise<WsEvents> eventType?: 'notification' | 'update' preprocess?: (items: any[]) => any[] }>() diff --git a/components/notification/NotificationPaginator.vue b/components/notification/NotificationPaginator.vue index 6c08b264..d6dd98c7 100644 --- a/components/notification/NotificationPaginator.vue +++ b/components/notification/NotificationPaginator.vue @@ -4,7 +4,7 @@ import type { GroupedAccountLike, NotificationSlot } from '~/types' const { paginator, stream } = defineProps<{ paginator: Paginator<any, Notification[]> - stream?: WsEvents + stream?: Promise<WsEvents> }>() const groupCapacity = Number.MAX_VALUE // No limit diff --git a/components/timeline/TimelineHome.vue b/components/timeline/TimelineHome.vue index 10d5c26a..9581e452 100644 --- a/components/timeline/TimelineHome.vue +++ b/components/timeline/TimelineHome.vue @@ -1,8 +1,8 @@ <script setup lang="ts"> import type { Status } from 'masto' const paginator = useMasto().timelines.iterateHome() -const stream = await useMasto().stream.streamUser() -onBeforeUnmount(() => stream.disconnect()) +const stream = useMasto().stream.streamUser() +onBeforeUnmount(() => stream?.then(s => s.disconnect())) const maxDistance = 10 function preprocess(items: Status[]) { diff --git a/components/timeline/TimelineMentions.vue b/components/timeline/TimelineMentions.vue index 8e0a925b..edc57a31 100644 --- a/components/timeline/TimelineMentions.vue +++ b/components/timeline/TimelineMentions.vue @@ -5,7 +5,7 @@ const paginator = useMasto().notifications.iterate({ limit: 30, types: ['mention const { clearNotifications } = useNotifications() onActivated(clearNotifications) -const stream = await useMasto().stream.streamUser() +const stream = useMasto().stream.streamUser() </script> <template> diff --git a/components/timeline/TimelineNotifications.vue b/components/timeline/TimelineNotifications.vue index 53c067ec..11e6fd4a 100644 --- a/components/timeline/TimelineNotifications.vue +++ b/components/timeline/TimelineNotifications.vue @@ -5,7 +5,7 @@ const paginator = useMasto().notifications.iterate({ limit: 30 }) const { clearNotifications } = useNotifications() onActivated(clearNotifications) -const stream = await useMasto().stream.streamUser() +const stream = useMasto().stream.streamUser() </script> <template> diff --git a/components/timeline/TimelinePaginator.vue b/components/timeline/TimelinePaginator.vue index a6be7618..8c5831f5 100644 --- a/components/timeline/TimelinePaginator.vue +++ b/components/timeline/TimelinePaginator.vue @@ -6,7 +6,7 @@ import type { FilterContext, Paginator, Status, WsEvents } from 'masto' const { paginator, stream } = defineProps<{ paginator: Paginator<any, Status[]> - stream?: WsEvents + stream?: Promise<WsEvents> context?: FilterContext preprocess?: (items: any[]) => any[] }>() diff --git a/components/timeline/TimelinePublic.vue b/components/timeline/TimelinePublic.vue new file mode 100644 index 00000000..2c1e1e16 --- /dev/null +++ b/components/timeline/TimelinePublic.vue @@ -0,0 +1,11 @@ +<script setup lang="ts"> +const paginator = useMasto().timelines.iteratePublic() +const stream = useMasto().stream.streamPublicTimeline() +onBeforeUnmount(() => stream.then(s => s.disconnect())) +</script> + +<template> + <div> + <TimelinePaginator v-bind="{ paginator, stream }" context="public" /> + </div> +</template> diff --git a/components/timeline/TimelinePublicLocal.vue b/components/timeline/TimelinePublicLocal.vue new file mode 100644 index 00000000..829c75da --- /dev/null +++ b/components/timeline/TimelinePublicLocal.vue @@ -0,0 +1,11 @@ +<script setup lang="ts"> +const paginator = useMasto().timelines.iteratePublic({ local: true }) +const stream = useMasto().stream.streamCommunityTimeline() +onBeforeUnmount(() => stream.then(s => s.disconnect())) +</script> + +<template> + <div> + <TimelinePaginator v-bind="{ paginator, stream }" context="public" /> + </div> +</template> diff --git a/composables/paginator.ts b/composables/paginator.ts index 7daef178..72e0791e 100644 --- a/composables/paginator.ts +++ b/composables/paginator.ts @@ -4,7 +4,7 @@ import type { PaginatorState } from '~/types' export function usePaginator<T>( paginator: Paginator<any, T[]>, - stream?: WsEvents, + stream?: Promise<WsEvents>, eventType: 'notification' | 'update' = 'update', preprocess: (items: T[]) => T[] = (items: T[]) => items, ) { @@ -24,32 +24,34 @@ export function usePaginator<T>( prevItems.value = [] } - stream?.on(eventType, (status) => { - if ('uri' in status) + stream?.then((s) => { + s.on(eventType, (status) => { + if ('uri' in status) + cacheStatus(status, undefined, true) + + const index = prevItems.value.findIndex((i: any) => i.id === status.id) + if (index >= 0) + prevItems.value.splice(index, 1) + + prevItems.value.unshift(status as any) + }) + + // TODO: update statuses + s.on('status.update', (status) => { cacheStatus(status, undefined, true) - const index = prevItems.value.findIndex((i: any) => i.id === status.id) - if (index >= 0) - prevItems.value.splice(index, 1) + const index = items.value.findIndex((s: any) => s.id === status.id) + if (index >= 0) + items.value[index] = status as any + }) - prevItems.value.unshift(status as any) - }) + s.on('delete', (id) => { + removeCachedStatus(id) - // TODO: update statuses - stream?.on('status.update', (status) => { - cacheStatus(status, undefined, true) - - const index = items.value.findIndex((s: any) => s.id === status.id) - if (index >= 0) - items.value[index] = status as any - }) - - stream?.on('delete', (id) => { - removeCachedStatus(id) - - const index = items.value.findIndex((s: any) => s.id === id) - if (index >= 0) - items.value.splice(index, 1) + const index = items.value.findIndex((s: any) => s.id === id) + if (index >= 0) + items.value.splice(index, 1) + }) }) async function loadNext() { @@ -95,9 +97,9 @@ export function usePaginator<T>( () => { if ( isInScreen - && state.value === 'idle' - // No new content is loaded when the keepAlive page enters the background - && deactivated.value === false + && state.value === 'idle' + // No new content is loaded when the keepAlive page enters the background + && deactivated.value === false ) loadNext() }, diff --git a/pages/[[server]]/public/index.vue b/pages/[[server]]/public/index.vue index cb5acd4f..c72c18d5 100644 --- a/pages/[[server]]/public/index.vue +++ b/pages/[[server]]/public/index.vue @@ -1,7 +1,5 @@ <script setup lang="ts"> -const paginator = useMasto().timelines.iteratePublic() -const stream = await useMasto().stream.streamPublicTimeline() -onBeforeUnmount(() => stream.disconnect()) + const { t } = useI18n() @@ -19,8 +17,6 @@ useHeadFixed({ </NuxtLink> </template> - <slot> - <TimelinePaginator v-bind="{ paginator, stream }" context="public" /> - </slot> + <TimelinePublic v-if="isMastoInitialised" /> </MainContent> </template> diff --git a/pages/[[server]]/public/local.vue b/pages/[[server]]/public/local.vue index d66fde81..303a4796 100644 --- a/pages/[[server]]/public/local.vue +++ b/pages/[[server]]/public/local.vue @@ -1,7 +1,4 @@ <script setup lang="ts"> -const paginator = useMasto().timelines.iteratePublic({ local: true }) -const stream = await useMasto().stream.streamCommunityTimeline() -onBeforeUnmount(() => stream.disconnect()) const { t } = useI18n() @@ -19,8 +16,6 @@ useHeadFixed({ </NuxtLink> </template> - <slot> - <TimelinePaginator v-bind="{ paginator, stream }" context="public" /> - </slot> + <TimelinePublicLocal v-if="isMastoInitialised" /> </MainContent> </template> diff --git a/pages/[[server]]/tags/[tag].vue b/pages/[[server]]/tags/[tag].vue index 005d904b..717ac746 100644 --- a/pages/[[server]]/tags/[tag].vue +++ b/pages/[[server]]/tags/[tag].vue @@ -6,8 +6,8 @@ const masto = useMasto() const { data: tag, refresh } = $(await useAsyncData(() => masto.tags.fetch(tagName), { watch: [isMastoInitialised], immediate: isMastoInitialised.value })) const paginator = masto.timelines.iterateHashtag(tagName) -const stream = await masto.stream.streamTagTimeline(tagName) -onBeforeUnmount(() => stream.disconnect()) +const stream = masto.stream.streamTagTimeline(tagName) +onBeforeUnmount(() => stream.then(s => s.disconnect())) if (tag) { useHeadFixed({