Theme switching (#361)

* init

* init

* theme override mechanism by changing href value in header link tag

* remove debugging code

* remove debugging code. no need to force rerender

* remove overrides.less

* get some light colors showing in light theme
This commit is contained in:
Red J Adaya 2024-03-01 16:01:23 +08:00 committed by GitHub
parent 402c8c2485
commit b5d481734f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 152 additions and 140 deletions

View File

@ -11,6 +11,8 @@
<link rel="stylesheet" href="public/fontawesome/css/sharp-solid.min.css"> <link rel="stylesheet" href="public/fontawesome/css/sharp-solid.min.css">
<link rel="stylesheet" href="public/fontawesome/css/sharp-regular.min.css"> <link rel="stylesheet" href="public/fontawesome/css/sharp-regular.min.css">
<link rel="stylesheet" href="dist-dev/waveterm.css" /> <link rel="stylesheet" href="dist-dev/waveterm.css" />
<link rel="stylesheet" id="theme-stylesheet" href="public/themes/default.css">
</head> </head>
<body> <body>
<div id="measure"></div> <div id="measure"></div>

View File

@ -11,6 +11,8 @@
<link rel="stylesheet" href="public/fontawesome/css/sharp-solid.min.css"> <link rel="stylesheet" href="public/fontawesome/css/sharp-solid.min.css">
<link rel="stylesheet" href="public/fontawesome/css/sharp-regular.min.css"> <link rel="stylesheet" href="public/fontawesome/css/sharp-regular.min.css">
<link rel="stylesheet" href="dist/waveterm.css" /> <link rel="stylesheet" href="dist/waveterm.css" />
<link rel="stylesheet" id="theme-stylesheet" href="public/themes/default.css" />
</head> </head>
<body> <body>
<div id="measure"></div> <div id="measure"></div>

View File

@ -1,18 +1,18 @@
// Copyright 2024, Command Line Inc. /* Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0 */
:root { :root {
--fa-style-family: "Font Awesome 6 Sharp"; --fa-style-family: "Font Awesome 6 Sharp";
// these variables are overridden by user settings /* these variables are overridden by user settings */
--termfontfamily: "JetBrains Mono", monospace; --termfontfamily: "JetBrains Mono", monospace;
--termfontsize: 12px; --termfontsize: 12px;
--termlineheight: 15px; --termlineheight: 15px;
--termpad: 7px; // padding value (scaled to termfontsize) --termpad: 7px; /* padding value (scaled to termfontsize) */
--termfontsize-sm: 10px; --termfontsize-sm: 10px;
--termlineheight-sm: 13px; --termlineheight-sm: 13px;
// other fonts /* other fonts */
--base-font-family: "Lato", sans-serif; --base-font-family: "Lato", sans-serif;
--base-font-size: 15px; --base-font-size: 15px;
--base-font-weight: normal; --base-font-weight: normal;
@ -29,19 +29,19 @@
--markdown-font-size: 14px; --markdown-font-size: 14px;
--screentabs-height: 38px; // magic --screentabs-height: 38px; /* magic */
--screentabs-line-height: 21px; // magic --screentabs-line-height: 21px; /* magic */
--screentabs-font-size: 15px; --screentabs-font-size: 15px;
--screentabs-font-weight: normal; --screentabs-font-weight: normal;
--screentabs-selected-font-weight: bold; --screentabs-selected-font-weight: bold;
--screen-tab-width: 11.4em; --screen-tab-width: 11.4em;
// floating logo settings /* floating logo settings */
--floating-logo-width-darwin: 110px; --floating-logo-width-darwin: 110px;
--floating-logo-width: 40px; --floating-logo-width: 40px;
--floating-logo-height: var(--screentabs-height); --floating-logo-height: var(--screentabs-height);
// global colors /* global colors */
--app-bg-color: black; --app-bg-color: black;
--app-accent-color: rgb(88, 193, 66); --app-accent-color: rgb(88, 193, 66);
--app-error-color: rgb(204, 0, 0); --app-error-color: rgb(204, 0, 0);
@ -56,19 +56,19 @@
--app-panel-bg-color: rgba(21, 23, 21, 1); --app-panel-bg-color: rgba(21, 23, 21, 1);
--app-panel-bg-color-dev: rgb(21, 23, 48); --app-panel-bg-color-dev: rgb(21, 23, 48);
// global generic colors /* global generic colors */
--app-black: rgb(0, 0, 0); --app-black: rgb(0, 0, 0);
// scrollbar colors /* scrollbar colors */
// --scrollbar-background-color: rgba(21, 23, 21, 1); /* --scrollbar-background-color: rgba(21, 23, 21, 1); */
--scrollbar-background-color: #030303; --scrollbar-background-color: #030303;
--scrollbar-thumb-color: #333; --scrollbar-thumb-color: #333;
--scrollbar-thumb-hover-color: rgb(211, 215, 207); --scrollbar-thumb-hover-color: rgb(211, 215, 207);
// code color /* code color */
--pre-bg-color: rgb(0, 0, 0); --pre-bg-color: rgb(0, 0, 0);
// tab colors /* tab colors */
--tab-red: rgb(229, 77, 46); --tab-red: rgb(229, 77, 46);
--tab-orange: rgb(239, 113, 59); --tab-orange: rgb(239, 113, 59);
--tab-yellow: rgb(224, 185, 86); --tab-yellow: rgb(224, 185, 86);
@ -80,7 +80,7 @@
--tab-pink: rgb(224, 86, 119); --tab-pink: rgb(224, 86, 119);
--tab-white: rgb(255, 255, 255); --tab-white: rgb(255, 255, 255);
// term colors /* term colors */
--term-black: #000000; --term-black: #000000;
--term-red: #cc0000; --term-red: #cc0000;
--term-green: #4e9a06; --term-green: #4e9a06;
@ -97,80 +97,78 @@
--term-bright-magenta: #ad7fa8; --term-bright-magenta: #ad7fa8;
--term-bright-cyan: #34e2e2; --term-bright-cyan: #34e2e2;
--term-bright-white: #ffffff; --term-bright-white: #ffffff;
--term-gray: rgb(139, 145, 138); // not an official terminal color --term-gray: rgb(139, 145, 138); /* not an official terminal color */
// button colors /* button colors */
--button-text-color: rgb(255, 255, 255); --button-text-color: rgb(255, 255, 255);
--button-primary-bg-color: rgb(78, 154, 6); --button-primary-bg-color: rgb(78, 154, 6);
--button-secondary-bg-color: rgba(255, 255, 255, 0.09); --button-secondary-bg-color: rgba(255, 255, 255, 0.09);
--button-warning-bg-color: rgb(204, 0, 0); --button-warning-bg-color: rgb(204, 0, 0);
// input colors /* input colors */
--checkbox-text-color: rgb(255, 255, 255); --checkbox-text-color: rgb(255, 255, 255);
--checkbox-bg-color: rgb(78, 154, 6); --checkbox-bg-color: rgb(78, 154, 6);
--checkbox-check-color: rgb(255, 255, 255); --checkbox-check-color: rgb(255, 255, 255);
// dropdown colors /* dropdown colors */
--dropdown-text-color: rgb(211, 215, 207); --dropdown-text-color: rgb(211, 215, 207);
--dropdown-error-color: rgb(229, 77, 46); --dropdown-error-color: rgb(229, 77, 46);
--dropdown-focus-color: rgb(78, 154, 6); --dropdown-focus-color: rgb(78, 154, 6);
// textfield colors /* textfield colors */
--textfield-focused-border-color: rgb(78, 154, 6); --textfield-focused-border-color: rgb(78, 154, 6);
--textfield-error-border-color: rgb(229, 77, 46); --textfield-error-border-color: rgb(229, 77, 46);
--textfield-label-color: rgb(195, 200, 194); --textfield-label-color: rgb(195, 200, 194);
--textfield-text-color: rgb(255, 255, 255); --textfield-text-color: rgb(255, 255, 255);
--textfield-bg-color: rgba(48, 49, 48, 0.6); --textfield-bg-color: rgba(48, 49, 48, 0.6);
// toggle colors /* toggle colors */
--toggle-bg-color: rgb(51, 51, 51); --toggle-bg-color: rgb(51, 51, 51);
--toggle-thumb-color: rgb(211, 215, 207); --toggle-thumb-color: rgb(211, 215, 207);
--toggle-checked-bg-color: rgb(78, 154, 6); --toggle-checked-bg-color: rgb(78, 154, 6);
// cmdstrcode colors /* cmdstrcode colors */
--cmdstrcode-bg-color: rgb(0, 0, 0); --cmdstrcode-bg-color: rgb(0, 0, 0);
--cmdstrcode-text-color: rgb(211, 215, 207); --cmdstrcode-text-color: rgb(211, 215, 207);
// markdown colors /* markdown colors */
--markdown-bg-color: rgb(35, 35, 35); --markdown-bg-color: rgb(35, 35, 35);
--markdown-outline-color: rgb(78, 154, 6); --markdown-outline-color: rgb(78, 154, 6);
// status(remote) colors /* status(remote) colors */
// todo: all status colors must be unified /* todo: all status colors must be unified */
--status-connected-color: rgb(70, 167, 88); --status-connected-color: rgb(70, 167, 88);
--status-connecting-color: rgb(245, 217, 10); --status-connecting-color: rgb(245, 217, 10);
--status-error-color: rgb(229, 77, 46); --status-error-color: rgb(229, 77, 46);
--status-disconnected-color: rgb(195, 200, 194); --status-disconnected-color: rgb(195, 200, 194);
// status indicator colors /* status indicator colors */
// todo: all status colors must be unified /* todo: all status colors must be unified */
--status-indicator-color: rgb(211, 215, 207); --status-indicator-color: rgb(211, 215, 207);
--status-indicator-error: rgb(204, 0, 0); --status-indicator-error: rgb(204, 0, 0);
--status-indicator-success: rgb(78, 154, 6); --status-indicator-success: rgb(78, 154, 6);
// status(version) colors /* status(version) colors */
// todo: all status colors must be unified /* todo: all status colors must be unified */
--status-outdated-color: rgb(196, 160, 0); --status-outdated-color: rgb(196, 160, 0);
--status-updated-color: rgb(78, 154, 6); --status-updated-color: rgb(78, 154, 6);
// term status colors /* term status colors */
// todo: all status colors must be unified /* todo: all status colors must be unified */
--term-error-color: rgb(204, 0, 0); --term-error-color: rgb(204, 0, 0);
--term-warning-color: rgb(196, 160, 0); --term-warning-color: rgb(196, 160, 0);
// hotkey colors /* hotkey colors */
--hotkey-text-color: rgb(195, 200, 194); --hotkey-text-color: rgb(195, 200, 194);
// sidebar colors /* sidebar colors */
--sidebar-settings-color: rgb(255, 255, 255);
--sidebar-separator-color: var(--app-border-color);
--sidebar-highlight-color: rgba(241, 246, 243, 0.08); --sidebar-highlight-color: rgba(241, 246, 243, 0.08);
--sidebar-font-size: 15px; --sidebar-font-size: 15px;
--sidebar-line-height: 1.5; --sidebar-line-height: 1.5;
--sidebar-font-weight: normal; --sidebar-font-weight: normal;
--sidebar-highlight-font-weight: bold; --sidebar-highlight-font-weight: bold;
// line colors /* line colors */
--line-sidebar-message-color: rgb(196, 160, 0); --line-sidebar-message-color: rgb(196, 160, 0);
--line-background: rgba(21, 23, 21, 1); --line-background: rgba(21, 23, 21, 1);
--line-avatar-color: #eceeec; --line-avatar-color: #eceeec;
@ -199,21 +197,21 @@
--line-actions-inactive-color: rgba(255, 255, 255, 0.5); --line-actions-inactive-color: rgba(255, 255, 255, 0.5);
--line-actions-active-color: rgba(255, 255, 255, 1); --line-actions-active-color: rgba(255, 255, 255, 1);
// view colors /* view colors */
// todo: bookmarks is a view, colors must be unified with --view* colors /* todo: bookmarks is a view, colors must be unified with --view* colors */
--bookmarks-text-color: rgb(211, 215, 207); --bookmarks-text-color: rgb(211, 215, 207);
--bookmarks-textarea-bg-color: rgb(0, 0, 0); --bookmarks-textarea-bg-color: rgb(0, 0, 0);
--bookmarks-disabled-text-color: rgb(173, 173, 173); --bookmarks-disabled-text-color: rgb(173, 173, 173);
--bookmarks-control-hover-color: rgb(255, 255, 255); --bookmarks-control-hover-color: rgb(255, 255, 255);
// view colors /* view colors */
--view-error-color: rgb(204, 0, 0); --view-error-color: rgb(204, 0, 0);
--view-text-color: rgb(195, 200, 194); --view-text-color: rgb(195, 200, 194);
// session colors /* session colors */
--session-bg-color: rgba(13, 13, 13, 0.85); --session-bg-color: rgba(13, 13, 13, 0.85);
// cmdinput colors /* cmdinput colors */
--cmdinput-textarea-bg-color: #171717; --cmdinput-textarea-bg-color: #171717;
--cmdinput-text-error-color: rgb(239, 41, 41); --cmdinput-text-error-color: rgb(239, 41, 41);
--cmdinput-title-color: rgb(114, 159, 207); --cmdinput-title-color: rgb(114, 159, 207);
@ -225,9 +223,9 @@
--cmdinput-disabled-icon-color: rgb(76, 81, 75, 1); --cmdinput-disabled-icon-color: rgb(76, 81, 75, 1);
--cmdinput-history-bg-color: rgb(21, 23, 21, 1); --cmdinput-history-bg-color: rgb(21, 23, 21, 1);
// screen view color /* screen view color */
--screen-view-text-caption-color: rgb(139, 145, 138); --screen-view-text-caption-color: rgb(139, 145, 138);
// plugins colors /* plugins colors */
--code-gutter-bg-color: rgba(88, 193, 66, 0.4); --code-gutter-bg-color: rgba(88, 193, 66, 0.4);
} }

16
public/themes/light.css Normal file
View File

@ -0,0 +1,16 @@
/* Copyright 2024, Command Line Inc.
SPDX-License-Identifier: Apache-2.0 */
@import "./default.css";
:root {
--app-bg-color: #ffffff;
--app-text-color: #000000;
/* sidebar colors */
--app-panel-bg-color: #cccccc;
--app-panel-bg-color-dev: #eeeeff;
--term-black: #ffffff;
--term-white: #000000;
}

View File

@ -1,9 +1,6 @@
// Copyright 2024, Command Line Inc. // Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
@import "./root.less";
@import "./overrides.less";
html, html,
body { body {
overflow: hidden; overflow: hidden;

View File

@ -27,6 +27,7 @@ export const DevServerEndpoint = "http://127.0.0.1:8090";
export const DevServerWsEndpoint = "ws://127.0.0.1:8091"; export const DevServerWsEndpoint = "ws://127.0.0.1:8091";
export const DefaultTermFontSize = 12; export const DefaultTermFontSize = 12;
export const DefaultTermFontFamily = "JetBrains Mono"; export const DefaultTermFontFamily = "JetBrains Mono";
export const DefaultTheme = "dark";
export const MinFontSize = 8; export const MinFontSize = 8;
export const MaxFontSize = 24; export const MaxFontSize = 24;
export const InputChunkSize = 500; export const InputChunkSize = 500;

View File

@ -44,6 +44,15 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
commandRtnHandler(prtn, this.errorMessage); commandRtnHandler(prtn, this.errorMessage);
} }
@boundMethod
handleChangeTheme(theme: string): void {
if (GlobalModel.getTheme() == theme) {
return;
}
const prtn = GlobalCommandRunner.setTheme(theme, false);
commandRtnHandler(prtn, this.errorMessage);
}
@boundMethod @boundMethod
handleChangeTelemetry(val: boolean): void { handleChangeTelemetry(val: boolean): void {
let prtn: Promise<CommandRtnType> = null; let prtn: Promise<CommandRtnType> = null;
@ -82,6 +91,13 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
return availableFontFamilies; return availableFontFamilies;
} }
getThemes(): DropdownItem[] {
const themes: DropdownItem[] = [];
themes.push({ label: "Dark", value: "dark" });
themes.push({ label: "Light", value: "light" });
return themes;
}
@boundMethod @boundMethod
inlineUpdateOpenAIModel(newModel: string): void { inlineUpdateOpenAIModel(newModel: string): void {
const prtn = GlobalCommandRunner.setClientOpenAISettings({ model: newModel }); const prtn = GlobalCommandRunner.setClientOpenAISettings({ model: newModel });
@ -148,6 +164,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.getTheme();
return ( return (
<MainView viewName="clientsettings" title="Client Settings" onClose={this.handleClose}> <MainView viewName="clientsettings" title="Client Settings" onClose={this.handleClose}>
@ -174,6 +191,17 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
/> />
</div> </div>
</div> </div>
<div className="settings-field">
<div className="settings-label">Theme</div>
<div className="settings-input">
<Dropdown
className="theme-dropdown"
options={this.getThemes()}
defaultValue={curTheme}
onChange={this.handleChangeTheme}
/>
</div>
</div>
<div className="settings-field"> <div className="settings-field">
<div className="settings-label">Client ID</div> <div className="settings-label">Client ID</div>
<div className="settings-input">{cdata.clientid}</div> <div className="settings-input">{cdata.clientid}</div>

View File

@ -1,86 +0,0 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
@base-color: #eceeec;
@base-background: rgba(21, 23, 21, 1);
@base-background-transparent: rgba(15, 17, 15, 0.7);
@base-background-dev: rgba(21, 23, 48, 1);
@base-border: rgba(241, 246, 243, 0.08);
@background-session: rgba(13, 13, 13, 0.85);
@background-session-components: rgba(48, 49, 48, 0.6);
@background-session-components-solid: rgb(33, 34, 33);
@wave-green: rgb(88, 193, 66);
@disabled-background: rgba(76, 81, 75, 1);
@disabled-color: #adadad;
@scrollbar-background: rgba(21, 23, 21, 1);
@scrollbar-thumb: rgb(134, 134, 134);
@button-background: rgb(38, 38, 38);
@button-disabled-background: rgb(30, 29, 29);
@success-green: rgb(38, 97, 26);
@error-red: #cc0000;
@error-red-brightened: #ff8888;
@warning-yellow: #ffa500;
@textarea-background: #171717;
@text-primary: #fff;
@text-secondary: #c3c8c2;
@text-caption: #8b918a;
@accent-color: #3b3f3a;
@status-outline: #151715;
@dropdown-menu: rgba(21, 23, 21, 1);
@status-connected: #46a758;
@status-connecting: #f5d90a;
@status-error: #e54d2e;
@status-disconnected: #c3c8c2;
@term-black: #000000;
@term-red: #cc0000;
@term-green: #4e9a06;
@term-yellow: #c4a000;
@term-blue: #3465a4;
@term-magenta: #75507b;
@term-cyan: #06989a;
@term-white: #d3d7cf;
@term-bright-black: #555753;
@term-bright-red: #ef2929;
@term-bright-green: #58c142;
@term-bright-yellow: #fce94f;
@term-bright-blue: #32afff;
@term-bright-magenta: #ad7fa8;
@term-bright-cyan: #34e2e2;
@term-bright-white: #ffffff;
@tab-red: #e54d2e;
@tab-orange: #ef713b;
@tab-yellow: #e0b956;
@tab-green: #58c142;
@tab-mint: #4bffa9;
@tab-cyan: #4bdfff;
@tab-blue: #3971ff;
@tab-violet: #ba76ff;
@tab-pink: #e05677;
@tab-white: #ffffff;
@tab-black-text: #333;
@tab-white-text: #d7d7d7;
@soft-blue: #729fcf;
@active-menu-color: rgb(0, 71, 171);
// @font-face declaration lives in app.less
@fixed-font: "Martian Mono", sans-serif;
@terminal-font: "JetBrains Mono", sans-serif;
@text-s1-font: "Martian Mono", sans-serif;
// to match Github
@markdown-font: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif,
"Apple Color Emoji", "Segoe UI Emoji";
@markdown-highlight: rgb(35, 35, 35);
@thin-border-color: #333;
@main-content-bottom-background: #333;

View File

@ -1,6 +0,0 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
:root {
// can put dev overrides for testing here
}

View File

@ -55,7 +55,7 @@
.separator { .separator {
height: 1px; height: 1px;
margin: 16px 0; margin: 16px 0;
background-color: var(--sidebar-separator-color); background-color: var(--app-border-color);
} }
.item.workspaces-item { .item.workspaces-item {
@ -64,7 +64,7 @@
.middle { .middle {
padding: 4px 6px 8px 6px; padding: 4px 6px 8px 6px;
border-bottom: 1px solid var(--sidebar-separator-color); border-bottom: 1px solid var(--app-border-color);
.item { .item {
&.active { &.active {
background-color: var(--sidebar-highlight-color); background-color: var(--sidebar-highlight-color);

View File

@ -361,6 +361,14 @@ class CommandRunner {
return GlobalModel.submitCommand("client", "set", null, kwargs, interactive); return GlobalModel.submitCommand("client", "set", null, kwargs, interactive);
} }
setTheme(theme: string, interactive: boolean): Promise<CommandRtnType> {
let kwargs = {
nohist: "1",
theme: theme,
};
return GlobalModel.submitCommand("client", "set", null, kwargs, interactive);
}
setClientOpenAISettings(opts: { model?: string; apitoken?: string; maxtokens?: string }): Promise<CommandRtnType> { setClientOpenAISettings(opts: { model?: string; apitoken?: string; maxtokens?: string }): Promise<CommandRtnType> {
let kwargs = { let kwargs = {
nohist: "1", nohist: "1",

View File

@ -14,6 +14,7 @@ import {
isBlank, isBlank,
} from "@/util/util"; } from "@/util/util";
import { loadFonts } from "@/util/fontutil"; import { loadFonts } from "@/util/fontutil";
import { loadTheme } from "@/util/themeutil";
import { WSControl } from "./ws"; import { WSControl } from "./ws";
import { cmdStatusIsRunning } from "@/app/line/lineutil"; import { cmdStatusIsRunning } from "@/app/line/lineutil";
import * as appconst from "@/app/appconst"; import * as appconst from "@/app/appconst";
@ -340,6 +341,15 @@ class Model {
return ff; return ff;
} }
getTheme(): string {
let cdata = this.clientData.get();
let theme = cdata?.feopts?.theme;
if (theme == null) {
theme = appconst.DefaultTheme;
}
return theme;
}
getTermFontSize(): number { getTermFontSize(): number {
return this.termFontSize.get(); return this.termFontSize.get();
} }
@ -1173,6 +1183,12 @@ class Model {
} }
const ffUpdated = newFontFamily != this.getTermFontFamily(); const ffUpdated = newFontFamily != this.getTermFontFamily();
const fsUpdated = newFontSize != this.getTermFontSize(); const fsUpdated = newFontSize != this.getTermFontSize();
let newTheme = clientData?.feopts?.theme;
if (newTheme == null) {
newTheme = appconst.DefaultTheme;
}
const themeUpdated = newTheme != this.getTheme();
mobx.action(() => { mobx.action(() => {
this.clientData.set(clientData); this.clientData.set(clientData);
})(); })();
@ -1192,6 +1208,9 @@ class Model {
} else if (fsUpdated) { } else if (fsUpdated) {
this.updateTermFontSizeVars(); this.updateTermFontSizeVars();
} }
if (themeUpdated) {
loadTheme(newTheme);
}
} }
submitCommandPacket(cmdPk: FeCmdPacketType, interactive: boolean): Promise<CommandRtnType> { submitCommandPacket(cmdPk: FeCmdPacketType, interactive: boolean): Promise<CommandRtnType> {

View File

@ -562,6 +562,7 @@ declare global {
type FeOptsType = { type FeOptsType = {
termfontsize: number; termfontsize: number;
termfontfamily: string; termfontfamily: string;
theme: string;
}; };
type ConfirmFlagsType = { type ConfirmFlagsType = {

10
src/util/themeutil.ts Normal file
View File

@ -0,0 +1,10 @@
function loadTheme(theme: string) {
const linkTag: any = document.getElementById("theme-stylesheet");
if (theme === "dark") {
linkTag.href = "public/themes/default.css";
} else {
linkTag.href = `public/themes/${theme}.css`;
}
}
export { loadTheme };

View File

@ -97,6 +97,7 @@ var RemoteColorNames = []string{"red", "green", "yellow", "blue", "magenta", "cy
var RemoteSetArgs = []string{"alias", "connectmode", "key", "password", "autoinstall", "color"} var RemoteSetArgs = []string{"alias", "connectmode", "key", "password", "autoinstall", "color"}
var ConfirmFlags = []string{"hideshellprompt"} var ConfirmFlags = []string{"hideshellprompt"}
var SidebarNames = []string{"main"} var SidebarNames = []string{"main"}
var ThemeNames = []string{"light", "dark"}
var ScreenCmds = []string{"run", "comment", "cd", "cr", "clear", "sw", "reset", "signal", "chat"} var ScreenCmds = []string{"run", "comment", "cd", "cr", "clear", "sw", "reset", "signal", "chat"}
var NoHistCmds = []string{"_compgen", "line", "history", "_killserver"} var NoHistCmds = []string{"_compgen", "line", "history", "_killserver"}
@ -5198,6 +5199,26 @@ func ClientSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sc
} }
varsUpdated = append(varsUpdated, "termfontfamily") varsUpdated = append(varsUpdated, "termfontfamily")
} }
if themeStr, found := pk.Kwargs["theme"]; found {
newTheme := themeStr
found := false
for _, theme := range ThemeNames {
if newTheme == theme {
found = true
break
}
}
if !found {
return nil, fmt.Errorf("invalid theme name")
}
feOpts := clientData.FeOpts
feOpts.Theme = newTheme
err = sstore.UpdateClientFeOpts(ctx, feOpts)
if err != nil {
return nil, fmt.Errorf("error updating client feopts: %v", err)
}
varsUpdated = append(varsUpdated, "theme")
}
if apiToken, found := pk.Kwargs["openaiapitoken"]; found { if apiToken, found := pk.Kwargs["openaiapitoken"]; found {
err = validateOpenAIAPIToken(apiToken) err = validateOpenAIAPIToken(apiToken)
if err != nil { if err != nil {

View File

@ -297,6 +297,7 @@ type ClientOptsType struct {
type FeOptsType struct { type FeOptsType struct {
TermFontSize int `json:"termfontsize,omitempty"` TermFontSize int `json:"termfontsize,omitempty"`
TermFontFamily string `json:"termfontfamily,omitempty"` TermFontFamily string `json:"termfontfamily,omitempty"`
Theme string `json:"theme,omitempty"`
} }
type ReleaseInfoType struct { type ReleaseInfoType struct {