Files
tolaria/src/components/StartupScreen.tsx
2026-05-10 10:56:57 +02:00

157 lines
5.1 KiB
TypeScript

import { AiAgentsOnboardingPrompt } from './AiAgentsOnboardingPrompt'
import { TelemetryConsentDialog } from './TelemetryConsentDialog'
import { Toast } from './Toast'
import { WelcomeScreen } from './WelcomeScreen'
import type { useAiAgentsOnboarding } from '../hooks/useAiAgentsOnboarding'
import type { useAiAgentsStatus } from '../hooks/useAiAgentsStatus'
import type { useOnboarding } from '../hooks/useOnboarding'
import type { useVaultSwitcher } from '../hooks/useVaultSwitcher'
import type { Settings } from '../types'
import type { NoteWindowParams } from '../utils/windowMode'
type OnboardingState = ReturnType<typeof useOnboarding>
type VaultSwitcherState = ReturnType<typeof useVaultSwitcher>
type AiAgentsOnboardingState = ReturnType<typeof useAiAgentsOnboarding>
export interface StartupScreenParams {
aiAgentsOnboarding: AiAgentsOnboardingState
aiAgentsStatus: ReturnType<typeof useAiAgentsStatus>
isOffline: boolean
isStartupLoading: boolean
noteWindowParams: NoteWindowParams | null
onboarding: OnboardingState
runtimeMissingVaultPath: string | null
saveSettings: (settings: Settings) => Promise<void>
settings: Settings
settingsLoaded: boolean
shouldResumeFreshStartOnboarding: boolean
showMcpSetupDialog: boolean
setToastMessage: (message: string | null) => void
toastMessage: string | null
vaultSwitcher: VaultSwitcherState
}
function shouldShowTelemetryConsent(params: StartupScreenParams): boolean {
return !params.noteWindowParams
&& !params.isStartupLoading
&& params.settingsLoaded
&& params.settings.telemetry_consent === null
}
function shouldShowWelcomeView(params: StartupScreenParams): boolean {
return !params.noteWindowParams
&& (
Boolean(params.runtimeMissingVaultPath)
|| params.onboarding.state.status === 'welcome'
|| params.onboarding.state.status === 'vault-missing'
|| params.shouldResumeFreshStartOnboarding
)
}
function welcomeOnboardingState(params: StartupScreenParams): OnboardingState {
if (params.runtimeMissingVaultPath) {
return {
...params.onboarding,
state: {
status: 'vault-missing' as const,
vaultPath: params.runtimeMissingVaultPath,
defaultPath: params.vaultSwitcher.defaultPath || params.runtimeMissingVaultPath,
},
}
}
if (params.shouldResumeFreshStartOnboarding) {
return { ...params.onboarding, state: { status: 'welcome' as const, defaultPath: params.vaultSwitcher.vaultPath } }
}
return params.onboarding
}
function shouldShowAiAgentsOnboarding(params: StartupScreenParams): boolean {
return !params.noteWindowParams
&& params.onboarding.state.status === 'ready'
&& params.aiAgentsOnboarding.showPrompt
&& !params.showMcpSetupDialog
}
function WelcomeView({ onboarding, isOffline }: { onboarding: OnboardingState; isOffline: boolean }) {
const state = onboarding.state as { status: 'welcome' | 'vault-missing'; defaultPath: string; vaultPath?: string }
return (
<div className="app-shell">
<WelcomeScreen
mode={state.status === 'welcome' ? 'welcome' : 'vault-missing'}
missingPath={state.status === 'vault-missing' ? state.vaultPath : undefined}
defaultVaultPath={state.defaultPath}
onCreateVault={onboarding.handleCreateVault}
onRetryCreateVault={onboarding.retryCreateVault}
onCreateEmptyVault={onboarding.handleCreateEmptyVault}
onOpenFolder={onboarding.handleOpenFolder}
isOffline={isOffline}
creatingAction={onboarding.creatingAction}
error={onboarding.error}
canRetryTemplate={onboarding.canRetryTemplate}
/>
</div>
)
}
function AiAgentsOnboardingView({
statuses,
onContinue,
}: {
statuses: ReturnType<typeof useAiAgentsStatus>
onContinue: () => void
}) {
return (
<div className="app-shell">
<AiAgentsOnboardingPrompt statuses={statuses} onContinue={onContinue} />
</div>
)
}
export function StartupScreen(params: StartupScreenParams) {
if (shouldShowTelemetryConsent(params)) {
return (
<TelemetryConsentDialog
onAccept={() => {
const id = crypto.randomUUID()
params.saveSettings({
...params.settings,
telemetry_consent: true,
crash_reporting_enabled: true,
analytics_enabled: true,
anonymous_id: id,
})
}}
onDecline={() => {
params.saveSettings({
...params.settings,
telemetry_consent: false,
crash_reporting_enabled: false,
analytics_enabled: false,
anonymous_id: null,
})
}}
/>
)
}
if (shouldShowWelcomeView(params)) {
return (
<WelcomeView
onboarding={welcomeOnboardingState(params)}
isOffline={params.isOffline}
/>
)
}
if (!shouldShowAiAgentsOnboarding(params)) return null
return (
<>
<AiAgentsOnboardingView
statuses={params.aiAgentsStatus}
onContinue={params.aiAgentsOnboarding.dismissPrompt}
/>
<Toast message={params.toastMessage} onDismiss={() => params.setToastMessage(null)} />
</>
)
}