mirror of
https://github.com/esengine/DeepSeek-Reasonix.git
synced 2026-11-11 01:51:33 -10:00
* feat(desktop): add pane opacity control and fix base style revert on custom theme save New feature — per-scene pane opacity (面板透明度): - ThemePackBackground / ThemePackSceneBackground gain a paneOpacity field (0-1) that controls how transparent the shell panels render when a theme pack is active. Home defaults to 0.50, task defaults to 0.68. - Independent sliders in ThemeGallery editor for both scenes. - applyBackgroundCSSVars pre-computes CSS variables (--theme-pane-alpha, --theme-pane-shell-pct, --theme-pane-task-*) for color-mix rules. - CSS rules under :root[data-theme-pack] apply pane opacity to sidebar, topicbar, dock, statusbar, chat-pane, composer-card, and transcript with cascading opacity tiers (shell < card < inner). - ThemePreviewSurface preview cards now reflect pane opacity. - Task background opacity caps relaxed from 0.45 to 1.0 per user demand. - All 8 official mock themes include paneOpacity: 0.50. - Schema and docs (EN/ZH) updated with paneOpacity field. Bug fix — base style revert on Save & apply: When ThemeGallery.saveEditor(activate=true) called activateThemePack(), the downstream onExperienceChange callback passed exp.baseStyle (the config-file appearance, e.g. graphite) to the parent's onThemeStyle. The parent then called applyTheme(theme, OLD_style) which overwrote the pack's baseStyle (e.g. refined) that applyThemePack had just set on the DOM. Fixes: - AppearanceOverview.onExperienceChange now syncs exp.effectiveStyle instead of exp.baseStyle, and no longer calls onTheme (which reads stale themeStyle from its closure). - SettingsPanel.onThemeStyle now reads the current theme from the DOM via getTheme() instead of the React closure theme state. - ThemeGallery.saveEditor moves cancelThemePreview() to only the non-activate branch; the activate path must not restore the preview snapshot after the new pack is applied. - themeExperience.activateThemePack calls clearPreviewSnapshotOnly() first so endPreviewIfAny() cannot overwrite the newly activated pack. - Layout transparency CSS selectors gain .app:not(.app--creation) to exclude the creation-mode surface. Test contract: - TestTaskOpacityCapped renamed to TestOpacityClamped, now validates the new 0-1 clamping and PaneOpacity defaults for both scenes. - 'layout background transparent' contract test updated to a single flexible regex that tolerates intermediate selectors. - i18n: taskBackgroundHint adjusted (removed stale 45% cap reference); new paneOpacity label in EN/ZH/ZH-TW. * fix(desktop): preserve theme pane transparency state Problem: - Explicit 0% pane opacity was replaced by legacy defaults. - Token-only theme packs received background transparency rules. - Failed theme activation discarded the reversible preview snapshot. Root cause: - A scalar JSON field could not distinguish omission from an explicit zero. - Extended pane selectors were scoped to any theme pack instead of packs with backgrounds. - The preview snapshot was cleared before persistence succeeded. Fix: - Represent pane opacity as an optional persisted value and preserve explicit zero through normalization and JSON round trips. - Guard background and pane transparency CSS with data-theme-has-bg. - Commit preview state only after successful activation and add focused regressions. Verification: - cd desktop && go test ./... - cd desktop/frontend && pnpm run test - cd desktop/frontend && pnpm run build - Browser DOM/CSS checks for token-only and background theme previews * fix(desktop): separate theme base state from pack effects Problem: - Applying a theme pack mirrored its effective style into the configured base appearance, so direct theme reset restored the pack style. - Pane opacity previews changed while live card surfaces remained fixed at 88%. Root cause: - The gallery callback reused the configured-style owner callback for a temporary effective style. - Card-tier CSS variables were computed but not consumed, and preview offsets differed from live formulas. Fix: - Synchronize configured base style only when no active pack owns the effective style. - Consume scene-specific card opacity variables in live surfaces and use the same formulas in previews. - Remove unused pane variables and add regressions for direct reset and opacity consumers. Verification: - cd desktop/frontend && pnpm run test - cd desktop/frontend && pnpm run build - cd desktop && go test ./... - Browser: Sage/Slate reset restored Graphite; live and preview card opacity matched scene variables * fix(desktop): preserve theme preview lifecycle Problem: - Save and apply closed the theme editor before activation completed, allowing unmount cleanup to restore the old preview snapshot. - Base and token-only gallery previews received background pane transparency that live surfaces do not apply. Root cause: - Editor teardown occurred before activateThemePack committed the preview. - Preview opacity variables were derived without checking whether the pack had a background. Fix: - Activate or cancel the preview before closing the editor and reloading the gallery. - Keep pane previews opaque when no theme background is present. - Add regressions for lifecycle ordering and preview opacity. Verification: - cd desktop/frontend && pnpm run test - cd desktop/frontend && pnpm run build - cd desktop && go test ./... - Browser preview check: base previews stayed opaque while background previews retained configured alpha * fix(desktop): keep theme activation and previews consistent Problem: - Save and apply persisted activation twice, so a later activation failure could split persistent state from the reversible preview. - Browser official-theme mocks used 50% pane opacity while embedded manifests fell back to legacy defaults. - Legacy task scene payloads without pane opacity did not inherit the home setting. Root cause: - ThemeGallery delegated activation to SaveThemePack and then called the experience activation controller again. - Official manifests omitted the new field, and the task fallback tested object presence instead of field presence. Fix: - Make the experience controller the sole owner of active-theme pointer updates after saving. - Declare 50% pane opacity in every official manifest and verify Wails/browser parity. - Use nullish field fallback for legacy task scenes and add regression coverage. Verification: - pnpm exec tsx src/__tests__/theme-pack.test.ts (230 passed) - pnpm run typecheck - pnpm run check:css - pnpm run test - pnpm run build - go test ./... --------- Co-authored-by: SivanCola <[email protected]>
110 lines
4.0 KiB
JSON
110 lines
4.0 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": "https://reasonix.dev/schemas/theme-pack-v2.json",
|
|
"title": "Reasonix Theme Pack V2",
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["schemaVersion", "id", "name", "baseStyle"],
|
|
"properties": {
|
|
"schemaVersion": { "type": "integer", "enum": [1, 2] },
|
|
"id": {
|
|
"type": "string",
|
|
"pattern": "^[a-z]([a-z0-9-]{0,62}[a-z0-9])?$"
|
|
},
|
|
"name": { "type": "string", "minLength": 1, "maxLength": 80 },
|
|
"author": { "type": "string", "maxLength": 240 },
|
|
"description": { "type": "string", "maxLength": 240 },
|
|
"license": { "type": "string", "maxLength": 240 },
|
|
"baseStyle": {
|
|
"type": "string",
|
|
"enum": ["graphite", "aurora", "slate", "carbon", "nocturne", "amber"]
|
|
},
|
|
"tokens": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"light": { "$ref": "#/$defs/tokenMap" },
|
|
"dark": { "$ref": "#/$defs/tokenMap" }
|
|
}
|
|
},
|
|
"recipes": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"density": { "type": "string", "enum": ["compact", "comfortable"] },
|
|
"corners": { "type": "string", "enum": ["square", "soft", "round"] }
|
|
}
|
|
},
|
|
"background": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"image": {
|
|
"type": "string",
|
|
"pattern": "^[a-zA-Z0-9][a-zA-Z0-9._-]{0,120}\\.(png|jpe?g|webp)$"
|
|
},
|
|
"focusX": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
"focusY": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
"safeArea": { "type": "string", "enum": ["left", "right", "center"] },
|
|
"homeOpacity": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
"taskOpacity": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
"overlayStrength": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
"paneOpacity": { "type": "number", "minimum": 0, "maximum": 1 }
|
|
}
|
|
},
|
|
"taskBackground": { "$ref": "#/$defs/sceneBackground" }
|
|
},
|
|
"allOf": [
|
|
{
|
|
"if": { "required": ["taskBackground"] },
|
|
"then": { "properties": { "schemaVersion": { "const": 2 } } }
|
|
}
|
|
],
|
|
"$defs": {
|
|
"hexColor": {
|
|
"type": "string",
|
|
"pattern": "^#([0-9a-fA-F]{6}|[0-9a-fA-F]{8})$"
|
|
},
|
|
"sceneBackground": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"image": {
|
|
"type": "string",
|
|
"pattern": "^[a-zA-Z0-9][a-zA-Z0-9._-]{0,120}\\.(png|jpe?g|webp)$"
|
|
},
|
|
"focusX": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
"focusY": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
"safeArea": { "type": "string", "enum": ["left", "right", "center"] },
|
|
"opacity": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
"overlayStrength": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
"paneOpacity": { "type": "number", "minimum": 0, "maximum": 1 }
|
|
}
|
|
},
|
|
"tokenMap": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"bg": { "$ref": "#/$defs/hexColor" },
|
|
"bgSoft": { "$ref": "#/$defs/hexColor" },
|
|
"bgElev": { "$ref": "#/$defs/hexColor" },
|
|
"panel": { "$ref": "#/$defs/hexColor" },
|
|
"sidebar": { "$ref": "#/$defs/hexColor" },
|
|
"chat": { "$ref": "#/$defs/hexColor" },
|
|
"workspace": { "$ref": "#/$defs/hexColor" },
|
|
"workspaceFiles": { "$ref": "#/$defs/hexColor" },
|
|
"border": { "$ref": "#/$defs/hexColor" },
|
|
"borderSoft": { "$ref": "#/$defs/hexColor" },
|
|
"fg": { "$ref": "#/$defs/hexColor" },
|
|
"fgDim": { "$ref": "#/$defs/hexColor" },
|
|
"fgFaint": { "$ref": "#/$defs/hexColor" },
|
|
"accent": { "$ref": "#/$defs/hexColor" },
|
|
"accentFg": { "$ref": "#/$defs/hexColor" },
|
|
"ok": { "$ref": "#/$defs/hexColor" },
|
|
"warn": { "$ref": "#/$defs/hexColor" },
|
|
"err": { "$ref": "#/$defs/hexColor" }
|
|
}
|
|
}
|
|
}
|
|
}
|