@@ -6,7 +6,16 @@ import { waveEventSubscribe } from "@/app/store/wps";
6
6
import { RpcApi } from "@/app/store/wshclientapi" ;
7
7
import { WindowRpcClient } from "@/app/store/wshrpcutil" ;
8
8
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" ;
10
19
import * as services from "@/store/services" ;
11
20
import * as keyutil from "@/util/keyutil" ;
12
21
import * as util from "@/util/util" ;
@@ -106,15 +115,19 @@ class TermViewModel {
106
115
termMode : jotai . Atom < string > ;
107
116
htmlElemFocusRef : React . RefObject < HTMLInputElement > ;
108
117
blockId : string ;
118
+ nodeModel : NodeModel ;
109
119
viewIcon : jotai . Atom < string > ;
110
120
viewName : jotai . Atom < string > ;
111
121
blockBg : jotai . Atom < MetaType > ;
112
122
manageConnection : jotai . Atom < boolean > ;
113
123
connStatus : jotai . Atom < ConnStatus > ;
124
+ fontSizeAtom : jotai . Atom < number > ;
125
+ termThemeNameAtom : jotai . Atom < string > ;
114
126
115
- constructor ( blockId : string ) {
127
+ constructor ( blockId : string , nodeModel : NodeModel ) {
116
128
this . viewType = "term" ;
117
129
this . blockId = blockId ;
130
+ this . nodeModel = nodeModel ;
118
131
this . blockAtom = WOS . getWaveObjectAtom < Block > ( `block:${ blockId } ` ) ;
119
132
this . termMode = jotai . atom ( ( get ) => {
120
133
const blockData = get ( this . blockAtom ) ;
@@ -150,6 +163,25 @@ class TermViewModel {
150
163
const connAtom = getConnStatusAtom ( connName ) ;
151
164
return get ( connAtom ) ;
152
165
} ) ;
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
+ } ) ;
153
185
}
154
186
155
187
giveFocus ( ) : boolean {
@@ -179,6 +211,10 @@ class TermViewModel {
179
211
const fullConfig = globalStore . get ( atoms . fullConfigAtom ) ;
180
212
const termThemes = fullConfig ?. termthemes ?? { } ;
181
213
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" ] ;
182
218
183
219
termThemeKeys . sort ( ( a , b ) => {
184
220
return termThemes [ a ] [ "display:order" ] - termThemes [ b ] [ "display:order" ] ;
@@ -187,13 +223,45 @@ class TermViewModel {
187
223
const submenu : ContextMenuItem [ ] = termThemeKeys . map ( ( themeName ) => {
188
224
return {
189
225
label : termThemes [ themeName ] [ "display:name" ] ?? themeName ,
226
+ type : "checkbox" ,
227
+ checked : curThemeName == themeName ,
190
228
click : ( ) => this . setTerminalTheme ( themeName ) ,
191
229
} ;
192
230
} ) ;
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
+ } ) ;
193
257
fullMenu . push ( {
194
258
label : "Themes" ,
195
259
submenu : submenu ,
196
260
} ) ;
261
+ fullMenu . push ( {
262
+ label : "Font Size" ,
263
+ submenu : fontSizeSubMenu ,
264
+ } ) ;
197
265
fullMenu . push ( { type : "separator" } ) ;
198
266
fullMenu . push ( {
199
267
label : "Force Restart Controller" ,
@@ -215,8 +283,8 @@ class TermViewModel {
215
283
}
216
284
}
217
285
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 ) ;
220
288
}
221
289
222
290
interface TerminalViewProps {
@@ -258,6 +326,8 @@ const TerminalView = ({ blockId, model }: TerminalViewProps) => {
258
326
const termSettingsAtom = useSettingsPrefixAtom ( "term" ) ;
259
327
const termSettings = jotai . useAtomValue ( termSettingsAtom ) ;
260
328
329
+ const termFontSize = jotai . useAtomValue ( model . fontSizeAtom ) ;
330
+
261
331
React . useEffect ( ( ) => {
262
332
function handleTerminalKeydown ( event : KeyboardEvent ) : boolean {
263
333
const waveEvent = keyutil . adaptFromReactOrNativeKeyEvent ( event ) ;
@@ -321,12 +391,13 @@ const TerminalView = ({ blockId, model }: TerminalViewProps) => {
321
391
if ( termScrollback > 10000 ) {
322
392
termScrollback = 10000 ;
323
393
}
394
+ const wasFocused = termRef . current != null && globalStore . get ( model . nodeModel . isFocused ) ;
324
395
const termWrap = new TermWrap (
325
396
blockId ,
326
397
connectElemRef . current ,
327
398
{
328
399
theme : themeCopy ,
329
- fontSize : termSettings ?. [ "term:fontsize" ] ?? 12 ,
400
+ fontSize : termFontSize ,
330
401
fontFamily : termSettings ?. [ "term:fontfamily" ] ?? "Hack" ,
331
402
drawBoldTextInBrightColors : false ,
332
403
fontWeight : "normal" ,
@@ -346,11 +417,16 @@ const TerminalView = ({ blockId, model }: TerminalViewProps) => {
346
417
} ) ;
347
418
rszObs . observe ( connectElemRef . current ) ;
348
419
termWrap . initTerminal ( ) ;
420
+ if ( wasFocused ) {
421
+ setTimeout ( ( ) => {
422
+ model . giveFocus ( ) ;
423
+ } , 10 ) ;
424
+ }
349
425
return ( ) => {
350
426
termWrap . dispose ( ) ;
351
427
rszObs . disconnect ( ) ;
352
428
} ;
353
- } , [ blockId , termSettings ] ) ;
429
+ } , [ blockId , termSettings , termFontSize ] ) ;
354
430
355
431
const handleHtmlKeyDown = ( event : React . KeyboardEvent < HTMLInputElement > ) => {
356
432
const waveEvent = keyutil . adaptFromReactOrNativeKeyEvent ( event ) ;
0 commit comments