mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-08 19:38:51 +01:00
big update to get base history info panel working
This commit is contained in:
parent
087c0c4f1f
commit
9ed993078d
131
src/main.tsx
131
src/main.tsx
@ -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 ⌘S]</span>
|
||||
<span className="history-opt">[this session ⌘S]</span>
|
||||
{" "}
|
||||
<span className="term-bright-white">[this window ⌘W]</span>
|
||||
<span className="history-opt">[this window ⌘W]</span>
|
||||
{" "}
|
||||
<span className="term-bright-white">[this remote ⌘R]</span>
|
||||
<span className="history-opt">[this remote ⌘R]</span>
|
||||
{" "}
|
||||
<span className="term-bright-white">[including metacmds ⌘M]</span>
|
||||
<span className="history-opt">[including metacmds ⌘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">
|
||||
|
463
src/model.ts
463
src/model.ts
@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
|
23
src/sh2.less
23
src/sh2.less
@ -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 {
|
||||
|
@ -220,7 +220,10 @@ type ModelUpdateType = {
|
||||
};
|
||||
|
||||
type HistoryInfoType = {
|
||||
sessionid : string,
|
||||
windowid : string,
|
||||
items : HistoryItem[],
|
||||
show : boolean,
|
||||
};
|
||||
|
||||
type CmdLineUpdateType = {
|
||||
|
Loading…
Reference in New Issue
Block a user