authorgravatar for 91240327+shivamhwp@users.noreply.github.comshivam <91240327+shivamhwp@users.noreply.github.com> 2026-10-02 10:34:17+05:30
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-10-02 10:34:17+05:30
log3e60fecf39f37faaca9bdf37e64b7a58229ea547
treeeff937afe5b4895d12c7317065015095bf248749
parent2731929610ecb64617ff5e066980302da328f658
signature Signed by PGP key B5690EEEBB952194

fix(desktop): markdown pages no longer render invisible in the dark-mode browser (#14601)

Co-authored-by: PR Batch Tester <agent@local.test> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

2 files changed, 28 insertions(+), 1 deletions(-)

apps/desktop/src/preview/Manager.test.ts+15-1
...@@ -1601,7 +1601,7 @@ describe("PreviewManager", () => {...@@ -1601,7 +1601,7 @@ describe("PreviewManager", () => {
1601 ),1601 ),
1602 );1602 );
16031603
1604 effectIt.effect("emulates prefers-color-scheme and re-applies it across webview swaps", () =>1604 effectIt.effect("re-applies opaque base and color scheme across webview swaps", () =>
1605 withManager((manager) =>1605 withManager((manager) =>
1606 Effect.gen(function* () {1606 Effect.gen(function* () {
1607 const makeWebContents = (id: number) => {1607 const makeWebContents = (id: number) => {
...@@ -1650,6 +1650,16 @@ describe("PreviewManager", () => {...@@ -1650,6 +1650,16 @@ describe("PreviewManager", () => {
1650 yield* manager.registerWebview("tab_scheme", 42);1650 yield* manager.registerWebview("tab_scheme", 42);
1651 yield* Effect.yieldNow;1651 yield* Effect.yieldNow;
16521652
1653 // Guests start with a transparent base; dark-scheme pages need an opaque
1654 // one or Chromium skips their dark canvas.
1655 const opaqueBase = {
1656 color: { r: 255, g: 255, b: 255, a: 1 },
1657 };
1658 expect(first.sendCommand).toHaveBeenCalledWith(
1659 "Emulation.setDefaultBackgroundColorOverride",
1660 opaqueBase,
1661 );
1662
1653 yield* manager.setColorScheme("tab_scheme", "dark");1663 yield* manager.setColorScheme("tab_scheme", "dark");
16541664
1655 expect(first.sendCommand).toHaveBeenCalledWith("Emulation.setEmulatedMedia", {1665 expect(first.sendCommand).toHaveBeenCalledWith("Emulation.setEmulatedMedia", {
...@@ -1662,6 +1672,10 @@ describe("PreviewManager", () => {...@@ -1662,6 +1672,10 @@ describe("PreviewManager", () => {
1662 yield* manager.registerWebview("tab_scheme", 43);1672 yield* manager.registerWebview("tab_scheme", 43);
1663 yield* Effect.yieldNow;1673 yield* Effect.yieldNow;
16641674
1675 expect(replacement.sendCommand).toHaveBeenCalledWith(
1676 "Emulation.setDefaultBackgroundColorOverride",
1677 opaqueBase,
1678 );
1665 expect(replacement.sendCommand).toHaveBeenCalledWith("Emulation.setEmulatedMedia", {1679 expect(replacement.sendCommand).toHaveBeenCalledWith("Emulation.setEmulatedMedia", {
1666 features: [{ name: "prefers-color-scheme", value: "dark" }],1680 features: [{ name: "prefers-color-scheme", value: "dark" }],
1667 });1681 });
apps/desktop/src/preview/Manager.ts+13
...@@ -1418,6 +1418,19 @@ const makeNativeOperations = Effect.fn("PreviewManager.makeOperations")(function...@@ -1418,6 +1418,19 @@ const makeNativeOperations = Effect.fn("PreviewManager.makeOperations")(function
1418 ),1418 ),
1419 { concurrency: "unbounded", discard: true },1419 { concurrency: "unbounded", discard: true },
1420 );1420 );
1421 // Electron gives `<webview>` guests a transparent base background, and
1422 // Chromium only paints a dark canvas for dark color-scheme pages over an
1423 // opaque base. Without this, dark-scheme pages with no background of
1424 // their own (text/plain, e.g. .md files) render white text on white.
1425 // White matches the webview's existing white backing, so light pages look
1426 // the same; Chromium still swaps in its dark canvas for dark-scheme pages.
1427 yield* attemptPromise(
1428 { operation: "initializeDebugger.defaultBackground", webContentsId: wc.id },
1429 () =>
1430 wcDebugger.sendCommand("Emulation.setDefaultBackgroundColorOverride", {
1431 color: { r: 255, g: 255, b: 255, a: 1 },
1432 }),
1433 );
1421 return [1434 return [
1422 control,1435 control,
1423 replaceMap(sessions, (copy) => {1436 replaceMap(sessions, (copy) => {