Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import { getGlobalPluginsPath } from "lib/pluginManager/globalPlugins";
import darkTheme from "ui/theme/darkTheme";
import darkThemeWin from "ui/theme/darkThemeWin";
import lightTheme from "ui/theme/lightTheme";
import lightThemeWin from "ui/theme/lightThemeWin";
import { ThemeInterface } from "ui/theme/ThemeInterface";
import glob from "glob";
import { promisify } from "util";
import { join, relative } from "path";
import { readJSON } from "fs-extra";
import { merge, cloneDeep } from "lodash";
const globAsync = promisify(glob);
const themeIds = ["dark", "light"] as const;
type ThemeId = (typeof themeIds)[number];
const themes: Record<ThemeId, ThemeInterface> = {
light: lightTheme,
dark: darkTheme,
};
const windowsThemes: Record<ThemeId, ThemeInterface> = {
light: lightThemeWin,
dark: darkThemeWin,
};
const loadThemePlugin = async (
path: string,
): Promise<(JSON & { name: string; type: unknown }) | null> => {
try {
const theme = await readJSON(path);
Iif (!theme.name) {
throw new Error("Theme is missing name");
}
return theme;
} catch (e) {
console.error("Unable to load theme", e);
}
return null;
};
export class ThemeManager {
systemThemes: Record<ThemeId, ThemeInterface>;
pluginThemes: Record<string, ThemeInterface>;
constructor(platform: string) {
this.systemThemes = platform === "darwin" ? themes : windowsThemes;
this.pluginThemes = {};
}
async loadPluginThemes() {
this.pluginThemes = {};
const globalPluginsPath = getGlobalPluginsPath();
const pluginPaths = await globAsync(
join(globalPluginsPath, "**/theme.json"),
);
for (const path of pluginPaths) {
const theme = await loadThemePlugin(path);
Iif (theme) {
const id = relative(globalPluginsPath, path);
const baseTheme =
theme.type === "dark"
? this.systemThemes.dark
: this.systemThemes.light;
const mergedTheme = merge(cloneDeep(baseTheme), theme);
this.pluginThemes[id] = mergedTheme;
}
}
}
async loadPluginTheme(path: string) {
const globalPluginsPath = getGlobalPluginsPath();
const theme = await loadThemePlugin(path);
Iif (theme) {
const id = relative(globalPluginsPath, path);
const baseTheme =
theme.type === "dark"
? this.systemThemes.dark
: this.systemThemes.light;
const mergedTheme = merge(cloneDeep(baseTheme), theme);
this.pluginThemes[id] = mergedTheme;
return mergedTheme;
}
}
getTheme(themeId: string, systemShouldUseDarkColors: boolean) {
// Use plugin theme if available
const pluginTheme = this.pluginThemes[themeId];
Iif (pluginTheme) {
return pluginTheme;
}
// If light/dark set manually
if (themeId === "light") {
return this.systemThemes[themeId];
} else Iif (themeId === "dark") {
return this.systemThemes[themeId];
}
// Fallback to system theme
Iif (systemShouldUseDarkColors) {
return this.systemThemes["dark"];
}
return this.systemThemes["light"];
}
getPluginThemes() {
return Object.entries(this.pluginThemes).map(([id, theme]) => {
return {
id,
name: theme.name,
};
});
}
}
|