From cb94936aad1de8fab3811c2b1f8d4ddb36d7fad9 Mon Sep 17 00:00:00 2001 From: sawka Date: Mon, 10 Oct 2022 23:44:04 -0700 Subject: [PATCH] checkpoint on selection/fg model --- src/main.tsx | 68 ++++++++++++++++++++++++++++++++++++++++++---------- src/model.ts | 42 +++++++++++++++++++++----------- src/term.ts | 16 +++++++++---- src/types.ts | 3 ++- 4 files changed, 96 insertions(+), 33 deletions(-) diff --git a/src/main.tsx b/src/main.tsx index ad70bd4c..fb426f29 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -141,7 +141,7 @@ class LineText extends React.Component<{sw : ScreenWindow, line : LineType}, {}> let {sw, line} = this.props; let formattedTime = getLineDateStr(line.ts); let isSelected = (sw.selectedLine.get() == line.linenum); - let isFocused = (sw.focusType.get() == "lines"); + let isFocused = (sw.focusType.get() == "cmd"); return (
@@ -393,11 +393,45 @@ class TextAreaInput extends React.Component<{}, {}> { lastTab : boolean = false; lastHistoryUpDown : boolean = false; lastTabCurLine : mobx.IObservableValue = mobx.observable.box(null); - + lastFocusType : string = null; + mainInputRef : React.RefObject; + historyInputRef : React.RefObject; + + constructor(props) { + super(props); + this.mainInputRef = React.createRef(); + this.historyInputRef = React.createRef(); + } + + setFocus() : void { + let inputModel = GlobalModel.inputModel; + if (inputModel.historyShow.get()) { + this.historyInputRef.current.focus(); + } + else { + this.mainInputRef.current.focus(); + } + } + componentDidMount() { - let input = document.getElementById("main-cmd-input"); - if (input != null) { - input.focus(); + let activeSW = GlobalModel.getActiveSW(); + if (activeSW != null) { + let focusType = activeSW.focusType.get(); + if (focusType == "input") { + this.setFocus(); + } + this.lastFocusType = focusType; + } + } + + componentDidUpdate() { + let activeSW = GlobalModel.getActiveSW(); + if (activeSW != null) { + let focusType = activeSW.focusType.get(); + if (this.lastFocusType != focusType && focusType == "input") { + this.setFocus(); + } + this.lastFocusType = focusType; } } @@ -603,14 +637,16 @@ class TextAreaInput extends React.Component<{}, {}> { if (inputModel.historyShow.get()) { e.preventDefault(); inputModel.giveFocus(); + return; } - else { - inputModel.setPhysicalInputFocused(true); - } + inputModel.setPhysicalInputFocused(true); } @boundMethod handleMainBlur(e : any) { + if (document.activeElement == this.mainInputRef.current) { + return; + } GlobalModel.inputModel.setPhysicalInputFocused(false); } @@ -620,14 +656,16 @@ class TextAreaInput extends React.Component<{}, {}> { if (!inputModel.historyShow.get()) { e.preventDefault(); inputModel.giveFocus(); + return; } - else { - inputModel.setPhysicalInputFocused(true); - } + inputModel.setPhysicalInputFocused(true); } @boundMethod handleHistoryBlur(e : any) { + if (document.activeElement == this.historyInputRef.current) { + return; + } GlobalModel.inputModel.setPhysicalInputFocused(false); } @@ -644,10 +682,14 @@ class TextAreaInput extends React.Component<{}, {}> { if (disabled) { displayLines = 1; } + let activeSW = GlobalModel.getActiveSW(); + if (activeSW != null) { + activeSW.focusType.get(); // for reaction + } return (
- - + +
); } diff --git a/src/model.ts b/src/model.ts index 562e9ffa..dc6a00c3 100644 --- a/src/model.ts +++ b/src/model.ts @@ -265,15 +265,14 @@ class ScreenWindow { layout : OV; lastCols : number; selectedLine : OV; - scrollTop : OV; - focusType : OV<"input"|"lines"> = mobx.observable.box("input"); + focusType : OV<"input"|"cmd"|"cmd-fg">; anchorLine : number = null; anchorOffset : number = 0; // cmdid => TermWrap terms : Record = {}; - setScrollTop_debounced : (scrollTop : number) => void; + setAnchor_debounced : (anchorLine : number, anchorOffset : number) => void; constructor(swdata : ScreenWindowType) { this.sessionId = swdata.sessionid; @@ -281,9 +280,9 @@ class ScreenWindow { this.windowId = swdata.windowid; this.name = mobx.observable.box(swdata.name); this.layout = mobx.observable.box(swdata.layout); + this.focusType = mobx.observable.box(swdata.focustype); this.selectedLine = mobx.observable.box(swdata.selectedline == 0 ? null : swdata.selectedline); - this.scrollTop = mobx.observable.box(swdata.scrolltop); - this.setScrollTop_debounced = debounce(1000, this.setScrollTop.bind(this)); + this.setAnchor_debounced = debounce(1000, this.setAnchor.bind(this)); if (swdata.selectedline != 0) { this.anchorLine = swdata.selectedline; this.anchorOffset = 0; @@ -295,18 +294,20 @@ class ScreenWindow { this.name.set(swdata.name); this.layout.set(swdata.layout); this.selectedLine.set(swdata.selectedline); - // do not set scrolltop! + this.focusType.set(swdata.focustype); + // do not update anchorLine/anchorOffset (only stored) })(); } - setFocusType(ftype : "input" | "lines") : void { + setFocusType(ftype : "input" | "cmd" | "cmd-fg") : void { mobx.action(() => { this.focusType.set(ftype); })(); } - setScrollTop(scrollTop : number) : void { - GlobalCommandRunner.swSetScrollTop(this.sessionId, this.screenId, this.windowId, scrollTop); + setAnchor(anchorLine : number, anchorOffset : number) : void { + let setVal = ((anchorLine == null || anchorLine == 0) ? "0" : sprintf("%d:%d", anchorLine, anchorOffset)); + GlobalCommandRunner.swSetAnchor(this.sessionId, this.screenId, this.windowId, setVal); } getMaxLineNum() : number { @@ -784,6 +785,8 @@ class InputModel { } giveFocus() : void { + return; + if (this.historyShow.get()) { this._focusHistoryInput(); } @@ -1434,7 +1437,7 @@ class Model { onLCmd(e : any, mods : KeyModsType) { let sw = this.getActiveSW(); if (sw != null) { - sw.setFocusType("lines"); + sw.setFocusType("cmd"); } // this.inputModel.giveCmdFocus(); } @@ -2088,20 +2091,31 @@ class CommandRunner { GlobalModel.submitCommand("remote", "archive", null, {"remote": remoteid, "nohist": "1"}, true); } - swSelectLine(lineArg : string) { - GlobalModel.submitCommand("sw", "set", null, {"nohist": "1", "line": lineArg}, true); + swSelectLine(lineArg : string, focusVal? : string) { + let kwargs : Record = { + "nohist": "1", + "line": lineArg, + }; + if (focusVal != null) { + kwargs["focus"] = focusVal; + } + GlobalModel.submitCommand("sw", "set", null, kwargs, true); } - swSetScrollTop(sessionId : string, screenId : string, windowId : string, scrollTopVal : number) { + swSetAnchor(sessionId : string, screenId : string, windowId : string, anchorVal : string) : void { let kwargs = { "nohist": "1", - "scrolltop": String(scrollTopVal), + "anchor": anchorVal, "session": sessionId, "screen": screenId, "window": windowId, }; GlobalModel.submitCommand("sw", "set", null, kwargs, true); } + + swSetFocus(focusVal : string) : void { + GlobalModel.submitCommand("sw", "set", null, {"focus": focusVal, "nohist": "1"}, true); + } }; let GlobalModel : Model = null; diff --git a/src/term.ts b/src/term.ts index ca274eca..e87dd561 100644 --- a/src/term.ts +++ b/src/term.ts @@ -3,7 +3,7 @@ import {Terminal} from 'xterm'; import {sprintf} from "sprintf-js"; import {boundMethod} from "autobind-decorator"; import {v4 as uuidv4} from "uuid"; -import {GlobalModel, widthToCols} from "./model"; +import {GlobalModel, widthToCols, GlobalCommandRunner} from "./model"; import {boundInt} from "./util"; import type {TermOptsType, TermWinSize} from "./types"; @@ -71,7 +71,10 @@ class TermWrap { this.terminal.textarea.addEventListener("focus", () => { this.setFocus(true); }); - this.terminal.textarea.addEventListener("blur", () => { + this.terminal.textarea.addEventListener("blur", (e : any) => { + if (document.activeElement == this.terminal.textarea) { + return; + } this.setFocus(false); }); this.reloadTerminal(0); @@ -96,10 +99,13 @@ class TermWrap { mobx.action(() => { this.isFocused.set(focus); })(); - if (this.connectedElem != null) { - let lineElem = this.connectedElem.closest(".line"); + if (this.connectedElem != null && focus) { + let lineElem : HTMLElement = this.connectedElem.closest(".line"); if (lineElem != null) { - lineElem.scrollIntoView({behavior: "smooth", block: "nearest"}); + let lineNum = parseInt(lineElem.dataset.linenum); + if (!isNaN(lineNum) && lineNum > 0) { + GlobalCommandRunner.swSelectLine(String(lineNum), "cmd"); + } } } } diff --git a/src/types.ts b/src/types.ts index 26d36a57..960c29d9 100644 --- a/src/types.ts +++ b/src/types.ts @@ -68,7 +68,8 @@ type ScreenWindowType = { name : string, layout : LayoutType, selectedline : number, - scrolltop : number, + focustype : "input"|"cmd"|"cmd-fg", + anchor : {anchorline : number, anchoroffset : number}, // for updates remove? : boolean,