mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-25 11:55:47 -06:00
fix(ui): propagate user accent to Talk Mode and widget frames (#128577)
talk.config forwarded only the operator ui.seamColor, so a user-selected ui.prefs.accent never reached the native Talk overlay; it now wins with the same precedence the Control UI applies (regression test fails pre-fix). The widget-theme observer now explicitly watches the <html> style attribute that carries the inline accent override instead of relying on incidental data-theme re-sets.
This commit is contained in:
committed by
GitHub
parent
538791a34c
commit
4dc083dc29
@@ -1118,6 +1118,26 @@ describe("talk.config handler", () => {
|
||||
},
|
||||
);
|
||||
|
||||
it("prefers the user accent over the operator seam color", async () => {
|
||||
markTalkOwnerCold("tts");
|
||||
const runtimeConfig = createTalkConfig("healthy-talk-key");
|
||||
mocks.getSpeechProvider.mockReturnValue({ id: "acme" });
|
||||
mocks.readConfigFileSnapshot.mockResolvedValue({
|
||||
config: { ...runtimeConfig, ui: { seamColor: "#123456", prefs: { accent: "#52c99a" } } },
|
||||
});
|
||||
const respond = vi.fn();
|
||||
|
||||
await callTalkHandler("talk.config", {
|
||||
params: {},
|
||||
client: { connect: { scopes: ["operator.read"] } },
|
||||
respond,
|
||||
context: { getRuntimeConfig: () => runtimeConfig },
|
||||
});
|
||||
|
||||
expect(respond.mock.calls[0]?.[0]).toBe(true);
|
||||
expect(respond.mock.calls[0]?.[1]?.config?.ui).toEqual({ seamColor: "#52c99a" });
|
||||
});
|
||||
|
||||
it("projects the runtime realtime transport when source config is invalid", async () => {
|
||||
mocks.readConfigFileSnapshot.mockResolvedValue({
|
||||
path: "/tmp/openclaw.json",
|
||||
|
||||
@@ -802,7 +802,9 @@ export const talkHandlers: GatewayRequestHandlers = {
|
||||
configPayload.session = { mainKey: sessionMainKey };
|
||||
}
|
||||
|
||||
const seamColor = snapshot.config.ui?.seamColor;
|
||||
// User accent wins over the operator seam color, matching Control UI
|
||||
// precedence (ui.prefs.accent -> ui.seamColor -> theme default).
|
||||
const seamColor = snapshot.config.ui?.prefs?.accent ?? snapshot.config.ui?.seamColor;
|
||||
if (typeof seamColor === "string") {
|
||||
configPayload.ui = { seamColor };
|
||||
}
|
||||
|
||||
@@ -94,6 +94,8 @@ export function installWidgetThemeObserver(): void {
|
||||
}
|
||||
}).observe(root, {
|
||||
attributes: true,
|
||||
attributeFilter: ["data-theme", "data-theme-mode"],
|
||||
// "style" carries the accent override (inline custom properties on <html>);
|
||||
// without it a user accent change would only reach frames incidentally.
|
||||
attributeFilter: ["data-theme", "data-theme-mode", "style"],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ describe("widget theme bridge", () => {
|
||||
document.documentElement,
|
||||
{
|
||||
attributes: true,
|
||||
attributeFilter: ["data-theme", "data-theme-mode"],
|
||||
attributeFilter: ["data-theme", "data-theme-mode", "style"],
|
||||
},
|
||||
);
|
||||
FakeMutationObserver.instances[0]?.trigger({
|
||||
@@ -139,5 +139,12 @@ describe("widget theme bridge", () => {
|
||||
expect(chatPost).toHaveBeenCalledOnce();
|
||||
expect(boardPost).toHaveBeenCalledOnce();
|
||||
expect(unrelatedPost).not.toHaveBeenCalled();
|
||||
// Accent overrides land as inline style mutations on <html>.
|
||||
FakeMutationObserver.instances[0]?.trigger({
|
||||
attributeName: "style",
|
||||
} as MutationRecord);
|
||||
expect(chatPost).toHaveBeenCalledTimes(2);
|
||||
expect(boardPost).toHaveBeenCalledTimes(2);
|
||||
expect(unrelatedPost).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user