* Add first-run onboarding wizard for recording mechanics Introduce a minimal, skippable first-run wizard that teaches the record key. On first authenticated launch it renders as a full-screen takeover (gated above PusherProvider) so the stream/compose keyboard handlers are not mounted to compete for the same keys. Steps: welcome, hold ` to record, tap V to switch audio/video, tap ` to toggle recording, mic/camera permission priming, and a recap. The lessons detect the real gestures and never block — Esc or the Skip control dismisses at any point. Reuses existing pieces: VideoAudioToggle, useMediaDevices().requestLabels for permission priming, KeyHint, and isTypingTarget. Extracts the shared HOLD_THRESHOLD_MS into lib/constants and reuses it in the compose overlay. Resolves #259 Co-Authored-By: Claude Opus 4.8 <[email protected]> Claude-Session: https://claude.ai/code/session_01A9AHySdLb1zfZAEm6SuaQP * nits * light mode support for onboarding --------- Co-authored-by: Claude <[email protected]>
23 lines
609 B
TypeScript
23 lines
609 B
TypeScript
import { create } from 'zustand';
|
|
|
|
const KEY = 'llink:onboarding-completed';
|
|
|
|
interface OnboardingState {
|
|
hasCompletedOnboarding: boolean;
|
|
markComplete: () => void;
|
|
/** Clears the flag so the wizard runs again (handy for QA). */
|
|
reset: () => void;
|
|
}
|
|
|
|
export const useOnboardingStore = create<OnboardingState>((set) => ({
|
|
hasCompletedOnboarding: localStorage.getItem(KEY) === 'true',
|
|
markComplete: () => {
|
|
localStorage.setItem(KEY, 'true');
|
|
set({ hasCompletedOnboarding: true });
|
|
},
|
|
reset: () => {
|
|
localStorage.removeItem(KEY);
|
|
set({ hasCompletedOnboarding: false });
|
|
},
|
|
}));
|