forked from 27hrs/dsh-long-skin
fix: sync liang skin theme and dark controls
This commit is contained in:
@@ -65,6 +65,13 @@ interface PreferenceStore {
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
type NativeThemeId = "light" | "dark";
|
||||
|
||||
interface ThemeService {
|
||||
getTheme(): { preference: string };
|
||||
setTheme(id: NativeThemeId): void;
|
||||
}
|
||||
|
||||
interface ModelSelection {
|
||||
provider: string;
|
||||
model: string;
|
||||
@@ -126,6 +133,7 @@ const cssVariables = [
|
||||
|
||||
class SkinPresenter {
|
||||
private readonly scope: PreferenceStore;
|
||||
private readonly theme: ThemeService;
|
||||
private readonly root: HTMLDivElement;
|
||||
private readonly video: HTMLVideoElement;
|
||||
private readonly poster: HTMLImageElement;
|
||||
@@ -138,8 +146,9 @@ class SkinPresenter {
|
||||
private disposed = false;
|
||||
private unsubscribe: () => void;
|
||||
|
||||
constructor(scope: PreferenceStore) {
|
||||
constructor(scope: PreferenceStore, theme: ThemeService) {
|
||||
this.scope = scope;
|
||||
this.theme = theme;
|
||||
this.root = document.createElement("div");
|
||||
this.root.className = "liang-skin-backdrop";
|
||||
this.root.dataset.plugin = PACKAGE_ID;
|
||||
@@ -242,6 +251,7 @@ class SkinPresenter {
|
||||
private applyFrame() {
|
||||
const palette = paletteForFrame(this.frame);
|
||||
const body = document.body;
|
||||
this.syncNativeTheme(palette.stage === 5 ? "dark" : "light");
|
||||
body.dataset.liangStage = String(palette.stage);
|
||||
body.style.setProperty("--liang-strength", String(palette.strength));
|
||||
body.style.setProperty("--liang-page", palette.page);
|
||||
@@ -262,6 +272,11 @@ class SkinPresenter {
|
||||
this.seek(this.frame);
|
||||
}
|
||||
|
||||
syncNativeTheme(theme: NativeThemeId = paletteForFrame(this.frame).stage === 5 ? "dark" : "light") {
|
||||
if (!this.enabled || this.theme.getTheme().preference === theme) return;
|
||||
this.theme.setTheme(theme);
|
||||
}
|
||||
|
||||
private updatePortrait(level: number) {
|
||||
const { lowerIndex, upperIndex, mix } = portraitBlendForLevel(
|
||||
level,
|
||||
@@ -515,6 +530,7 @@ export const inject = [
|
||||
"sessions",
|
||||
"modelDirectories",
|
||||
"locale",
|
||||
"theme",
|
||||
];
|
||||
|
||||
function createPreferenceStore(): PreferenceStore {
|
||||
@@ -558,8 +574,13 @@ export function apply(ctx: ClientContext) {
|
||||
|
||||
const scope = createPreferenceStore();
|
||||
ctx.effect(() => () => scope.dispose(), "liang-intensity-skin: appearance preference");
|
||||
const presenter = new SkinPresenter(scope);
|
||||
const theme = ctx.get("theme") as ThemeService;
|
||||
const presenter = new SkinPresenter(scope, theme);
|
||||
ctx.effect(() => () => presenter.dispose(), "liang-intensity-skin: backdrop presenter");
|
||||
ctx.effect(
|
||||
() => ctx.on("theme/change", () => presenter.syncNativeTheme()),
|
||||
"liang-intensity-skin: native theme synchronization",
|
||||
);
|
||||
|
||||
ctx.effect(() => ctx.locale.register(LOCALE_NAMESPACE, {
|
||||
zh: {
|
||||
|
||||
@@ -100,6 +100,14 @@ body[data-liang-skin="on"] {
|
||||
--dsw-specific-input-major: var(--liang-layer-1) !important;
|
||||
--dsw-specific-menu: var(--liang-layer-3) !important;
|
||||
--dsw-specific-selector: var(--liang-layer-2) !important;
|
||||
--dsw-alias-markdown-citation: var(--liang-layer-2) !important;
|
||||
--dsw-alias-markdown-code-block-banner: var(--liang-layer-1) !important;
|
||||
--dsw-alias-markdown-code-block: var(--liang-layer-1) !important;
|
||||
--dsw-alias-markdown-code-segment-selected: var(--liang-layer-2) !important;
|
||||
--dsw-alias-markdown-code-segment-unselected: var(--liang-layer-1) !important;
|
||||
--dsw-alias-markdown-inline-code: var(--liang-layer-2) !important;
|
||||
--dsw-alias-markdown-placeholder: var(--liang-layer-1) !important;
|
||||
--dsw-alias-markdown-tag: var(--liang-layer-2) !important;
|
||||
background: var(--liang-page) !important;
|
||||
}
|
||||
|
||||
@@ -135,10 +143,85 @@ body[data-liang-skin="on"][data-liang-stage="5"] {
|
||||
--dsw-alias-button-info-fill: #c19a49 !important;
|
||||
--dsw-alias-button-info-hover: #d5b56e !important;
|
||||
--dsw-alias-state-business-primary: #c19a49 !important;
|
||||
--dsw-alias-bg-module-platform: var(--liang-layer-3) !important;
|
||||
--dsw-specific-sidebar-nav-item-active: var(--liang-layer-3) !important;
|
||||
--dsw-specific-sidebar-nav-item-hover: var(--liang-hover) !important;
|
||||
}
|
||||
|
||||
/* Preserve the wordmark badge contrast even when the underlying Harness
|
||||
preference is dark while our low-intensity shell is light. */
|
||||
/* The low-intensity skin is light by default, but it must not turn a dark
|
||||
Harness document into a light surface. Keep the skin's portrait progression
|
||||
while switching the shared UI layers back to a readable charcoal palette. */
|
||||
body[data-liang-skin="on"][data-ds-dark-theme]:is(
|
||||
[data-liang-stage="0"],
|
||||
[data-liang-stage="1"],
|
||||
[data-liang-stage="2"],
|
||||
[data-liang-stage="3"]
|
||||
) {
|
||||
--liang-page: rgb(17 17 17) !important;
|
||||
--liang-bg-base: rgb(17 17 17 / 42%) !important;
|
||||
--liang-layer-1: rgb(30 27 25 / 94%) !important;
|
||||
--liang-layer-2: rgb(41 35 30 / 96%) !important;
|
||||
--liang-layer-3: rgb(41 35 30 / 99%) !important;
|
||||
--liang-sidebar: rgb(23 20 18 / 96%) !important;
|
||||
--liang-ink: rgb(244 241 232) !important;
|
||||
--liang-secondary: rgb(184 180 169) !important;
|
||||
--liang-tertiary: rgb(137 134 126) !important;
|
||||
--liang-border: rgb(244 241 232 / 15%) !important;
|
||||
--liang-hover: rgb(244 241 232 / 9%) !important;
|
||||
--dsw-alias-brand-primary: var(--liang-accent) !important;
|
||||
--dsw-alias-brand-text: var(--liang-accent) !important;
|
||||
--dsw-alias-button-primary-fill: var(--liang-accent) !important;
|
||||
--dsw-alias-button-primary-hover: var(--liang-accent-hover) !important;
|
||||
--dsw-alias-button-info-fill: var(--liang-accent) !important;
|
||||
--dsw-alias-button-info-hover: var(--liang-accent-hover) !important;
|
||||
--dsw-alias-state-business-primary: var(--liang-accent) !important;
|
||||
--dsw-alias-button-elevated-fill: var(--liang-layer-1) !important;
|
||||
--dsw-alias-button-floating-fill: var(--liang-layer-2) !important;
|
||||
--dsw-alias-button-floating-hover: var(--liang-layer-3) !important;
|
||||
--dsw-alias-interactive-bg-hover-solid: var(--liang-layer-2) !important;
|
||||
--dsw-specific-bubble: var(--liang-layer-2) !important;
|
||||
--dsw-specific-input-major: var(--liang-layer-1) !important;
|
||||
--dsw-specific-menu: var(--liang-layer-3) !important;
|
||||
--dsw-specific-selector: var(--liang-layer-2) !important;
|
||||
background: var(--liang-page) !important;
|
||||
}
|
||||
|
||||
body[data-liang-skin="on"][data-ds-dark-theme]:is(
|
||||
[data-liang-stage="0"],
|
||||
[data-liang-stage="1"],
|
||||
[data-liang-stage="2"],
|
||||
[data-liang-stage="3"]
|
||||
) .liang-skin-backdrop {
|
||||
background: var(--liang-page) !important;
|
||||
}
|
||||
|
||||
body[data-liang-skin="on"][data-ds-dark-theme]:is(
|
||||
[data-liang-stage="0"],
|
||||
[data-liang-stage="1"],
|
||||
[data-liang-stage="2"],
|
||||
[data-liang-stage="3"]
|
||||
) .liang-skin-backdrop::after {
|
||||
background: linear-gradient(90deg, var(--liang-page) 0 28%, transparent 57% 100%);
|
||||
}
|
||||
|
||||
/* The host's running-turn label uses a transparent blue shimmer. In the
|
||||
custom dark skin it is a semantic status accent, so keep both the label
|
||||
and its elapsed clock gold without changing the original light theme. */
|
||||
body[data-liang-skin="on"][data-liang-stage="5"] [class*="_turnStatus"] {
|
||||
color: #c19a49 !important;
|
||||
background: #c19a49 !important;
|
||||
background-clip: initial !important;
|
||||
-webkit-background-clip: initial !important;
|
||||
-webkit-text-fill-color: #c19a49 !important;
|
||||
animation: none !important;
|
||||
}
|
||||
|
||||
body[data-liang-skin="on"][data-liang-stage="5"] [class*="_turnStatusClock"] {
|
||||
color: #c19a49 !important;
|
||||
-webkit-text-fill-color: #c19a49 !important;
|
||||
}
|
||||
|
||||
/* Preserve the wordmark badge contrast in the low-intensity shell. */
|
||||
body[data-liang-skin="on"]:is(
|
||||
[data-liang-stage="0"],
|
||||
[data-liang-stage="1"],
|
||||
@@ -219,9 +302,8 @@ body[data-liang-skin="on"] textarea {
|
||||
transition: color 160ms linear, background-color 160ms linear, border-color 160ms linear;
|
||||
}
|
||||
|
||||
/* Harness can itself be in dark mode while the low intensity stages are light.
|
||||
The composer card has a native theme-mode fill, so explicitly bring only
|
||||
those light stages back to the original light surface and readable ink. */
|
||||
/* The composer card has a native theme-mode fill, so keep its surface and
|
||||
readable ink aligned with the active Liang palette. */
|
||||
body[data-liang-skin="on"]:is(
|
||||
[data-liang-stage="0"],
|
||||
[data-liang-stage="1"],
|
||||
|
||||
Reference in New Issue
Block a user