47 lines
2.2 KiB
TypeScript
47 lines
2.2 KiB
TypeScript
import { leaderboardMetrics } from './leaderboard.js';
|
|
|
|
const origin = 'https://electric-cherry.invalid';
|
|
const contextKeys = ['game', 'map', 'players', 'metric', 'q', 'offset'] as const;
|
|
|
|
/** Only retain a local leaderboard destination and its supported view state. */
|
|
export function leaderboardReturnHref(value: string | null | undefined): string {
|
|
if (!value?.startsWith('/leaderboard')) return '/leaderboard';
|
|
try {
|
|
const url = new URL(value, origin);
|
|
if (url.origin !== origin || url.pathname !== '/leaderboard') return '/leaderboard';
|
|
const params = new URLSearchParams();
|
|
for (const key of contextKeys) {
|
|
const entry = url.searchParams.get(key);
|
|
if (entry || key === 'map' && entry !== null) params.set(key, entry!);
|
|
}
|
|
return `/leaderboard${params.size ? `?${params}` : ''}`;
|
|
} catch { return '/leaderboard'; }
|
|
}
|
|
|
|
export function playerContextHref(guid: string, source: string): string {
|
|
const returnTo = leaderboardReturnHref(source);
|
|
const original = new URL(returnTo, origin).searchParams;
|
|
const params = new URLSearchParams({ returnTo });
|
|
// History pagination is independent of the originating leaderboard page.
|
|
const game = original.get('game');
|
|
const map = original.get('map');
|
|
const metric = original.get('metric');
|
|
const players = original.get('players');
|
|
// Match the leaderboard's displayed defaults for older or hand-edited URLs.
|
|
if (game === 't5' || game === 't6') params.set('game', game);
|
|
if (map !== null && map.length <= 1024) params.set('map', map);
|
|
if (players && /^[1-4]$/.test(players)) params.set('players', players);
|
|
if (metric && leaderboardMetrics.some(item => item.key === metric)) params.set('metric', metric);
|
|
return `/leaderboard/players/${encodeURIComponent(guid)}?${params}`;
|
|
}
|
|
|
|
export function profileViewHref(current: URL, changes: Record<string, string>): string {
|
|
const params = new URLSearchParams(current.search);
|
|
params.delete('offset');
|
|
for (const [key, value] of Object.entries(changes)) {
|
|
if (value || key === 'map') params.set(key, value);
|
|
else params.delete(key);
|
|
}
|
|
return `${current.pathname}${params.size ? `?${params}` : ''}`;
|
|
}
|