diff --git a/packages/client/src/nirax.ts b/packages/client/src/nirax.ts index 6db633566..9dc787de4 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 ae68341d1..f76799fff 100644 --- a/packages/client/src/pages/about.vue +++ b/packages/client/src/pages/about.vue @@ -93,8 +93,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 b91330e1b..7af75367b 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 769d9cb2a..8dca559e0 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')), @@ -215,7 +216,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); @@ -240,7 +241,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(() => { // 遷移直後はタイミングによってはコンポーネントが復元し切ってない可能性も考えられるため少し時間を空けて再度スクロール