@anionex/dsh-eye-care 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.i18n.yaml +6 -0
- package/README.md +86 -0
- package/README.zh.md +86 -0
- package/assets/eye-care-dark.png +0 -0
- package/assets/eye-care-light.png +0 -0
- package/cordis.patch.yml +3 -0
- package/lib/client.js +1106 -0
- package/lib/client.js.map +1 -0
- package/lib/index.js +14 -0
- package/lib/index.js.map +1 -0
- package/lib/rpc.js +123 -0
- package/lib/rpc.js.map +1 -0
- package/lib/settings.js +12 -0
- package/lib/settings.js.map +1 -0
- package/lib/shared.js +70 -0
- package/lib/shared.js.map +1 -0
- package/lib/types/client/EyeCareRow.d.ts +20 -0
- package/lib/types/client/EyeCareRow.d.ts.map +1 -0
- package/lib/types/client/controller.d.ts +96 -0
- package/lib/types/client/controller.d.ts.map +1 -0
- package/lib/types/client/index.d.ts +23 -0
- package/lib/types/client/index.d.ts.map +1 -0
- package/lib/types/client/locales.d.ts +54 -0
- package/lib/types/client/locales.d.ts.map +1 -0
- package/lib/types/client/themes.d.ts +14 -0
- package/lib/types/client/themes.d.ts.map +1 -0
- package/lib/types/index.d.ts +10 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/rpc.d.ts +17 -0
- package/lib/types/rpc.d.ts.map +1 -0
- package/lib/types/settings.d.ts +8 -0
- package/lib/types/settings.d.ts.map +1 -0
- package/lib/types/shared.d.ts +59 -0
- package/lib/types/shared.d.ts.map +1 -0
- package/package.json +99 -0
- package/src/client/EyeCareRow.module.css +137 -0
- package/src/client/EyeCareRow.tsx +122 -0
- package/src/client/controller.ts +435 -0
- package/src/client/css-modules.d.ts +5 -0
- package/src/client/index.tsx +72 -0
- package/src/client/locales.ts +56 -0
- package/src/client/themes.ts +254 -0
- package/src/index.ts +30 -0
- package/src/rpc.ts +138 -0
- package/src/settings.ts +22 -0
- package/src/shared.ts +112 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","names":["css"],"sources":["../src/client/EyeCareRow.tsx","../src/shared.ts","../src/client/themes.ts","../src/client/controller.ts","../src/client/locales.ts","../src/client/index.tsx"],"sourcesContent":["/** General-settings row for eye-care mode and warmth controls. */\n\nimport type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { EyeCareController } from './controller.ts'\nimport type { EyeCareKey } from './locales.ts'\nimport type { EyeCareIntensity, EyeCareMode } from '../shared.ts'\nimport css from './EyeCareRow.module.css'\n\n/** Injected business face used by the row. */\nexport interface EyeCareRowInjected {\n /** State source. */\n hooks: { eyeCare: EyeCareController['store'] }\n /** Set the selected mode. */\n setMode: (mode: EyeCareMode) => Promise<void>\n /** Set the selected warmth. */\n setIntensity: (intensity: EyeCareIntensity) => Promise<void>\n}\n\n/** Full composed props for the settings slot. */\nexport type EyeCareRowProps = PropsRuntime<'settings.general.item'>\n & PropsLocale<'settings.eyeCare'>\n & InjectFace<EyeCareRowInjected>\n\nconst MODES: readonly { id: EyeCareMode; label: EyeCareKey }[] = [\n { id: 'off', label: 'mode.off' },\n { id: 'auto', label: 'mode.auto' },\n { id: 'light', label: 'mode.light' },\n { id: 'dark', label: 'mode.dark' },\n]\n\nconst INTENSITIES: readonly { id: EyeCareIntensity; label: EyeCareKey }[] = [\n { id: 'soft', label: 'intensity.soft' },\n { id: 'balanced', label: 'intensity.balanced' },\n { id: 'warm', label: 'intensity.warm' },\n]\n\nfunction statusKey(mode: EyeCareMode): EyeCareKey {\n return `status.${mode}` as EyeCareKey\n}\n\n/** Render the feature-owned General settings row. */\nexport function EyeCareRow({ t, useEyeCare, setMode, setIntensity }: EyeCareRowProps) {\n const state = useEyeCare(value => value)\n const busy = state.status === 'loading' || state.status === 'saving'\n const enabled = state.settings.mode !== 'off'\n const status = state.status === 'error' && state.error !== null ? state.error : t(statusKey(state.settings.mode))\n const statusText = state.status === 'unavailable' ? `${status} · ${t('status.local')}` : status\n return (\n <section className={css.row} aria-labelledby=\"dsh-eye-care-title\">\n <div className={css.copy}>\n <h3 id=\"dsh-eye-care-title\" className={css.title}>{t('title')}</h3>\n <p className={css.description}>{t('description')}</p>\n </div>\n <div className={css.controls}>\n <div className={css.primaryLine}>\n <div className={css.controlGroup} role=\"group\" aria-label={t('enabled.title')}>\n <button\n type=\"button\"\n className={`${css.option}${!enabled ? ` ${css.selected}` : ''}`}\n aria-pressed={!enabled}\n disabled={busy}\n onClick={() => { void setMode('off') }}\n >\n {t('enabled.off')}\n </button>\n <button\n type=\"button\"\n className={`${css.option}${enabled ? ` ${css.selected}` : ''}`}\n aria-pressed={enabled}\n disabled={busy}\n onClick={() => { void setMode(state.settings.mode === 'off' ? 'auto' : state.settings.mode) }}\n >\n {t('enabled.on')}\n </button>\n </div>\n </div>\n {enabled ? <details className={css.advanced}>\n <summary>{t('advanced.title')}</summary>\n <div className={css.advancedBody}>\n <div className={css.settingLine}>\n <span className={css.settingLabel}>{t('mode.title')}</span>\n <div className={css.controlGroup} role=\"group\" aria-label={t('mode.title')}>\n {MODES.filter(({ id }) => id !== 'off').map(({ id, label }) => (\n <button\n key={id}\n type=\"button\"\n className={`${css.smallOption}${state.settings.mode === id ? ` ${css.selected}` : ''}`}\n aria-pressed={state.settings.mode === id}\n disabled={busy}\n onClick={() => { void setMode(id) }}\n >\n {t(label)}\n </button>\n ))}\n </div>\n </div>\n <div className={css.settingLine}>\n <span className={css.settingLabel}>{t('intensity.title')}</span>\n <div className={css.controlGroup} role=\"group\" aria-label={t('intensity.title')}>\n {INTENSITIES.map(({ id, label }) => (\n <button\n key={id}\n type=\"button\"\n className={`${css.smallOption}${state.settings.intensity === id ? ` ${css.selected}` : ''}`}\n aria-pressed={state.settings.intensity === id}\n disabled={busy}\n onClick={() => { void setIntensity(id) }}\n >\n {t(label)}\n </button>\n ))}\n </div>\n </div>\n </div>\n </details> : null}\n <div className={css.status} aria-live=\"polite\">\n {state.status === 'saving' ? t('status.saving') : statusText}\n </div>\n </div>\n </section>\n )\n}\n","/** Browser-safe eye-care settings and RPC wire values. */\n\n/** User-selectable eye-care operating modes. */\nexport const EYE_CARE_MODES = ['off', 'auto', 'light', 'dark'] as const\n\n/** Warmth levels shared by light and dark palettes. */\nexport const EYE_CARE_INTENSITIES = ['soft', 'balanced', 'warm'] as const\n\n/** Eye-care operating mode. */\nexport type EyeCareMode = typeof EYE_CARE_MODES[number]\n\n/** Eye-care warmth level. */\nexport type EyeCareIntensity = typeof EYE_CARE_INTENSITIES[number]\n\n/** Settings namespace owned by this package. */\nexport const EYE_CARE_SETTINGS_NAMESPACE = 'eye-care'\n\n/** Loopback-only Connection RPC channel owned by this package. */\nexport const EYE_CARE_RPC_CHANNEL = '/eye-care'\n\n/** RPC endpoint that reads the current settings snapshot. */\nexport const EYE_CARE_RPC_READ = 'settings.read'\n\n/** RPC endpoint that replaces the settings section. */\nexport const EYE_CARE_RPC_SAVE = 'settings.save'\n\n/** Settings field carrying the selected mode. */\nexport const MODE_FIELD = 'mode'\n\n/** Settings field carrying the selected warmth. */\nexport const INTENSITY_FIELD = 'intensity'\n\n/** Defaults used when no user section exists. */\nexport const DEFAULT_EYE_CARE_SETTINGS: Readonly<EyeCareSettings> = Object.freeze({\n mode: 'off',\n intensity: 'balanced',\n})\n\n/** Persisted eye-care preferences. */\nexport interface EyeCareSettings {\n /** Whether eye care is disabled, system-aware, light, or dark. */\n mode: EyeCareMode\n /** Warmth applied by the active eye-care palette. */\n intensity: EyeCareIntensity\n}\n\n/** Browser-safe Host snapshot returned through the loopback RPC channel. */\nexport interface EyeCareSettingsSnapshot {\n /** Wire schema version for this dedicated endpoint. */\n schemaVersion: 1\n /** Whether the active settings provider accepts writes. */\n writable: boolean\n /** Resolved settings and the revision fencing the next write. */\n settings: {\n value: EyeCareSettings\n revision: number\n applies: 'live'\n }\n /** Durable built-in Appearance preference used to fence startup convergence. */\n baseThemePreference?: 'light' | 'dark' | 'system'\n}\n\n/** Revision-fenced write request. */\nexport interface EyeCareSettingsWriteRequest {\n expectedRevision: number\n value: EyeCareSettings\n}\n\n/** Narrow an unknown value to one supported mode. */\nexport function isEyeCareMode(value: unknown): value is EyeCareMode {\n return EYE_CARE_MODES.some(mode => mode === value)\n}\n\n/** Narrow an unknown value to one supported warmth. */\nexport function isEyeCareIntensity(value: unknown): value is EyeCareIntensity {\n return EYE_CARE_INTENSITIES.some(intensity => intensity === value)\n}\n\n/** Decode a complete settings value from the RPC boundary. */\nexport function decodeEyeCareSettings(value: unknown): EyeCareSettings | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined\n const record = value as Record<string, unknown>\n if (!isEyeCareMode(record[MODE_FIELD]) || !isEyeCareIntensity(record[INTENSITY_FIELD])) return undefined\n return { mode: record[MODE_FIELD], intensity: record[INTENSITY_FIELD] }\n}\n\n/** Decode one complete Host snapshot from the RPC boundary. */\nexport function decodeEyeCareSnapshot(value: unknown): EyeCareSettingsSnapshot | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined\n const record = value as Record<string, unknown>\n const settingsEnvelope = record['settings']\n if (record['schemaVersion'] !== 1 || typeof record['writable'] !== 'boolean'\n || typeof settingsEnvelope !== 'object' || settingsEnvelope === null || Array.isArray(settingsEnvelope)) return undefined\n const settingsRecord = settingsEnvelope as Record<string, unknown>\n const settings = decodeEyeCareSettings(settingsRecord['value'])\n const revision = settingsRecord['revision']\n if (settings === undefined || !Number.isSafeInteger(revision) || (revision as number) < 0\n || settingsRecord['applies'] !== 'live') return undefined\n const baseThemePreference = record['baseThemePreference']\n if (baseThemePreference !== undefined\n && baseThemePreference !== 'light' && baseThemePreference !== 'dark' && baseThemePreference !== 'system') return undefined\n return {\n schemaVersion: 1,\n writable: record['writable'],\n settings: {\n value: settings,\n revision: revision as number,\n applies: 'live',\n },\n ...(baseThemePreference === undefined ? {} : { baseThemePreference }),\n }\n}\n","/** Fixed eye-care themes built from semantic DSH Web tokens. */\n\nimport type { ThemeDefinition, ThemeTokens } from '@deepseek-ai/dsh-client-ui-theme/client'\nimport type { EyeCareIntensity } from '../shared.ts'\n\n/** Theme id prefix reserved by this package. */\nexport const EYE_CARE_THEME_PREFIX = 'eye-care-'\n\ntype Scheme = 'light' | 'dark'\n\ninterface Palette {\n bgBase: string\n bgLayer1: string\n bgLayer2: string\n bgLayer3: string\n bgModule: string\n bgOverlay: string\n textPrimary: string\n textSecondary: string\n textTertiary: string\n textCaption: string\n border1: string\n border2: string\n border3: string\n hover: string\n hoverSolid: string\n active: string\n primaryFill: string\n primaryHover: string\n primaryDimmed: string\n bubble: string\n bubbleHighlight: string\n input: string\n selector: string\n sidebar: string\n sidebarHover: string\n sidebarActive: string\n sidebarAccent: string\n code: string\n codeBanner: string\n inlineCode: string\n scrollbar: string\n scrollbarHover: string\n shiki: {\n constant: string\n string: string\n comment: string\n keyword: string\n parameter: string\n function: string\n stringExpression: string\n punctuation: string\n link: string\n }\n}\n\nconst LIGHT: Record<EyeCareIntensity, Palette> = {\n soft: {\n bgBase: '#fbf8ef', bgLayer1: '#fffdf6', bgLayer2: '#f8f3e8', bgLayer3: '#f2ecde',\n bgModule: '#f7f2e7', bgOverlay: '#ece4d5', textPrimary: '#29271f', textSecondary: '#575247',\n textTertiary: '#716a5d', textCaption: '#958b7a', border1: 'rgba(85, 72, 46, 0.08)',\n border2: 'rgba(85, 72, 46, 0.15)', border3: 'rgba(85, 72, 46, 0.21)',\n hover: 'rgba(126, 101, 53, 0.08)', hoverSolid: '#f1eadc', active: 'rgba(126, 101, 53, 0.14)',\n primaryFill: '#44583d', primaryHover: '#536a49', primaryDimmed: '#dfe6d9',\n bubble: '#eef3df', bubbleHighlight: '#e0e9cb', input: '#fffdf6', selector: '#f2ecde',\n sidebar: '#f4efe3', sidebarHover: '#ebe4d5', sidebarActive: '#e2dac9', sidebarAccent: '#d6e0c1',\n code: '#f2eee4', codeBanner: '#ebe5d8', inlineCode: '#eee8db', scrollbar: '#d1c6b4',\n scrollbarHover: '#baad98',\n shiki: {\n constant: '#176f88', string: '#34783c', comment: '#817768', keyword: '#a03e58',\n parameter: '#a15b1f', function: '#6950a6', stringExpression: '#2f7040', punctuation: '#5a554d', link: '#246d9a',\n },\n },\n balanced: {\n bgBase: '#faf5e8', bgLayer1: '#fffaf0', bgLayer2: '#f5eddd', bgLayer3: '#eee3d0',\n bgModule: '#f3ead9', bgOverlay: '#e7dbc7', textPrimary: '#2b281f', textSecondary: '#5b5345',\n textTertiary: '#766d5b', textCaption: '#9b8e77', border1: 'rgba(93, 72, 36, 0.09)',\n border2: 'rgba(93, 72, 36, 0.17)', border3: 'rgba(93, 72, 36, 0.24)',\n hover: 'rgba(139, 100, 37, 0.09)', hoverSolid: '#eee3d1', active: 'rgba(139, 100, 37, 0.16)',\n primaryFill: '#425b3c', primaryHover: '#52704a', primaryDimmed: '#dce7d3',\n bubble: '#eaf1d5', bubbleHighlight: '#dce7bc', input: '#fffaf0', selector: '#eee3d0',\n sidebar: '#f1e8d7', sidebarHover: '#e7dcc8', sidebarActive: '#ddd0b9', sidebarAccent: '#d2dfb3',\n code: '#efe9dc', codeBanner: '#e6dece', inlineCode: '#ebe2d1', scrollbar: '#ccbda6',\n scrollbarHover: '#b3a188',\n shiki: {\n constant: '#146d87', string: '#39753b', comment: '#837664', keyword: '#a13e57',\n parameter: '#a1581c', function: '#684ba3', stringExpression: '#34703d', punctuation: '#5d5549', link: '#206c98',\n },\n },\n warm: {\n bgBase: '#f8efda', bgLayer1: '#fff7e7', bgLayer2: '#f2e6d0', bgLayer3: '#eadcc4',\n bgModule: '#f0e3cc', bgOverlay: '#e1d0b5', textPrimary: '#30291f', textSecondary: '#615343',\n textTertiary: '#7c6a56', textCaption: '#a08b70', border1: 'rgba(105, 73, 30, 0.10)',\n border2: 'rgba(105, 73, 30, 0.19)', border3: 'rgba(105, 73, 30, 0.27)',\n hover: 'rgba(151, 97, 27, 0.10)', hoverSolid: '#eadbc2', active: 'rgba(151, 97, 27, 0.18)',\n primaryFill: '#3f5c39', primaryHover: '#506f46', primaryDimmed: '#d8e5ce',\n bubble: '#e6efc9', bubbleHighlight: '#d6e3ac', input: '#fff7e7', selector: '#eadcc4',\n sidebar: '#eee1ca', sidebarHover: '#e3d3b9', sidebarActive: '#d7c4a7', sidebarAccent: '#cedeaa',\n code: '#ece2d1', codeBanner: '#e2d5c0', inlineCode: '#e7dac4', scrollbar: '#c7b398',\n scrollbarHover: '#ad9779',\n shiki: {\n constant: '#116b83', string: '#3e7439', comment: '#85735e', keyword: '#a33b54',\n parameter: '#a25418', function: '#67459e', stringExpression: '#386d39', punctuation: '#625344', link: '#1c6b94',\n },\n },\n}\n\nconst DARK: Record<EyeCareIntensity, Palette> = {\n soft: {\n bgBase: '#20211c', bgLayer1: '#25261f', bgLayer2: '#2a2b23', bgLayer3: '#313128',\n bgModule: '#2d2e26', bgOverlay: '#3a392e', textPrimary: '#ece9dc', textSecondary: '#c7c1b0',\n textTertiary: '#aaa28f', textCaption: '#7f786a', border1: 'rgba(245, 233, 201, 0.07)',\n border2: 'rgba(245, 233, 201, 0.13)', border3: 'rgba(245, 233, 201, 0.19)',\n hover: 'rgba(244, 227, 182, 0.08)', hoverSolid: '#36362c', active: 'rgba(244, 227, 182, 0.14)',\n primaryFill: '#dfe9cf', primaryHover: '#f1f5e7', primaryDimmed: '#4d5143',\n bubble: '#30372a', bubbleHighlight: '#3d4933', input: '#2b2d25', selector: '#37382e',\n sidebar: '#252820', sidebarHover: '#30342a', sidebarActive: '#3a3e32', sidebarAccent: '#3f4b35',\n code: '#1c1e1b', codeBanner: '#252821', inlineCode: '#292c24', scrollbar: '#57584d',\n scrollbarHover: '#707064',\n shiki: {\n constant: '#68b7d2', string: '#91c88b', comment: '#9d988d', keyword: '#e39aaf',\n parameter: '#e6ad72', function: '#b9a5df', stringExpression: '#9bcf91', punctuation: '#c7c2b7', link: '#77b8d9',\n },\n },\n balanced: {\n bgBase: '#211f19', bgLayer1: '#27231c', bgLayer2: '#2d2921', bgLayer3: '#353027',\n bgModule: '#302b22', bgOverlay: '#40382b', textPrimary: '#efe7d6', textSecondary: '#cbc0aa',\n textTertiary: '#aea087', textCaption: '#837662', border1: 'rgba(250, 230, 190, 0.08)',\n border2: 'rgba(250, 230, 190, 0.15)', border3: 'rgba(250, 230, 190, 0.21)',\n hover: 'rgba(247, 216, 157, 0.09)', hoverSolid: '#3b352b', active: 'rgba(247, 216, 157, 0.16)',\n primaryFill: '#e0ebcf', primaryHover: '#f2f7e6', primaryDimmed: '#505243',\n bubble: '#32392a', bubbleHighlight: '#404c32', input: '#302b23', selector: '#3b352a',\n sidebar: '#282820', sidebarHover: '#33342a', sidebarActive: '#3d3e32', sidebarAccent: '#435036',\n code: '#1d1d19', codeBanner: '#28251f', inlineCode: '#2d2922', scrollbar: '#5b584b',\n scrollbarHover: '#757062',\n shiki: {\n constant: '#69b8d0', string: '#94c985', comment: '#a19a8d', keyword: '#e49aad',\n parameter: '#e7aa6c', function: '#bca2df', stringExpression: '#9dcc89', punctuation: '#cbc2b2', link: '#79b9d5',\n },\n },\n warm: {\n bgBase: '#231e17', bgLayer1: '#2a231b', bgLayer2: '#31291f', bgLayer3: '#3a3025',\n bgModule: '#342b21', bgOverlay: '#46392b', textPrimary: '#f1e4cf', textSecondary: '#cdbb9f',\n textTertiary: '#b09a7e', textCaption: '#857058', border1: 'rgba(255, 225, 177, 0.09)',\n border2: 'rgba(255, 225, 177, 0.17)', border3: 'rgba(255, 225, 177, 0.24)',\n hover: 'rgba(252, 207, 136, 0.10)', hoverSolid: '#403529', active: 'rgba(252, 207, 136, 0.18)',\n primaryFill: '#e1ebcc', primaryHover: '#f3f7e4', primaryDimmed: '#535143',\n bubble: '#353a28', bubbleHighlight: '#444d30', input: '#342a20', selector: '#403428',\n sidebar: '#2b271e', sidebarHover: '#363127', sidebarActive: '#413a2e', sidebarAccent: '#485235',\n code: '#1f1b17', codeBanner: '#2b241d', inlineCode: '#31281f', scrollbar: '#605548',\n scrollbarHover: '#7a6b5b',\n shiki: {\n constant: '#6ab9ce', string: '#98c87e', comment: '#a59a89', keyword: '#e696a8',\n parameter: '#e8a765', function: '#bea0dc', stringExpression: '#a0cb82', punctuation: '#cec0ad', link: '#7bb9d1',\n },\n },\n}\n\n/** Build the stable id for one concrete eye-care theme. */\nexport function eyeCareThemeId(scheme: Scheme, intensity: EyeCareIntensity): string {\n return `${EYE_CARE_THEME_PREFIX}${scheme}-${intensity}`\n}\n\nfunction tokensOf(palette: Palette): ThemeTokens {\n return Object.freeze({\n '--dsw-alias-bg-base': palette.bgBase,\n '--dsw-alias-bg-layer-1': palette.bgLayer1,\n '--dsw-alias-bg-layer-2': palette.bgLayer2,\n '--dsw-alias-bg-layer-3': palette.bgLayer3,\n '--dsw-alias-bg-module-platform': palette.bgModule,\n '--dsw-alias-bg-multi-select': palette.bgModule,\n '--dsw-alias-bg-overlay': palette.bgOverlay,\n '--dsw-alias-bg-skeleton': palette.hover,\n '--dsw-alias-border-l1': palette.border1,\n '--dsw-alias-border-l2-darkmode-thin': palette.border2,\n '--dsw-alias-border-l2': palette.border2,\n '--dsw-alias-border-l3': palette.border3,\n '--dsw-alias-border-l4': palette.border3,\n '--dsw-alias-brand-primary': palette.textPrimary,\n '--dsw-alias-brand-text': palette.textPrimary,\n '--dsw-alias-button-contrast-fill': palette.textSecondary,\n '--dsw-alias-button-elevated-fill': palette.bgLayer3,\n '--dsw-alias-button-floating-fill': palette.bgLayer2,\n '--dsw-alias-button-floating-hover': palette.hoverSolid,\n '--dsw-alias-button-ghost-active-border': palette.textCaption,\n '--dsw-alias-button-ghost-active-fill': palette.active,\n '--dsw-alias-button-ghost-active-hover': palette.hoverSolid,\n '--dsw-alias-button-primary-fill': palette.primaryFill,\n '--dsw-alias-button-primary-hover': palette.primaryHover,\n '--dsw-alias-button-primary-dimmed': palette.primaryDimmed,\n '--dsw-alias-interactive-bg-active': palette.active,\n '--dsw-alias-interactive-bg-hover-accent': palette.active,\n '--dsw-alias-interactive-bg-hover': palette.hover,\n '--dsw-alias-interactive-bg-hover-solid': palette.hoverSolid,\n '--dsw-alias-label-caption': palette.textCaption,\n '--dsw-alias-label-dimmed': palette.border3,\n '--dsw-alias-label-primary-bluish': palette.textPrimary,\n '--dsw-alias-label-primary-dimmed': palette.textPrimary,\n '--dsw-alias-label-primary': palette.textPrimary,\n '--dsw-alias-label-secondary': palette.textSecondary,\n '--dsw-alias-label-tertiary': palette.textTertiary,\n '--dsw-alias-markdown-citation': palette.hoverSolid,\n '--dsw-alias-markdown-code-block-banner': palette.codeBanner,\n '--dsw-alias-markdown-code-block': palette.code,\n '--dsw-alias-markdown-code-segment-selected': palette.bgLayer3,\n '--dsw-alias-markdown-code-segment-unselected': palette.code,\n '--dsw-alias-markdown-inline-code': palette.inlineCode,\n '--dsw-alias-markdown-placeholder': palette.bgModule,\n '--dsw-alias-markdown-tag': palette.hoverSolid,\n '--dsw-alias-scrollbar-bg-l1': palette.scrollbar,\n '--dsw-alias-scrollbar-bg-l2': palette.scrollbar,\n '--dsw-alias-scrollbar-hover-l1': palette.scrollbarHover,\n '--dsw-alias-scrollbar-hover-l2': palette.scrollbarHover,\n '--dsw-specific-bubble-highlight': palette.bubbleHighlight,\n '--dsw-specific-bubble': palette.bubble,\n '--dsw-specific-input-major': palette.input,\n '--dsw-specific-login-input': palette.bgLayer2,\n '--dsw-specific-menu': palette.bgLayer3,\n '--dsw-specific-selector': palette.selector,\n '--dsw-specific-sidebar-fill': palette.sidebar,\n '--dsw-specific-sidebar-nav-item-active-accent': palette.sidebarAccent,\n '--dsw-specific-sidebar-nav-item-active': palette.sidebarActive,\n '--dsw-specific-sidebar-nav-item-hover': palette.sidebarHover,\n '--dsw-specific-tip': palette.bgModule,\n '--shiki-foreground': palette.textPrimary,\n '--shiki-background': palette.code,\n '--shiki-token-constant': palette.shiki.constant,\n '--shiki-token-string': palette.shiki.string,\n '--shiki-token-comment': palette.shiki.comment,\n '--shiki-token-keyword': palette.shiki.keyword,\n '--shiki-token-parameter': palette.shiki.parameter,\n '--shiki-token-function': palette.shiki.function,\n '--shiki-token-string-expression': palette.shiki.stringExpression,\n '--shiki-token-punctuation': palette.shiki.punctuation,\n '--shiki-token-link': palette.shiki.link,\n })\n}\n\n/** Six concrete themes registered for the two schemes and three warmth levels. */\nexport const EYE_CARE_THEMES: readonly ThemeDefinition[] = Object.freeze(\n (['light', 'dark'] as const).flatMap(scheme =>\n (['soft', 'balanced', 'warm'] as const).map(intensity => Object.freeze({\n id: eyeCareThemeId(scheme, intensity),\n colorScheme: scheme,\n tokens: tokensOf((scheme === 'light' ? LIGHT : DARK)[intensity]),\n }))),\n)\n\nconst EYE_CARE_THEME_IDS = new Set(EYE_CARE_THEMES.map(theme => theme.id))\n\n/** Whether a theme id is one of this package's registered concrete themes. */\nexport function isEyeCareThemeId(id: string): boolean {\n return EYE_CARE_THEME_IDS.has(id)\n}\n","/** Eye-care state owner: durable settings synchronization plus theme lifecycle. */\n\nimport type { ClientConnectionRpc } from '@deepseek-ai/dsh-client-connection/client'\nimport { createSnapshotStore, type SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client'\nimport type { ThemeRuntime, ThemeSnapshot } from '@deepseek-ai/dsh-client-ui-theme/client'\nimport {\n DEFAULT_EYE_CARE_SETTINGS,\n decodeEyeCareSnapshot,\n EYE_CARE_RPC_CHANNEL,\n EYE_CARE_RPC_READ,\n EYE_CARE_RPC_SAVE,\n type EyeCareIntensity,\n type EyeCareMode,\n type EyeCareSettings,\n type EyeCareSettingsSnapshot,\n} from '../shared.ts'\nimport {\n EYE_CARE_THEMES,\n eyeCareThemeId,\n isEyeCareThemeId,\n} from './themes.ts'\n\n/** State consumed by the General-settings row. */\nexport interface EyeCareState {\n /** Current eye-care selection. */\n settings: EyeCareSettings\n /** Persistence lifecycle. */\n status: 'loading' | 'ready' | 'saving' | 'unavailable' | 'error'\n /** Whether the Host settings document can be written. */\n writable: boolean\n /** Host namespace revision for the next write. */\n revision: number | undefined\n /** User-facing read or write failure, when one stands. */\n error: string | null\n}\n\n/** Inputs isolated for deterministic controller tests. */\nexport interface EyeCareControllerOptions {\n /** DSH theme registry. */\n theme: Pick<ThemeRuntime, 'getTheme' | 'setTheme' | 'register'>\n /** Snapshot change subscription. */\n subscribeTheme(listener: (snapshot: ThemeSnapshot) => void): () => void\n /** Loopback-only Connection RPC; absent remote browsers stay process-local. */\n rpc?: ClientConnectionRpc\n /** System dark-mode sensor. */\n media?: MediaQueryList\n /** Monotonic wall-clock source used only by the one-shot startup adoption fence. */\n now?: () => number\n}\n\nconst INITIAL_STATE: EyeCareState = {\n settings: { ...DEFAULT_EYE_CARE_SETTINGS },\n status: 'loading',\n writable: false,\n revision: undefined,\n error: null,\n}\n\n/** Maximum delay accepted for ui-theme's already-started Host adoption. */\nconst STARTUP_BASE_THEME_GRACE_MS = 1000\n\nfunction sameSettings(left: EyeCareSettings, right: EyeCareSettings): boolean {\n return left.mode === right.mode && left.intensity === right.intensity\n}\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\n/** Stateful controller shared by theme listeners and the Settings row. */\nexport class EyeCareController {\n /** Reactive row source. */\n readonly store: SnapshotStore<EyeCareState> = createSnapshotStore(INITIAL_STATE)\n\n private readonly theme: EyeCareControllerOptions['theme']\n private readonly rpc: ClientConnectionRpc | undefined\n private readonly media: MediaQueryList | undefined\n private readonly now: () => number\n private readonly unregisterThemes: Array<() => void> = []\n private unsubscribeTheme: (() => void) | undefined\n private unsubscribeMedia: (() => void) | undefined\n private tail: Promise<void> = Promise.resolve()\n private disposeTask: Promise<void> | undefined\n private pendingSettings: EyeCareSettings | undefined\n private disposed = false\n private applyingTheme = 0\n private restoreTheme = 'system'\n private hasRestoreTheme = false\n private acceptedRemoteSnapshot = false\n private startupBaseTheme: 'light' | 'dark' | 'system' | undefined\n private startupBaseThemeDeadline = 0\n\n /**\n * Register the concrete themes and lifecycle listeners.\n * @param options - theme, transport, and system-scheme collaborators.\n */\n constructor(options: EyeCareControllerOptions) {\n this.theme = options.theme\n this.rpc = options.rpc\n this.now = options.now ?? Date.now\n this.media = options.media ?? (typeof matchMedia === 'function' ? matchMedia('(prefers-color-scheme: dark)') : undefined)\n const currentTheme = this.theme.getTheme().preference\n if (!isEyeCareThemeId(currentTheme)) {\n this.restoreTheme = currentTheme\n this.hasRestoreTheme = true\n }\n try {\n for (const definition of EYE_CARE_THEMES) {\n this.unregisterThemes.push(this.theme.register(definition))\n }\n this.unsubscribeTheme = options.subscribeTheme(snapshot => { this.onThemeChanged(snapshot) })\n if (this.media !== undefined) {\n const media = this.media\n const listener = (): void => {\n if (!this.disposed && this.store.getSnapshot().settings.mode === 'auto') this.applyCurrentTheme()\n }\n media.addEventListener('change', listener)\n this.unsubscribeMedia = () => { media.removeEventListener('change', listener) }\n }\n } catch (error) {\n for (const unregister of this.unregisterThemes.splice(0).reverse()) unregister()\n throw error\n }\n }\n\n /**\n * Load durable settings without blocking plugin activation.\n * @returns settlement after this read reaches the serialized transport queue.\n */\n load(): Promise<void> {\n if (this.rpc === undefined) {\n this.setUnavailable()\n return Promise.resolve()\n }\n if (this.store.getSnapshot().revision === undefined) {\n this.store.update(state => {\n state.status = 'loading'\n state.error = null\n })\n }\n return this.enqueue(async () => { await this.readRemote() })\n }\n\n /**\n * Select a mode and persist the latest selection when Host settings are writable.\n * @param mode - next operating mode.\n * @returns settlement after the serialized persistence attempt.\n */\n setMode(mode: EyeCareMode): Promise<void> {\n return this.select({ ...this.store.getSnapshot().settings, mode })\n }\n\n /**\n * Select a warmth and persist the latest selection when Host settings are writable.\n * @param intensity - next warmth level.\n * @returns settlement after the serialized persistence attempt.\n */\n setIntensity(intensity: EyeCareIntensity): Promise<void> {\n return this.select({ ...this.store.getSnapshot().settings, intensity })\n }\n\n /** Queue a refresh after a Host settings invalidation. */\n refresh(): void {\n void this.load()\n }\n\n /**\n * Reach transport quiescence, restore the user's live non-eye-care theme, and unregister all resources.\n * @returns settlement after cleanup completes.\n */\n dispose(): Promise<void> {\n return this.disposeTask ??= this.disposeOnce()\n }\n\n private async disposeOnce(): Promise<void> {\n this.disposed = true\n this.pendingSettings = undefined\n\n const failures: unknown[] = []\n for (const unsubscribe of [this.unsubscribeMedia, this.unsubscribeTheme]) {\n if (unsubscribe === undefined) continue\n try { unsubscribe() } catch (error) { failures.push(error) }\n }\n this.unsubscribeMedia = undefined\n this.unsubscribeTheme = undefined\n\n await this.tail\n\n const current = this.theme.getTheme()\n if (isEyeCareThemeId(current.preference)) {\n try {\n this.setTheme(this.resolveRestoreTheme())\n } catch (error) {\n failures.push(error)\n try { this.setTheme('system') } catch (fallbackError) { failures.push(fallbackError) }\n }\n }\n for (const unregister of this.unregisterThemes.splice(0).reverse()) {\n try { unregister() } catch (error) { failures.push(error) }\n }\n if (failures.length > 0) throw new AggregateError(failures, 'eye-care cleanup failed')\n }\n\n private enqueue(operation: () => Promise<void>): Promise<void> {\n if (this.disposed) return Promise.resolve()\n const task = this.tail.then(async () => {\n if (!this.disposed) await operation()\n })\n this.tail = task.catch(() => {})\n return task\n }\n\n private select(settings: EyeCareSettings): Promise<void> {\n if (this.disposed) return Promise.resolve()\n const previous = this.store.getSnapshot().settings\n if (previous.mode === 'off' && settings.mode !== 'off') this.captureRestoreTheme()\n this.store.update(state => {\n state.settings = settings\n state.error = null\n if (state.status === 'error') state.status = state.revision === undefined ? 'unavailable' : 'ready'\n })\n this.applyCurrentTheme()\n return this.persist(settings)\n }\n\n private persist(settings: EyeCareSettings): Promise<void> {\n const state = this.store.getSnapshot()\n if (this.rpc === undefined) {\n this.setUnavailable(state.error)\n return Promise.resolve()\n }\n if (state.revision !== undefined && !state.writable) {\n this.setUnavailable(state.error)\n return Promise.resolve()\n }\n this.pendingSettings = { ...settings }\n return this.enqueue(async () => { await this.flushPending() })\n }\n\n private async flushPending(): Promise<void> {\n while (!this.disposed && this.pendingSettings !== undefined) {\n const desired = this.pendingSettings\n this.pendingSettings = undefined\n\n let state = this.store.getSnapshot()\n if (state.revision === undefined) {\n if (this.pendingSettings === undefined) this.pendingSettings = desired\n if (!await this.readRemote()) return\n continue\n }\n if (!state.writable || state.revision === undefined) {\n this.setUnavailable(state.error)\n return\n }\n\n this.store.update(next => {\n next.status = 'saving'\n next.error = null\n })\n let response: Awaited<ReturnType<ClientConnectionRpc['call']>>\n try {\n const rpc = this.rpc\n if (rpc === undefined) return\n response = await rpc.call(EYE_CARE_RPC_CHANNEL, EYE_CARE_RPC_SAVE, {\n expectedRevision: state.revision,\n value: desired,\n })\n } catch (error) {\n if (!this.disposed) this.setUnavailable(messageOf(error))\n return\n }\n if (this.disposed) return\n if (!response.ok) {\n if (response.error.code === 'settings-conflict') {\n const latest = this.pendingSettings ?? desired\n this.pendingSettings = latest\n if (!await this.readRemote()) return\n if (this.disposed) return\n continue\n }\n this.setUnavailable(response.error.message)\n return\n }\n const snapshot = decodeEyeCareSnapshot(response.value)\n if (snapshot === undefined) {\n this.store.update(next => {\n next.status = 'error'\n next.error = 'eye-care Settings returned an invalid save response'\n })\n return\n }\n const preserveSettings = this.pendingSettings !== undefined\n || !sameSettings(this.store.getSnapshot().settings, desired)\n this.accept(snapshot, preserveSettings)\n }\n }\n\n private async readRemote(): Promise<boolean> {\n let response: Awaited<ReturnType<ClientConnectionRpc['call']>>\n try {\n const rpc = this.rpc\n if (rpc === undefined) return false\n response = await rpc.call(EYE_CARE_RPC_CHANNEL, EYE_CARE_RPC_READ, {})\n } catch (error) {\n if (!this.disposed) this.setUnavailable(messageOf(error), true)\n return false\n }\n if (this.disposed) return false\n if (!response.ok) {\n this.setUnavailable(response.error.message, true)\n return false\n }\n const snapshot = decodeEyeCareSnapshot(response.value)\n if (snapshot === undefined) {\n this.store.update(state => {\n state.status = 'error'\n state.error = 'eye-care Settings returned an invalid read response'\n })\n return false\n }\n this.accept(snapshot, this.pendingSettings !== undefined)\n return true\n }\n\n private accept(snapshot: EyeCareSettingsSnapshot, preserveSettings: boolean): void {\n const previous = this.store.getSnapshot().settings\n const next = preserveSettings ? previous : snapshot.settings.value\n const firstRemote = !this.acceptedRemoteSnapshot\n this.acceptedRemoteSnapshot = true\n\n if (next.mode === 'off') {\n this.startupBaseTheme = undefined\n this.startupBaseThemeDeadline = 0\n if (!this.hasRestoreTheme && snapshot.baseThemePreference !== undefined) {\n this.restoreTheme = snapshot.baseThemePreference\n this.hasRestoreTheme = true\n }\n } else if (firstRemote) {\n const base = snapshot.baseThemePreference\n if (base === undefined) {\n if (!this.hasRestoreTheme) this.captureRestoreTheme()\n } else {\n this.restoreTheme = base\n this.hasRestoreTheme = true\n if (this.theme.getTheme().preference !== base) {\n this.startupBaseTheme = base\n this.startupBaseThemeDeadline = this.now() + STARTUP_BASE_THEME_GRACE_MS\n }\n }\n } else if (!preserveSettings && previous.mode === 'off') {\n this.captureRestoreTheme(snapshot.baseThemePreference)\n }\n\n this.store.set({\n settings: next,\n status: snapshot.writable ? 'ready' : 'unavailable',\n writable: snapshot.writable,\n revision: snapshot.settings.revision,\n error: null,\n })\n this.applyCurrentTheme()\n }\n\n private setUnavailable(error: string | null = null, clearRevision = false): void {\n this.store.update(state => {\n state.status = 'unavailable'\n state.writable = false\n if (clearRevision) state.revision = undefined\n state.error = error\n })\n }\n\n private captureRestoreTheme(fallback?: 'light' | 'dark' | 'system'): void {\n const preference = this.theme.getTheme().preference\n const candidate = isEyeCareThemeId(preference) ? fallback ?? 'system' : preference\n this.restoreTheme = candidate\n this.hasRestoreTheme = true\n }\n\n private resolveRestoreTheme(): string {\n if (!this.hasRestoreTheme || this.restoreTheme === 'system') return 'system'\n return this.theme.getTheme().themes.some(theme => theme.id === this.restoreTheme)\n ? this.restoreTheme\n : 'system'\n }\n\n private applyCurrentTheme(): void {\n const { mode, intensity } = this.store.getSnapshot().settings\n const current = this.theme.getTheme().preference\n if (mode === 'off') {\n if (isEyeCareThemeId(current)) this.setTheme(this.resolveRestoreTheme())\n this.hasRestoreTheme = false\n return\n }\n if (!this.hasRestoreTheme) this.captureRestoreTheme()\n const scheme = mode === 'auto' ? (this.media?.matches === true ? 'dark' : 'light') : mode\n this.setTheme(eyeCareThemeId(scheme, intensity))\n }\n\n private setTheme(id: string): void {\n if (this.theme.getTheme().preference === id) return\n this.applyingTheme += 1\n try {\n this.theme.setTheme(id)\n } finally {\n this.applyingTheme -= 1\n }\n }\n\n private onThemeChanged(snapshot: ThemeSnapshot): void {\n if (this.disposed || this.applyingTheme > 0 || isEyeCareThemeId(snapshot.preference)) return\n if (this.startupBaseTheme !== undefined) {\n const expected = this.startupBaseTheme\n const withinStartupWindow = this.now() <= this.startupBaseThemeDeadline\n this.startupBaseTheme = undefined\n this.startupBaseThemeDeadline = 0\n if (withinStartupWindow && snapshot.preference === expected) {\n this.restoreTheme = expected\n this.hasRestoreTheme = true\n this.applyCurrentTheme()\n return\n }\n }\n const state = this.store.getSnapshot()\n if (state.settings.mode === 'off') return\n this.restoreTheme = snapshot.preference\n this.hasRestoreTheme = true\n const settings = { ...state.settings, mode: 'off' as const }\n this.store.update(next => {\n next.settings = settings\n next.error = null\n })\n void this.persist(settings)\n }\n}\n","/** `settings.eyeCare` dictionaries. */\n\n/** Simplified Chinese dictionary. */\nexport const zh = {\n 'title': '护眼模式',\n 'description': '降低页面的冷白光感,长时间阅读更柔和。',\n 'enabled.title': '护眼模式',\n 'enabled.off': '关闭',\n 'enabled.on': '开启',\n 'advanced.title': '显示方式与暖色强度',\n 'mode.title': '显示方式',\n 'mode.off': '关闭',\n 'mode.auto': '自动',\n 'mode.light': '日间',\n 'mode.dark': '夜间',\n 'intensity.title': '暖色强度',\n 'intensity.soft': '柔和',\n 'intensity.balanced': '均衡',\n 'intensity.warm': '温暖',\n 'status.off': '护眼模式已关闭',\n 'status.auto': '自动跟随系统明暗外观',\n 'status.light': '正在使用暖色日间主题',\n 'status.dark': '正在使用暖暗夜间主题',\n 'status.local': '仅当前浏览器有效',\n 'status.saving': '正在保存',\n 'status.error': '设置暂未保存',\n} satisfies Record<string, string>\n\n/** Dictionary key union. */\nexport type EyeCareKey = keyof typeof zh\n\n/** English dictionary. */\nexport const en = {\n 'title': 'Eye care',\n 'description': 'Use warm semantic themes to reduce cool-white glare during long reading sessions',\n 'enabled.title': 'Eye care',\n 'enabled.off': 'Off',\n 'enabled.on': 'On',\n 'advanced.title': 'Appearance and warmth',\n 'mode.title': 'Appearance',\n 'mode.off': 'Off',\n 'mode.auto': 'Auto',\n 'mode.light': 'Day',\n 'mode.dark': 'Night',\n 'intensity.title': 'Warmth',\n 'intensity.soft': 'Soft',\n 'intensity.balanced': 'Balanced',\n 'intensity.warm': 'Warm',\n 'status.off': 'Eye care is off',\n 'status.auto': 'Following the system light or dark appearance',\n 'status.light': 'Warm day theme is active',\n 'status.dark': 'Warm night theme is active',\n 'status.local': 'Current browser only',\n 'status.saving': 'Saving',\n 'status.error': 'Setting is not saved yet',\n} satisfies Record<EyeCareKey, string>\n","/** DSH Web browser half for the eye-care profile bundle. */\n\nimport type { ConnectionHandle } from '@deepseek-ai/dsh-client-connection/client'\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type { ThemeRuntime, ThemeSnapshot } from '@deepseek-ai/dsh-client-ui-theme/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type {} from '@deepseek-ai/dsh-api-remotes/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-theme/client'\nimport { EyeCareRow, type EyeCareRowInjected } from './EyeCareRow.tsx'\nimport { EyeCareController } from './controller.ts'\nimport { en, zh, type EyeCareKey } from './locales.ts'\n\n/** Required browser services. */\nexport const inject = ['slots', 'locale', 'theme', 'connection', 'remote']\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** Eye-care General row copy. */\n 'settings.eyeCare': EyeCareKey\n }\n}\n\n/** Browser context with the theme service declaration merged by ui-theme. */\ntype EyeCareClientContext = ClientContext & { theme: ThemeRuntime }\n\n/** Register settings copy, controller lifecycle, and General row. */\nexport function apply(ctx: EyeCareClientContext): void {\n const theme = ctx.get('theme') as ThemeRuntime\n const connection = ctx.get('connection') as ConnectionHandle\n const controller = new EyeCareController({\n theme,\n ...(connection.isLoopback ? { rpc: connection.rpc } : {}),\n subscribeTheme: (listener: (snapshot: ThemeSnapshot) => void): (() => void) => ctx.on('theme/change', listener),\n })\n ctx.effect(() => ctx.locale.register('settings.eyeCare', { zh, en }), 'dsh-eye-care: dictionaries')\n ctx.effect(() => {\n const refresh = (namespace?: string): void => {\n if (namespace !== undefined && namespace !== 'eye-care') return\n controller.refresh()\n }\n const disposers = [\n ctx.remote.$on('settings/document-updated', refresh),\n ctx.on('connection/reset', () => {\n if (connection.isLoopback) controller.refresh()\n }),\n ]\n void controller.load()\n return async () => {\n for (const dispose of disposers) dispose()\n await controller.dispose()\n }\n }, 'dsh-eye-care: controller lifecycle')\n\n const injected = (): EyeCareRowInjected => ({\n hooks: { eyeCare: controller.store },\n setMode: mode => controller.setMode(mode),\n setIntensity: intensity => controller.setIntensity(intensity),\n })\n ctx.slots.inject('settings.general.item', () => ctx.slots.register({\n name: 'settings.general.item',\n id: 'eye-care',\n order: 15,\n locale: 'settings.eyeCare',\n inject: injected,\n }, EyeCareRow))\n}\n\nexport type { EyeCareRowInjected, EyeCareRowProps } from './EyeCareRow.tsx'\nexport type { EyeCareState } from './controller.ts'\nexport { EyeCareController } from './controller.ts'\nexport { EYE_CARE_THEMES, eyeCareThemeId, isEyeCareThemeId } from './themes.ts'\n"],"mappings":"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"}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** DSH eye-care Host plugin: settings ownership and loopback RPC transport. */
|
|
2
|
+
import { installEyeCareRpc } from "./rpc.js";
|
|
3
|
+
import { EYE_CARE_SETTINGS_NS, EyeCareSettingsSchema } from "./settings.js";
|
|
4
|
+
export { DEFAULT_EYE_CARE_SETTINGS, EYE_CARE_INTENSITIES, EYE_CARE_MODES, EYE_CARE_SETTINGS_NAMESPACE, EYE_CARE_RPC_CHANNEL, EYE_CARE_RPC_READ, EYE_CARE_RPC_SAVE, } from "./shared.js";
|
|
5
|
+
export { EYE_CARE_SETTINGS_NS, EyeCareSettingsSchema } from "./settings.js";
|
|
6
|
+
export { EyeCareRpcBackend } from "./rpc.js";
|
|
7
|
+
/** Required Host capability. */
|
|
8
|
+
export const inject = ['settings'];
|
|
9
|
+
/** Register the durable namespace and the optional loopback browser transport. */
|
|
10
|
+
export function apply(ctx) {
|
|
11
|
+
ctx.settings.register(EYE_CARE_SETTINGS_NS, EyeCareSettingsSchema);
|
|
12
|
+
installEyeCareRpc(ctx);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAI/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAE3E,OAAO,EACL,yBAAyB,EACzB,oBAAoB,EACpB,cAAc,EACd,2BAA2B,EAC3B,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,GAIlB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAE5C,gCAAgC;AAChC,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,UAAU,CAAC,CAAA;AAElC,kFAAkF;AAClF,MAAM,UAAU,KAAK,CAAC,GAAY;IAChC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,oBAAoB,EAAE,qBAAqB,CAAC,CAAA;IAClE,iBAAiB,CAAC,GAAG,CAAC,CAAA;AACxB,CAAC"}
|
package/lib/rpc.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/** Loopback-only Connection RPC for durable eye-care preferences. */
|
|
2
|
+
import { SettingsConflictError } from '@deepseek-ai/dsh-settings';
|
|
3
|
+
import { decodeEyeCareSettings, EYE_CARE_RPC_CHANNEL, EYE_CARE_RPC_READ, EYE_CARE_RPC_SAVE, } from "./shared.js";
|
|
4
|
+
import { EYE_CARE_SETTINGS_NS } from "./settings.js";
|
|
5
|
+
function descriptorOf(ctx) {
|
|
6
|
+
const descriptor = ctx.settings.describe().find(row => row.ns === EYE_CARE_SETTINGS_NS);
|
|
7
|
+
if (descriptor === undefined)
|
|
8
|
+
throw new Error('eye-care settings namespace is not registered');
|
|
9
|
+
return descriptor;
|
|
10
|
+
}
|
|
11
|
+
function baseThemePreferenceOf(ctx) {
|
|
12
|
+
const descriptor = ctx.settings.describe().find(row => String(row.ns) === 'ui-theme');
|
|
13
|
+
if (typeof descriptor?.value !== 'object' || descriptor.value === null || Array.isArray(descriptor.value))
|
|
14
|
+
return undefined;
|
|
15
|
+
const preference = descriptor.value['preference'];
|
|
16
|
+
return preference === 'light' || preference === 'dark' || preference === 'system' ? preference : undefined;
|
|
17
|
+
}
|
|
18
|
+
function parseWriteRequest(value) {
|
|
19
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
20
|
+
throw new TypeError('request must be an object');
|
|
21
|
+
}
|
|
22
|
+
const record = value;
|
|
23
|
+
const settings = decodeEyeCareSettings(record['value']);
|
|
24
|
+
const revision = record['expectedRevision'];
|
|
25
|
+
if (!Number.isSafeInteger(revision) || revision < 0 || settings === undefined) {
|
|
26
|
+
throw new TypeError('save requires a non-negative expectedRevision and a valid eye-care value');
|
|
27
|
+
}
|
|
28
|
+
return { expectedRevision: revision, value: settings };
|
|
29
|
+
}
|
|
30
|
+
function publicMessage(error) {
|
|
31
|
+
return (error instanceof Error ? error.message : String(error)).slice(0, 1000);
|
|
32
|
+
}
|
|
33
|
+
/** Host backend used by the loopback-only Connection RPC registration. */
|
|
34
|
+
export class EyeCareRpcBackend {
|
|
35
|
+
ctx;
|
|
36
|
+
/** Create a backend over the active Settings service. */
|
|
37
|
+
constructor(ctx) {
|
|
38
|
+
this.ctx = ctx;
|
|
39
|
+
}
|
|
40
|
+
/** Read the current browser-safe settings snapshot. */
|
|
41
|
+
snapshot() {
|
|
42
|
+
const descriptor = descriptorOf(this.ctx);
|
|
43
|
+
const baseThemePreference = baseThemePreferenceOf(this.ctx);
|
|
44
|
+
return {
|
|
45
|
+
schemaVersion: 1,
|
|
46
|
+
writable: this.ctx.settings.writable,
|
|
47
|
+
settings: {
|
|
48
|
+
value: descriptor.value,
|
|
49
|
+
revision: descriptor.revision,
|
|
50
|
+
applies: 'live',
|
|
51
|
+
},
|
|
52
|
+
...(baseThemePreference === undefined ? {} : { baseThemePreference }),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/** Handle one Connection RPC endpoint. */
|
|
56
|
+
handle = async (endpoint, payload) => {
|
|
57
|
+
if (endpoint === EYE_CARE_RPC_READ) {
|
|
58
|
+
return { ok: true, value: this.snapshot() };
|
|
59
|
+
}
|
|
60
|
+
if (endpoint !== EYE_CARE_RPC_SAVE) {
|
|
61
|
+
return {
|
|
62
|
+
ok: false,
|
|
63
|
+
error: {
|
|
64
|
+
code: 'bad-request',
|
|
65
|
+
message: `unknown eye-care endpoint: ${endpoint}`,
|
|
66
|
+
details: { issues: [] },
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
let request;
|
|
71
|
+
try {
|
|
72
|
+
request = parseWriteRequest(payload);
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
return {
|
|
76
|
+
ok: false,
|
|
77
|
+
error: {
|
|
78
|
+
code: 'bad-request',
|
|
79
|
+
message: publicMessage(error),
|
|
80
|
+
details: { issues: [] },
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
if (!this.ctx.settings.writable)
|
|
86
|
+
throw new Error('settings provider is read-only');
|
|
87
|
+
await this.ctx.settings.replace(EYE_CARE_SETTINGS_NS, request.value, request.expectedRevision);
|
|
88
|
+
return { ok: true, value: this.snapshot() };
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
if (error instanceof SettingsConflictError) {
|
|
92
|
+
return {
|
|
93
|
+
ok: false,
|
|
94
|
+
error: {
|
|
95
|
+
code: 'settings-conflict',
|
|
96
|
+
message: publicMessage(error),
|
|
97
|
+
details: {
|
|
98
|
+
ns: String(EYE_CARE_SETTINGS_NS),
|
|
99
|
+
expected: error.expected,
|
|
100
|
+
actual: error.actual,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
ok: false,
|
|
107
|
+
error: {
|
|
108
|
+
code: 'settings-rejected',
|
|
109
|
+
message: publicMessage(error),
|
|
110
|
+
details: { ns: String(EYE_CARE_SETTINGS_NS) },
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/** Register the RPC channel when the Web Connection Host is composed. */
|
|
117
|
+
export function installEyeCareRpc(ctx) {
|
|
118
|
+
const backend = new EyeCareRpcBackend(ctx);
|
|
119
|
+
ctx.inject(['connection'], (connectionCtx) => {
|
|
120
|
+
connectionCtx.connection.rpc.handle(EYE_CARE_RPC_CHANNEL, backend.handle, { authority: 'loopback' });
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=rpc.js.map
|
package/lib/rpc.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc.js","sourceRoot":"","sources":["../src/rpc.ts"],"names":[],"mappings":"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"}
|
package/lib/settings.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Host-only schema and branded namespace for eye-care settings. */
|
|
2
|
+
import z from '@deepseek-ai/schemastery';
|
|
3
|
+
import { settingsNamespace } from '@deepseek-ai/dsh-settings';
|
|
4
|
+
import { DEFAULT_EYE_CARE_SETTINGS, EYE_CARE_INTENSITIES, EYE_CARE_MODES, EYE_CARE_SETTINGS_NAMESPACE, INTENSITY_FIELD, MODE_FIELD, } from "./shared.js";
|
|
5
|
+
/** Branded settings namespace used by the Host service. */
|
|
6
|
+
export const EYE_CARE_SETTINGS_NS = settingsNamespace(EYE_CARE_SETTINGS_NAMESPACE);
|
|
7
|
+
/** Host schema for the eye-care settings section. */
|
|
8
|
+
export const EyeCareSettingsSchema = z.object({
|
|
9
|
+
[MODE_FIELD]: z.union([...EYE_CARE_MODES]).default(DEFAULT_EYE_CARE_SETTINGS.mode),
|
|
10
|
+
[INTENSITY_FIELD]: z.union([...EYE_CARE_INTENSITIES]).default(DEFAULT_EYE_CARE_SETTINGS.intensity),
|
|
11
|
+
});
|
|
12
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAEpE,OAAO,CAAC,MAAM,0BAA0B,CAAA;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EACL,yBAAyB,EACzB,oBAAoB,EACpB,cAAc,EACd,2BAA2B,EAC3B,eAAe,EACf,UAAU,GAEX,MAAM,aAAa,CAAA;AAEpB,2DAA2D;AAC3D,MAAM,CAAC,MAAM,oBAAoB,GAAG,iBAAiB,CAAC,2BAA2B,CAAC,CAAA;AAElF,qDAAqD;AACrD,MAAM,CAAC,MAAM,qBAAqB,GAAuB,CAAC,CAAC,MAAM,CAAC;IAChE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,yBAAyB,CAAC,IAAI,CAAC;IAClF,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,oBAAoB,CAAC,CAAC,CAAC,OAAO,CAAC,yBAAyB,CAAC,SAAS,CAAC;CACnG,CAAC,CAAA"}
|
package/lib/shared.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/** Browser-safe eye-care settings and RPC wire values. */
|
|
2
|
+
/** User-selectable eye-care operating modes. */
|
|
3
|
+
export const EYE_CARE_MODES = ['off', 'auto', 'light', 'dark'];
|
|
4
|
+
/** Warmth levels shared by light and dark palettes. */
|
|
5
|
+
export const EYE_CARE_INTENSITIES = ['soft', 'balanced', 'warm'];
|
|
6
|
+
/** Settings namespace owned by this package. */
|
|
7
|
+
export const EYE_CARE_SETTINGS_NAMESPACE = 'eye-care';
|
|
8
|
+
/** Loopback-only Connection RPC channel owned by this package. */
|
|
9
|
+
export const EYE_CARE_RPC_CHANNEL = '/eye-care';
|
|
10
|
+
/** RPC endpoint that reads the current settings snapshot. */
|
|
11
|
+
export const EYE_CARE_RPC_READ = 'settings.read';
|
|
12
|
+
/** RPC endpoint that replaces the settings section. */
|
|
13
|
+
export const EYE_CARE_RPC_SAVE = 'settings.save';
|
|
14
|
+
/** Settings field carrying the selected mode. */
|
|
15
|
+
export const MODE_FIELD = 'mode';
|
|
16
|
+
/** Settings field carrying the selected warmth. */
|
|
17
|
+
export const INTENSITY_FIELD = 'intensity';
|
|
18
|
+
/** Defaults used when no user section exists. */
|
|
19
|
+
export const DEFAULT_EYE_CARE_SETTINGS = Object.freeze({
|
|
20
|
+
mode: 'off',
|
|
21
|
+
intensity: 'balanced',
|
|
22
|
+
});
|
|
23
|
+
/** Narrow an unknown value to one supported mode. */
|
|
24
|
+
export function isEyeCareMode(value) {
|
|
25
|
+
return EYE_CARE_MODES.some(mode => mode === value);
|
|
26
|
+
}
|
|
27
|
+
/** Narrow an unknown value to one supported warmth. */
|
|
28
|
+
export function isEyeCareIntensity(value) {
|
|
29
|
+
return EYE_CARE_INTENSITIES.some(intensity => intensity === value);
|
|
30
|
+
}
|
|
31
|
+
/** Decode a complete settings value from the RPC boundary. */
|
|
32
|
+
export function decodeEyeCareSettings(value) {
|
|
33
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
34
|
+
return undefined;
|
|
35
|
+
const record = value;
|
|
36
|
+
if (!isEyeCareMode(record[MODE_FIELD]) || !isEyeCareIntensity(record[INTENSITY_FIELD]))
|
|
37
|
+
return undefined;
|
|
38
|
+
return { mode: record[MODE_FIELD], intensity: record[INTENSITY_FIELD] };
|
|
39
|
+
}
|
|
40
|
+
/** Decode one complete Host snapshot from the RPC boundary. */
|
|
41
|
+
export function decodeEyeCareSnapshot(value) {
|
|
42
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
43
|
+
return undefined;
|
|
44
|
+
const record = value;
|
|
45
|
+
const settingsEnvelope = record['settings'];
|
|
46
|
+
if (record['schemaVersion'] !== 1 || typeof record['writable'] !== 'boolean'
|
|
47
|
+
|| typeof settingsEnvelope !== 'object' || settingsEnvelope === null || Array.isArray(settingsEnvelope))
|
|
48
|
+
return undefined;
|
|
49
|
+
const settingsRecord = settingsEnvelope;
|
|
50
|
+
const settings = decodeEyeCareSettings(settingsRecord['value']);
|
|
51
|
+
const revision = settingsRecord['revision'];
|
|
52
|
+
if (settings === undefined || !Number.isSafeInteger(revision) || revision < 0
|
|
53
|
+
|| settingsRecord['applies'] !== 'live')
|
|
54
|
+
return undefined;
|
|
55
|
+
const baseThemePreference = record['baseThemePreference'];
|
|
56
|
+
if (baseThemePreference !== undefined
|
|
57
|
+
&& baseThemePreference !== 'light' && baseThemePreference !== 'dark' && baseThemePreference !== 'system')
|
|
58
|
+
return undefined;
|
|
59
|
+
return {
|
|
60
|
+
schemaVersion: 1,
|
|
61
|
+
writable: record['writable'],
|
|
62
|
+
settings: {
|
|
63
|
+
value: settings,
|
|
64
|
+
revision: revision,
|
|
65
|
+
applies: 'live',
|
|
66
|
+
},
|
|
67
|
+
...(baseThemePreference === undefined ? {} : { baseThemePreference }),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** General-settings row for eye-care mode and warmth controls. */
|
|
2
|
+
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
3
|
+
import type { EyeCareController } from './controller.ts';
|
|
4
|
+
import type { EyeCareIntensity, EyeCareMode } from '../shared.ts';
|
|
5
|
+
/** Injected business face used by the row. */
|
|
6
|
+
export interface EyeCareRowInjected {
|
|
7
|
+
/** State source. */
|
|
8
|
+
hooks: {
|
|
9
|
+
eyeCare: EyeCareController['store'];
|
|
10
|
+
};
|
|
11
|
+
/** Set the selected mode. */
|
|
12
|
+
setMode: (mode: EyeCareMode) => Promise<void>;
|
|
13
|
+
/** Set the selected warmth. */
|
|
14
|
+
setIntensity: (intensity: EyeCareIntensity) => Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
/** Full composed props for the settings slot. */
|
|
17
|
+
export type EyeCareRowProps = PropsRuntime<'settings.general.item'> & PropsLocale<'settings.eyeCare'> & InjectFace<EyeCareRowInjected>;
|
|
18
|
+
/** Render the feature-owned General settings row. */
|
|
19
|
+
export declare function EyeCareRow({ t, useEyeCare, setMode, setIntensity }: EyeCareRowProps): import("react").JSX.Element;
|
|
20
|
+
//# sourceMappingURL=EyeCareRow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EyeCareRow.d.ts","sourceRoot":"","sources":["../../../src/client/EyeCareRow.tsx"],"names":[],"mappings":"AAAA,kEAAkE;AAElE,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAC7F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAExD,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAGjE,8CAA8C;AAC9C,MAAM,WAAW,kBAAkB;IACjC,oBAAoB;IACpB,KAAK,EAAE;QAAE,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAA;KAAE,CAAA;IAC9C,6BAA6B;IAC7B,OAAO,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7C,+BAA+B;IAC/B,YAAY,EAAE,CAAC,SAAS,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7D;AAED,iDAAiD;AACjD,MAAM,MAAM,eAAe,GAAG,YAAY,CAAC,uBAAuB,CAAC,GAC/D,WAAW,CAAC,kBAAkB,CAAC,GAC/B,UAAU,CAAC,kBAAkB,CAAC,CAAA;AAmBlC,qDAAqD;AACrD,wBAAgB,UAAU,CAAC,EAAE,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,eAAe,+BAgFnF"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/** Eye-care state owner: durable settings synchronization plus theme lifecycle. */
|
|
2
|
+
import type { ClientConnectionRpc } from '@deepseek-ai/dsh-client-connection/client';
|
|
3
|
+
import { type SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client';
|
|
4
|
+
import type { ThemeRuntime, ThemeSnapshot } from '@deepseek-ai/dsh-client-ui-theme/client';
|
|
5
|
+
import { type EyeCareIntensity, type EyeCareMode, type EyeCareSettings } from '../shared.ts';
|
|
6
|
+
/** State consumed by the General-settings row. */
|
|
7
|
+
export interface EyeCareState {
|
|
8
|
+
/** Current eye-care selection. */
|
|
9
|
+
settings: EyeCareSettings;
|
|
10
|
+
/** Persistence lifecycle. */
|
|
11
|
+
status: 'loading' | 'ready' | 'saving' | 'unavailable' | 'error';
|
|
12
|
+
/** Whether the Host settings document can be written. */
|
|
13
|
+
writable: boolean;
|
|
14
|
+
/** Host namespace revision for the next write. */
|
|
15
|
+
revision: number | undefined;
|
|
16
|
+
/** User-facing read or write failure, when one stands. */
|
|
17
|
+
error: string | null;
|
|
18
|
+
}
|
|
19
|
+
/** Inputs isolated for deterministic controller tests. */
|
|
20
|
+
export interface EyeCareControllerOptions {
|
|
21
|
+
/** DSH theme registry. */
|
|
22
|
+
theme: Pick<ThemeRuntime, 'getTheme' | 'setTheme' | 'register'>;
|
|
23
|
+
/** Snapshot change subscription. */
|
|
24
|
+
subscribeTheme(listener: (snapshot: ThemeSnapshot) => void): () => void;
|
|
25
|
+
/** Loopback-only Connection RPC; absent remote browsers stay process-local. */
|
|
26
|
+
rpc?: ClientConnectionRpc;
|
|
27
|
+
/** System dark-mode sensor. */
|
|
28
|
+
media?: MediaQueryList;
|
|
29
|
+
/** Monotonic wall-clock source used only by the one-shot startup adoption fence. */
|
|
30
|
+
now?: () => number;
|
|
31
|
+
}
|
|
32
|
+
/** Stateful controller shared by theme listeners and the Settings row. */
|
|
33
|
+
export declare class EyeCareController {
|
|
34
|
+
/** Reactive row source. */
|
|
35
|
+
readonly store: SnapshotStore<EyeCareState>;
|
|
36
|
+
private readonly theme;
|
|
37
|
+
private readonly rpc;
|
|
38
|
+
private readonly media;
|
|
39
|
+
private readonly now;
|
|
40
|
+
private readonly unregisterThemes;
|
|
41
|
+
private unsubscribeTheme;
|
|
42
|
+
private unsubscribeMedia;
|
|
43
|
+
private tail;
|
|
44
|
+
private disposeTask;
|
|
45
|
+
private pendingSettings;
|
|
46
|
+
private disposed;
|
|
47
|
+
private applyingTheme;
|
|
48
|
+
private restoreTheme;
|
|
49
|
+
private hasRestoreTheme;
|
|
50
|
+
private acceptedRemoteSnapshot;
|
|
51
|
+
private startupBaseTheme;
|
|
52
|
+
private startupBaseThemeDeadline;
|
|
53
|
+
/**
|
|
54
|
+
* Register the concrete themes and lifecycle listeners.
|
|
55
|
+
* @param options - theme, transport, and system-scheme collaborators.
|
|
56
|
+
*/
|
|
57
|
+
constructor(options: EyeCareControllerOptions);
|
|
58
|
+
/**
|
|
59
|
+
* Load durable settings without blocking plugin activation.
|
|
60
|
+
* @returns settlement after this read reaches the serialized transport queue.
|
|
61
|
+
*/
|
|
62
|
+
load(): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Select a mode and persist the latest selection when Host settings are writable.
|
|
65
|
+
* @param mode - next operating mode.
|
|
66
|
+
* @returns settlement after the serialized persistence attempt.
|
|
67
|
+
*/
|
|
68
|
+
setMode(mode: EyeCareMode): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Select a warmth and persist the latest selection when Host settings are writable.
|
|
71
|
+
* @param intensity - next warmth level.
|
|
72
|
+
* @returns settlement after the serialized persistence attempt.
|
|
73
|
+
*/
|
|
74
|
+
setIntensity(intensity: EyeCareIntensity): Promise<void>;
|
|
75
|
+
/** Queue a refresh after a Host settings invalidation. */
|
|
76
|
+
refresh(): void;
|
|
77
|
+
/**
|
|
78
|
+
* Reach transport quiescence, restore the user's live non-eye-care theme, and unregister all resources.
|
|
79
|
+
* @returns settlement after cleanup completes.
|
|
80
|
+
*/
|
|
81
|
+
dispose(): Promise<void>;
|
|
82
|
+
private disposeOnce;
|
|
83
|
+
private enqueue;
|
|
84
|
+
private select;
|
|
85
|
+
private persist;
|
|
86
|
+
private flushPending;
|
|
87
|
+
private readRemote;
|
|
88
|
+
private accept;
|
|
89
|
+
private setUnavailable;
|
|
90
|
+
private captureRestoreTheme;
|
|
91
|
+
private resolveRestoreTheme;
|
|
92
|
+
private applyCurrentTheme;
|
|
93
|
+
private setTheme;
|
|
94
|
+
private onThemeChanged;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../src/client/controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** DSH Web browser half for the eye-care profile bundle. */
|
|
2
|
+
import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
|
|
3
|
+
import type { ThemeRuntime } from '@deepseek-ai/dsh-client-ui-theme/client';
|
|
4
|
+
import { type EyeCareKey } from './locales.ts';
|
|
5
|
+
/** Required browser services. */
|
|
6
|
+
export declare const inject: string[];
|
|
7
|
+
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
8
|
+
interface LocaleNamespaceMap {
|
|
9
|
+
/** Eye-care General row copy. */
|
|
10
|
+
'settings.eyeCare': EyeCareKey;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/** Browser context with the theme service declaration merged by ui-theme. */
|
|
14
|
+
type EyeCareClientContext = ClientContext & {
|
|
15
|
+
theme: ThemeRuntime;
|
|
16
|
+
};
|
|
17
|
+
/** Register settings copy, controller lifecycle, and General row. */
|
|
18
|
+
export declare function apply(ctx: EyeCareClientContext): void;
|
|
19
|
+
export type { EyeCareRowInjected, EyeCareRowProps } from './EyeCareRow.tsx';
|
|
20
|
+
export type { EyeCareState } from './controller.ts';
|
|
21
|
+
export { EyeCareController } from './controller.ts';
|
|
22
|
+
export { EYE_CARE_THEMES, eyeCareThemeId, isEyeCareThemeId } from './themes.ts';
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.tsx"],"names":[],"mappings":"AAAA,4DAA4D;AAG5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAC3E,OAAO,KAAK,EAAE,YAAY,EAAiB,MAAM,yCAAyC,CAAA;AAO1F,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,cAAc,CAAA;AAEtD,iCAAiC;AACjC,eAAO,MAAM,MAAM,UAAuD,CAAA;AAE1E,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,iCAAiC;QACjC,kBAAkB,EAAE,UAAU,CAAA;KAC/B;CACF;AAED,6EAA6E;AAC7E,KAAK,oBAAoB,GAAG,aAAa,GAAG;IAAE,KAAK,EAAE,YAAY,CAAA;CAAE,CAAA;AAEnE,qEAAqE;AACrE,wBAAgB,KAAK,CAAC,GAAG,EAAE,oBAAoB,GAAG,IAAI,CAuCrD;AAED,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAC3E,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** `settings.eyeCare` dictionaries. */
|
|
2
|
+
/** Simplified Chinese dictionary. */
|
|
3
|
+
export declare const zh: {
|
|
4
|
+
title: string;
|
|
5
|
+
description: string;
|
|
6
|
+
'enabled.title': string;
|
|
7
|
+
'enabled.off': string;
|
|
8
|
+
'enabled.on': string;
|
|
9
|
+
'advanced.title': string;
|
|
10
|
+
'mode.title': string;
|
|
11
|
+
'mode.off': string;
|
|
12
|
+
'mode.auto': string;
|
|
13
|
+
'mode.light': string;
|
|
14
|
+
'mode.dark': string;
|
|
15
|
+
'intensity.title': string;
|
|
16
|
+
'intensity.soft': string;
|
|
17
|
+
'intensity.balanced': string;
|
|
18
|
+
'intensity.warm': string;
|
|
19
|
+
'status.off': string;
|
|
20
|
+
'status.auto': string;
|
|
21
|
+
'status.light': string;
|
|
22
|
+
'status.dark': string;
|
|
23
|
+
'status.local': string;
|
|
24
|
+
'status.saving': string;
|
|
25
|
+
'status.error': string;
|
|
26
|
+
};
|
|
27
|
+
/** Dictionary key union. */
|
|
28
|
+
export type EyeCareKey = keyof typeof zh;
|
|
29
|
+
/** English dictionary. */
|
|
30
|
+
export declare const en: {
|
|
31
|
+
title: string;
|
|
32
|
+
description: string;
|
|
33
|
+
'enabled.title': string;
|
|
34
|
+
'enabled.off': string;
|
|
35
|
+
'enabled.on': string;
|
|
36
|
+
'advanced.title': string;
|
|
37
|
+
'mode.title': string;
|
|
38
|
+
'mode.off': string;
|
|
39
|
+
'mode.auto': string;
|
|
40
|
+
'mode.light': string;
|
|
41
|
+
'mode.dark': string;
|
|
42
|
+
'intensity.title': string;
|
|
43
|
+
'intensity.soft': string;
|
|
44
|
+
'intensity.balanced': string;
|
|
45
|
+
'intensity.warm': string;
|
|
46
|
+
'status.off': string;
|
|
47
|
+
'status.auto': string;
|
|
48
|
+
'status.light': string;
|
|
49
|
+
'status.dark': string;
|
|
50
|
+
'status.local': string;
|
|
51
|
+
'status.saving': string;
|
|
52
|
+
'status.error': string;
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=locales.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA,uCAAuC;AAEvC,qCAAqC;AACrC,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;CAuBmB,CAAA;AAElC,4BAA4B;AAC5B,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,EAAE,CAAA;AAExC,0BAA0B;AAC1B,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;CAuBuB,CAAA"}
|