Keep dashboard project selection in the URL so refreshing or sharing the page retains the active project. - Hydrate current project state from the existing ?project= query parameter before falling back to cached or global defaults. - Update project selection, setup completion, overview, and unregister flows to preserve or clear the project URL parameter without dropping other URL state. - Cover URL-driven project persistence and query/hash preservation with hook tests. - Document the refresh-safe project URL behavior and add a patch changeset. Files changed: .changeset/fn-7416-project-url-persistence.md | 7 +++ docs/dashboard-guide.md | 2 + packages/dashboard/app/App.tsx | 2 +- .../app/hooks/__tests__/useCurrentProject.test.ts | 64 ++++++++++++++++++++++ .../app/hooks/__tests__/useProjectActions.test.ts | 40 +++++++++++++- packages/dashboard/app/hooks/useCurrentProject.ts | 54 ++++++++++++++++-- packages/dashboard/app/hooks/useProjectActions.ts | 5 ++ packages/dashboard/app/utils/projectUrlState.ts | 24 ++++++++ 8 files changed, 190 insertions(+), 8 deletions(-) Fusion-Task-Id: FN-7416 Fusion-Task-Lineage: 2d640ae6-629f-4632-9014-986320acfef5 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
25 lines
1.0 KiB
TypeScript
25 lines
1.0 KiB
TypeScript
export function getProjectIdFromUrl(): string | null {
|
|
if (typeof window === "undefined") return null;
|
|
return new URL(window.location.href).searchParams.get("project");
|
|
}
|
|
|
|
export function replaceProjectIdInUrl(projectId: string | null): void {
|
|
if (typeof window === "undefined") return;
|
|
|
|
const url = new URL(window.location.href);
|
|
if (projectId && projectId.length > 0) {
|
|
url.searchParams.set("project", projectId);
|
|
} else {
|
|
url.searchParams.delete("project");
|
|
}
|
|
|
|
const query = url.searchParams.toString();
|
|
const nextUrl = `${url.pathname}${query ? `?${query}` : ""}${url.hash}`;
|
|
const existingState = window.history.state ?? {};
|
|
/*
|
|
* FNXC:ProjectUrlState 2026-07-02-00:00:
|
|
* Project selection must survive browser refresh through the dashboard's existing `?project=` deep-link contract. Replace only the project query param so task/view/mailbox/room/PR params, hashes, and history state remain intact across desktop and mobile selector paths.
|
|
*/
|
|
window.history.replaceState(existingState, "", nextUrl);
|
|
}
|