Show a one-time GitHub star prompt after a task first reaches done. - detect task status transitions into done and trigger the prompt only in project view - add a dismissible GitHub star prompt component plus localStorage-backed persistence hook - cover the new prompt behavior with component, hook, and transition helper tests - document the prompt behavior and styling guidance in the dashboard guide Files changed: docs/dashboard-guide.md | 3 + packages/dashboard/app/App.tsx | 21 +++++- .../dashboard/app/components/GitHubStarPrompt.css | 76 ++++++++++++++++++++++ .../dashboard/app/components/GitHubStarPrompt.tsx | 53 +++++++++++++++ .../app/components/__tests__/App.test.tsx | 12 +++- .../components/__tests__/GitHubStarPrompt.test.tsx | 40 ++++++++++++ .../hooks/__tests__/useGitHubStarPrompt.test.ts | 64 ++++++++++++++++++ .../dashboard/app/hooks/useGitHubStarPrompt.ts | 46 +++++++++++++ 8 files changed, 313 insertions(+), 2 deletions(-) Fusion-Task-Id: FN-5967 Fusion-Task-Lineage: 5fffdf4d-61d8-4ac8-bcf4-8b453b639b28
47 lines
1.2 KiB
TypeScript
47 lines
1.2 KiB
TypeScript
import { useSyncExternalStore } from "react";
|
|
|
|
const STORAGE_KEY = "fusion:github-star-prompt-shown";
|
|
const EVENT_NAME = "fusion:github-star-prompt-changed";
|
|
|
|
function read(): boolean {
|
|
if (typeof window === "undefined") return false;
|
|
try {
|
|
return window.localStorage.getItem(STORAGE_KEY) === "1";
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function subscribe(onChange: () => void): () => void {
|
|
if (typeof window === "undefined") return () => {};
|
|
|
|
const handleStorage = (event: StorageEvent) => {
|
|
if (event.key === STORAGE_KEY) {
|
|
onChange();
|
|
}
|
|
};
|
|
const handleCustom = () => onChange();
|
|
|
|
window.addEventListener("storage", handleStorage);
|
|
window.addEventListener(EVENT_NAME, handleCustom);
|
|
|
|
return () => {
|
|
window.removeEventListener("storage", handleStorage);
|
|
window.removeEventListener(EVENT_NAME, handleCustom);
|
|
};
|
|
}
|
|
|
|
export function markGitHubStarPromptShown(): void {
|
|
if (typeof window === "undefined") return;
|
|
try {
|
|
window.localStorage.setItem(STORAGE_KEY, "1");
|
|
window.dispatchEvent(new Event(EVENT_NAME));
|
|
} catch {
|
|
// ignore
|
|
}
|
|
}
|
|
|
|
export function useGitHubStarPromptShown(): boolean {
|
|
return useSyncExternalStore(subscribe, read, () => false);
|
|
}
|