checkpoint on selection/fg model

This commit is contained in:
sawka
2022-10-10 23:44:04 -07:00
parent 8c01aa787b
commit cb94936aad
4 changed files with 96 additions and 33 deletions
+55 -13
View File
@@ -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 (
<div className="line line-text" data-lineid={line.lineid} data-linenum={line.linenum} data-windowid={line.windowid}>
<div className={cn("focus-indicator", {"selected": isSelected}, {"active": isSelected && isFocused})}/>
@@ -393,11 +393,45 @@ class TextAreaInput extends React.Component<{}, {}> {
lastTab : boolean = false;
lastHistoryUpDown : boolean = false;
lastTabCurLine : mobx.IObservableValue<string> = mobx.observable.box(null);
lastFocusType : string = null;
mainInputRef : React.RefObject<any>;
historyInputRef : React.RefObject<any>;
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 (
<div className="control cmd-input-control is-expanded">
<textarea spellCheck="false" id="main-cmd-input" onFocus={this.handleMainFocus} onBlur={this.handleMainBlur} rows={displayLines} value={curLine} onKeyDown={this.onKeyDown} onChange={this.onChange} className={cn("textarea", {"display-disabled": disabled})}></textarea>
<input spellCheck="false" className="history-input" type="text" onFocus={this.handleHistoryFocus} onKeyDown={this.onHistoryKeyDown} onChange={this.handleHistoryInput} value={inputModel.historyQueryOpts.get().queryStr}/>
<textarea ref={this.mainInputRef} spellCheck="false" id="main-cmd-input" onFocus={this.handleMainFocus} onBlur={this.handleMainBlur} rows={displayLines} value={curLine} onKeyDown={this.onKeyDown} onChange={this.onChange} className={cn("textarea", {"display-disabled": disabled})}></textarea>
<input ref={this.historyInputRef} spellCheck="false" className="history-input" type="text" onFocus={this.handleHistoryFocus} onKeyDown={this.onHistoryKeyDown} onChange={this.handleHistoryInput} value={inputModel.historyQueryOpts.get().queryStr}/>
</div>
);
}
+28 -14
View File
@@ -265,15 +265,14 @@ class ScreenWindow {
layout : OV<LayoutType>;
lastCols : number;
selectedLine : OV<number>;
scrollTop : OV<number>;
focusType : OV<"input"|"lines"> = mobx.observable.box("input");
focusType : OV<"input"|"cmd"|"cmd-fg">;
anchorLine : number = null;
anchorOffset : number = 0;
// cmdid => TermWrap
terms : Record<string, TermWrap> = {};
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<string, string> = {
"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;
+11 -5
View File
@@ -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");
}
}
}
}
+2 -1
View File
@@ -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,