From bb68cfaa815ce4b33f0671710fd94f9d94f4324c Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 29 Jun 2022 16:00:00 +0900 Subject: [PATCH] enhance(client): improve router Fix #8902 --- packages/client/src/nirax.ts | 11 +++++++++++ packages/client/src/pages/about.vue | 8 +++++++- packages/client/src/pages/admin/index.vue | 2 +- packages/client/src/router.ts | 5 +++-- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/packages/client/src/nirax.ts b/packages/client/src/nirax.ts index 6db6335669..9dc787de4e 100644 --- a/packages/client/src/nirax.ts +++ b/packages/client/src/nirax.ts @@ -8,6 +8,7 @@ type RouteDef = { component: Component; query?: Record; name?: string; + hash?: string; globalCacheKey?: string; }; @@ -78,7 +79,12 @@ export class Router extends EventEmitter<{ public resolve(path: string): { route: RouteDef; props: Map; } | null { let queryString: string | null = null; + let hash: string | null = null; if (path[0] === '/') path = path.substring(1); + if (path.includes('#')) { + hash = path.substring(path.indexOf('#') + 1); + path = path.substring(0, path.indexOf('#')); + } if (path.includes('?')) { queryString = path.substring(path.indexOf('?') + 1); path = path.substring(0, path.indexOf('?')); @@ -127,6 +133,10 @@ export class Router extends EventEmitter<{ if (parts.length !== 0) continue forEachRouteLoop; + if (route.hash != null && hash != null) { + props.set(route.hash, hash); + } + if (route.query != null && queryString != null) { const queryObject = [...new URLSearchParams(queryString).entries()] .reduce((obj, entry) => ({ ...obj, [entry[0]]: entry[1] }), {}); @@ -138,6 +148,7 @@ export class Router extends EventEmitter<{ } } } + return { route, props, diff --git a/packages/client/src/pages/about.vue b/packages/client/src/pages/about.vue index de89e3593c..683f7446b8 100644 --- a/packages/client/src/pages/about.vue +++ b/packages/client/src/pages/about.vue @@ -95,8 +95,14 @@ import number from '@/filters/number'; import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; +const props = withDefaults(defineProps<{ + initialTab?: string; +}>(), { + initialTab: 'overview', +}); + let stats = $ref(null); -let tab = $ref('overview'); +let tab = $ref(props.initialTab); const initStats = () => os.api('stats', { }).then((res) => { diff --git a/packages/client/src/pages/admin/index.vue b/packages/client/src/pages/admin/index.vue index 5ffbe34955..d967a081b7 100644 --- a/packages/client/src/pages/admin/index.vue +++ b/packages/client/src/pages/admin/index.vue @@ -109,7 +109,7 @@ const menuDef = $computed(() => [{ }, { icon: 'fas fa-globe', text: i18n.ts.federation, - to: '/admin/federation', + to: '/about#federation', active: props.initialPage === 'federation', }, { icon: 'fas fa-clipboard-list', diff --git a/packages/client/src/router.ts b/packages/client/src/router.ts index a452a8bb3d..d257612f35 100644 --- a/packages/client/src/router.ts +++ b/packages/client/src/router.ts @@ -50,6 +50,7 @@ export const routes = [{ }, { path: '/about', component: page(() => import('./pages/about.vue')), + hash: 'initialTab', }, { path: '/about-misskey', component: page(() => import('./pages/about-misskey.vue')), @@ -203,7 +204,7 @@ export const routes = [{ component: page(() => import('./pages/not-found.vue')), }]; -export const mainRouter = new Router(routes, location.pathname + location.search); +export const mainRouter = new Router(routes, location.pathname + location.search + location.hash); window.history.replaceState({ key: mainRouter.getCurrentKey() }, '', location.href); @@ -228,7 +229,7 @@ mainRouter.addListener('push', ctx => { }); window.addEventListener('popstate', (event) => { - mainRouter.change(location.pathname + location.search, event.state?.key); + mainRouter.change(location.pathname + location.search + location.hash, event.state?.key); const scrollPos = scrollPosStore.get(event.state?.key) ?? 0; window.scroll({ top: scrollPos, behavior: 'instant' }); window.setTimeout(() => { // 遷移直後はタイミングによってはコンポーネントが復元し切ってない可能性も考えられるため少し時間を空けて再度スクロール