diff --git a/apps/desktop/src/preview/Manager.test.ts b/apps/desktop/src/preview/Manager.test.ts index d3f6971b820b537e826806a0c28b9c4e50711b2b..95197d8916a05e9a29dcc58f01391c856ef245e3 100644 --- a/apps/desktop/src/preview/Manager.test.ts +++ b/apps/desktop/src/preview/Manager.test.ts @@ -1601,7 +1601,7 @@ describe("PreviewManager", () => { ), ); - effectIt.effect("emulates prefers-color-scheme and re-applies it across webview swaps", () => + effectIt.effect("re-applies opaque base and color scheme across webview swaps", () => withManager((manager) => Effect.gen(function* () { const makeWebContents = (id: number) => { @@ -1650,6 +1650,16 @@ describe("PreviewManager", () => { yield* manager.registerWebview("tab_scheme", 42); yield* Effect.yieldNow; + // Guests start with a transparent base; dark-scheme pages need an opaque + // one or Chromium skips their dark canvas. + const opaqueBase = { + color: { r: 255, g: 255, b: 255, a: 1 }, + }; + expect(first.sendCommand).toHaveBeenCalledWith( + "Emulation.setDefaultBackgroundColorOverride", + opaqueBase, + ); + yield* manager.setColorScheme("tab_scheme", "dark"); expect(first.sendCommand).toHaveBeenCalledWith("Emulation.setEmulatedMedia", { @@ -1662,6 +1672,10 @@ describe("PreviewManager", () => { yield* manager.registerWebview("tab_scheme", 43); yield* Effect.yieldNow; + expect(replacement.sendCommand).toHaveBeenCalledWith( + "Emulation.setDefaultBackgroundColorOverride", + opaqueBase, + ); expect(replacement.sendCommand).toHaveBeenCalledWith("Emulation.setEmulatedMedia", { features: [{ name: "prefers-color-scheme", value: "dark" }], }); diff --git a/apps/desktop/src/preview/Manager.ts b/apps/desktop/src/preview/Manager.ts index cc1a8f524dc8a507e238b6eb9499a4e1b25d7dfc..4195bdffff6a6672ff43eed9edae8799036f6cab 100644 --- a/apps/desktop/src/preview/Manager.ts +++ b/apps/desktop/src/preview/Manager.ts @@ -1418,6 +1418,19 @@ const makeNativeOperations = Effect.fn("PreviewManager.makeOperations")(function ), { concurrency: "unbounded", discard: true }, ); + // Electron gives `` guests a transparent base background, and + // Chromium only paints a dark canvas for dark color-scheme pages over an + // opaque base. Without this, dark-scheme pages with no background of + // their own (text/plain, e.g. .md files) render white text on white. + // White matches the webview's existing white backing, so light pages look + // the same; Chromium still swaps in its dark canvas for dark-scheme pages. + yield* attemptPromise( + { operation: "initializeDebugger.defaultBackground", webContentsId: wc.id }, + () => + wcDebugger.sendCommand("Emulation.setDefaultBackgroundColorOverride", { + color: { r: 255, g: 255, b: 255, a: 1 }, + }), + ); return [ control, replaceMap(sessions, (copy) => {