@@ -6,7 +6,16 @@ import { waveEventSubscribe } from "@/app/store/wps";
66import { RpcApi } from "@/app/store/wshclientapi" ;
77import { WindowRpcClient } from "@/app/store/wshrpcutil" ;
88import { 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" ;
1019import * as services from "@/store/services" ;
1120import * as keyutil from "@/util/keyutil" ;
1221import * 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
222290interface 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