diff --git a/src/main.tsx b/src/main.tsx index 24b03a589..dd8278860 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -249,12 +249,12 @@ class CmdInput extends React.Component<{}, {}> { e.preventDefault(); let lastTab = (ltCurLine != null && curLine == ltCurLine); if (lastTab) { - GlobalModel.submitCommand("compgen", null, [curLine], {"comppos": String(curLine.length), "compshow": "1"}); + GlobalModel.submitCommand("compgen", null, [curLine], {"comppos": String(curLine.length), "compshow": "1", "nohist": "1"}); return; } else { this.lastTabCurLine.set(curLine); - GlobalModel.submitCommand("compgen", null, [curLine], {"comppos": String(curLine.length)}); + GlobalModel.submitCommand("compgen", null, [curLine], {"comppos": String(curLine.length), "nohist": "1"}); GlobalModel.clearInfoMsg(true); return; } @@ -306,7 +306,7 @@ class CmdInput extends React.Component<{}, {}> { let hitem = {cmdtext: commandStr}; inputModel.clearCurLine(); GlobalModel.clearInfoMsg(true); - model.submitRawCommand(commandStr); + model.submitRawCommand(commandStr, true); } getAfterSlash(s : string) : string { diff --git a/src/model.ts b/src/model.ts index c68263487..5a1c3fd3c 100644 --- a/src/model.ts +++ b/src/model.ts @@ -263,7 +263,6 @@ class Window { loaded : OV = mobx.observable.box(false); loadError : OV = mobx.observable.box(null); lines : OArr = mobx.observable.array([], {deep: false}); - history : any[] = []; cmds : Record = {}; remoteInstances : OArr = mobx.observable.array([]); @@ -272,14 +271,6 @@ class Window { this.windowId = windowId; } - getNumHistoryItems() : number { - return 0; - } - - getHistoryItem(hnum : number) : any { - return null - } - updatePtyData(ptyMsg : PtyDataUpdateType) { let cmd = this.cmds[ptyMsg.cmdid]; if (cmd == null) { @@ -297,7 +288,6 @@ class Window { this.loaded.set(true); } genMergeSimpleData(this.lines, win.lines, (l : LineType) => String(l.lineid), (l : LineType) => l.lineid); - this.history = win.history || []; let cmds = win.cmds || []; for (let i=0; i = mobx.observable.box(0, {name: "history-index"}); + historyLoading : mobx.IObservableValue = mobx.observable.box(false); + historySessionId : string = null; + historyItems : mobx.IObservableValue = mobx.observable.box(null, {name: "history-items", deep: false}); + historyIndex : mobx.IObservableValue = mobx.observable.box(0, {name: "history-index"}); // 1-indexed (because 0 is current) modHistory : mobx.IObservableArray = mobx.observable.array([""], {name: "mod-history"}); + setHIdx : number = 0; updateCmdLine(cmdLine : CmdLineUpdateType) { mobx.action(() => { @@ -516,14 +510,66 @@ class InputModel { setCurLine(val : string) { let hidx = this.historyIndex.get(); - this.modHistory[hidx] = val; + mobx.action(() => { + if (this.modHistory.length <= hidx) { + this.modHistory.length = hidx + 1; + } + this.modHistory[hidx] = val; + })(); + } + + loadHistory() { + if (this.historyLoading.get()) { + return; + } + let sessionId = GlobalModel.activeSessionId.get(); + if (sessionId == null) { + this.setHIdx = 0; + return; + } + mobx.action(() => { + this.historySessionId = sessionId; + this.historyItems.set(null); + this.historyLoading.set(true); + })(); + let usp = new URLSearchParams({sessionid: sessionId}); + let url = new URL("http://localhost:8080/api/get-history?" + usp.toString()); + fetch(url).then((resp) => handleJsonFetchResponse(url, resp)).then((data) => { + 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.historySessionId = sessionId; + 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) => { + GlobalModel.errorHandler("getting history items", err, false); + mobx.action(() => { + this.historyLoading.set(false); + this.historyIndex.set(0); + })(); + }); } clearCurLine() { mobx.action(() => { - this.historyIndex.set(0); - this.modHistory.clear(); - this.modHistory[0] = ""; + this.resetHistory(); + this.modHistory.replace([""]); })(); } @@ -533,24 +579,43 @@ class InputModel { if (hidx < this.modHistory.length && this.modHistory[hidx] != null) { return this.modHistory[hidx]; } - let win = model.getActiveWindow(); - if (win == null) { + let hitems = this.historyItems.get(); + if (hidx == 0 || hitems == null || hidx > hitems.length) { return ""; } - let hitem = win.getHistoryItem(-hidx); + let hitem = hitems[hidx-1]; if (hitem == null) { return ""; } - return hitem.cmdtext; + return hitem.cmdstr; + } + + resetHistory() : void { + mobx.action(() => { + 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; + })(); } prevHistoryItem() : void { - let model = GlobalModel; - let win = model.getActiveWindow(); + 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 > win.getNumHistoryItems()) { - hidx = win.getNumHistoryItems(); + if (hidx > hitems.length) { + hidx = hitems.length; } mobx.action(() => { this.historyIndex.set(hidx); @@ -560,6 +625,9 @@ class InputModel { nextHistoryItem() : void { let hidx = this.historyIndex.get(); + if (hidx == 0) { + return; + } hidx -= 1; if (hidx < 0) { hidx = 0; @@ -854,13 +922,16 @@ class Model { this.submitCommandPacket(pk); } - submitRawCommand(cmdStr : string) { + submitRawCommand(cmdStr : string, addToHistory : boolean) { let pk : FeCmdPacketType = { type: "fecmd", metacmd: "eval", args: [cmdStr], kwargs: this.getClientKwargs(), }; + if (!addToHistory) { + pk.kwargs["nohist"] = "1"; + } this.submitCommandPacket(pk) } @@ -913,7 +984,11 @@ class Model { } mobx.action(() => { this.deactivateWindows(); - this.activeSessionId.set(sessionId); + let curSessionId = this.activeSessionId.get(); + if (curSessionId != sessionId) { + this.activeSessionId.set(sessionId); + this.inputModel.resetHistory(); + } this.getActiveSession().activeScreenId.set(screenId); })(); let curScreen = this.getActiveScreen(); @@ -1005,23 +1080,23 @@ class InputClass { } switchSession(session : string) { - GlobalModel.submitCommand("session", null, [session], null); + GlobalModel.submitCommand("session", null, [session], {"nohist": "1"}); } switchScreen(screen : string) { - GlobalModel.submitCommand("screen", null, [screen], null); + GlobalModel.submitCommand("screen", null, [screen], {"nohist": "1"}); } createNewSession() { - GlobalModel.submitCommand("session", "open", null, null); + GlobalModel.submitCommand("session", "open", null, {"nohist": "1"}); } createNewScreen() { - GlobalModel.submitCommand("screen", "open", null, null); + GlobalModel.submitCommand("screen", "open", null, {"nohist": "1"}); } closeScreen(screen : string) { - GlobalModel.submitCommand("screen", "close", [screen], null); + GlobalModel.submitCommand("screen", "close", [screen], {"nohist": "1"}); } }; diff --git a/src/types.ts b/src/types.ts index 38e7496c0..e01cc66dc 100644 --- a/src/types.ts +++ b/src/types.ts @@ -98,7 +98,6 @@ type WindowDataType = { windowid : string, curremote : string, lines : LineType[], - history : HistoryItem[], cmds : CmdDataType[], remotes : RemoteInstanceType[], @@ -107,7 +106,17 @@ type WindowDataType = { }; type HistoryItem = { + historyid : string, + ts : number, + userid : string, + sessionid : string, + screenid : string, + windowid : string, + lineid : number, + haderror : boolean, + cmdid : string, cmdstr : string, + remove : boolean, }; type CmdRemoteStateType = {