feat(web): add versioned first-run welcome

This commit is contained in:
NI0317
2026-07-30 22:17:56 +08:00
parent b6130b178d
commit bef8db3add
49 changed files with 1096 additions and 115 deletions
@@ -4,7 +4,7 @@
* routes the user to that page's single credential editor.
*/
import { useEffect, useState } from 'react'
import { useEffect } from 'react'
import type { ReactNode } from 'react'
import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'
import { Button, Modal } from '@deepseek-ai/dsh-client-ui-primitives'
@@ -64,26 +64,23 @@ function unavailableDiagnostic(
* @returns the controlled modal or null when onboarding needs no intervention.
*/
export function DeepSeekOnboardingDialog(props: DeepSeekOnboardingDialogProps): ReactNode {
const { active, openSection, controller, useSnapshot, t } = props
const { complete, openSection, controller, useSnapshot, t } = props
const state = useSnapshot(snapshot => snapshot)
const readiness = deepSeekReadiness(state)
const [dismissed, setDismissed] = useState(false)
useEffect(() => {
if (active && !dismissed && state.status === 'idle') void controller.load()
}, [active, controller, dismissed, state.status])
if (state.status === 'idle') void controller.load()
}, [controller, state.status])
const close = (): void => {
setDismissed(true)
}
useEffect(() => {
if (readiness.kind === 'adapter-absent' || readiness.kind === 'configured') complete()
}, [complete, readiness.kind])
const openModels = (): void => {
close()
complete()
openSection('models')
}
if (!active || dismissed) return null
let unavailableReason: UnavailableReason | undefined
switch (readiness.kind) {
case 'loading':
@@ -108,7 +105,7 @@ export function DeepSeekOnboardingDialog(props: DeepSeekOnboardingDialogProps):
return (
<Modal
open
onClose={close}
onClose={complete}
title={unavailable ? t('onboardingUnavailableTitle') : t('onboardingTitle')}
closeLabel={t('onboardingLater')}
{...(unavailable ? {} : { description: t('onboardingDescription') })}