This commit is contained in:
Red Adaya 2024-04-04 11:02:27 +08:00
parent e4d353b5c1
commit 97595a7718
11 changed files with 102 additions and 31 deletions

View File

@ -125,6 +125,7 @@ class App extends React.Component<{}, {}> {
const activeMainView = GlobalModel.activeMainView.get();
const lightDarkClass = GlobalModel.isDarkTheme.get() ? "is-dark" : "is-light";
const termTheme = GlobalModel.getTermTheme();
return (
<div
key={`version- + ${renderVersion}`}
@ -152,7 +153,12 @@ class App extends React.Component<{}, {}> {
</div>
</If>
<div ref={this.mainContentRef} className="main-content">
<StyleBlock termTheme={termTheme} themeSrcEl={this.mainContentRef.current} themeKey="global" />
<StyleBlock
scope="main"
termTheme={termTheme}
themeSrcEl={this.mainContentRef.current}
themeKey="main"
/>
<MainSideBar parentRef={this.mainContentRef} />
<ErrorBoundary>
<PluginsView />

View File

@ -76,14 +76,14 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
@boundMethod
handleChangeTermTheme(theme: string): void {
// For global terminal theme, the key is global, otherwise it's either
// For main terminal theme, the key is main, otherwise it's either
// sessionId or screenId.
const currTheme = GlobalModel.getTermTheme()["global"];
const currTheme = GlobalModel.getTermTheme()["main"];
if (currTheme == theme) {
return;
}
const prtn = GlobalCommandRunner.setGlobalTermTheme(theme, false);
const prtn = GlobalCommandRunner.setMainTermTheme(theme, false);
commandRtnHandler(prtn, this.errorMessage);
}
@ -208,7 +208,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
const curFontFamily = GlobalModel.getTermFontFamily();
const curTheme = GlobalModel.getThemeSource();
const termThemes = getTermThemes(GlobalModel.termThemes, "Wave Default");
const currTermTheme = GlobalModel.getTermTheme()["global"] ?? termThemes[0].label;
const currTermTheme = GlobalModel.getTermTheme()["main"] ?? termThemes[0].label;
return (
<MainView className="clientsettings-view" title="Client Settings" onClose={this.handleClose}>

View File

@ -9,14 +9,13 @@ import { isBlank } from "@/util/util";
@mobxReact.observer
class StyleBlock extends React.Component<
{ themeSrcEl: HTMLElement; themeKey: string; termTheme: TermThemeType },
{ scope: "main" | "session" | "screen"; themeSrcEl: HTMLElement; themeKey: string; termTheme: TermThemeType },
{ styleRules: string }
> {
styleRules: OV<string> = mobx.observable.box("", { name: "StyleBlock-styleRules" });
theme: string;
componentDidMount(): void {
GlobalModel.termThemeSrcEl.set(this.props.themeSrcEl);
this.loadThemeStyles();
}
@ -26,13 +25,10 @@ class StyleBlock extends React.Component<
if (themeKey !== prevProps.themeKey || currTheme !== this.theme) {
this.loadThemeStyles();
}
if (this.props.themeSrcEl !== prevProps.themeSrcEl) {
GlobalModel.termThemeSrcEl.set(this.props.themeSrcEl);
}
}
async loadThemeStyles() {
const { themeKey, termTheme } = this.props;
const { themeKey, termTheme, scope } = this.props;
const currTheme = termTheme[themeKey];
if (currTheme && currTheme !== this.theme && currTheme) {
@ -43,7 +39,10 @@ class StyleBlock extends React.Component<
.map(([key, value]) => `--term-${key}: ${value};`)
.join(" ");
this.styleRules.set(`:root { ${styleProperties} }`);
mobx.action(() => {
this.styleRules.set(`:root { ${styleProperties} }`);
GlobalModel.termThemeSrcEls.set(scope, this.props.themeSrcEl);
})();
GlobalModel.bumpTermRenderVersion();
this.theme = currTheme;
} else {
@ -53,7 +52,12 @@ class StyleBlock extends React.Component<
console.error("error loading theme styles:", error);
});
} else {
this.styleRules.set("");
mobx.action(() => {
this.styleRules.set("");
GlobalModel.termThemeSrcEls.set(scope, null);
})();
this.theme = currTheme;
GlobalModel.bumpTermRenderVersion();
}
}

View File

@ -185,11 +185,18 @@ class ScreenView extends React.Component<{ session: Session; screen: Screen }, {
sidebarWidth = realWidth - MagicLayout.ScreenSidebarWidthPadding + "px";
}
const termTheme = GlobalModel.getTermTheme();
const termRenderVersion = GlobalModel.termRenderVersion.get();
return (
<div className="screen-view" data-screenid={screen.screenId} ref={this.screenViewRef}>
{/* <StyleBlock termTheme={termTheme} themeSrcEl={} /> */}
<StyleBlock
scope="screen"
termTheme={termTheme}
themeSrcEl={this.screenViewRef.current}
themeKey={screen.screenId}
/>
<ScreenWindowView
key={screen.screenId + ":" + fontSize + ":" + dprStr}
key={screen.screenId + ":" + fontSize + ":" + dprStr + ":" + termRenderVersion}
session={session}
screen={screen}
width={winWidth}

View File

@ -0,0 +1,45 @@
.screen-tabs-container {
position: relative;
height: var(--screentabs-height);
.screen-tabs-container-inner {
position: relative; // Needed for absolute positioning of child tabs
white-space: nowrap;
height: 100%;
margin-right: 42px;
overflow: hidden;
}
.new-screen {
width: 42px;
height: 40px;
background-color: var(--app-bg-color);
cursor: pointer;
position: absolute;
top: 50%;
transform: translateY(-50%);
font-size: 20px;
text-align: center;
line-height: 38px;
user-select: none;
}
}
// This ensures the tab bar does not collide with the floating logo. The floating logo sits above the sidebar when it is not collapsed, so no additional margin is needed in that case.
// More margin is given on macOS to account for the traffic light buttons
#app.platform-darwin.mainsidebar-collapsed .screen-tabs-container {
margin-left: var(--floating-logo-width-darwin);
}
#app:not(.platform-darwin).mainsidebar-collapsed .screen-tabs-container {
margin-left: var(--floating-logo-width);
}
// This ensures the tab bar does not collide with the right sidebar triggers.
#app.platform-darwin.rightsidebar-collapsed .screen-tabs-container {
margin-right: var(--floating-right-sidebar-triggers-width-darwin);
}
#app:not(.platform-darwin).rightsidebar-collapsed .screen-tabs-container {
margin-left: var(--floating-right-sidebar-triggers-width);
}

