From 409cd4fbd3289f591e6c7a875dbb8bb2789f5f7b Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 19 Mar 2025 15:54:30 +0900 Subject: refactor(frontend): router refactoring --- packages/frontend/src/lib/nirax.ts | 340 +++++++++++++++++++++++++++++++++++++ 1 file changed, 340 insertions(+) create mode 100644 packages/frontend/src/lib/nirax.ts (limited to 'packages/frontend/src/lib/nirax.ts') diff --git a/packages/frontend/src/lib/nirax.ts b/packages/frontend/src/lib/nirax.ts new file mode 100644 index 0000000000..cc20d497e6 --- /dev/null +++ b/packages/frontend/src/lib/nirax.ts @@ -0,0 +1,340 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +// NIRAX --- A lightweight router + +import { onMounted, shallowRef } from 'vue'; +import { EventEmitter } from 'eventemitter3'; +import type { Component, ShallowRef } from 'vue'; + +function safeURIDecode(str: string): string { + try { + return decodeURIComponent(str); + } catch { + return str; + } +} + +interface RouteDefBase { + path: string; + query?: Record; + loginRequired?: boolean; + name?: string; + hash?: string; + children?: RouteDef[]; +} + +interface RouteDefWithComponent extends RouteDefBase { + component: Component, +} + +interface RouteDefWithRedirect extends RouteDefBase { + redirect: string | ((props: Map) => string); +} + +export type RouteDef = RouteDefWithComponent | RouteDefWithRedirect; + +export type RouterFlag = 'forcePage'; + +type ParsedPath = (string | { + name: string; + startsWith?: string; + wildcard?: boolean; + optional?: boolean; +})[]; + +export type RouterEvent = { + change: (ctx: { + beforePath: string; + path: string; + resolved: Resolved; + }) => void; + replace: (ctx: { + path: string; + }) => void; + push: (ctx: { + beforePath: string; + path: string; + route: RouteDef | null; + props: Map | null; + }) => void; + same: () => void; +}; + +export type Resolved = { + route: RouteDef; + props: Map; + child?: Resolved; + redirected?: boolean; + + /** @internal */ + _parsedRoute: { + fullPath: string; + queryString: string | null; + hash: string | null; + }; +}; + +function parsePath(path: string): ParsedPath { + const res = [] as ParsedPath; + + path = path.substring(1); + + for (const part of path.split('/')) { + if (part.includes(':')) { + const prefix = part.substring(0, part.indexOf(':')); + const placeholder = part.substring(part.indexOf(':') + 1); + const wildcard = placeholder.includes('(*)'); + const optional = placeholder.endsWith('?'); + res.push({ + name: placeholder.replace('(*)', '').replace('?', ''), + startsWith: prefix !== '' ? prefix : undefined, + wildcard, + optional, + }); + } else if (part.length !== 0) { + res.push(part); + } + } + + return res; +} + +export class Nirax extends EventEmitter { + private routes: DEF; + public current: Resolved; + public currentRef: ShallowRef; + public currentRoute: ShallowRef; + private currentPath: string; + private isLoggedIn: boolean; + private notFoundPageComponent: Component; + private redirectCount = 0; + + public navHook: ((path: string, flag?: RouterFlag) => boolean) | null = null; + + constructor(routes: DEF, currentPath: Nirax['currentPath'], isLoggedIn: boolean, notFoundPageComponent: Component) { + super(); + + this.routes = routes; + this.current = this.resolve(currentPath)!; + this.currentRef = shallowRef(this.current); + this.currentRoute = shallowRef(this.current.route); + this.currentPath = currentPath; + this.isLoggedIn = isLoggedIn; + this.notFoundPageComponent = notFoundPageComponent; + } + + public init() { + const res = this.navigate(this.currentPath, false); + this.emit('replace', { + path: res._parsedRoute.fullPath, + }); + } + + public resolve(path: string): Resolved | null { + const fullPath = path; + 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('?')); + } + + const _parsedRoute = { + fullPath, + queryString, + hash, + }; + + function check(routes: RouteDef[], _parts: string[]): Resolved | null { + forEachRouteLoop: + for (const route of routes) { + let parts = [..._parts]; + const props = new Map(); + + pathMatchLoop: + for (const p of parsePath(route.path)) { + if (typeof p === 'string') { + if (p === parts[0]) { + parts.shift(); + } else { + continue forEachRouteLoop; + } + } else { + if (parts[0] == null && !p.optional) { + continue forEachRouteLoop; + } + if (p.wildcard) { + if (parts.length !== 0) { + props.set(p.name, safeURIDecode(parts.join('/'))); + parts = []; + } + break pathMatchLoop; + } else { + if (p.startsWith) { + if (parts[0] == null || !parts[0].startsWith(p.startsWith)) continue forEachRouteLoop; + + props.set(p.name, safeURIDecode(parts[0].substring(p.startsWith.length))); + parts.shift(); + } else { + if (parts[0]) { + props.set(p.name, safeURIDecode(parts[0])); + } + parts.shift(); + } + } + } + } + + if (parts.length === 0) { + if (route.children) { + const child = check(route.children, []); + if (child) { + return { + route, + props, + child, + _parsedRoute, + }; + } else { + continue forEachRouteLoop; + } + } + + if (route.hash != null && hash != null) { + props.set(route.hash, safeURIDecode(hash)); + } + + if (route.query != null && queryString != null) { + const queryObject = [...new URLSearchParams(queryString).entries()] + .reduce((obj, entry) => ({ ...obj, [entry[0]]: entry[1] }), {}); + + for (const q in route.query) { + const as = route.query[q]; + if (queryObject[q]) { + props.set(as, safeURIDecode(queryObject[q])); + } + } + } + + return { + route, + props, + _parsedRoute, + }; + } else { + if (route.children) { + const child = check(route.children, parts); + if (child) { + return { + route, + props, + child, + _parsedRoute, + }; + } else { + continue forEachRouteLoop; + } + } else { + continue forEachRouteLoop; + } + } + } + + return null; + } + + const _parts = path.split('/').filter(part => part.length !== 0); + + return check(this.routes, _parts); + } + + private navigate(path: string, emitChange = true, _redirected = false): Resolved { + const beforePath = this.currentPath; + this.currentPath = path; + + const res = this.resolve(this.currentPath); + + if (res == null) { + throw new Error('no route found for: ' + path); + } + + if ('redirect' in res.route) { + let redirectPath: string; + if (typeof res.route.redirect === 'function') { + redirectPath = res.route.redirect(res.props); + } else { + redirectPath = res.route.redirect + (res._parsedRoute.queryString ? '?' + res._parsedRoute.queryString : '') + (res._parsedRoute.hash ? '#' + res._parsedRoute.hash : ''); + } + if (_DEV_) console.log('Redirecting to: ', redirectPath); + if (_redirected && this.redirectCount++ > 10) { + throw new Error('redirect loop detected'); + } + return this.navigate(redirectPath, emitChange, true); + } + + if (res.route.loginRequired && !this.isLoggedIn) { + res.route.component = this.notFoundPageComponent; + res.props.set('showLoginPopup', true); + } + + this.current = res; + this.currentRef.value = res; + this.currentRoute.value = res.route; + + if (emitChange && res.route.path !== '/:(*)') { + this.emit('change', { + beforePath, + path, + resolved: res, + }); + } + + this.redirectCount = 0; + return { + ...res, + redirected: _redirected, + }; + } + + public getCurrentPath() { + return this.currentPath; + } + + public push(path: string, flag?: RouterFlag) { + const beforePath = this.currentPath; + if (path === beforePath) { + this.emit('same'); + return; + } + if (this.navHook) { + const cancel = this.navHook(path, flag); + if (cancel) return; + } + const res = this.navigate(path); + if (res.route.path === '/:(*)') { + location.href = path; + } else { + this.emit('push', { + beforePath, + path: res._parsedRoute.fullPath, + route: res.route, + props: res.props, + }); + } + } + + public replace(path: string) { + const res = this.navigate(path); + this.emit('replace', { + path: res._parsedRoute.fullPath, + }); + } +} -- cgit v1.2.3-freya From 81ac71f7e59623625369aaff75a8712923450b80 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 19 Mar 2025 18:06:22 +0900 Subject: refactor(frontend): router refactoring --- packages/frontend/src/components/MkPageWindow.vue | 22 ++--- .../src/components/global/NestedRouterView.vue | 19 ++--- .../frontend/src/components/global/RouterView.vue | 49 ++--------- .../src/components/global/StackingRouterView.vue | 71 +++++++--------- packages/frontend/src/events.ts | 1 - packages/frontend/src/lib/nirax.ts | 94 ++++++++++++---------- packages/frontend/src/pages/settings/profile.vue | 5 -- packages/frontend/src/router.ts | 16 ++-- packages/frontend/src/ui/classic.vue | 2 +- packages/frontend/src/ui/universal.vue | 2 +- 10 files changed, 114 insertions(+), 167 deletions(-) (limited to 'packages/frontend/src/lib/nirax.ts') diff --git a/packages/frontend/src/components/MkPageWindow.vue b/packages/frontend/src/components/MkPageWindow.vue index fae4246335..4fbdc51d22 100644 --- a/packages/frontend/src/components/MkPageWindow.vue +++ b/packages/frontend/src/components/MkPageWindow.vue @@ -59,7 +59,7 @@ const windowRouter = createRouter(props.initialPath); const pageMetadata = ref(null); const windowEl = shallowRef>(); const history = ref<{ path: string; }[]>([{ - path: windowRouter.getCurrentPath(), + path: windowRouter.getCurrentFullPath(), }]); const buttonsLeft = computed(() => { const buttons: Record[] = []; @@ -97,20 +97,20 @@ function getSearchMarker(path: string) { const searchMarkerId = ref(getSearchMarker(props.initialPath)); windowRouter.addListener('push', ctx => { - history.value.push({ path: ctx.path }); + history.value.push({ path: ctx.fullPath }); }); windowRouter.addListener('replace', ctx => { history.value.pop(); - history.value.push({ path: ctx.path }); + history.value.push({ path: ctx.fullPath }); }); windowRouter.addListener('change', ctx => { - if (_DEV_) console.log('windowRouter: change', ctx.path); - searchMarkerId.value = getSearchMarker(ctx.path); + if (_DEV_) console.log('windowRouter: change', ctx.fullPath); + searchMarkerId.value = getSearchMarker(ctx.fullPath); analytics.page({ - path: ctx.path, - title: ctx.path, + path: ctx.fullPath, + title: ctx.fullPath, }); }); @@ -139,14 +139,14 @@ const contextmenu = computed(() => ([{ icon: 'ti ti-external-link', text: i18n.ts.openInNewTab, action: () => { - window.open(url + windowRouter.getCurrentPath(), '_blank', 'noopener'); + window.open(url + windowRouter.getCurrentFullPath(), '_blank', 'noopener'); windowEl.value?.close(); }, }, { icon: 'ti ti-link', text: i18n.ts.copyLink, action: () => { - copyToClipboard(url + windowRouter.getCurrentPath()); + copyToClipboard(url + windowRouter.getCurrentFullPath()); }, }])); @@ -164,12 +164,12 @@ function close() { } function expand() { - mainRouter.push(windowRouter.getCurrentPath(), 'forcePage'); + mainRouter.push(windowRouter.getCurrentFullPath(), 'forcePage'); windowEl.value?.close(); } function popout() { - _popout(windowRouter.getCurrentPath(), windowEl.value?.$el); + _popout(windowRouter.getCurrentFullPath(), windowEl.value?.$el); windowEl.value?.close(); } diff --git a/packages/frontend/src/components/global/NestedRouterView.vue b/packages/frontend/src/components/global/NestedRouterView.vue index 5b22d0b7a8..af00347db8 100644 --- a/packages/frontend/src/components/global/NestedRouterView.vue +++ b/packages/frontend/src/components/global/NestedRouterView.vue @@ -14,8 +14,9 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/components/global/RouterView.vue b/packages/frontend/src/components/global/RouterView.vue index 720034a942..fbdb7d261e 100644 --- a/packages/frontend/src/components/global/RouterView.vue +++ b/packages/frontend/src/components/global/RouterView.vue @@ -5,10 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/components/global/StackingRouterView.vue b/packages/frontend/src/components/global/StackingRouterView.vue index b94e020072..c95c74aef3 100644 --- a/packages/frontend/src/components/global/StackingRouterView.vue +++ b/packages/frontend/src/components/global/StackingRouterView.vue @@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only :duration="200" tag="div" :class="$style.tabs" > -
+
@@ -41,10 +41,9 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/events.ts b/packages/frontend/src/events.ts index a74018223c..dfd3d4120c 100644 --- a/packages/frontend/src/events.ts +++ b/packages/frontend/src/events.ts @@ -10,5 +10,4 @@ export const globalEvents = new EventEmitter<{ themeChanging: () => void; themeChanged: () => void; clientNotification: (notification: Misskey.entities.Notification) => void; - requestClearPageCache: () => void; }>(); diff --git a/packages/frontend/src/lib/nirax.ts b/packages/frontend/src/lib/nirax.ts index cc20d497e6..8783874bc2 100644 --- a/packages/frontend/src/lib/nirax.ts +++ b/packages/frontend/src/lib/nirax.ts @@ -5,7 +5,7 @@ // NIRAX --- A lightweight router -import { onMounted, shallowRef } from 'vue'; +import { onBeforeUnmount, onMounted, shallowRef } from 'vue'; import { EventEmitter } from 'eventemitter3'; import type { Component, ShallowRef } from 'vue'; @@ -45,28 +45,28 @@ type ParsedPath = (string | { optional?: boolean; })[]; -export type RouterEvent = { +export type RouterEvents = { change: (ctx: { - beforePath: string; - path: string; - resolved: Resolved; + beforeFullPath: string; + fullPath: string; + resolved: PathResolvedResult; }) => void; replace: (ctx: { - path: string; + fullPath: string; }) => void; push: (ctx: { - beforePath: string; - path: string; + beforeFullPath: string; + fullPath: string; route: RouteDef | null; props: Map | null; }) => void; same: () => void; }; -export type Resolved = { +export type PathResolvedResult = { route: RouteDef; props: Map; - child?: Resolved; + child?: PathResolvedResult; redirected?: boolean; /** @internal */ @@ -102,39 +102,39 @@ function parsePath(path: string): ParsedPath { return res; } -export class Nirax extends EventEmitter { +export class Nirax extends EventEmitter { private routes: DEF; - public current: Resolved; - public currentRef: ShallowRef; + public current: PathResolvedResult; + public currentRef: ShallowRef; public currentRoute: ShallowRef; - private currentPath: string; + private currentFullPath: string; // /foo/bar?baz=qux#hash private isLoggedIn: boolean; private notFoundPageComponent: Component; private redirectCount = 0; - public navHook: ((path: string, flag?: RouterFlag) => boolean) | null = null; + public navHook: ((fullPath: string, flag?: RouterFlag) => boolean) | null = null; - constructor(routes: DEF, currentPath: Nirax['currentPath'], isLoggedIn: boolean, notFoundPageComponent: Component) { + constructor(routes: DEF, currentFullPath: Nirax['currentFullPath'], isLoggedIn: boolean, notFoundPageComponent: Component) { super(); this.routes = routes; - this.current = this.resolve(currentPath)!; + this.current = this.resolve(currentFullPath)!; this.currentRef = shallowRef(this.current); this.currentRoute = shallowRef(this.current.route); - this.currentPath = currentPath; + this.currentFullPath = currentFullPath; this.isLoggedIn = isLoggedIn; this.notFoundPageComponent = notFoundPageComponent; } public init() { - const res = this.navigate(this.currentPath, false); + const res = this.navigate(this.currentFullPath, false); this.emit('replace', { - path: res._parsedRoute.fullPath, + fullPath: res._parsedRoute.fullPath, }); } - public resolve(path: string): Resolved | null { - const fullPath = path; + public resolve(fullPath: string): PathResolvedResult | null { + let path = fullPath; let queryString: string | null = null; let hash: string | null = null; if (path[0] === '/') path = path.substring(1); @@ -153,7 +153,7 @@ export class Nirax extends EventEmitter { hash, }; - function check(routes: RouteDef[], _parts: string[]): Resolved | null { + function check(routes: RouteDef[], _parts: string[]): PathResolvedResult | null { forEachRouteLoop: for (const route of routes) { let parts = [..._parts]; @@ -256,14 +256,14 @@ export class Nirax extends EventEmitter { return check(this.routes, _parts); } - private navigate(path: string, emitChange = true, _redirected = false): Resolved { - const beforePath = this.currentPath; - this.currentPath = path; + private navigate(fullPath: string, emitChange = true, _redirected = false): PathResolvedResult { + const beforeFullPath = this.currentFullPath; + this.currentFullPath = fullPath; - const res = this.resolve(this.currentPath); + const res = this.resolve(this.currentFullPath); if (res == null) { - throw new Error('no route found for: ' + path); + throw new Error('no route found for: ' + fullPath); } if ('redirect' in res.route) { @@ -291,8 +291,8 @@ export class Nirax extends EventEmitter { if (emitChange && res.route.path !== '/:(*)') { this.emit('change', { - beforePath, - path, + beforeFullPath, + fullPath, resolved: res, }); } @@ -304,37 +304,45 @@ export class Nirax extends EventEmitter { }; } - public getCurrentPath() { - return this.currentPath; + public getCurrentFullPath() { + return this.currentFullPath; } - public push(path: string, flag?: RouterFlag) { - const beforePath = this.currentPath; - if (path === beforePath) { + public push(fullPath: string, flag?: RouterFlag) { + const beforeFullPath = this.currentFullPath; + if (fullPath === beforeFullPath) { this.emit('same'); return; } if (this.navHook) { - const cancel = this.navHook(path, flag); + const cancel = this.navHook(fullPath, flag); if (cancel) return; } - const res = this.navigate(path); + const res = this.navigate(fullPath); if (res.route.path === '/:(*)') { - location.href = path; + location.href = fullPath; } else { this.emit('push', { - beforePath, - path: res._parsedRoute.fullPath, + beforeFullPath, + fullPath: res._parsedRoute.fullPath, route: res.route, props: res.props, }); } } - public replace(path: string) { - const res = this.navigate(path); + public replace(fullPath: string) { + const res = this.navigate(fullPath); this.emit('replace', { - path: res._parsedRoute.fullPath, + fullPath: res._parsedRoute.fullPath, + }); + } + + public useListener(event: E, listener: L) { + this.addListener(event, listener); + + onBeforeUnmount(() => { + this.removeListener(event, listener); }); } } diff --git a/packages/frontend/src/pages/settings/profile.vue b/packages/frontend/src/pages/settings/profile.vue index e9b1ee8101..30b7cf9a86 100644 --- a/packages/frontend/src/pages/settings/profile.vue +++ b/packages/frontend/src/pages/settings/profile.vue @@ -169,7 +169,6 @@ import { langmap } from '@/utility/langmap.js'; import { definePage } from '@/page.js'; import { claimAchievement } from '@/utility/achievements.js'; import { store } from '@/store.js'; -import { globalEvents } from '@/events.js'; import MkInfo from '@/components/MkInfo.vue'; import MkTextarea from '@/components/MkTextarea.vue'; @@ -223,7 +222,6 @@ function saveFields() { os.apiWithDialog('i/update', { fields: fields.value.filter(field => field.name !== '' && field.value !== '').map(field => ({ name: field.name, value: field.value })), }); - globalEvents.emit('requestClearPageCache'); } function save() { @@ -249,7 +247,6 @@ function save() { text: i18n.ts.yourNameContainsProhibitedWordsDescription, }, }); - globalEvents.emit('requestClearPageCache'); claimAchievement('profileFilled'); if (profile.name === 'syuilo' || profile.name === 'しゅいろ') { claimAchievement('setNameToSyuilo'); @@ -281,7 +278,6 @@ function changeAvatar(ev) { }); $i.avatarId = i.avatarId; $i.avatarUrl = i.avatarUrl; - globalEvents.emit('requestClearPageCache'); claimAchievement('profileFilled'); }); } @@ -308,7 +304,6 @@ function changeBanner(ev) { }); $i.bannerId = i.bannerId; $i.bannerUrl = i.bannerUrl; - globalEvents.emit('requestClearPageCache'); }); } diff --git a/packages/frontend/src/router.ts b/packages/frontend/src/router.ts index b5f59b30c1..dd70571d64 100644 --- a/packages/frontend/src/router.ts +++ b/packages/frontend/src/router.ts @@ -13,8 +13,8 @@ import { DI } from '@/di.js'; export type Router = Nirax; -export function createRouter(path: string): Router { - return new Nirax(ROUTE_DEF, path, !!$i, page(() => import('@/pages/not-found.vue'))); +export function createRouter(fullPath: string): Router { + return new Nirax(ROUTE_DEF, fullPath, !!$i, page(() => import('@/pages/not-found.vue'))); } export const mainRouter = createRouter(location.pathname + location.search + location.hash); @@ -24,23 +24,23 @@ window.addEventListener('popstate', (event) => { }); mainRouter.addListener('push', ctx => { - window.history.pushState({ }, '', ctx.path); + window.history.pushState({ }, '', ctx.fullPath); }); mainRouter.addListener('replace', ctx => { - window.history.replaceState({ }, '', ctx.path); + window.history.replaceState({ }, '', ctx.fullPath); }); mainRouter.addListener('change', ctx => { - console.log('mainRouter: change', ctx.path); + console.log('mainRouter: change', ctx.fullPath); analytics.page({ - path: ctx.path, - title: ctx.path, + path: ctx.fullPath, + title: ctx.fullPath, }); }); mainRouter.init(); export function useRouter(): Router { - return inject(DI.router, null) ?? mainRouter; + return inject(DI.router) ?? mainRouter; } diff --git a/packages/frontend/src/ui/classic.vue b/packages/frontend/src/ui/classic.vue index fa63586ef7..2ef06726f9 100644 --- a/packages/frontend/src/ui/classic.vue +++ b/packages/frontend/src/ui/classic.vue @@ -112,7 +112,7 @@ function onContextmenu(ev: MouseEvent) { if (isLink(ev.target)) return; if (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO', 'CANVAS'].includes(ev.target.tagName) || ev.target.attributes['contenteditable']) return; if (window.getSelection().toString() !== '') return; - const path = mainRouter.getCurrentPath(); + const path = mainRouter.getCurrentFullPath(); os.contextMenu([{ type: 'label', text: path, diff --git a/packages/frontend/src/ui/universal.vue b/packages/frontend/src/ui/universal.vue index a6695de39d..133360972b 100644 --- a/packages/frontend/src/ui/universal.vue +++ b/packages/frontend/src/ui/universal.vue @@ -186,7 +186,7 @@ const onContextmenu = (ev) => { if (isLink(ev.target)) return; if (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO', 'CANVAS'].includes(ev.target.tagName) || ev.target.attributes['contenteditable']) return; if (window.getSelection()?.toString() !== '') return; - const path = mainRouter.getCurrentPath(); + const path = mainRouter.getCurrentFullPath(); os.contextMenu([{ type: 'label', text: path, -- cgit v1.2.3-freya From 7f534a41a65ec93a0eafd02796b782309b3d0702 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 20 Mar 2025 16:07:52 +0900 Subject: fix lint --- packages/frontend/src/_boot_.ts | 2 +- packages/frontend/src/accounts.ts | 2 +- packages/frontend/src/boot/common.ts | 12 ++++++------ packages/frontend/src/boot/main-boot.ts | 8 ++++---- packages/frontend/src/components/MkEmbedCodeGenDialog.vue | 2 +- packages/frontend/src/components/global/MkA.vue | 2 +- packages/frontend/src/lib/nirax.ts | 2 +- packages/frontend/src/navbar.ts | 2 +- packages/frontend/src/pages/auth.vue | 2 +- packages/frontend/src/pages/lookup.vue | 6 +++--- packages/frontend/src/pages/miauth.vue | 2 +- packages/frontend/src/pages/share.vue | 4 ++-- packages/frontend/src/router.ts | 4 ++-- packages/frontend/src/ui/_common_/stream-indicator.vue | 2 +- packages/frontend/src/ui/classic.vue | 2 +- packages/frontend/src/ui/universal.vue | 2 +- packages/frontend/src/ui/zen.vue | 2 +- packages/frontend/src/utility/reload-ask.ts | 2 +- packages/frontend/src/utility/unison-reload.ts | 4 ++-- 19 files changed, 32 insertions(+), 32 deletions(-) (limited to 'packages/frontend/src/lib/nirax.ts') diff --git a/packages/frontend/src/_boot_.ts b/packages/frontend/src/_boot_.ts index 24fafce18c..3241f2dc92 100644 --- a/packages/frontend/src/_boot_.ts +++ b/packages/frontend/src/_boot_.ts @@ -14,7 +14,7 @@ import { subBoot } from '@/boot/sub-boot.js'; const subBootPaths = ['/share', '/auth', '/miauth', '/oauth', '/signup-complete', '/install-extensions']; -if (subBootPaths.some(i => location.pathname === i || location.pathname.startsWith(i + '/'))) { +if (subBootPaths.some(i => window.location.pathname === i || window.location.pathname.startsWith(i + '/'))) { subBoot(); } else { mainBoot(); diff --git a/packages/frontend/src/accounts.ts b/packages/frontend/src/accounts.ts index dbeb13eb63..a25f3c51d1 100644 --- a/packages/frontend/src/accounts.ts +++ b/packages/frontend/src/accounts.ts @@ -191,7 +191,7 @@ export async function login(token: AccountWithToken['token'], redirect?: string) // 他のタブは再読み込みするだけ reloadChannel.postMessage(null); // このページはredirectで指定された先に移動 - location.href = redirect; + window.location.href = redirect; return; } diff --git a/packages/frontend/src/boot/common.ts b/packages/frontend/src/boot/common.ts index 402ccca587..8096c46960 100644 --- a/packages/frontend/src/boot/common.ts +++ b/packages/frontend/src/boot/common.ts @@ -98,14 +98,14 @@ export async function common(createVue: () => App) { document.addEventListener('touchend', () => {}, { passive: true }); // URLに#pswpを含む場合は取り除く - if (location.hash === '#pswp') { - history.replaceState(null, '', location.href.replace('#pswp', '')); + if (window.location.hash === '#pswp') { + history.replaceState(null, '', window.location.href.replace('#pswp', '')); } // 一斉リロード reloadChannel.addEventListener('message', path => { - if (path !== null) location.href = path; - else location.reload(); + if (path !== null) window.location.href = path; + else window.location.reload(); }); // If mobile, insert the viewport meta tag @@ -130,11 +130,11 @@ export async function common(createVue: () => App) { }); //#region loginId - const params = new URLSearchParams(location.search); + const params = new URLSearchParams(window.location.search); const loginId = params.get('loginId'); if (loginId) { - const target = getUrlWithoutLoginId(location.href); + const target = getUrlWithoutLoginId(window.location.href); if (!$i || $i.id !== loginId) { const account = await getAccountFromId(loginId); diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts index 62ee0c5d72..f7360a7340 100644 --- a/packages/frontend/src/boot/main-boot.ts +++ b/packages/frontend/src/boot/main-boot.ts @@ -43,7 +43,7 @@ export async function mainBoot() { if (!$i) uiStyle = 'visitor'; if (searchParams.has('zen')) uiStyle = 'zen'; - if (uiStyle === 'deck' && prefer.s['deck.useSimpleUiForNonRootPages'] && location.pathname !== '/') uiStyle = 'zen'; + if (uiStyle === 'deck' && prefer.s['deck.useSimpleUiForNonRootPages'] && window.location.pathname !== '/') uiStyle = 'zen'; if (searchParams.has('ui')) uiStyle = searchParams.get('ui'); @@ -216,7 +216,7 @@ export async function mainBoot() { let reloadDialogShowing = false; stream.on('_disconnected_', async () => { if (prefer.s.serverDisconnectedBehavior === 'reload') { - location.reload(); + window.location.reload(); } else if (prefer.s.serverDisconnectedBehavior === 'dialog') { if (reloadDialogShowing) return; reloadDialogShowing = true; @@ -227,7 +227,7 @@ export async function mainBoot() { }); reloadDialogShowing = false; if (!canceled) { - location.reload(); + window.location.reload(); } } }); @@ -458,7 +458,7 @@ export async function mainBoot() { const latestDonationInfoShownAt = miLocalStorage.getItem('latestDonationInfoShownAt'); const neverShowDonationInfo = miLocalStorage.getItem('neverShowDonationInfo'); - if (neverShowDonationInfo !== 'true' && (createdAt.getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 3))) && !location.pathname.startsWith('/miauth')) { + if (neverShowDonationInfo !== 'true' && (createdAt.getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 3))) && !window.location.pathname.startsWith('/miauth')) { if (latestDonationInfoShownAt == null || (new Date(latestDonationInfoShownAt).getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 30)))) { const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDonation.vue')), {}, { closed: () => dispose(), diff --git a/packages/frontend/src/components/MkEmbedCodeGenDialog.vue b/packages/frontend/src/components/MkEmbedCodeGenDialog.vue index a4e9547f90..d18fe0ed0c 100644 --- a/packages/frontend/src/components/MkEmbedCodeGenDialog.vue +++ b/packages/frontend/src/components/MkEmbedCodeGenDialog.vue @@ -180,7 +180,7 @@ function applyToPreview() { nextTick(() => { if (currentPreviewUrl === embedPreviewUrl.value) { // URLが変わらなくてもリロード - iframeEl.value?.contentWindow?.location.reload(); + iframeEl.value?.contentWindow?.window.location.reload(); } }); } diff --git a/packages/frontend/src/components/global/MkA.vue b/packages/frontend/src/components/global/MkA.vue index 336160ec17..4004db5b12 100644 --- a/packages/frontend/src/components/global/MkA.vue +++ b/packages/frontend/src/components/global/MkA.vue @@ -87,7 +87,7 @@ function openWindow() { function nav(ev: MouseEvent) { if (behavior === 'browser') { - location.href = props.to; + window.location.href = props.to; return; } diff --git a/packages/frontend/src/lib/nirax.ts b/packages/frontend/src/lib/nirax.ts index 8783874bc2..a97803e879 100644 --- a/packages/frontend/src/lib/nirax.ts +++ b/packages/frontend/src/lib/nirax.ts @@ -320,7 +320,7 @@ export class Nirax extends EventEmitter { } const res = this.navigate(fullPath); if (res.route.path === '/:(*)') { - location.href = fullPath; + window.location.href = fullPath; } else { this.emit('push', { beforeFullPath, diff --git a/packages/frontend/src/navbar.ts b/packages/frontend/src/navbar.ts index c0a6a370fc..d478ece641 100644 --- a/packages/frontend/src/navbar.ts +++ b/packages/frontend/src/navbar.ts @@ -167,7 +167,7 @@ export const navbarItemDef = reactive({ title: i18n.ts.reload, icon: 'ti ti-refresh', action: (ev) => { - location.reload(); + window.location.reload(); }, }, profile: { diff --git a/packages/frontend/src/pages/auth.vue b/packages/frontend/src/pages/auth.vue index e4699379f0..0dcdc5e9cb 100644 --- a/packages/frontend/src/pages/auth.vue +++ b/packages/frontend/src/pages/auth.vue @@ -64,7 +64,7 @@ function accepted() { if (session.value && session.value.app.callbackUrl) { const url = new URL(session.value.app.callbackUrl); if (['javascript:', 'file:', 'data:', 'mailto:', 'tel:', 'vbscript:'].includes(url.protocol)) throw new Error('invalid url'); - location.href = `${session.value.app.callbackUrl}?token=${session.value.token}`; + window.location.href = `${session.value.app.callbackUrl}?token=${session.value.token}`; } } diff --git a/packages/frontend/src/pages/lookup.vue b/packages/frontend/src/pages/lookup.vue index fafad8af4a..4eb4808048 100644 --- a/packages/frontend/src/pages/lookup.vue +++ b/packages/frontend/src/pages/lookup.vue @@ -31,7 +31,7 @@ import MkButton from '@/components/MkButton.vue'; const state = ref<'fetching' | 'done'>('fetching'); function fetch() { - const params = new URL(location.href).searchParams; + const params = new URL(window.location.href).searchParams; // acctのほうはdeprecated let uri = params.get('uri') ?? params.get('acct'); @@ -76,12 +76,12 @@ function close(): void { // 閉じなければ100ms後タイムラインに window.setTimeout(() => { - location.href = '/'; + window.location.href = '/'; }, 100); } function goToMisskey(): void { - location.href = '/'; + window.location.href = '/'; } fetch(); diff --git a/packages/frontend/src/pages/miauth.vue b/packages/frontend/src/pages/miauth.vue index 687315e9b7..e809395848 100644 --- a/packages/frontend/src/pages/miauth.vue +++ b/packages/frontend/src/pages/miauth.vue @@ -61,7 +61,7 @@ async function onAccept(token: string) { const cbUrl = new URL(props.callback); if (['javascript:', 'file:', 'data:', 'mailto:', 'tel:', 'vbscript:'].includes(cbUrl.protocol)) throw new Error('invalid url'); cbUrl.searchParams.set('session', props.session); - location.href = cbUrl.toString(); + window.location.href = cbUrl.toString(); } else { authRoot.value?.showUI('success'); } diff --git a/packages/frontend/src/pages/share.vue b/packages/frontend/src/pages/share.vue index abd84c8590..f88f9ebc1e 100644 --- a/packages/frontend/src/pages/share.vue +++ b/packages/frontend/src/pages/share.vue @@ -182,12 +182,12 @@ function close(): void { // 閉じなければ100ms後タイムラインに window.setTimeout(() => { - location.href = '/'; + window.location.href = '/'; }, 100); } function goToMisskey(): void { - location.href = '/'; + window.location.href = '/'; } function onPosted(): void { diff --git a/packages/frontend/src/router.ts b/packages/frontend/src/router.ts index dd70571d64..3b79569995 100644 --- a/packages/frontend/src/router.ts +++ b/packages/frontend/src/router.ts @@ -17,10 +17,10 @@ export function createRouter(fullPath: string): Router { return new Nirax(ROUTE_DEF, fullPath, !!$i, page(() => import('@/pages/not-found.vue'))); } -export const mainRouter = createRouter(location.pathname + location.search + location.hash); +export const mainRouter = createRouter(window.location.pathname + window.location.search + window.location.hash); window.addEventListener('popstate', (event) => { - mainRouter.replace(location.pathname + location.search + location.hash); + mainRouter.replace(window.location.pathname + window.location.search + window.location.hash); }); mainRouter.addListener('push', ctx => { diff --git a/packages/frontend/src/ui/_common_/stream-indicator.vue b/packages/frontend/src/ui/_common_/stream-indicator.vue index 1eb809d198..5f7600881f 100644 --- a/packages/frontend/src/ui/_common_/stream-indicator.vue +++ b/packages/frontend/src/ui/_common_/stream-indicator.vue @@ -34,7 +34,7 @@ function resetDisconnected() { } function reload() { - location.reload(); + window.location.reload(); } useStream().on('_disconnected_', onDisconnected); diff --git a/packages/frontend/src/ui/classic.vue b/packages/frontend/src/ui/classic.vue index c17e78bb03..8f35ce0c68 100644 --- a/packages/frontend/src/ui/classic.vue +++ b/packages/frontend/src/ui/classic.vue @@ -139,7 +139,7 @@ if (window.innerWidth < 1024) { const currentUI = miLocalStorage.getItem('ui'); miLocalStorage.setItem('ui_temp', currentUI ?? 'default'); miLocalStorage.setItem('ui', 'default'); - location.reload(); + window.location.reload(); } document.documentElement.style.overflowY = 'scroll'; diff --git a/packages/frontend/src/ui/universal.vue b/packages/frontend/src/ui/universal.vue index d85745bde6..92b5d253d3 100644 --- a/packages/frontend/src/ui/universal.vue +++ b/packages/frontend/src/ui/universal.vue @@ -170,7 +170,7 @@ if (window.innerWidth > 1024) { if (tempUI) { miLocalStorage.setItem('ui', tempUI); miLocalStorage.removeItem('ui_temp'); - location.reload(); + window.location.reload(); } } diff --git a/packages/frontend/src/ui/zen.vue b/packages/frontend/src/ui/zen.vue index 8a09ad80d9..bfb2ef634b 100644 --- a/packages/frontend/src/ui/zen.vue +++ b/packages/frontend/src/ui/zen.vue @@ -37,7 +37,7 @@ const isRoot = computed(() => mainRouter.currentRoute.value.name === 'index'); const pageMetadata = ref(null); -const showBottom = !(new URLSearchParams(location.search)).has('zen') && ui === 'deck'; +const showBottom = !(new URLSearchParams(window.location.search)).has('zen') && ui === 'deck'; provide(DI.router, mainRouter); provideMetadataReceiver((metadataGetter) => { diff --git a/packages/frontend/src/utility/reload-ask.ts b/packages/frontend/src/utility/reload-ask.ts index 057f57471a..7c7ea113d4 100644 --- a/packages/frontend/src/utility/reload-ask.ts +++ b/packages/frontend/src/utility/reload-ask.ts @@ -35,6 +35,6 @@ export async function reloadAsk(opts: { if (opts.unison) { unisonReload(); } else { - location.reload(); + window.location.reload(); } } diff --git a/packages/frontend/src/utility/unison-reload.ts b/packages/frontend/src/utility/unison-reload.ts index a24941d02e..c4804192f8 100644 --- a/packages/frontend/src/utility/unison-reload.ts +++ b/packages/frontend/src/utility/unison-reload.ts @@ -12,9 +12,9 @@ export const reloadChannel = new BroadcastChannel('reload'); export function unisonReload(path?: string) { if (path !== undefined) { reloadChannel.postMessage(path); - location.href = path; + window.location.href = path; } else { reloadChannel.postMessage(null); - location.reload(); + window.location.reload(); } } -- cgit v1.2.3-freya