mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-19 21:11:32 +01:00
use themes coming from backend
This commit is contained in:
parent
b10910d229
commit
6b5d2833eb
@ -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;
|
|
||||||
}
|
|
@ -82,7 +82,6 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
|||||||
if (currTheme == theme) {
|
if (currTheme == theme) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const prtn = GlobalCommandRunner.setMainTermTheme(theme, false);
|
const prtn = GlobalCommandRunner.setMainTermTheme(theme, false);
|
||||||
commandRtnHandler(prtn, this.errorMessage);
|
commandRtnHandler(prtn, this.errorMessage);
|
||||||
}
|
}
|
||||||
@ -207,7 +206,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
|||||||
const curFontSize = GlobalModel.getTermFontSize();
|
const curFontSize = GlobalModel.getTermFontSize();
|
||||||
const curFontFamily = GlobalModel.getTermFontFamily();
|
const curFontFamily = GlobalModel.getTermFontFamily();
|
||||||
const curTheme = GlobalModel.getThemeSource();
|
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;
|
const currTermTheme = GlobalModel.getTermTheme()["main"] ?? termThemes[0].label;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import * as mobxReact from "mobx-react";
|
import * as mobxReact from "mobx-react";
|
||||||
import * as mobx from "mobx";
|
|
||||||
import { GlobalModel } from "@/models";
|
import { GlobalModel } from "@/models";
|
||||||
|
|
||||||
const VALID_CSS_VARIABLES = [
|
const VALID_CSS_VARIABLES = [
|
||||||
@ -36,8 +35,9 @@ class TermStyleBlock extends React.Component<{
|
|||||||
themeName: string;
|
themeName: string;
|
||||||
selector: string;
|
selector: string;
|
||||||
}> {
|
}> {
|
||||||
styleRules: OV<string> = mobx.observable.box("", { name: "StyleBlock-styleRules" });
|
componentDidUpdate(): void {
|
||||||
injectedStyleElement: HTMLStyleElement | null = null;
|
GlobalModel.bumpTermRenderVersion();
|
||||||
|
}
|
||||||
|
|
||||||
isValidCSSColor(color) {
|
isValidCSSColor(color) {
|
||||||
const element = document.createElement("div");
|
const element = document.createElement("div");
|
||||||
@ -45,7 +45,7 @@ class TermStyleBlock extends React.Component<{
|
|||||||
return element.style.color !== "";
|
return element.style.color !== "";
|
||||||
}
|
}
|
||||||
|
|
||||||
isValidTermCSSVariable(key, value) {
|
isValidTermCSSVariable(key) {
|
||||||
const cssVarName = `--term-${key}`;
|
const cssVarName = `--term-${key}`;
|
||||||
return VALID_CSS_VARIABLES.includes(cssVarName);
|
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();
|
return str.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
removeInjectedStyle() {
|
getStyleRules() {
|
||||||
if (this.injectedStyleElement) {
|
const { selector, themeName } = this.props;
|
||||||
document.head.removeChild(this.injectedStyleElement);
|
const termThemeOptions = GlobalModel.getTermThemeOptions();
|
||||||
this.injectedStyleElement = null;
|
if (!termThemeOptions) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
const theme = termThemeOptions[themeName];
|
||||||
|
if (!theme) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
const styleProperties = Object.entries(theme)
|
||||||
loadThemeStyles(selector: string, theme: string) {
|
// .filter(([key, value]) => {
|
||||||
// Inject new style element
|
// const cssVarName = `--term-${this.camelCaseToKebabCase(key)}`;
|
||||||
GlobalModel.getTermThemeJson(theme)
|
// return this.isValidTermCSSVariable(cssVarName) && this.isValidCSSColor(value);
|
||||||
.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};`)
|
.map(([key, value]) => `--term-${key}: ${value};`)
|
||||||
.join(" ");
|
.join(" ");
|
||||||
|
|
||||||
const styleRules = `${selector} { ${styleProperties} }`;
|
if (!styleProperties) {
|
||||||
|
return null;
|
||||||
mobx.action(() => {
|
|
||||||
this.styleRules.set(styleRules);
|
|
||||||
})();
|
|
||||||
|
|
||||||
console.log("loaded theme styles:", this.styleRules.get());
|
|
||||||
} else {
|
|
||||||
console.error("termThemeJson is not an object:", termThemeJson);
|
|
||||||
}
|
}
|
||||||
})
|
return `${selector} { ${styleProperties} }`;
|
||||||
.then(() => {
|
|
||||||
GlobalModel.bumpTermRenderVersion();
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error("error loading theme styles:", error);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { themeName, selector } = this.props;
|
const styleRules = this.getStyleRules();
|
||||||
console.log("themeName:", themeName, "selector:", selector);
|
|
||||||
|
|
||||||
return this.styleRules.get() ? <style>{this.styleRules.get()}</style> : null;
|
return styleRules ? <style>{styleRules}</style> : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ class SessionSettingsModal extends React.Component<{}, {}> {
|
|||||||
if (this.session == null) {
|
if (this.session == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const termThemes = getTermThemes(GlobalModel.termThemes);
|
const termThemes = getTermThemes(GlobalModel.termThemeOptions.get());
|
||||||
const currTermTheme = GlobalModel.getTermTheme()[this.sessionId] ?? termThemes[0].label;
|
const currTermTheme = GlobalModel.getTermTheme()[this.sessionId] ?? termThemes[0].label;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -153,7 +153,7 @@ class TabSettings extends React.Component<{ screen: Screen }, {}> {
|
|||||||
render() {
|
render() {
|
||||||
const { screen } = this.props;
|
const { screen } = this.props;
|
||||||
const rptr = screen.curRemote.get();
|
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;
|
const currTermTheme = GlobalModel.getTermTheme()[screen.screenId] ?? termThemes[0].label;
|
||||||
return (
|
return (
|
||||||
<div className="newtab-container">
|
<div className="newtab-container">
|
||||||
|
@ -135,11 +135,10 @@ class Model {
|
|||||||
renderVersion: OV<number> = mobx.observable.box(0, {
|
renderVersion: OV<number> = mobx.observable.box(0, {
|
||||||
name: "renderVersion",
|
name: "renderVersion",
|
||||||
});
|
});
|
||||||
|
|
||||||
appUpdateStatus = mobx.observable.box(getApi().getAppUpdateStatus(), {
|
appUpdateStatus = mobx.observable.box(getApi().getAppUpdateStatus(), {
|
||||||
name: "appUpdateStatus",
|
name: "appUpdateStatus",
|
||||||
});
|
});
|
||||||
termThemes: OMap<string, OMap<string, string>> = mobx.observable.array([], {
|
termThemeOptions: OV<TermThemeOptionsType> = mobx.observable.box(null, {
|
||||||
name: "terminalThemes",
|
name: "terminalThemes",
|
||||||
deep: false,
|
deep: false,
|
||||||
});
|
});
|
||||||
@ -159,7 +158,6 @@ class Model {
|
|||||||
this.ws.reconnect();
|
this.ws.reconnect();
|
||||||
this.keybindManager = new KeybindManager(this);
|
this.keybindManager = new KeybindManager(this);
|
||||||
this.readConfigKeybindings();
|
this.readConfigKeybindings();
|
||||||
this.fetchTerminalThemes();
|
|
||||||
this.initSystemKeybindings();
|
this.initSystemKeybindings();
|
||||||
this.initAppKeybindings();
|
this.initAppKeybindings();
|
||||||
this.inputModel = new InputModel(this);
|
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() {
|
bumpTermRenderVersion() {
|
||||||
mobx.action(() => {
|
mobx.action(() => {
|
||||||
this.termRenderVersion.set(this.termRenderVersion.get() + 1);
|
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[]) {
|
updateScreenStatusIndicators(screenStatusIndicators: ScreenStatusIndicatorUpdateType[]) {
|
||||||
for (const update of screenStatusIndicators) {
|
for (const update of screenStatusIndicators) {
|
||||||
this.getScreenById_single(update.screenid)?.setStatusIndicator(update.status);
|
this.getScreenById_single(update.screenid)?.setStatusIndicator(update.status);
|
||||||
@ -1034,6 +1013,9 @@ class Model {
|
|||||||
} else if (update.userinputrequest != null) {
|
} else if (update.userinputrequest != null) {
|
||||||
const userInputRequest: UserInputRequest = update.userinputrequest;
|
const userInputRequest: UserInputRequest = update.userinputrequest;
|
||||||
this.modalsModel.pushModal(appconst.USER_INPUT, 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) {
|
} else if (update.sessiontombstone != null || update.screentombstone != null) {
|
||||||
// nothing (ignore)
|
// nothing (ignore)
|
||||||
} else {
|
} else {
|
||||||
|
9
src/types/custom.d.ts
vendored
9
src/types/custom.d.ts
vendored
@ -379,6 +379,13 @@ declare global {
|
|||||||
userinputrequest?: UserInputRequest;
|
userinputrequest?: UserInputRequest;
|
||||||
screentombstone?: any;
|
screentombstone?: any;
|
||||||
sessiontombstone?: any;
|
sessiontombstone?: any;
|
||||||
|
termthemeoptions?: TermThemeOptionsType;
|
||||||
|
};
|
||||||
|
|
||||||
|
type TermThemeOptionsType = {
|
||||||
|
[key: string]: {
|
||||||
|
[innerKey: string]: string;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
type HistoryViewDataType = {
|
type HistoryViewDataType = {
|
||||||
@ -582,7 +589,7 @@ declare global {
|
|||||||
termfontsize: number;
|
termfontsize: number;
|
||||||
termfontfamily: string;
|
termfontfamily: string;
|
||||||
theme: NativeThemeSource;
|
theme: NativeThemeSource;
|
||||||
termtheme: TermThemeType;
|
termthemeconfig: TermThemeType;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ConfirmFlagsType = {
|
type ConfirmFlagsType = {
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
function getTermThemes(termThemes: string[], noneLabel = "Inherit"): DropdownItem[] {
|
function getTermThemes(termThemeOptions: string[], noneLabel = "Inherit"): DropdownItem[] {
|
||||||
|
if (!termThemeOptions) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
const tt: DropdownItem[] = [];
|
const tt: DropdownItem[] = [];
|
||||||
tt.push({
|
tt.push({
|
||||||
label: noneLabel,
|
label: noneLabel,
|
||||||
value: null,
|
value: null,
|
||||||
});
|
});
|
||||||
for (const themeName of termThemes) {
|
for (const themeName of Object.keys(termThemeOptions)) {
|
||||||
tt.push({
|
tt.push({
|
||||||
label: themeName,
|
label: themeName,
|
||||||
value: themeName,
|
value: themeName,
|
||||||
|
@ -16,7 +16,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TermThemesTypeStr = "termthemes"
|
TermThemesTypeStr = "termthemeoptions"
|
||||||
TermThemeDir = "config/terminal-themes/"
|
TermThemeDir = "config/terminal-themes/"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user