View File

@ -287,7 +287,6 @@ class WorkspaceView extends React.Component<{}, {}> {
const mainSidebarModel = GlobalModel.mainSidebarModel;
const showTabSettings = GlobalModel.tabSettingsOpen.get();
const termTheme = GlobalModel.getTermTheme();
const termRenderVersion = GlobalModel.termRenderVersion.get();
return (
<div
@ -300,6 +299,7 @@ class WorkspaceView extends React.Component<{}, {}> {
>
<If condition={session != null}>
<StyleBlock
scope="session"
themeSrcEl={this.sessionRef.current}
themeKey={session.sessionId}
termTheme={termTheme}
@ -321,11 +321,7 @@ class WorkspaceView extends React.Component<{}, {}> {
</div>
</If>
<ErrorBoundary key="eb">
<ScreenView
key={`screenview-${sessionId}-${termRenderVersion}`}
session={session}
screen={activeScreen}
/>
<ScreenView key={`screenview-${sessionId}`} session={session} screen={activeScreen} />
<div className="cmdinput-height-placeholder" style={{ height: cmdInputHeight }}></div>
<If condition={activeScreen != null}>
<CmdInput key={"cmdinput-" + sessionId} />

View File

@ -377,7 +377,7 @@ class CommandRunner {
return GlobalModel.submitCommand("client", "set", null, kwargs, interactive);
}
setGlobalTermTheme(theme: string, interactive: boolean): Promise<CommandRtnType> {
setMainTermTheme(theme: string, interactive: boolean): Promise<CommandRtnType> {
let kwargs = {
nohist: "1",
termtheme: theme,
@ -386,7 +386,6 @@ class CommandRunner {
}
setSessionTermTheme(sessionId: string, name: string, interactive: boolean): Promise<CommandRtnType> {
console.log("setSessionTermTheme-------");
let kwargs = {
nohist: "1",
id: sessionId,

View File

@ -144,13 +144,15 @@ class Model {
name: "terminalThemes",
deep: false,
});
termThemeSrcEl: OV<HTMLElement> = mobx.observable.box(null, {
name: "termThemeSrcEl",
});
termThemeSrcEls: OMap<string, HTMLElement> = mobx.observable.map(
{},
{
name: "termThemeSrcEls",
}
);
termRenderVersion: OV<number> = mobx.observable.box(0, {
name: "termRenderVersion",
});
currGlobalTermTheme: string;
private constructor() {
this.clientId = getApi().getId();
@ -214,6 +216,16 @@ class Model {
};
}
getThemeSrcElForScope() {
const scopes = ["screen", "session", "main"];
for (let scope of scopes) {
if (this.termThemeSrcEls.get(scope)) {
return this.termThemeSrcEls.get(scope);
}
}
return document.documentElement;
}
readConfigKeybindings() {
const url = new URL(this.getBaseHostPort() + "/config/keybindings.json");
let prtn = fetch(url, { method: "get", body: null, headers: this.getFetchHeaders() });
@ -1331,7 +1343,7 @@ class Model {
// Only for global terminal theme. For session and screen terminal theme,
// they are handled in workspace view.
if (ttUpdated) {
this.bumpTermRenderVersion();
// this.bumpTermRenderVersion();
// const el = document.documentElement;
// const globaltt = newTermTheme["global"] ?? this.currGlobalTermTheme;
// const reset = newTermTheme["global"] == null;

View File

@ -169,6 +169,7 @@ class RemotesModel {
}
createTermWrap(elem: HTMLElement): void {
console.log("createTermWrap", elem);
this.disposeTerm();
let remoteId = this.selectedRemoteId.get();
if (remoteId == null) {

View File

@ -53,6 +53,7 @@ type TermWrapOpts = {
function getThemeFromCSSVars(themeSrcEl: HTMLElement): ITheme {
const theme: ITheme = {};
console.log("themeSrcEl", themeSrcEl);
const tse = themeSrcEl ?? document.documentElement;
let rootStyle = getComputedStyle(tse);
theme.foreground = rootStyle.getPropertyValue("--term-foreground");
@ -131,7 +132,7 @@ class TermWrap {
let cols = windowWidthToCols(opts.winSize.width, opts.fontSize);
this.termSize = { rows: opts.termOpts.rows, cols: cols };
}
const themeSrcEl = GlobalModel.termThemeSrcEl.get();
const themeSrcEl = GlobalModel.getThemeSrcElForScope();
let theme = getThemeFromCSSVars(themeSrcEl);
this.terminal = new Terminal({
rows: this.termSize.rows,

View File

@ -5811,9 +5811,9 @@ func ClientSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sc
feOpts.TermTheme = make(map[string]string)
}
if termthemeStr == "" {
delete(feOpts.TermTheme, "global")
delete(feOpts.TermTheme, "main")
} else {
feOpts.TermTheme["global"] = termthemeStr
feOpts.TermTheme["main"] = termthemeStr
}
err = sstore.UpdateClientFeOpts(ctx, feOpts)
if err != nil {