mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-08-16 08:31:57 +02:00
93 lines
2.8 KiB
TypeScript
93 lines
2.8 KiB
TypeScript
import { platform } from "@yaakapp-internal/platform";
|
|
import { setWindowTheme } from "@yaakapp-internal/mac-window";
|
|
import type { ModelPayload } from "@yaakapp-internal/models";
|
|
import type { Appearance } from "@yaakapp-internal/theme";
|
|
import {
|
|
applyThemeToDocument,
|
|
getCSSAppearance,
|
|
subscribeToPreferredAppearanceChange,
|
|
subscribeToSystemAppearanceChange,
|
|
} from "@yaakapp-internal/theme";
|
|
import { getSettings } from "./lib/settings";
|
|
import { getResolvedTheme } from "./lib/themes";
|
|
|
|
// NOTE: CSS appearance isn't as accurate as getting it async from the window (next step), but we want
|
|
// a good appearance guess so we're not waiting too long
|
|
let preferredAppearance: Appearance = getInitialAppearance();
|
|
let linuxSystemAppearanceAvailable =
|
|
platform.osType() === "linux" && window.__YAAK_INITIAL_APPEARANCE_SOURCE__ === "linux-system";
|
|
let configureThemeGeneration = 0;
|
|
let windowShown = false;
|
|
|
|
configureThemeAndShow().catch((err) => console.log("Failed to configure theme", err));
|
|
|
|
subscribeToPreferredAppearanceChange(async (a) => {
|
|
if (linuxSystemAppearanceAvailable) return;
|
|
preferredAppearance = a;
|
|
await configureThemeAndShow();
|
|
});
|
|
|
|
subscribeToSystemAppearanceChange(async (a) => {
|
|
linuxSystemAppearanceAvailable = true;
|
|
preferredAppearance = a;
|
|
await configureThemeAndShow();
|
|
});
|
|
|
|
async function configureThemeAndShow() {
|
|
const applied = await configureTheme();
|
|
if (applied && !windowShown) {
|
|
windowShown = true;
|
|
// To prevent theme flashing, the backend hides new windows by default, so we
|
|
// need to show it here, after configuring the theme for the first time.
|
|
await platform.window.show();
|
|
}
|
|
}
|
|
|
|
// Listen for settings changes, the re-compute theme
|
|
platform.listen<ModelPayload[]>("model_writes", async (payloads) => {
|
|
const relevant = payloads.some(
|
|
(p) =>
|
|
p.change.type === "upsert" &&
|
|
(p.model.model === "settings" || p.model.model === "plugin"),
|
|
);
|
|
if (!relevant) return;
|
|
await configureThemeAndShow();
|
|
});
|
|
|
|
async function configureTheme(): Promise<boolean> {
|
|
const generation = ++configureThemeGeneration;
|
|
const settings = await getSettings();
|
|
const theme = await getResolvedTheme(
|
|
preferredAppearance,
|
|
settings.appearance,
|
|
settings.themeLight,
|
|
settings.themeDark,
|
|
);
|
|
|
|
if (generation !== configureThemeGeneration) {
|
|
return false;
|
|
}
|
|
|
|
applyThemeToDocument(theme.active);
|
|
if (theme.active.base.surface != null) {
|
|
setWindowTheme(theme.active.base.surface);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function getInitialAppearance(): Appearance {
|
|
const initialAppearance = window.__YAAK_INITIAL_APPEARANCE__;
|
|
if (initialAppearance === "dark" || initialAppearance === "light") {
|
|
return initialAppearance;
|
|
}
|
|
return getCSSAppearance();
|
|
}
|
|
|
|
declare global {
|
|
interface Window {
|
|
__YAAK_INITIAL_APPEARANCE__?: Appearance;
|
|
__YAAK_INITIAL_APPEARANCE_SOURCE__?: "settings" | "linux-system";
|
|
}
|
|
}
|