Files
makelore/src/lib/settings-navigation.ts
T

31 lines
1.6 KiB
TypeScript

import { AI_MODULE_SELECTION_PATH, getGuardedAiModuleForPath } from './ai-modules';
type SettingsLocation = { pathname: string; search?: string; hash?: string; state?: unknown };
function localReturnPath(value: unknown): string | null {
if (typeof value !== 'string' || !value.startsWith('/') || value.startsWith('//') || value.includes('\\')) return null;
try {
const target = new URL(value, 'https://makelore.local');
if (target.origin !== 'https://makelore.local') return null;
if (target.pathname !== AI_MODULE_SELECTION_PATH && !getGuardedAiModuleForPath(target.pathname)) return null;
return `${target.pathname}${target.search}${target.hash}`;
} catch { return null; }
}
export function getSettingsReturnPath(state: unknown): string {
const candidate = state && typeof state === 'object' && 'settingsReturnTo' in state
? (state as { settingsReturnTo?: unknown }).settingsReturnTo : null;
return localReturnPath(candidate) ?? AI_MODULE_SELECTION_PATH;
}
export function getSettingsReturnState(location: SettingsLocation): { settingsReturnTo: string } {
const inSettings = location.pathname === '/settings' || location.pathname.startsWith('/settings/');
return { settingsReturnTo: inSettings ? getSettingsReturnPath(location.state)
: localReturnPath(`${location.pathname}${location.search ?? ''}${location.hash ?? ''}`) ?? AI_MODULE_SELECTION_PATH };
}
/** Honor the current page's existing unsaved-input protection before internal navigation. */
export function canLeaveCurrentPage(): boolean {
return typeof window === 'undefined' || window.dispatchEvent(new Event('beforeunload', { cancelable: true }));
}