big update to get base history info panel working

This commit is contained in:
sawka 2022-08-30 23:12:37 -07:00
parent 087c0c4f1f
commit 9ed993078d
4 changed files with 365 additions and 255 deletions

View File

@ -441,10 +441,6 @@ class TextAreaInput extends React.Component<{}, {}> {
}
if (e.code == "Enter") {
e.preventDefault();
if (inputModel.historyShow.get()) {
inputModel.grabSelectedHistoryItem();
return;
}
if (!ctrlMod) {
setTimeout(() => GlobalModel.inputModel.uiSubmitCommand(), 0);
return;
@ -460,19 +456,22 @@ class TextAreaInput extends React.Component<{}, {}> {
}
if (e.code == "KeyC" && e.getModifierState("Control")) {
e.preventDefault();
inputModel.clearCurLine();
inputModel.resetInput();
return;
}
if (e.code == "KeyR" && e.getModifierState("Control")) {
e.preventDefault();
GlobalCommandRunner.openHistory();
inputModel.openHistory();
return;
}
if (e.code == "ArrowUp" || e.code == "ArrowDown") {
if (inputModel.historyShow.get()) {
inputModel.moveHistorySelection(e.code == "ArrowUp" ? -1 : 1);
if (!inputModel.isHistoryLoaded()) {
if (e.code == "ArrowUp") {
inputModel.loadHistory(false, 1);
}
return;
}
// invisible history movement
let linePos = this.getLinePos(e.target);
if (e.code == "ArrowUp") {
if (!lastHist && linePos.linePos > 1) {
@ -480,7 +479,7 @@ class TextAreaInput extends React.Component<{}, {}> {
return;
}
e.preventDefault();
inputModel.prevHistoryItem();
inputModel.moveHistorySelection(1);
this.lastHistoryUpDown = true;
return;
}
@ -490,17 +489,13 @@ class TextAreaInput extends React.Component<{}, {}> {
return;
}
e.preventDefault();
inputModel.nextHistoryItem();
inputModel.moveHistorySelection(-1);
this.lastHistoryUpDown = true;
return;
}
}
if (e.code == "PageUp" || e.code == "PageDown") {
e.preventDefault();
if (inputModel.historyShow.get()) {
inputModel.moveHistorySelection(e.code == "PageUp" ? -10 : 10);
return;
}
let infoScroll = inputModel.hasScrollingInfoMsg();
if (infoScroll) {
let div = document.querySelector(".cmd-input-info");
@ -529,6 +524,66 @@ class TextAreaInput extends React.Component<{}, {}> {
})();
}
@boundMethod
onHistoryKeyDown(e : any) {
let inputModel = GlobalModel.inputModel;
if (e.code == "Escape") {
e.preventDefault();
inputModel.resetHistory();
return;
}
if (e.code == "Enter") {
e.preventDefault();
inputModel.grabSelectedHistoryItem();
return;
}
if (e.code == "KeyC" && e.getModifierState("Control")) {
e.preventDefault();
inputModel.resetInput();
return;
}
if (e.code == "Tab") {
e.preventDefault();
return;
}
if (e.code == "ArrowUp" || e.code == "ArrowDown") {
e.preventDefault();
inputModel.moveHistorySelection(e.code == "ArrowUp" ? 1 : -1);
return;
}
if (e.code == "PageUp" || e.code == "PageDown") {
e.preventDefault();
inputModel.moveHistorySelection(e.code == "PageUp" ? 10 : -10);
return;
}
}
@boundMethod
handleHistoryInput(e : any) {
let inputModel = GlobalModel.inputModel;
mobx.action(() => {
inputModel.historyQueryOpts.get().queryStr = e.target.value;
})();
}
@boundMethod
handleMainFocus(e : any) {
let inputModel = GlobalModel.inputModel;
if (inputModel.historyShow.get()) {
e.preventDefault();
inputModel.giveFocus();
}
}
@boundMethod
handleHistoryFocus(e : any) {
let inputModel = GlobalModel.inputModel;
if (!inputModel.historyShow.get()) {
e.preventDefault();
inputModel.giveFocus();
}
}
render() {
let model = GlobalModel;
let inputModel = model.inputModel;
@ -538,8 +593,12 @@ class TextAreaInput extends React.Component<{}, {}> {
if (displayLines > 5) {
displayLines = 5;
}
let disabled = inputModel.historyShow.get();
return (
<textarea id="main-cmd-input" rows={displayLines} value={curLine} onKeyDown={this.onKeyDown} onChange={this.onChange} className="textarea"></textarea>
<div className="control cmd-input-control is-expanded">
<textarea spellCheck="false" id="main-cmd-input" onFocus={this.handleMainFocus} 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}/>
</div>
);
}
}
@ -548,24 +607,28 @@ class TextAreaInput extends React.Component<{}, {}> {
class HistoryInfo extends React.Component<{}, {}> {
lastClickHNum : string = null;
lastClickTs : number = 0;
containingText : mobx.IObservableValue<string> = mobx.observable.box("");
componentDidMount() {
let inputModel = GlobalModel.inputModel;
let selNum = inputModel.historySelectedNum.get();
if (selNum != null) {
inputModel.scrollHistoryItemIntoView(selNum);
let hitem = inputModel.getHistorySelectedItem();
if (hitem == null) {
hitem = inputModel.getFirstHistoryItem();
}
if (hitem != null) {
inputModel.scrollHistoryItemIntoView(hitem.historynum);
}
}
@boundMethod
handleItemClick(hitem : HistoryItem) {
let inputModel = GlobalModel.inputModel;
let selNum = inputModel.historySelectedNum.get();
if (this.lastClickHNum == hitem.historynum && selNum == hitem.historynum) {
let selItem = inputModel.getHistorySelectedItem();
if (this.lastClickHNum == hitem.historynum && selItem != null && selItem.historynum == hitem.historynum) {
inputModel.grabSelectedHistoryItem();
return;
}
inputModel.focusCmdInput();
inputModel.giveFocus();
inputModel.setHistorySelectionNum(hitem.historynum);
let now = Date.now();
this.lastClickHNum = hitem.historynum;
@ -578,13 +641,13 @@ class HistoryInfo extends React.Component<{}, {}> {
}, 3000);
}
renderHItem(hitem : HistoryItem, selNum : string) : any {
renderHItem(hitem : HistoryItem, isSelected : boolean) : any {
let lines = hitem.cmdstr.split("\n");
let line : string = "";
let idx = 0;
return (
<div key={hitem.historynum} className={cn("history-item", {"is-selected": selNum == hitem.historynum}, "hnum-" + hitem.historynum)} onClick={() => this.handleItemClick(hitem)}>
<div className="history-line">{(selNum == hitem.historynum ? "*" : " ")}{sprintf("%5s", hitem.historynum)} {lines[0]}</div>
<div key={hitem.historynum} className={cn("history-item", {"is-selected": isSelected}, "hnum-" + hitem.historynum)} onClick={() => this.handleItemClick(hitem)}>
<div className="history-line">{(isSelected ? "*" : " ")}{sprintf("%5s", hitem.historynum)} {lines[0]}</div>
<For each="line" index="index" of={lines.slice(1)}>
<div key={idx} className="history-line">{line}</div>
</For>
@ -596,11 +659,11 @@ class HistoryInfo extends React.Component<{}, {}> {
handleClose() {
GlobalModel.inputModel.toggleInfoMsg();
}
render() {
let inputModel = GlobalModel.inputModel;
let idx : number = 0;
let selNum = inputModel.historySelectedNum.get();
let selItem = inputModel.getHistorySelectedItem();
let hitems = inputModel.getFilteredHistoryItems();
hitems = hitems.slice().reverse();
let hitem : HistoryItem = null;
@ -609,15 +672,15 @@ class HistoryInfo extends React.Component<{}, {}> {
<div className="history-title">
history
{" "}
<span className="term-bright-white">[containing '']</span>
<span className="history-opt">[containing '']</span>
{" "}
<span className="term-bright-white">[this session &#x2318;S]</span>
<span className="history-opt">[this session &#x2318;S]</span>
{" "}
<span className="term-bright-white">[this window &#x2318;W]</span>
<span className="history-opt">[this window &#x2318;W]</span>
{" "}
<span className="term-bright-white">[this remote &#x2318;R]</span>
<span className="history-opt">[this remote &#x2318;R]</span>
{" "}
<span className="term-bright-white">[including metacmds &#x2318;M]</span>
<span className="history-opt">[including metacmds &#x2318;M]</span>
{" "} <span className="history-clickable-opt" onClick={this.handleClose}>(close ESC)</span>
</div>
<div className="history-items">
@ -626,7 +689,7 @@ class HistoryInfo extends React.Component<{}, {}> {
</If>
<If condition={hitems.length > 0}>
<For each="hitem" index="idx" of={hitems}>
{this.renderHItem(hitem, selNum)}
{this.renderHItem(hitem, (hitem == selItem))}
</For>
</If>
</div>
@ -728,9 +791,7 @@ class CmdInput extends React.Component<{}, {}> {
<div className="control cmd-quick-context">
<div className="button is-static">{remoteStr}</div>
</div>
<div className="control cmd-input-control is-expanded">
<TextAreaInput/>
</div>
<TextAreaInput/>
<div className="control cmd-exec">
<div onClick={GlobalModel.inputModel.uiSubmitCommand} className="button">
<span className="icon">

View File

@ -571,29 +571,120 @@ type HistoryQueryOpts = {
fromTs : number,
};
function getDefaultHistoryQueryOpts() : HistoryQueryOpts {
return {
queryType: "window",
limitRemote: true,
limitRemoteInstance: true,
limitUser: true,
queryStr: "",
maxItems: 10000,
includeMeta: true,
fromTs: 0,
};
}
class InputModel {
historyShow : OV<boolean> = mobx.observable.box(false);
infoShow : OV<boolean> = mobx.observable.box(false);
loadId : string = null;
historyLoading : mobx.IObservableValue<boolean> = mobx.observable.box(false);
historyAfterLoadIndex : number = 0;
historyItems : mobx.IObservableValue<HistoryItem[]> = mobx.observable.box(null, {name: "history-items", deep: false}); // sorted in reverse (most recent is index 0)
historyIndex : mobx.IObservableValue<number> = mobx.observable.box(0, {name: "history-index"}); // 1-indexed (because 0 is current)
modHistory : mobx.IObservableArray<string> = mobx.observable.array([""], {name: "mod-history"});
setHIdx : number = 0;
queryOpts : OV<HistoryQueryOpts> = mobx.observable.box(null);
historyQueryOpts : OV<HistoryQueryOpts> = mobx.observable.box(getDefaultHistoryQueryOpts());
infoMsg : OV<InfoType> = mobx.observable.box(null);
infoTimeoutId : any = null;
historySelectedNum : OV<string> = mobx.observable.box(null);
focusCmdInput() : void {
_focusCmdInput() : void {
let elem = document.getElementById("main-cmd-input");
if (elem != null) {
elem.focus();
}
}
_focusHistoryInput() : void {
let elem : HTMLElement = document.querySelector(".cmd-input input.history-input");
if (elem != null) {
elem.focus();
}
}
giveFocus() : void {
if (this.historyShow.get()) {
this._focusHistoryInput();
}
else {
this._focusCmdInput();
}
}
hasFocus() : boolean {
let mainInputElem = document.getElementById("main-cmd-input");
if (document.activeElement == mainInputElem) {
return true;
}
let historyInputElem = document.querySelector(".cmd-input input.history-input");
if (document.activeElement == historyInputElem) {
return true;
}
return false;
}
setHistoryShow(show : boolean) : void {
if (this.historyShow.get() == show) {
return;
}
mobx.action(() => {
this.historyShow.set(show);
if (this.hasFocus()) {
this.giveFocus();
}
})();
}
isHistoryLoaded() : boolean {
if (this.historyLoading.get()) {
return false;
}
let hitems = this.historyItems.get();
return (hitems != null);
}
loadHistory(show : boolean, afterLoadIndex : number) {
if (this.historyLoading.get()) {
return;
}
if (this.isHistoryLoaded()) {
return;
}
this.historyAfterLoadIndex = afterLoadIndex;
mobx.action(() => {
this.historyLoading.set(true);
})();
GlobalCommandRunner.loadHistory(show);
}
openHistory() : void {
if (this.historyLoading.get()) {
return;
}
if (!this.isHistoryLoaded()) {
this.loadHistory(true, 0);
return;
}
if (!this.historyShow.get()) {
mobx.action(() => {
this.setHistoryShow(true);
this.infoShow.set(false);
this.dropModHistory(true);
this.giveFocus();
})();
}
}
updateCmdLine(cmdLine : CmdLineUpdateType) : void {
mobx.action(() => {
let curLine = this.getCurLine();
@ -606,19 +697,49 @@ class InputModel {
})();
}
showHistory(hinfo : HistoryInfoType) : void {
getHistorySelectedItem() : HistoryItem {
let hidx = this.historyIndex.get();
if (hidx == 0) {
return null;
}
let hitems = this.getFilteredHistoryItems();
if (hidx > hitems.length) {
return null;
}
return hitems[hidx-1];
}
getFirstHistoryItem() : HistoryItem {
let hitems = this.getFilteredHistoryItems();
if (hitems.length == 0) {
return null;
}
return hitems[0];
}
setHistorySelectionNum(hnum : string) : void {
let hitems = this.getFilteredHistoryItems();
for (let i=0; i<hitems.length; i++) {
if (hitems[i].historynum == hnum) {
this.setHistoryIndex(i+1);
return;
}
}
}
setHistoryInfo(hinfo : HistoryInfoType) : void {
mobx.action(() => {
if (this.infoShow.get()) {
this.infoShow.set(false);
let hitems : HistoryItem[] = hinfo.items ?? [];
this.historyItems.set(hitems);
this.historyLoading.set(false);
if (this.historyAfterLoadIndex) {
if (hitems.length >= this.historyAfterLoadIndex) {
this.setHistoryIndex(this.historyAfterLoadIndex);
}
this.historyAfterLoadIndex = 0;
}
this.historyShow.set(true);
let items = hinfo.items ?? [];
this.historyItems.set(items);
if (items.length == 0) {
this.historySelectedNum.set(null);
}
else {
this.historySelectedNum.set(items[0].historynum);
if (hinfo.show) {
this.openHistory();
}
})();
}
@ -628,17 +749,6 @@ class InputModel {
return hitems;
}
findCurrentHistoryIndex() : number {
let hitems = this.historyItems.get();
let selNum = this.historySelectedNum.get();
for (let i=0; i<hitems.length; i++) {
if (hitems[i].historynum == selNum) {
return i;
}
}
return -1;
}
scrollHistoryItemIntoView(hnum : string) : void {
let elem : HTMLElement = document.querySelector(".cmd-history .hnum-" + hnum);
if (elem == null) {
@ -672,59 +782,60 @@ class InputModel {
}
}
setHistorySelectionNum(hnum : string) : void {
grabSelectedHistoryItem() : void {
let hitem = this.getHistorySelectedItem();
if (hitem == null) {
this.resetHistory();
return;
}
mobx.action(() => {
this.historySelectedNum.set(hnum);
this.scrollHistoryItemIntoView(hnum);
this.resetInput();
this.setCurLine(hitem.cmdstr);
})();
}
grabSelectedHistoryItem() : void {
let idx = this.findCurrentHistoryIndex();
if (idx == -1) {
setHistoryIndex(hidx : number) : void {
if (hidx < 0) {
return;
}
if (this.historyIndex.get() == hidx) {
return;
}
let hitem = this.historyItems.get()[idx];
mobx.action(() => {
this.clearCurLine();
this.setCurLine(hitem.cmdstr);
this.historyShow.set(false);
this.historyIndex.set(hidx);
if (this.historyShow.get()) {
let hitem = this.getHistorySelectedItem();
if (hitem == null) {
hitem = this.getFirstHistoryItem();
}
if (hitem != null) {
this.scrollHistoryItemIntoView(hitem.historynum);
}
}
})();
}
moveHistorySelection(amt : number) : void {
let hitems : HistoryItem[] = this.historyItems.get() ?? [];
if (hitems.length == 0 || amt == 0) {
if (amt == 0) {
return;
}
let idx = this.findCurrentHistoryIndex();
if (idx == -1) {
if (amt < 0) {
let hitem = hitems[hitems.length-1];
this.setHistorySelectionNum(hitem.historynum);
}
else {
let hitem = hitems[0];
this.setHistorySelectionNum(hitem.historynum);
}
if (!this.isHistoryLoaded()) {
return;
}
idx += -amt; // negate because history array is sorted in reverse
let hitems = this.getFilteredHistoryItems();
let idx = this.historyIndex.get();
idx += amt;
if (idx < 0) {
idx = 0;
}
if (idx >= hitems.length) {
idx = hitems.length-1;
if (idx > hitems.length) {
idx = hitems.length;
}
let hitem = hitems[idx];
this.setHistorySelectionNum(hitem.historynum);
this.setHistoryIndex(idx);
}
flashInfoMsg(info : InfoType, timeoutMs : number) : void {
if (this.infoTimeoutId != null) {
clearTimeout(this.infoTimeoutId);
this.infoTimeoutId = null;
}
this._clearInfoTimeout();
mobx.action(() => {
this.infoMsg.set(info);
if (info == null) {
@ -732,7 +843,7 @@ class InputModel {
}
else {
this.infoShow.set(true);
this.historyShow.set(false);
this.setHistoryShow(false);
}
})();
if (info != null && timeoutMs) {
@ -760,10 +871,17 @@ class InputModel {
return div.scrollHeight > div.clientHeight;
}
_clearInfoTimeout() : void {
if (this.infoTimeoutId != null) {
clearTimeout(this.infoTimeoutId);
this.infoTimeoutId = null;
}
}
clearInfoMsg(setNull : boolean) : void {
this.infoTimeoutId = null;
this._clearInfoTimeout();
mobx.action(() => {
this.historyShow.set(false);
this.setHistoryShow(false);
this.infoShow.set(false);
if (setNull) {
this.infoMsg.set(null);
@ -772,10 +890,10 @@ class InputModel {
}
toggleInfoMsg() : void {
this.infoTimeoutId = null;
this._clearInfoTimeout();
mobx.action(() => {
if (this.historyShow.get()) {
this.historyShow.set(false);
this.setHistoryShow(false);
return;
}
let isShowing = this.infoShow.get();
@ -797,7 +915,7 @@ class InputModel {
if (commandStr.trim() == "") {
return;
}
this.clearCurLine();
this.resetInput();
GlobalModel.submitRawCommand(commandStr, true, true);
})();
}
@ -812,70 +930,14 @@ class InputModel {
})();
}
loadHistory() : void {
if (this.historyLoading.get()) {
return;
}
let sessionId = GlobalModel.activeSessionId.get();
if (sessionId == null) {
this.setHIdx = 0;
return;
}
let win = GlobalModel.getActiveWindow();
if (win == null) {
this.setHIdx = 0;
return;
}
let loadId = uuidv4();
mobx.action(() => {
this.loadId = loadId;
this.historyItems.set(null);
this.historyLoading.set(true);
})();
let usp = new URLSearchParams({sessionid: sessionId, windowid: win.windowId});
let url = new URL("http://localhost:8080/api/get-history?" + usp.toString());
fetch(url).then((resp) => handleJsonFetchResponse(url, resp)).then((data) => {
if (loadId != this.loadId) {
return; // stale load
}
mobx.action(() => {
if (!this.historyLoading.get()) {
return;
}
if (sessionId != GlobalModel.activeSessionId.get()) {
this.resetHistory();
return;
}
if (data.data && data.data.history) {
let hitems : HistoryItem[] = data.data.history || [];
this.historyItems.set(hitems);
this.historyLoading.set(false);
let hlen = hitems.length;
let setHIdx = this.setHIdx;
if (setHIdx > hlen) {
setHIdx = hlen;
}
this.historyIndex.set(setHIdx);
this.setHIdx = 0;
}
})();
}).catch((err) => {
let isStale = (loadId != this.loadId);
if (isStale) {
return;
}
GlobalModel.errorHandler("getting history items", err, false);
mobx.action(() => {
this.historyLoading.set(false);
this.historyIndex.set(0);
})();
});
}
clearCurLine() : void {
resetInput() : void {
mobx.action(() => {
this.setHistoryShow(false);
this.infoShow.set(false);
this.resetHistory();
this.modHistory.replace([""]);
this.dropModHistory(false);
this.infoMsg.set(null);
this._clearInfoTimeout();
})();
}
@ -885,7 +947,7 @@ class InputModel {
if (hidx < this.modHistory.length && this.modHistory[hidx] != null) {
return this.modHistory[hidx];
}
let hitems = this.historyItems.get();
let hitems = this.getFilteredHistoryItems();
if (hidx == 0 || hitems == null || hidx > hitems.length) {
return "";
}
@ -896,53 +958,30 @@ class InputModel {
return hitem.cmdstr;
}
dropModHistory(keepLine0 : boolean) : void {
mobx.action(() => {
if (keepLine0) {
if (this.modHistory.length > 1) {
this.modHistory.splice(1, this.modHistory.length-1);
}
}
else {
this.modHistory.replace([""]);
}
})();
}
resetHistory() : void {
mobx.action(() => {
this.setHistoryShow(false);
this.historyLoading.set(false);
this.historyItems.set(null);
this.historyIndex.set(0);
if (this.modHistory.length > 1) {
this.modHistory.splice(1, this.modHistory.length-1);
}
this.setHIdx = 0;
this.historyQueryOpts.set(getDefaultHistoryQueryOpts());
this.historyAfterLoadIndex = 0;
this.dropModHistory(true);
})();
}
prevHistoryItem() : void {
let loading = this.historyLoading.get();
let hitems = this.historyItems.get();
if (loading || hitems == null) {
this.setHIdx += 1;
if (!loading) {
this.loadHistory();
}
return;
}
let hidx = this.historyIndex.get();
hidx += 1;
if (hidx > hitems.length) {
hidx = hitems.length;
}
mobx.action(() => {
this.historyIndex.set(hidx);
})();
return;
}
nextHistoryItem() : void {
let hidx = this.historyIndex.get();
if (hidx == 0) {
return;
}
hidx -= 1;
if (hidx < 0) {
hidx = 0;
}
mobx.action(() => {
this.historyIndex.set(hidx);
})();
return;
}
};
type LineFocusType = {
@ -1025,19 +1064,18 @@ class Model {
}
onICmd(e : any, mods : KeyModsType) {
this.inputModel.focusCmdInput();
this.inputModel.giveFocus();
}
onHCmd(e : any, mods : KeyModsType) {
let focusedLine = this.getFocusedLine();
if (focusedLine != null && focusedLine.cmdInputFocus) {
GlobalCommandRunner.openHistory();
this.inputModel.openHistory();
}
}
getFocusedLine() : LineFocusType {
let elem = document.getElementById("main-cmd-input");
if (document.activeElement == elem) {
if (this.inputModel.hasFocus()) {
return {cmdInputFocus: true};
}
let lineElem : any = document.activeElement.closest(".line[data-lineid]");
@ -1121,7 +1159,7 @@ class Model {
}
let runningLines = win.getRunningCmdLines();
if (runningLines.length == 0) {
this.inputModel.focusCmdInput();
this.inputModel.giveFocus();
return;
}
let foundIdx = -1;
@ -1132,7 +1170,7 @@ class Model {
}
}
if (foundIdx == -1 || foundIdx == runningLines.length - 1) {
this.inputModel.focusCmdInput();
this.inputModel.giveFocus();
return;
}
let switchLine = runningLines[foundIdx+1];
@ -1167,11 +1205,21 @@ class Model {
runUpdate(genUpdate : UpdateMessage, interactive : boolean) {
mobx.action(() => {
this.runUpdate_internal(genUpdate, interactive);
let oldContext = this.getUIContext();
this.runUpdate_internal(genUpdate, oldContext, interactive);
let newContext = this.getUIContext()
if (oldContext.sessionid != newContext.sessionid
|| oldContext.screenid != newContext.screenid
|| oldContext.windowid != newContext.windowid) {
this.inputModel.resetInput();
}
else if (remotePtrToString(oldContext.remote) != remotePtrToString(newContext.remote)) {
this.inputModel.resetHistory();
}
})();
}
runUpdate_internal(genUpdate : UpdateMessage, interactive : boolean) {
runUpdate_internal(genUpdate : UpdateMessage, uiContext : UIContextType, interactive : boolean) {
if ("ptydata64" in genUpdate) {
let ptyMsg : PtyDataUpdateType = genUpdate;
let activeScreen = this.getActiveScreen();
@ -1189,16 +1237,16 @@ class Model {
let newActiveScreen = this.getActiveScreen();
if (oldActiveScreen != newActiveScreen) {
if (newActiveScreen == null) {
this.activateScreen(this.activeSessionId.get(), null, oldActiveScreen);
this._activateScreen(this.activeSessionId.get(), null, oldActiveScreen);
}
else {
this.activateScreen(newActiveScreen.sessionId, newActiveScreen.screenId, oldActiveScreen);
this._activateScreen(newActiveScreen.sessionId, newActiveScreen.screenId, oldActiveScreen);
}
}
}
}
if ("activesessionid" in update) {
this.activateSession(update.activesessionid);
this._activateSession(update.activesessionid);
}
if ("line" in update) {
if (update.line != null) {
@ -1218,12 +1266,14 @@ class Model {
let info : InfoType = update.info;
this.inputModel.flashInfoMsg(info, info.timeoutms);
}
if (interactive && "history" in update) {
this.inputModel.showHistory(update.history);
}
if ("cmdline" in update) {
this.inputModel.updateCmdLine(update.cmdline);
}
if (interactive && "history" in update) {
if (uiContext.sessionid == update.history.sessionid && uiContext.windowid == update.history.windowid) {
this.inputModel.setHistoryInfo(update.history);
}
}
// console.log("run-update>", Date.now(), interactive, update);
}
@ -1333,24 +1383,6 @@ class Model {
});
}
getClientKwargs() : Record<string, string> {
let session = this.getActiveSession();
let win = this.getActiveWindow();
let screen = this.getActiveScreen();
let rtn : Record<string, string> = {};
if (session != null) {
rtn.session = session.sessionId;
}
if (screen != null) {
rtn.screen = screen.screenId;
}
if (win != null) {
rtn.window = win.windowId;
rtn.remote = remotePtrToString(win.curRemote.get());
}
return rtn;
}
isInfoUpdate(update : UpdateMessage) : boolean {
if (update == null || "ptydata64" in update) {
return false;
@ -1381,7 +1413,7 @@ class Model {
metacmd: metaCmd,
metasubcmd: metaSubCmd,
args: args,
kwargs: Object.assign({}, this.getClientKwargs(), kwargs),
kwargs: Object.assign({}, kwargs),
uicontext : this.getUIContext(),
};
this.submitCommandPacket(pk, interactive);
@ -1392,7 +1424,7 @@ class Model {
type: "fecmd",
metacmd: "eval",
args: [cmdStr],
kwargs: this.getClientKwargs(),
kwargs: null,
uicontext : this.getUIContext(),
};
if (!addToHistory) {
@ -1414,7 +1446,7 @@ class Model {
});
}
activateSession(sessionId : string) {
_activateSession(sessionId : string) {
let oldActiveSession = this.getActiveSession();
if (oldActiveSession != null && oldActiveSession.sessionId == sessionId) {
return;
@ -1423,10 +1455,10 @@ class Model {
if (newSession == null) {
return;
}
this.activateScreen(sessionId, newSession.activeScreenId.get());
this._activateScreen(sessionId, newSession.activeScreenId.get());
}
activateScreen(sessionId : string, screenId : string, oldActiveScreen? : Screen) {
_activateScreen(sessionId : string, screenId : string, oldActiveScreen? : Screen) {
if (!oldActiveScreen) {
oldActiveScreen = this.getActiveScreen();
}
@ -1438,7 +1470,6 @@ class Model {
let curSessionId = this.activeSessionId.get();
if (curSessionId != sessionId) {
this.activeSessionId.set(sessionId);
this.inputModel.resetHistory();
}
this.getActiveSession().activeScreenId.set(screenId);
})();
@ -1545,40 +1576,32 @@ class CommandRunner {
constructor() {
}
clearCmdInput() : void {
mobx.action(() => {
GlobalModel.inputModel.clearInfoMsg(true);
GlobalModel.inputModel.clearCurLine();
})();
}
openHistory() {
GlobalModel.submitCommand("history", null, null, {"nohist": "1"}, true);
loadHistory(show : boolean) {
let kwargs = {"nohist": "1"};
if (!show) {
kwargs["noshow"] = "1";
}
GlobalModel.submitCommand("history", null, null, kwargs, true);
}
switchSession(session : string) {
GlobalModel.submitCommand("session", null, [session], {"nohist": "1"}, false);
this.clearCmdInput();
}
switchScreen(screen : string) {
GlobalModel.submitCommand("screen", null, [screen], {"nohist": "1"}, false);
this.clearCmdInput();
}
createNewSession() {
GlobalModel.submitCommand("session", "open", null, {"nohist": "1"}, false);
this.clearCmdInput();
}
createNewScreen() {
GlobalModel.submitCommand("screen", "open", null, {"nohist": "1"}, false);
this.clearCmdInput();
}
closeScreen(screen : string) {
GlobalModel.submitCommand("screen", "close", [screen], {"nohist": "1"}, false);
this.clearCmdInput();
}
};

View File

@ -538,6 +538,7 @@ body .xterm .xterm-viewport {
&::-webkit-scrollbar {
background-color: #777;
width: 5px;
height: 5px;
}
&::-webkit-scrollbar-thumb {
@ -591,6 +592,10 @@ body .xterm .xterm-viewport {
}
.cmd-input-field {
.cmd-input-control {
line-height: 0;
}
textarea {
color: white;
background-color: black;
@ -601,6 +606,16 @@ body .xterm .xterm-viewport {
&:active, &:focus {
border-color: white !important;
}
&.display-disabled {
background-color: #444;
}
}
input.history-input {
border: 0;
padding: 0;
height: 0;
}
.cmd-quick-context .button {
@ -632,6 +647,9 @@ body .xterm .xterm-viewport {
color: #729fcf;
padding-bottom: 4px;
.history-opt {
}
.history-clickable-opt {
cursor: pointer;
}
@ -655,6 +673,11 @@ body .xterm .xterm-viewport {
.history-item {
padding-left: 5px;
cursor: pointer;
&:hover {
background-color: #222;
}
}
.history-item.is-selected {

View File

@ -220,7 +220,10 @@ type ModelUpdateType = {
};
type HistoryInfoType = {
sessionid : string,
windowid : string,
items : HistoryItem[],
show : boolean,
};
type CmdLineUpdateType = {