import { CUSTOM_WORLD_AGENT_OPERATION_QUERY_KEY, CUSTOM_WORLD_AGENT_SESSION_QUERY_KEY, CUSTOM_WORLD_GENERATION_SOURCE_QUERY_KEY, } from './customWorldAgentUiState'; export const CREATION_URL_SESSION_QUERY_KEY = 'sessionId'; export const CREATION_URL_PROFILE_QUERY_KEY = 'profileId'; export const CREATION_URL_DRAFT_QUERY_KEY = 'draftId'; export const CREATION_URL_WORK_QUERY_KEY = 'workId'; export const CREATION_URL_RESTORE_QUERY_KEYS = [ CUSTOM_WORLD_AGENT_SESSION_QUERY_KEY, CUSTOM_WORLD_AGENT_OPERATION_QUERY_KEY, CUSTOM_WORLD_GENERATION_SOURCE_QUERY_KEY, CREATION_URL_SESSION_QUERY_KEY, CREATION_URL_PROFILE_QUERY_KEY, CREATION_URL_DRAFT_QUERY_KEY, CREATION_URL_WORK_QUERY_KEY, ] as const; export type CreationUrlState = { sessionId?: string | null; profileId?: string | null; draftId?: string | null; workId?: string | null; }; type CreationUrlEnvironment = { location?: { pathname: string; search: string; } | null; history?: { replaceState: ( data: unknown, unused: string, url?: string | URL | null, ) => void; } | null; }; const CREATION_PATH_PREFIXES = [ '/creation/rpg', '/creation/big-fish', '/creation/match3d', '/creation/square-hole', '/creation/jump-hop', '/creation/wooden-fish', '/creation/bark-battle', '/creation/visual-novel', '/creation/baby-object-match', '/creation/puzzle', ] as const; function resolveEnvironment( env?: CreationUrlEnvironment, ): Required { if (env) { return { location: env.location ?? null, history: env.history ?? null, }; } if (typeof window === 'undefined') { return { location: null, history: null, }; } return { location: window.location, history: window.history, }; } function normalizeValue(value: unknown) { return typeof value === 'string' && value.trim() ? value.trim() : null; } function normalizePathname(value: string | undefined) { const pathname = value?.trim().toLowerCase() ?? ''; if (!pathname || pathname === '/') { return '/'; } return pathname.replace(/\/+$/u, ''); } export function isCreationRestorePath(pathname: string | undefined) { const normalizedPathname = normalizePathname(pathname); return CREATION_PATH_PREFIXES.some( (pathPrefix) => normalizedPathname === pathPrefix || normalizedPathname.startsWith(`${pathPrefix}/`), ); } export function isSameCreationFlowPath( currentPathname: string | undefined, nextPathname: string | undefined, ) { const normalizedCurrentPath = normalizePathname(currentPathname); const normalizedNextPath = normalizePathname(nextPathname); if ( !normalizedCurrentPath || !normalizedNextPath || normalizedCurrentPath === '/' || normalizedNextPath === '/' ) { return false; } const currentCreationPrefix = CREATION_PATH_PREFIXES.find((pathPrefix) => normalizedCurrentPath === pathPrefix || normalizedCurrentPath.startsWith(`${pathPrefix}/`), ); const nextCreationPrefix = CREATION_PATH_PREFIXES.find((pathPrefix) => normalizedNextPath === pathPrefix || normalizedNextPath.startsWith(`${pathPrefix}/`), ); return Boolean( currentCreationPrefix && nextCreationPrefix && currentCreationPrefix === nextCreationPrefix, ); } export function buildCreationUrlSearchFromParams(search: string) { const params = new URLSearchParams(search); const preservedParams = new URLSearchParams(); CREATION_URL_RESTORE_QUERY_KEYS.forEach((key) => { const value = normalizeValue(params.get(key)); if (value) { preservedParams.set(key, value); } }); const queryString = preservedParams.toString(); return queryString ? `?${queryString}` : ''; } export function readCreationUrlState( env?: CreationUrlEnvironment, ): CreationUrlState { const resolved = resolveEnvironment(env); const params = new URLSearchParams(resolved.location?.search ?? ''); return { sessionId: normalizeValue(params.get(CREATION_URL_SESSION_QUERY_KEY)), profileId: normalizeValue(params.get(CREATION_URL_PROFILE_QUERY_KEY)), draftId: normalizeValue(params.get(CREATION_URL_DRAFT_QUERY_KEY)), workId: normalizeValue(params.get(CREATION_URL_WORK_QUERY_KEY)), }; } export function writeCreationUrlState( state: CreationUrlState, env?: CreationUrlEnvironment, ) { const resolved = resolveEnvironment(env); if ( !resolved.location || !resolved.history?.replaceState || !isCreationRestorePath(resolved.location.pathname) ) { return; } const params = new URLSearchParams(resolved.location.search); const entries = [ [CREATION_URL_SESSION_QUERY_KEY, state.sessionId], [CREATION_URL_PROFILE_QUERY_KEY, state.profileId], [CREATION_URL_DRAFT_QUERY_KEY, state.draftId], [CREATION_URL_WORK_QUERY_KEY, state.workId], ] as const; entries.forEach(([key, rawValue]) => { const value = normalizeValue(rawValue); if (value) { params.set(key, value); } else { params.delete(key); } }); const search = params.toString(); const nextUrl = search ? `${resolved.location.pathname}?${search}` : resolved.location.pathname; resolved.history.replaceState(null, '', nextUrl); } export function clearCreationUrlState(env?: CreationUrlEnvironment) { const resolved = resolveEnvironment(env); if ( !resolved.location || !resolved.history?.replaceState || !isCreationRestorePath(resolved.location.pathname) ) { return; } const params = new URLSearchParams(resolved.location.search); [ CREATION_URL_SESSION_QUERY_KEY, CREATION_URL_PROFILE_QUERY_KEY, CREATION_URL_DRAFT_QUERY_KEY, CREATION_URL_WORK_QUERY_KEY, ].forEach((key) => params.delete(key)); const search = params.toString(); const nextUrl = search ? `${resolved.location.pathname}?${search}` : resolved.location.pathname; resolved.history.replaceState(null, '', nextUrl); }