From c546408326be1dc1355522063d2f7dc848842bab Mon Sep 17 00:00:00 2001 From: userquin Date: Sat, 7 Jan 2023 16:27:09 +0100 Subject: [PATCH] feat: restore scroll position --- components/status/StatusActions.vue | 10 +++++--- composables/paginator.ts | 27 ++++++++++++++++++++++ constants/index.ts | 1 + plugins/remember-scroll-position.client.ts | 24 +++++++++++++++++++ 4 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 plugins/remember-scroll-position.client.ts diff --git a/components/status/StatusActions.vue b/components/status/StatusActions.vue index 1cc8c0b2..7f5cf0b8 100644 --- a/components/status/StatusActions.vue +++ b/components/status/StatusActions.vue @@ -7,6 +7,7 @@ const props = defineProps<{ command?: boolean }>() +const nuxtApp = useNuxtApp() const focusEditor = inject('focus-editor', noop) const { details, command } = $(props) @@ -24,11 +25,14 @@ const { formatHumanReadableNumber, formatNumber, forSR } = useHumanReadableNumbe const reply = () => { if (!checkLogin()) return - if (details) - focusEditor() - else + if (details) { + focusEditor() + } + else { + nuxtApp.$rememberScrollPosition(status) navigateTo({ path: getStatusRoute(status).href, state: { focusReply: true } }) + } } diff --git a/composables/paginator.ts b/composables/paginator.ts index 25ee81b7..a293f942 100644 --- a/composables/paginator.ts +++ b/composables/paginator.ts @@ -1,5 +1,6 @@ import type { Paginator, WsEvents } from 'masto' import type { PaginatorState } from '~/types' +import { onReactivated } from '~/composables/vue' export function usePaginator( paginator: Paginator, @@ -16,7 +17,10 @@ export function usePaginator( const bound = reactive(useElementBounding(endAnchor)) const isInScreen = $computed(() => bound.top < window.innerHeight * 2) const error = ref() + const loaded = ref(false) + const deactivated = useDeactivated() + const nuxtApp = useNuxtApp() async function update() { items.value.unshift(...prevItems.value) @@ -77,13 +81,36 @@ export function usePaginator( await nextTick() bound.update() + if (!loaded.value) { + loaded.value = true + await nextTick() + nuxtApp.$restoreScrollPosition() + } } if (process.client) { + const timeout = ref() useIntervalFn(() => { bound.update() }, 1000) + onDeactivated(() => { + window.clearTimeout(timeout.value) + loaded.value = false + }) + onReactivated(() => { + window.clearTimeout(timeout.value) + if (isMastoInitialised.value) { + if (!loaded.value) + loaded.value = true + + timeout.value = setTimeout(() => nuxtApp.$restoreScrollPosition(), 600) + } + else { + loaded.value = false + } + }) + if (!isMastoInitialised.value) { onMastoInit(() => { state.value = 'idle' diff --git a/constants/index.ts b/constants/index.ts index 7770ca1d..33978f47 100644 --- a/constants/index.ts +++ b/constants/index.ts @@ -17,6 +17,7 @@ export const STORAGE_KEY_HIDE_EXPLORE_NEWS_TIPS = 'elk-hide-explore-news-tips' export const STORAGE_KEY_HIDE_EXPLORE_TAGS_TIPS = 'elk-hide-explore-tags-tips' export const STORAGE_KEY_NOTIFICATION = 'elk-notification' export const STORAGE_KEY_NOTIFICATION_POLICY = 'elk-notification-policy' +export const STORAGE_KEY_LAST_SCROLL_POSITION = 'elk-last-scroll-position' export const COOKIE_MAX_AGE = 10 * 365 * 24 * 60 * 60 * 1000 diff --git a/plugins/remember-scroll-position.client.ts b/plugins/remember-scroll-position.client.ts new file mode 100644 index 00000000..b4f26518 --- /dev/null +++ b/plugins/remember-scroll-position.client.ts @@ -0,0 +1,24 @@ +import type { Status } from 'masto' + +import { STORAGE_KEY_LAST_SCROLL_POSITION } from '~/constants' + +export default defineNuxtPlugin(() => { + const lastStatus = useSessionStorage>(STORAGE_KEY_LAST_SCROLL_POSITION, {}) + return { + provide: { + restoreScrollPosition: () => { + const statusId = lastStatus.value[useRoute().fullPath] + if (statusId) { + const el = document.getElementById(`status-${statusId}`) + if (el) + nextTick().then(() => el?.scrollIntoView()) + else + delete lastStatus.value[useRoute().fullPath] + } + }, + rememberScrollPosition: (status: Status) => { + lastStatus.value[useRoute().fullPath] = status.id + }, + }, + } +})