diff --git a/packages/app-shell/src/console/home/HomePage.tsx b/packages/app-shell/src/console/home/HomePage.tsx index b248bbf3f..f403b9aa1 100644 --- a/packages/app-shell/src/console/home/HomePage.tsx +++ b/packages/app-shell/src/console/home/HomePage.tsx @@ -16,7 +16,7 @@ * @module */ -import { useMemo, type ComponentType } from 'react'; +import { useMemo, useState, useEffect, type ComponentType } from 'react'; import { useNavigate } from 'react-router-dom'; import { useMetadata } from '../../providers/MetadataProvider'; import { useRecentItems } from '../../hooks/useRecentItems'; @@ -27,7 +27,7 @@ import { AppCard } from './AppCard'; import { RecentApps } from './RecentApps'; import { StarredApps } from './StarredApps'; import { Empty, EmptyTitle, EmptyDescription, Button } from '@object-ui/components'; -import { Plus, Settings, Sparkles, Star, Clock, ArrowDown, Store, LayoutGrid } from 'lucide-react'; +import { Plus, Settings, Sparkles, Star, Clock, ArrowDown, Store, LayoutGrid, ShieldAlert, X } from 'lucide-react'; function pickGreetingKey(hour: number): string { if (hour < 5) return 'home.greetingNight'; @@ -102,6 +102,54 @@ function StatPill({ ); } +/** + * Dismissible nudge to set a local recovery password — shown when the user + * signed in via SSO and has no local credential yet. We no longer force this + * before the first session (it walled off the magic moment); this gentle, + * one-time reminder preserves instance self-sufficiency without the friction. + */ +function RecoveryPasswordReminder({ t }: { t: (key: string, opts?: any) => string }) { + const navigate = useNavigate(); + const { hasLocalPassword } = useAuth(); + const [show, setShow] = useState(false); + useEffect(() => { + if (typeof localStorage !== 'undefined' && localStorage.getItem('os:recovery-pw-dismissed') === '1') return; + let cancelled = false; + Promise.resolve(hasLocalPassword?.()) + .then((has) => { if (!cancelled && has === false) setShow(true); }) + .catch(() => { /* unknown → don't nag */ }); + return () => { cancelled = true; }; + }, [hasLocalPassword]); + const dismiss = () => { + try { localStorage.setItem('os:recovery-pw-dismissed', '1'); } catch { /* ignore */ } + setShow(false); + }; + if (!show) return null; + return ( +
+ {t('home.recoveryReminder.message', { defaultValue: 'Set a recovery password so you can still sign in if single sign-on is ever unavailable.' })} +
+ + +