fix terminal theming when applying global defaults #1287 (#1332)

This commit is contained in:
Mike Sawka 2024-11-21 10:44:16 -08:00 committed by GitHub
parent 9bbe87f617
commit b2b9432a7a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 48 additions and 61 deletions

View file

@ -25,6 +25,7 @@ New minor release that introduces Wave's connected computing extensions. We've i
- [bugfix] Presets directory was not loading correctly on Windows
- [bugfix] Magnified blocks were not showing correct on startup
- [bugfix] Window opacity and background color was not getting applied properly in all cases
- [bugfix] Fix terminal theming when applying global defaults [#1287](https://github.com/wavetermdev/waveterm/issues/1287)
- MacOS 10.15 (Catalina) is no longer supported
- Other bug fixes, docs improvements, and dependency bumps

View file

@ -246,7 +246,7 @@ function useBlockMetaKeyAtom<T extends keyof MetaType>(blockId: string, key: T):
const settingsAtomCache = new Map<string, Atom<any>>();
function makeOverrideConfigAtom<T extends keyof SettingsType>(blockId: string, key: T): Atom<SettingsType[T]> {
function getOverrideConfigAtom<T extends keyof SettingsType>(blockId: string, key: T): Atom<SettingsType[T]> {
const blockCache = getSingleBlockAtomCache(blockId);
const overrideAtomName = "#settingsoverride-" + key;
let overrideAtom = blockCache.get(overrideAtomName);
@ -271,7 +271,7 @@ function makeOverrideConfigAtom<T extends keyof SettingsType>(blockId: string, k
}
function useOverrideConfigAtom<T extends keyof SettingsType>(blockId: string, key: T): SettingsType[T] {
return useAtomValue(makeOverrideConfigAtom(blockId, key));
return useAtomValue(getOverrideConfigAtom(blockId, key));
}
function getSettingsKeyAtom<T extends keyof SettingsType>(key: T): Atom<SettingsType[T]> {
@ -636,6 +636,7 @@ export {
getConnStatusAtom,
getHostName,
getObjectId,
getOverrideConfigAtom,
getSettingsKeyAtom,
getUserName,
globalStore,
@ -643,7 +644,6 @@ export {
initGlobalWaveEventSubs,
isDev,
loadConnStatus,
makeOverrideConfigAtom,
openLink,
PLATFORM,
pushFlashError,

View file

@ -11,14 +11,16 @@ import { DefaultRouter, TabRpcClient } from "@/app/store/wshrpcutil";
import { TermWshClient } from "@/app/view/term/term-wsh";
import { VDomModel } from "@/app/view/vdom/vdom-model";
import {
WOS,
atoms,
getBlockComponentModel,
getBlockMetaKeyAtom,
getConnStatusAtom,
getOverrideConfigAtom,
getSettingsKeyAtom,
globalStore,
useBlockAtom,
useSettingsPrefixAtom,
WOS,
} from "@/store/global";
import * as services from "@/store/services";
import * as keyutil from "@/util/keyutil";
@ -28,7 +30,7 @@ import * as jotai from "jotai";
import * as React from "react";
import { TermStickers } from "./termsticker";
import { TermThemeUpdater } from "./termtheme";
import { computeTheme } from "./termutil";
import { computeTheme, DefaultTermTheme } from "./termutil";
import { TermWrap } from "./termwrap";
import "./xterm.css";
@ -138,16 +140,17 @@ class TermViewModel {
}
return true;
});
this.termThemeNameAtom = useBlockAtom(blockId, "termthemeatom", () => {
return jotai.atom<string>((get) => {
return get(getOverrideConfigAtom(this.blockId, "term:theme")) ?? DefaultTermTheme;
});
});
this.blockBg = jotai.atom((get) => {
const blockData = get(this.blockAtom);
const fullConfig = get(atoms.fullConfigAtom);
let themeName: string = get(getSettingsKeyAtom("term:theme"));
if (blockData?.meta?.["term:theme"]) {
themeName = blockData.meta["term:theme"];
}
const theme = computeTheme(fullConfig, themeName);
if (theme != null && theme.background != null) {
return { bg: theme.background };
const themeName = get(this.termThemeNameAtom);
const [_, bgcolor] = computeTheme(fullConfig, themeName);
if (bgcolor != null) {
return { bg: bgcolor };
}
return null;
});
@ -169,13 +172,6 @@ class TermViewModel {
return rtnFontSize;
});
});
this.termThemeNameAtom = useBlockAtom(blockId, "termthemeatom", () => {
return jotai.atom<string>((get) => {
const blockData = get(this.blockAtom);
const settingsKeyAtom = getSettingsKeyAtom("term:theme");
return blockData?.meta?.["term:theme"] ?? get(settingsKeyAtom) ?? "default-dark";
});
});
this.noPadding = jotai.atom(true);
this.endIconButtons = jotai.atom((get) => {
const blockData = get(this.blockAtom);
@ -329,7 +325,7 @@ class TermViewModel {
const fullConfig = globalStore.get(atoms.fullConfigAtom);
const termThemes = fullConfig?.termthemes ?? {};
const termThemeKeys = Object.keys(termThemes);
const curThemeName = globalStore.get(this.termThemeNameAtom);
const curThemeName = globalStore.get(getBlockMetaKeyAtom(this.blockId, "term:theme"));
const defaultFontSize = globalStore.get(getSettingsKeyAtom("term:fontsize")) ?? 12;
const blockData = globalStore.get(this.blockAtom);
const overrideFontSize = blockData?.meta?.["term:fontsize"];
@ -346,6 +342,12 @@ class TermViewModel {
click: () => this.setTerminalTheme(themeName),
};
});
submenu.unshift({
label: "Default",
type: "checkbox",
checked: curThemeName == null,
click: () => this.setTerminalTheme(null),
});
const fontSizeSubMenu: ContextMenuItem[] = [6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18].map(
(fontSize: number) => {
return {
@ -551,9 +553,8 @@ const TerminalView = ({ blockId, model }: TerminalViewProps) => {
React.useEffect(() => {
const fullConfig = globalStore.get(atoms.fullConfigAtom);
const termTheme = computeTheme(fullConfig, blockData?.meta?.["term:theme"]);
const themeCopy = { ...termTheme };
themeCopy.background = "#00000000";
const termThemeName = globalStore.get(model.termThemeNameAtom);
const [termTheme, _] = computeTheme(fullConfig, termThemeName);
let termScrollback = 1000;
if (termSettings?.["term:scrollback"]) {
termScrollback = Math.floor(termSettings["term:scrollback"]);
@ -572,7 +573,7 @@ const TerminalView = ({ blockId, model }: TerminalViewProps) => {
blockId,
connectElemRef.current,
{
theme: themeCopy,
theme: termTheme,
fontSize: termFontSize,
fontFamily: termSettings?.["term:fontfamily"] ?? "Hack",
drawBoldTextInBrightColors: false,
@ -650,7 +651,7 @@ const TerminalView = ({ blockId, model }: TerminalViewProps) => {
return (
<div className={clsx("view-term", "term-mode-" + termMode)} ref={viewRef}>
<TermResyncHandler blockId={blockId} model={model} />
<TermThemeUpdater blockId={blockId} termRef={termRef} />
<TermThemeUpdater blockId={blockId} model={model} termRef={termRef} />
<TermStickers config={stickerConfig} />
<TermToolbarVDomNode key="vdom-toolbar" blockId={blockId} model={model} />
<TermVDomNode key="vdom" blockId={blockId} model={model} />
@ -659,4 +660,4 @@ const TerminalView = ({ blockId, model }: TerminalViewProps) => {
);
};
export { TermViewModel, TerminalView, makeTerminalModel };
export { makeTerminalModel, TerminalView, TermViewModel };

View file

@ -1,41 +1,28 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
import { TermViewModel } from "@/app/view/term/term";
import { computeTheme } from "@/app/view/term/termutil";
import { TermWrap } from "@/app/view/term/termwrap";
import { atoms, WOS } from "@/store/global";
import * as util from "@/util/util";
import { atoms } from "@/store/global";
import { useAtomValue } from "jotai";
import { useEffect } from "react";
interface TermThemeProps {
blockId: string;
termRef: React.RefObject<TermWrap>;
model: TermViewModel;
}
const TermThemeUpdater = ({ blockId, termRef }: TermThemeProps) => {
const TermThemeUpdater = ({ blockId, model, termRef }: TermThemeProps) => {
const fullConfig = useAtomValue(atoms.fullConfigAtom);
const termthemes = fullConfig?.termthemes;
const [blockData] = WOS.useWaveObjectValue<Block>(WOS.makeORef("block", blockId));
let defaultThemeName = "default-dark";
let themeName = blockData.meta?.["term:theme"] ?? "default-dark";
const defaultTheme: TermThemeType = termthemes?.[defaultThemeName] || ({} as any);
const theme: TermThemeType = termthemes?.[themeName] || ({} as any);
const blockTermTheme = useAtomValue(model.termThemeNameAtom);
const [theme, _] = computeTheme(fullConfig, blockTermTheme);
useEffect(() => {
const combinedTheme = { ...defaultTheme };
for (const key in theme) {
if (!util.isBlank(theme[key])) {
combinedTheme[key] = theme[key];
}
}
if (termRef.current?.terminal) {
let themeCopy = { ...combinedTheme };
themeCopy.background = "#00000000";
termRef.current.terminal.options.theme = themeCopy;
termRef.current.terminal.options.theme = theme;
}
}, [defaultTheme, theme]);
}, [theme]);
return null;
};

View file

@ -1,20 +1,18 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
import * as util from "@/util/util";
export const DefaultTermTheme = "default-dark";
function computeTheme(fullConfig: FullConfigType, themeName: string): TermThemeType {
let defaultThemeName = "default-dark";
themeName = themeName ?? "default-dark";
const defaultTheme: TermThemeType = fullConfig?.termthemes?.[defaultThemeName] || ({} as any);
const theme: TermThemeType = fullConfig?.termthemes?.[themeName] || ({} as any);
const combinedTheme = { ...defaultTheme };
for (const key in theme) {
if (!util.isBlank(theme[key])) {
combinedTheme[key] = theme[key];
}
// returns (theme, bgcolor)
function computeTheme(fullConfig: FullConfigType, themeName: string): [TermThemeType, string] {
let theme: TermThemeType = fullConfig?.termthemes?.[themeName];
if (theme == null) {
theme = fullConfig?.termthemes?.[DefaultTermTheme] || ({} as any);
}
return combinedTheme;
const themeCopy = { ...theme };
let bgcolor = themeCopy.background;
themeCopy.background = "#00000000";
return [themeCopy, bgcolor];
}
export { computeTheme };