diff --git a/packages/frontend/src/components/MkPageWindow.vue b/packages/frontend/src/components/MkPageWindow.vue index aa4509b14b..7682452999 100644 --- a/packages/frontend/src/components/MkPageWindow.vue +++ b/packages/frontend/src/components/MkPageWindow.vue @@ -98,6 +98,15 @@ windowRouter.addListener('replace', ctx => { history.value.push({ path: ctx.path, key: ctx.key }); }); +windowRouter.navHook = (path) => { + const res = windowRouter.resolve(path); + if (res?.route.path === '/:(*)') { + window.open(path, '_blank', 'noopener'); + return true; + } + return res ?? false; +}; + windowRouter.init(); provide('router', windowRouter); diff --git a/packages/frontend/src/nirax.ts b/packages/frontend/src/nirax.ts index 6a8ea09ed6..3157185041 100644 --- a/packages/frontend/src/nirax.ts +++ b/packages/frontend/src/nirax.ts @@ -100,7 +100,13 @@ export interface IRouter extends EventEmitter { current: Resolved; currentRef: ShallowRef; currentRoute: ShallowRef; - navHook: ((path: string, flag?: any) => boolean) | null; + + /** + * ナビゲーションフック + * + * `true`でナビゲーションをキャンセル、`false`またはResolvedオブジェクトでナビゲーションを続行 + */ + navHook: ((path: string, flag?: any) => boolean | Resolved) | null; /** * ルートの初期化(eventListenerの定義後に必ず呼び出すこと) @@ -190,7 +196,7 @@ export class Router extends EventEmitter implements IRouter { private currentKey = Date.now().toString(); private redirectCount = 0; - public navHook: ((path: string, flag?: any) => boolean) | null = null; + public navHook: ((path: string, flag?: any) => boolean | Resolved) | null = null; constructor(routes: Router['routes'], currentPath: Router['currentPath'], isLoggedIn: boolean, notFoundPageComponent: Component) { super(); @@ -403,11 +409,20 @@ export class Router extends EventEmitter implements IRouter { this.emit('same'); return; } + + let res: Resolved | null = null; if (this.navHook) { - const cancel = this.navHook(path, flag); - if (cancel) return; + const hookRes = this.navHook(path, flag); + if (hookRes === true) return; + if (hookRes !== false) { + res = hookRes; + } } - const res = this.navigate(path, null); + + if (res == null) { + res = this.navigate(path, null); + } + if (res.route.path === '/:(*)') { location.href = path; } else { diff --git a/packages/frontend/src/ui/deck.vue b/packages/frontend/src/ui/deck.vue index 14a08f50ba..b6f1b98774 100644 --- a/packages/frontend/src/ui/deck.vue +++ b/packages/frontend/src/ui/deck.vue @@ -134,7 +134,7 @@ const columnComponents = { roleTimeline: XRoleTimelineColumn, }; -mainRouter.navHook = (path, flag): boolean => { +mainRouter.navHook = (path, flag) => { if (flag === 'forcePage') return false; const noMainColumn = !deckStore.state.columns.some(x => x.type === 'main'); if (deckStore.state.navWindow || noMainColumn) {