mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 13:05:32 +09:00
55 lines
1.9 KiB
TypeScript
55 lines
1.9 KiB
TypeScript
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
const SYNTHETIC_STATE_FLAG = '__fluxer_synth';
|
|
const MAX_SYNTHETIC_DEPTH = 6;
|
|
|
|
export interface SyntheticHistoryState {
|
|
[SYNTHETIC_STATE_FLAG]: true;
|
|
depth: number;
|
|
}
|
|
|
|
export function isSyntheticHistoryState(state: unknown): state is SyntheticHistoryState {
|
|
return (
|
|
typeof state === 'object' && state !== null && (state as Record<string, unknown>)[SYNTHETIC_STATE_FLAG] === true
|
|
);
|
|
}
|
|
|
|
export function derivePathStack(path: string): Array<string> {
|
|
const segments = path
|
|
.split('?')[0]
|
|
.split('#')[0]
|
|
.split('/')
|
|
.filter((s) => s.length > 0);
|
|
if (segments[0] !== 'channels' || segments.length < 2) return [];
|
|
const root = segments[1];
|
|
if (root === '@me' || root === '@favorites' || root === '@discover') {
|
|
const stack: Array<string> = [];
|
|
if (root !== '@me') stack.push('/channels/@me');
|
|
stack.push(`/channels/${root}`);
|
|
if (segments.length >= 3) stack.push(`/channels/${root}/${segments[2]}`);
|
|
return stack.slice(0, -1);
|
|
}
|
|
const stack: Array<string> = [`/channels/${root}`];
|
|
if (segments.length >= 3) stack.push(`/channels/${root}/${segments[2]}`);
|
|
return stack.slice(0, -1);
|
|
}
|
|
|
|
export function bootstrapSyntheticHistory(): void {
|
|
if (typeof window === 'undefined' || !window.history) return;
|
|
if (isSyntheticHistoryState(window.history.state)) return;
|
|
if (window.history.length > 1) return;
|
|
const path = window.location.pathname + window.location.search + window.location.hash;
|
|
const parents = derivePathStack(window.location.pathname).slice(-MAX_SYNTHETIC_DEPTH);
|
|
if (parents.length === 0) return;
|
|
const deepestParent = parents[0];
|
|
window.history.replaceState(
|
|
{[SYNTHETIC_STATE_FLAG]: true, depth: 0} satisfies SyntheticHistoryState,
|
|
'',
|
|
deepestParent,
|
|
);
|
|
for (let i = 1; i < parents.length; i++) {
|
|
window.history.pushState({[SYNTHETIC_STATE_FLAG]: true, depth: i} satisfies SyntheticHistoryState, '', parents[i]);
|
|
}
|
|
window.history.pushState(null, '', path);
|
|
}
|