Skip to content

Commit d65eabe

Browse files
authored
termfontsize override (#1118)
1 parent bf5bf6f commit d65eabe

File tree

2 files changed

+83
-7
lines changed

2 files changed

+83
-7
lines changed

frontend/app/block/block.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ type FullBlockProps = {
3636

3737
function makeViewModel(blockId: string, blockView: string, nodeModel: NodeModel): ViewModel {
3838
if (blockView === "term") {
39-
return makeTerminalModel(blockId);
39+
return makeTerminalModel(blockId, nodeModel);
4040
}
4141
if (blockView === "preview") {
4242
return makePreviewModel(blockId, nodeModel);

frontend/app/view/term/term.tsx

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,16 @@ import { waveEventSubscribe } from "@/app/store/wps";
66
import { RpcApi } from "@/app/store/wshclientapi";
77
import { WindowRpcClient } from "@/app/store/wshrpcutil";
88
import { VDomView } from "@/app/view/term/vdom";
9-
import { WOS, atoms, getConnStatusAtom, getSettingsKeyAtom, globalStore, useSettingsPrefixAtom } from "@/store/global";
9+
import { NodeModel } from "@/layout/index";
10+
import {
11+
WOS,
12+
atoms,
13+
getConnStatusAtom,
14+
getSettingsKeyAtom,
15+
globalStore,
16+
useBlockAtom,
17+
useSettingsPrefixAtom,
18+
} from "@/store/global";
1019
import * as services from "@/store/services";
1120
import * as keyutil from "@/util/keyutil";
1221
import * as util from "@/util/util";
@@ -106,15 +115,19 @@ class TermViewModel {
106115
termMode: jotai.Atom<string>;
107116
htmlElemFocusRef: React.RefObject<HTMLInputElement>;
108117
blockId: string;
118+
nodeModel: NodeModel;
109119
viewIcon: jotai.Atom<string>;
110120
viewName: jotai.Atom<string>;
111121
blockBg: jotai.Atom<MetaType>;
112122
manageConnection: jotai.Atom<boolean>;
113123
connStatus: jotai.Atom<ConnStatus>;
124+
fontSizeAtom: jotai.Atom<number>;
125+
termThemeNameAtom: jotai.Atom<string>;
114126

115-
constructor(blockId: string) {
127+
constructor(blockId: string, nodeModel: NodeModel) {
116128
this.viewType = "term";
117129
this.blockId = blockId;
130+
this.nodeModel = nodeModel;
118131
this.blockAtom = WOS.getWaveObjectAtom<Block>(`block:${blockId}`);
119132
this.termMode = jotai.atom((get) => {
120133
const blockData = get(this.blockAtom);
@@ -150,6 +163,25 @@ class TermViewModel {
150163
const connAtom = getConnStatusAtom(connName);
151164
return get(connAtom);
152165
});
166+
this.fontSizeAtom = useBlockAtom(blockId, "fontsizeatom", () => {
167+
return jotai.atom<number>((get) => {
168+
const blockData = get(this.blockAtom);
169+
const fsSettingsAtom = getSettingsKeyAtom("term:fontsize");
170+
const settingsFontSize = get(fsSettingsAtom);
171+
const rtnFontSize = blockData?.meta?.["term:fontsize"] ?? settingsFontSize ?? 12;
172+
if (typeof rtnFontSize != "number" || isNaN(rtnFontSize) || rtnFontSize < 4 || rtnFontSize > 64) {
173+
return 12;
174+
}
175+
return rtnFontSize;
176+
});
177+
});
178+
this.termThemeNameAtom = useBlockAtom(blockId, "termthemeatom", () => {
179+
return jotai.atom<string>((get) => {
180+
const blockData = get(this.blockAtom);
181+
const settingsKeyAtom = getSettingsKeyAtom("term:theme");
182+
return blockData?.meta?.["term:theme"] ?? get(settingsKeyAtom) ?? "default-dark";
183+
});
184+
});
153185
}
154186

155187
giveFocus(): boolean {
@@ -179,6 +211,10 @@ class TermViewModel {
179211
const fullConfig = globalStore.get(atoms.fullConfigAtom);
180212
const termThemes = fullConfig?.termthemes ?? {};
181213
const termThemeKeys = Object.keys(termThemes);
214+
const curThemeName = globalStore.get(this.termThemeNameAtom);
215+
const defaultFontSize = globalStore.get(getSettingsKeyAtom("term:fontsize")) ?? 12;
216+
const blockData = globalStore.get(this.blockAtom);
217+
const overrideFontSize = blockData?.meta?.["term:fontsize"];
182218

183219
termThemeKeys.sort((a, b) => {
184220
return termThemes[a]["display:order"] - termThemes[b]["display:order"];
@@ -187,13 +223,45 @@ class TermViewModel {
187223
const submenu: ContextMenuItem[] = termThemeKeys.map((themeName) => {
188224
return {
189225
label: termThemes[themeName]["display:name"] ?? themeName,
226+
type: "checkbox",
227+
checked: curThemeName == themeName,
190228
click: () => this.setTerminalTheme(themeName),
191229
};
192230
});
231+
const fontSizeSubMenu: ContextMenuItem[] = [6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18].map(
232+
(fontSize: number) => {
233+
return {
234+
label: fontSize.toString() + "px",
235+
type: "checkbox",
236+
checked: overrideFontSize == fontSize,
237+
click: () => {
238+
RpcApi.SetMetaCommand(WindowRpcClient, {
239+
oref: WOS.makeORef("block", this.blockId),
240+
meta: { "term:fontsize": fontSize },
241+
});
242+
},
243+
};
244+
}
245+
);
246+
fontSizeSubMenu.unshift({
247+
label: "Default (" + defaultFontSize + "px)",
248+
type: "checkbox",
249+
checked: overrideFontSize == null,
250+
click: () => {
251+
RpcApi.SetMetaCommand(WindowRpcClient, {
252+
oref: WOS.makeORef("block", this.blockId),
253+
meta: { "term:fontsize": null },
254+
});
255+
},
256+
});
193257
fullMenu.push({
194258
label: "Themes",
195259
submenu: submenu,
196260
});
261+
fullMenu.push({
262+
label: "Font Size",
263+
submenu: fontSizeSubMenu,
264+
});
197265
fullMenu.push({ type: "separator" });
198266
fullMenu.push({
199267
label: "Force Restart Controller",
@@ -215,8 +283,8 @@ class TermViewModel {
215283
}
216284
}
217285

218-
function makeTerminalModel(blockId: string): TermViewModel {
219-
return new TermViewModel(blockId);
286+
function makeTerminalModel(blockId: string, nodeModel: NodeModel): TermViewModel {
287+
return new TermViewModel(blockId, nodeModel);
220288
}
221289

222290
interface TerminalViewProps {
@@ -258,6 +326,8 @@ const TerminalView = ({ blockId, model }: TerminalViewProps) => {
258326
const termSettingsAtom = useSettingsPrefixAtom("term");
259327
const termSettings = jotai.useAtomValue(termSettingsAtom);
260328

329+
const termFontSize = jotai.useAtomValue(model.fontSizeAtom);
330+
261331
React.useEffect(() => {
262332
function handleTerminalKeydown(event: KeyboardEvent): boolean {
263333
const waveEvent = keyutil.adaptFromReactOrNativeKeyEvent(event);
@@ -321,12 +391,13 @@ const TerminalView = ({ blockId, model }: TerminalViewProps) => {
321391
if (termScrollback > 10000) {
322392
termScrollback = 10000;
323393
}
394+
const wasFocused = termRef.current != null && globalStore.get(model.nodeModel.isFocused);
324395
const termWrap = new TermWrap(
325396
blockId,
326397
connectElemRef.current,
327398
{
328399
theme: themeCopy,
329-
fontSize: termSettings?.["term:fontsize"] ?? 12,
400+
fontSize: termFontSize,
330401
fontFamily: termSettings?.["term:fontfamily"] ?? "Hack",
331402
drawBoldTextInBrightColors: false,
332403
fontWeight: "normal",
@@ -346,11 +417,16 @@ const TerminalView = ({ blockId, model }: TerminalViewProps) => {
346417
});
347418
rszObs.observe(connectElemRef.current);
348419
termWrap.initTerminal();
420+
if (wasFocused) {
421+
setTimeout(() => {
422+
model.giveFocus();
423+
}, 10);
424+
}
349425
return () => {
350426
termWrap.dispose();
351427
rszObs.disconnect();
352428
};
353-
}, [blockId, termSettings]);
429+
}, [blockId, termSettings, termFontSize]);
354430

355431
const handleHtmlKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
356432
const waveEvent = keyutil.adaptFromReactOrNativeKeyEvent(event);

0 commit comments

Comments
 (0)