feat(Tour): 同一设备不同帐号保存漫游使用记录

This commit is contained in:
肖应宇 2026-04-21 09:41:00 +08:00
parent 08b74314c4
commit fe33801008
1 changed files with 57 additions and 6 deletions

View File

@ -103,6 +103,42 @@ import { Tooltip } from "./tooltip";
const MAX_REFERENCES_PER_MESSAGE = 10; const MAX_REFERENCES_PER_MESSAGE = 10;
const INPUT_TOOLS_TOUR_SEEN_KEY = "workspace.input_tools_tour_seen.v1"; const INPUT_TOOLS_TOUR_SEEN_KEY = "workspace.input_tools_tour_seen.v1";
type InputToolsTourSeenState = {
seen: boolean;
threadIds?: string[];
};
function parseInputToolsTourSeenState(
value: string | null,
): InputToolsTourSeenState | null {
if (!value) return null;
if (value === "1") {
return { seen: true };
}
try {
const parsed = JSON.parse(value) as InputToolsTourSeenState & {
threadId?: string;
};
if (typeof parsed?.seen !== "boolean") {
return null;
}
if (
parsed.threadIds != null &&
(!Array.isArray(parsed.threadIds) ||
parsed.threadIds.some((id) => typeof id !== "string"))
) {
return null;
}
return {
seen: parsed.seen,
threadIds:
parsed.threadIds ??
(typeof parsed.threadId === "string" ? [parsed.threadId] : undefined),
};
} catch {
return null;
}
}
type WorkspaceToolButtonProps = ComponentProps<typeof PromptInputButton>; type WorkspaceToolButtonProps = ComponentProps<typeof PromptInputButton>;
@ -296,17 +332,32 @@ export function InputBox({
setIsInputToolsTourOpen(false); setIsInputToolsTourOpen(false);
return; return;
} }
const hasSeenTour = window.localStorage.getItem(INPUT_TOOLS_TOUR_SEEN_KEY); const seenState = parseInputToolsTourSeenState(
if (!hasSeenTour) { window.localStorage.getItem(INPUT_TOOLS_TOUR_SEEN_KEY),
);
const hasSeenTourForCurrentThread =
seenState?.seen === true && Boolean(seenState.threadIds?.includes(threadId));
if (!hasSeenTourForCurrentThread) {
setIsInputToolsTourOpen(true); setIsInputToolsTourOpen(true);
} }
}, [showWelcomeStyle, hasSubmitted, isInputToolsTourReady]); }, [showWelcomeStyle, hasSubmitted, isInputToolsTourReady, threadId]);
const finishInputToolsTour = useCallback(() => { const finishInputToolsTour = useCallback(() => {
window.localStorage.setItem(INPUT_TOOLS_TOUR_SEEN_KEY, "1"); const seenState = parseInputToolsTourSeenState(
window.localStorage.getItem(INPUT_TOOLS_TOUR_SEEN_KEY),
);
const seenThreadIds = new Set(seenState?.threadIds ?? []);
seenThreadIds.add(threadId);
window.localStorage.setItem(
INPUT_TOOLS_TOUR_SEEN_KEY,
JSON.stringify({
seen: true,
threadIds: Array.from(seenThreadIds),
} satisfies InputToolsTourSeenState),
);
setIsInputToolsTourOpen(false); setIsInputToolsTourOpen(false);
}, []); }, [threadId]);
const closeInputToolsTour = useCallback(() => { const closeInputToolsTour = useCallback(() => {
setIsInputToolsTourOpen(false); setIsInputToolsTourOpen(false);
}, []); }, []);