diff --git a/public/themes/test.css b/public/themes/test.css deleted file mode 100644 index 9ff6fd742..000000000 --- a/public/themes/test.css +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright 2024, Command Line Inc. - SPDX-License-Identifier: Apache-2.0 */ - -.main-content { - --term-black: #757575; - --term-red: #cc685c; - --term-green: #76c266; - --term-yellow: #cbca9b; - --term-blue: #85aacb; - --term-magenta: #cc72ca; - --term-cyan: #74a7cb; - --term-white: #c1c1c1; - - --term-bright-black: #727272; - --term-bright-red: #cc9d97; - --term-bright-green: #a3dd97; - --term-bright-yellow: #cbcaaa; - --term-bright-blue: #9ab6cb; - --term-bright-magenta: #cc8ecb; - --term-bright-cyan: #b7b8cb; - --term-bright-white: #f0f0f0; - - --term-gray: #8b918a; - --term-cmdtext: #f0f0f0; - --term-foreground: red; - --term-background: #00000000; -} diff --git a/src/app/clientsettings/clientsettings.tsx b/src/app/clientsettings/clientsettings.tsx index 94b1311e3..eea834e39 100644 --- a/src/app/clientsettings/clientsettings.tsx +++ b/src/app/clientsettings/clientsettings.tsx @@ -82,7 +82,6 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove if (currTheme == theme) { return; } - const prtn = GlobalCommandRunner.setMainTermTheme(theme, false); commandRtnHandler(prtn, this.errorMessage); } @@ -207,7 +206,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove const curFontSize = GlobalModel.getTermFontSize(); const curFontFamily = GlobalModel.getTermFontFamily(); const curTheme = GlobalModel.getThemeSource(); - const termThemes = getTermThemes(GlobalModel.termThemes, "Wave Default"); + const termThemes = getTermThemes(GlobalModel.termThemeOptions.get(), "Wave Default"); const currTermTheme = GlobalModel.getTermTheme()["main"] ?? termThemes[0].label; return ( diff --git a/src/app/common/elements/termstyleblock.tsx b/src/app/common/elements/termstyleblock.tsx index c00ab950e..3c7ffeee1 100644 --- a/src/app/common/elements/termstyleblock.tsx +++ b/src/app/common/elements/termstyleblock.tsx @@ -3,7 +3,6 @@ import * as React from "react"; import * as mobxReact from "mobx-react"; -import * as mobx from "mobx"; import { GlobalModel } from "@/models"; const VALID_CSS_VARIABLES = [ @@ -36,8 +35,9 @@ class TermStyleBlock extends React.Component<{ themeName: string; selector: string; }> { - styleRules: OV = mobx.observable.box("", { name: "StyleBlock-styleRules" }); - injectedStyleElement: HTMLStyleElement | null = null; + componentDidUpdate(): void { + GlobalModel.bumpTermRenderVersion(); + } isValidCSSColor(color) { const element = document.createElement("div"); @@ -45,7 +45,7 @@ class TermStyleBlock extends React.Component<{ return element.style.color !== ""; } - isValidTermCSSVariable(key, value) { + isValidTermCSSVariable(key) { const cssVarName = `--term-${key}`; return VALID_CSS_VARIABLES.includes(cssVarName); } @@ -54,50 +54,34 @@ class TermStyleBlock extends React.Component<{ return str.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(); } - removeInjectedStyle() { - if (this.injectedStyleElement) { - document.head.removeChild(this.injectedStyleElement); - this.injectedStyleElement = null; + getStyleRules() { + const { selector, themeName } = this.props; + const termThemeOptions = GlobalModel.getTermThemeOptions(); + if (!termThemeOptions) { + return null; } - } + const theme = termThemeOptions[themeName]; + if (!theme) { + return null; + } + const styleProperties = Object.entries(theme) + // .filter(([key, value]) => { + // const cssVarName = `--term-${this.camelCaseToKebabCase(key)}`; + // return this.isValidTermCSSVariable(cssVarName) && this.isValidCSSColor(value); + // }) + .map(([key, value]) => `--term-${key}: ${value};`) + .join(" "); - loadThemeStyles(selector: string, theme: string) { - // Inject new style element - GlobalModel.getTermThemeJson(theme) - .then((termThemeJson) => { - if (termThemeJson && typeof termThemeJson === "object") { - const styleProperties = Object.entries(termThemeJson) - .filter(([key, value]) => { - const cssVarName = `--term-${this.camelCaseToKebabCase(key)}`; - return VALID_CSS_VARIABLES.includes(cssVarName) && this.isValidCSSColor(value); - }) - .map(([key, value]) => `--term-${key}: ${value};`) - .join(" "); - - const styleRules = `${selector} { ${styleProperties} }`; - - mobx.action(() => { - this.styleRules.set(styleRules); - })(); - - console.log("loaded theme styles:", this.styleRules.get()); - } else { - console.error("termThemeJson is not an object:", termThemeJson); - } - }) - .then(() => { - GlobalModel.bumpTermRenderVersion(); - }) - .catch((error) => { - console.error("error loading theme styles:", error); - }); + if (!styleProperties) { + return null; + } + return `${selector} { ${styleProperties} }`; } render() { - const { themeName, selector } = this.props; - console.log("themeName:", themeName, "selector:", selector); + const styleRules = this.getStyleRules(); - return this.styleRules.get() ? : null; + return styleRules ? : null; } } diff --git a/src/app/common/modals/sessionsettings.tsx b/src/app/common/modals/sessionsettings.tsx index a208353a5..dd238e7da 100644 --- a/src/app/common/modals/sessionsettings.tsx +++ b/src/app/common/modals/sessionsettings.tsx @@ -99,7 +99,7 @@ class SessionSettingsModal extends React.Component<{}, {}> { if (this.session == null) { return null; } - const termThemes = getTermThemes(GlobalModel.termThemes); + const termThemes = getTermThemes(GlobalModel.termThemeOptions.get()); const currTermTheme = GlobalModel.getTermTheme()[this.sessionId] ?? termThemes[0].label; return ( diff --git a/src/app/workspace/workspaceview.tsx b/src/app/workspace/workspaceview.tsx index e686cc714..23d20e487 100644 --- a/src/app/workspace/workspaceview.tsx +++ b/src/app/workspace/workspaceview.tsx @@ -153,7 +153,7 @@ class TabSettings extends React.Component<{ screen: Screen }, {}> { render() { const { screen } = this.props; const rptr = screen.curRemote.get(); - const termThemes = getTermThemes(GlobalModel.termThemes); + const termThemes = getTermThemes(GlobalModel.termThemeOptions.get()); const currTermTheme = GlobalModel.getTermTheme()[screen.screenId] ?? termThemes[0].label; return (
diff --git a/src/models/model.ts b/src/models/model.ts index 3e9ffa9df..261c707b8 100644 --- a/src/models/model.ts +++ b/src/models/model.ts @@ -135,11 +135,10 @@ class Model { renderVersion: OV = mobx.observable.box(0, { name: "renderVersion", }); - appUpdateStatus = mobx.observable.box(getApi().getAppUpdateStatus(), { name: "appUpdateStatus", }); - termThemes: OMap> = mobx.observable.array([], { + termThemeOptions: OV = mobx.observable.box(null, { name: "terminalThemes", deep: false, }); @@ -159,7 +158,6 @@ class Model { this.ws.reconnect(); this.keybindManager = new KeybindManager(this); this.readConfigKeybindings(); - this.fetchTerminalThemes(); this.initSystemKeybindings(); this.initAppKeybindings(); this.inputModel = new InputModel(this); @@ -231,35 +229,6 @@ class Model { } } - fetchTerminalThemes() { - const url = new URL(this.getBaseHostPort() + "/config/terminal-themes"); - fetch(url, { method: "get", body: null, headers: this.getFetchHeaders() }) - .then((resp) => { - if (resp.status == 404) { - return []; - } else if (!resp.ok) { - util.handleNotOkResp(resp, url); - } - return resp.json(); - }) - .then((themes) => { - const tt = themes.map((theme) => theme.name.split(".")[0]); - this.termThemes.replace(tt); - }); - } - - getTermThemeJson(themeFileName: string) { - const url = new URL(this.getBaseHostPort() + `/config/terminal-themes/${themeFileName}.json`); - return fetch(url, { method: "get", body: null, headers: this.getFetchHeaders() }) - .then((resp) => resp.json()) - .then((themeVars: TermThemeType) => { - return themeVars; - }) - .catch((error) => { - console.error(`error applying theme: ${themeFileName}`, error); - }); - } - bumpTermRenderVersion() { mobx.action(() => { this.termRenderVersion.set(this.termRenderVersion.get() + 1); @@ -914,6 +883,16 @@ class Model { } } + setTermThemeOptions(termThemeOptions: TermThemeOptionsType) { + mobx.action(() => { + this.termThemeOptions.set(termThemeOptions); + })(); + } + + getTermThemeOptions(): TermThemeOptionsType { + return this.termThemeOptions.get(); + } + updateScreenStatusIndicators(screenStatusIndicators: ScreenStatusIndicatorUpdateType[]) { for (const update of screenStatusIndicators) { this.getScreenById_single(update.screenid)?.setStatusIndicator(update.status); @@ -1034,6 +1013,9 @@ class Model { } else if (update.userinputrequest != null) { const userInputRequest: UserInputRequest = update.userinputrequest; this.modalsModel.pushModal(appconst.USER_INPUT, userInputRequest); + } else if (update.termthemeoptions != null) { + console.log("got termthemeoptions==============", update.termthemeoptions); + this.setTermThemeOptions(update.termthemeoptions); } else if (update.sessiontombstone != null || update.screentombstone != null) { // nothing (ignore) } else { diff --git a/src/types/custom.d.ts b/src/types/custom.d.ts index 30003e0a2..361d71768 100644 --- a/src/types/custom.d.ts +++ b/src/types/custom.d.ts @@ -379,6 +379,13 @@ declare global { userinputrequest?: UserInputRequest; screentombstone?: any; sessiontombstone?: any; + termthemeoptions?: TermThemeOptionsType; + }; + + type TermThemeOptionsType = { + [key: string]: { + [innerKey: string]: string; + }; }; type HistoryViewDataType = { @@ -582,7 +589,7 @@ declare global { termfontsize: number; termfontfamily: string; theme: NativeThemeSource; - termtheme: TermThemeType; + termthemeconfig: TermThemeType; }; type ConfirmFlagsType = { diff --git a/src/util/themeutil.ts b/src/util/themeutil.ts index ceb93ebe3..a229c1fe4 100644 --- a/src/util/themeutil.ts +++ b/src/util/themeutil.ts @@ -1,10 +1,13 @@ -function getTermThemes(termThemes: string[], noneLabel = "Inherit"): DropdownItem[] { +function getTermThemes(termThemeOptions: string[], noneLabel = "Inherit"): DropdownItem[] { + if (!termThemeOptions) { + return []; + } const tt: DropdownItem[] = []; tt.push({ label: noneLabel, value: null, }); - for (const themeName of termThemes) { + for (const themeName of Object.keys(termThemeOptions)) { tt.push({ label: themeName, value: themeName, diff --git a/wavesrv/pkg/configstore/termthemes.go b/wavesrv/pkg/configstore/termthemes.go index ec357feb1..9075dff59 100644 --- a/wavesrv/pkg/configstore/termthemes.go +++ b/wavesrv/pkg/configstore/termthemes.go @@ -16,7 +16,7 @@ import ( ) const ( - TermThemesTypeStr = "termthemes" + TermThemesTypeStr = "termthemeoptions" TermThemeDir = "config/terminal-themes/" )