mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
use screenmap instead of screenlist, some tweaks to hints
This commit is contained in:
+5
-1
@@ -6,6 +6,10 @@ import {boundMethod} from "autobind-decorator";
|
|||||||
import cn from "classnames";
|
import cn from "classnames";
|
||||||
import {If, For, When, Otherwise, Choose} from "tsx-control-statements/components";
|
import {If, For, When, Otherwise, Choose} from "tsx-control-statements/components";
|
||||||
|
|
||||||
|
function renderCmdText(text : string) : any {
|
||||||
|
return <span>⌘{text}</span>;
|
||||||
|
}
|
||||||
|
|
||||||
class CmdStrCode extends React.Component<{cmdstr : string, onUse : () => void, onCopy : () => void, isCopied : boolean, fontSize : "normal" | "large", limitHeight : boolean}, {}> {
|
class CmdStrCode extends React.Component<{cmdstr : string, onUse : () => void, onCopy : () => void, isCopied : boolean, fontSize : "normal" | "large", limitHeight : boolean}, {}> {
|
||||||
@boundMethod
|
@boundMethod
|
||||||
handleUse(e : any) {
|
handleUse(e : any) {
|
||||||
@@ -65,4 +69,4 @@ class Toggle extends React.Component<{checked : boolean, onChange : (value : boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {CmdStrCode, Toggle};
|
export {CmdStrCode, Toggle, renderCmdText};
|
||||||
|
|||||||
+7
-1
@@ -12,6 +12,7 @@ import type {LineType, CmdDataType, FeStateType, RemoteType, RemotePtrType, Rend
|
|||||||
import cn from "classnames";
|
import cn from "classnames";
|
||||||
import {TermWrap} from "./term";
|
import {TermWrap} from "./term";
|
||||||
import type {LineContainerModel} from "./model";
|
import type {LineContainerModel} from "./model";
|
||||||
|
import {renderCmdText} from "./elements";
|
||||||
|
|
||||||
dayjs.extend(localizedFormat)
|
dayjs.extend(localizedFormat)
|
||||||
|
|
||||||
@@ -125,7 +126,7 @@ class LineAvatar extends React.Component<{line : LineType, cmd : Cmd}, {}> {
|
|||||||
|
|
||||||
|
|
||||||
@mobxReact.observer
|
@mobxReact.observer
|
||||||
class LineCmd extends React.Component<{screen : LineContainerModel, line : LineType, width : number, staticRender : boolean, visible : OV<boolean>, onHeightChange : HeightChangeCallbackType, topBorder : boolean, renderMode : RenderModeType, overrideCollapsed : OV<boolean>, noSelect? : boolean}, {}> {
|
class LineCmd extends React.Component<{screen : LineContainerModel, line : LineType, width : number, staticRender : boolean, visible : OV<boolean>, onHeightChange : HeightChangeCallbackType, topBorder : boolean, renderMode : RenderModeType, overrideCollapsed : OV<boolean>, noSelect? : boolean, showHints? : boolean}, {}> {
|
||||||
lineRef : React.RefObject<any> = React.createRef();
|
lineRef : React.RefObject<any> = React.createRef();
|
||||||
cmdTextRef : React.RefObject<any> = React.createRef();
|
cmdTextRef : React.RefObject<any> = React.createRef();
|
||||||
rtnStateDiff : mobx.IObservableValue<string> = mobx.observable.box(null, {name: "linecmd-rtn-state-diff"});
|
rtnStateDiff : mobx.IObservableValue<string> = mobx.observable.box(null, {name: "linecmd-rtn-state-diff"});
|
||||||
@@ -514,6 +515,11 @@ class LineCmd extends React.Component<{screen : LineContainerModel, line : LineT
|
|||||||
</If>
|
</If>
|
||||||
</div>
|
</div>
|
||||||
</If>
|
</If>
|
||||||
|
<If condition={isSelected && !isFocused}>
|
||||||
|
<div className="cmd-hints">
|
||||||
|
<div className="hint-item color-nohover-white">focus line ({renderCmdText("L")})</div>
|
||||||
|
</div>
|
||||||
|
</If>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-6
@@ -19,6 +19,7 @@ import {BookmarksView} from "./bookmarks";
|
|||||||
import {HistoryView} from "./history";
|
import {HistoryView} from "./history";
|
||||||
import {Line, Prompt} from "./linecomps";
|
import {Line, Prompt} from "./linecomps";
|
||||||
import {ScreenSettingsModal, SessionSettingsModal} from "./settings";
|
import {ScreenSettingsModal, SessionSettingsModal} from "./settings";
|
||||||
|
import {renderCmdText} from "./elements";
|
||||||
|
|
||||||
dayjs.extend(localizedFormat)
|
dayjs.extend(localizedFormat)
|
||||||
|
|
||||||
@@ -41,10 +42,6 @@ type InterObsValue = {
|
|||||||
timeoutid? : any,
|
timeoutid? : any,
|
||||||
};
|
};
|
||||||
|
|
||||||
function renderCmdText(text : string) : any {
|
|
||||||
return <span>⌘{text}</span>;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isBlank(s : string) : boolean {
|
function isBlank(s : string) : boolean {
|
||||||
return (s == null || s == "");
|
return (s == null || s == "");
|
||||||
}
|
}
|
||||||
@@ -1444,8 +1441,12 @@ class CmdInput extends React.Component<{}, {}> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@boundMethod
|
@boundMethod
|
||||||
clickHistoryHint() : void {
|
clickHistoryHint(e : any) : void {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
let inputModel = GlobalModel.inputModel;
|
let inputModel = GlobalModel.inputModel;
|
||||||
|
console.log("hitory hint", inputModel.historyShow.get());
|
||||||
if (inputModel.historyShow.get()) {
|
if (inputModel.historyShow.get()) {
|
||||||
inputModel.resetHistory();
|
inputModel.resetHistory();
|
||||||
}
|
}
|
||||||
@@ -1514,7 +1515,7 @@ class CmdInput extends React.Component<{}, {}> {
|
|||||||
</div>
|
</div>
|
||||||
<div className="cmd-hints">
|
<div className="cmd-hints">
|
||||||
<If condition={!focusVal}><div onClick={this.clickFocusInputHint} className="hint-item color-white">focus input ({renderCmdText("I")})</div></If>
|
<If condition={!focusVal}><div onClick={this.clickFocusInputHint} className="hint-item color-white">focus input ({renderCmdText("I")})</div></If>
|
||||||
<If condition={focusVal}><div onClick={this.clickHistoryHint} className="hint-item color-green"><i className={cn("fa-sharp fa-solid", (historyShow ? "fa-angle-down" : "fa-angle-up"))}/> {historyShow ? "close history (esc)" : "show history (ctrl-r)"}</div></If>
|
<If condition={focusVal}><div onMouseDown={this.clickHistoryHint} className="hint-item color-green"><i className={cn("fa-sharp fa-solid", (historyShow ? "fa-angle-down" : "fa-angle-up"))}/> {historyShow ? "close history (esc)" : "show history (ctrl-r)"}</div></If>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -2173,6 +2174,17 @@ class ScreenTabs extends React.Component<{session : Session}, {}> {
|
|||||||
showingScreens.push(screen);
|
showingScreens.push(screen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
showingScreens.sort((a, b) => {
|
||||||
|
let aidx = a.screenIdx.get();
|
||||||
|
let bidx = b.screenIdx.get();
|
||||||
|
if (aidx < bidx) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (aidx > bidx) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
return (
|
return (
|
||||||
<div className="screen-tabs-container">
|
<div className="screen-tabs-container">
|
||||||
<div className={cn("screen-tabs", {"scrolling": this.scrolling.get()})} ref={this.tabsRef} onScroll={this.handleScroll}>
|
<div className={cn("screen-tabs", {"scrolling": this.scrolling.get()})} ref={this.tabsRef} onScroll={this.handleScroll}>
|
||||||
|
|||||||
+9
-20
@@ -2,7 +2,7 @@ import * as mobx from "mobx";
|
|||||||
import {sprintf} from "sprintf-js";
|
import {sprintf} from "sprintf-js";
|
||||||
import {boundMethod} from "autobind-decorator";
|
import {boundMethod} from "autobind-decorator";
|
||||||
import {debounce} from "throttle-debounce";
|
import {debounce} from "throttle-debounce";
|
||||||
import {handleJsonFetchResponse, base64ToArray, genMergeData, genMergeSimpleData, boundInt, isModKeyPress} from "./util";
|
import {handleJsonFetchResponse, base64ToArray, genMergeData, genMergeDataMap, genMergeSimpleData, boundInt, isModKeyPress} from "./util";
|
||||||
import {TermWrap} from "./term";
|
import {TermWrap} from "./term";
|
||||||
import {v4 as uuidv4} from "uuid";
|
import {v4 as uuidv4} from "uuid";
|
||||||
import type {SessionDataType, LineType, RemoteType, HistoryItem, RemoteInstanceType, RemotePtrType, CmdDataType, FeCmdPacketType, TermOptsType, RemoteStateType, ScreenDataType, ScreenOptsType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, UIContextType, HistoryInfoType, HistoryQueryOpts, FeInputPacketType, TermWinSize, RemoteInputPacketType, FeStateType, ContextMenuOpts, RendererContext, RendererModel, PtyDataType, BookmarkType, ClientDataType, HistoryViewDataType, AlertMessageType, HistorySearchParams, FocusTypeStrs, ScreenLinesType, HistoryTypeStrs} from "./types";
|
import type {SessionDataType, LineType, RemoteType, HistoryItem, RemoteInstanceType, RemotePtrType, CmdDataType, FeCmdPacketType, TermOptsType, RemoteStateType, ScreenDataType, ScreenOptsType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, UIContextType, HistoryInfoType, HistoryQueryOpts, FeInputPacketType, TermWinSize, RemoteInputPacketType, FeStateType, ContextMenuOpts, RendererContext, RendererModel, PtyDataType, BookmarkType, ClientDataType, HistoryViewDataType, AlertMessageType, HistorySearchParams, FocusTypeStrs, ScreenLinesType, HistoryTypeStrs} from "./types";
|
||||||
@@ -2228,7 +2228,7 @@ class Model {
|
|||||||
activeSessionId : OV<string> = mobx.observable.box(null, {name: "activeSessionId"});
|
activeSessionId : OV<string> = mobx.observable.box(null, {name: "activeSessionId"});
|
||||||
sessionListLoaded : OV<boolean> = mobx.observable.box(false, {name: "sessionListLoaded"});
|
sessionListLoaded : OV<boolean> = mobx.observable.box(false, {name: "sessionListLoaded"});
|
||||||
sessionList : OArr<Session> = mobx.observable.array([], {name: "SessionList", deep: false});
|
sessionList : OArr<Session> = mobx.observable.array([], {name: "SessionList", deep: false});
|
||||||
screenList : OArr<Screen> = mobx.observable.array([], {name: "ScreenList", deep: false});
|
screenMap : OMap<string, Screen> = mobx.observable.map({}, {name: "ScreenMap", deep: false});
|
||||||
ws : WSControl;
|
ws : WSControl;
|
||||||
remotes : OArr<RemoteType> = mobx.observable.array([], {name: "remotes", deep: false});
|
remotes : OArr<RemoteType> = mobx.observable.array([], {name: "remotes", deep: false});
|
||||||
remotesLoaded : OV<boolean> = mobx.observable.box(false, {name: "remotesLoaded"});
|
remotesLoaded : OV<boolean> = mobx.observable.box(false, {name: "remotesLoaded"});
|
||||||
@@ -2580,14 +2580,11 @@ class Model {
|
|||||||
let update : ModelUpdateType = genUpdate;
|
let update : ModelUpdateType = genUpdate;
|
||||||
if ("screens" in update) {
|
if ("screens" in update) {
|
||||||
if (update.connect) {
|
if (update.connect) {
|
||||||
this.screenList.clear();
|
this.screenMap.clear();
|
||||||
}
|
}
|
||||||
genMergeData(this.screenList, update.screens, (s : Screen) => s.screenId, (sdata : ScreenDataType) => sdata.screenid, (sdata : ScreenDataType) => new Screen(sdata), null);
|
let mods = genMergeDataMap(this.screenMap, update.screens, (s : Screen) => s.screenId, (sdata : ScreenDataType) => sdata.screenid, (sdata : ScreenDataType) => new Screen(sdata));
|
||||||
for (let i=0; i<update.screens.length; i++) {
|
for (let i=0; i<mods.removed.length; i++) {
|
||||||
let screen = update.screens[i];
|
this.removeScreenLinesByScreenId(mods.removed[i]);
|
||||||
if (screen.remove) {
|
|
||||||
this.removeScreenLinesByScreenId(screen.screenid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ("sessions" in update) {
|
if ("sessions" in update) {
|
||||||
@@ -2689,8 +2686,7 @@ class Model {
|
|||||||
|
|
||||||
getScreenNames() : Record<string, string> {
|
getScreenNames() : Record<string, string> {
|
||||||
let rtn : Record<string, string> = {};
|
let rtn : Record<string, string> = {};
|
||||||
for (let i=0; i<this.screenList.length; i++) {
|
for (let screen of this.screenMap.values()) {
|
||||||
let screen = this.screenList[i];
|
|
||||||
rtn[screen.screenId] = screen.name.get();
|
rtn[screen.screenId] = screen.name.get();
|
||||||
}
|
}
|
||||||
return rtn;
|
return rtn;
|
||||||
@@ -2752,19 +2748,12 @@ class Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getScreenById(sessionId : string, screenId : string) : Screen {
|
getScreenById(sessionId : string, screenId : string) : Screen {
|
||||||
for (let i=0; i<this.screenList.length; i++) {
|
return this.screenMap.get(screenId);
|
||||||
let screen = this.screenList[i];
|
|
||||||
if (screen.screenId == screenId) {
|
|
||||||
return screen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getSessionScreens(sessionId : string) : Screen[] {
|
getSessionScreens(sessionId : string) : Screen[] {
|
||||||
let rtn : Screen[] = [];
|
let rtn : Screen[] = [];
|
||||||
for (let i=0; i<this.screenList.length; i++) {
|
for (let screen of this.screenMap.values()) {
|
||||||
let screen = this.screenList[i];
|
|
||||||
if (screen.sessionId == sessionId) {
|
if (screen.sessionId == sessionId) {
|
||||||
rtn.push(screen);
|
rtn.push(screen);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1671,6 +1671,21 @@ body::-webkit-scrollbar {
|
|||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cmd-hints {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0px;
|
||||||
|
right: 0px;
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
.hint-item {
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .cmd-hints {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
body .xterm .xterm-viewport {
|
body .xterm .xterm-viewport {
|
||||||
@@ -2782,6 +2797,12 @@ input[type=checkbox] {
|
|||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hint-item.color-nohover-green {
|
||||||
|
color: black;
|
||||||
|
background-color: @tab-green;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
.hint-item.color-white {
|
.hint-item.color-white {
|
||||||
color: black;
|
color: black;
|
||||||
@@ -2791,6 +2812,27 @@ input[type=checkbox] {
|
|||||||
background-color: @term-bright-white;
|
background-color: @term-bright-white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hint-item.color-nohover-white {
|
||||||
|
color: black;
|
||||||
|
background-color: @term-white;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint-item.color-blue {
|
||||||
|
color: black;
|
||||||
|
background-color: @tab-blue;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint-item.color-nohover-blue {
|
||||||
|
color: black;
|
||||||
|
background-color: @tab-blue;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-field {
|
.settings-field {
|
||||||
|
|||||||
+40
-1
@@ -142,6 +142,45 @@ function genMergeData<ObjType extends IObjType<DataType>, DataType extends IData
|
|||||||
objs.replace(newObjs);
|
objs.replace(newObjs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function genMergeDataMap<ObjType extends IObjType<DataType>, DataType extends IDataType>(
|
||||||
|
objMap : mobx.ObservableMap<string, ObjType>,
|
||||||
|
dataArr : DataType[],
|
||||||
|
objIdFn : (obj : ObjType) => string,
|
||||||
|
dataIdFn : (data : DataType) => string,
|
||||||
|
ctorFn : (data : DataType) => ObjType,
|
||||||
|
) : {added : string[], removed : string[]}
|
||||||
|
{
|
||||||
|
let rtn : {added : string[], removed : string[]} = {added: [], removed: []};
|
||||||
|
if (dataArr == null || dataArr.length == 0) {
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
for (let i=0; i<dataArr.length; i++) {
|
||||||
|
let dataItem = dataArr[i];
|
||||||
|
let id = dataIdFn(dataItem);
|
||||||
|
let obj = objMap.get(id);
|
||||||
|
if (dataItem.remove) {
|
||||||
|
if (obj != null) {
|
||||||
|
obj.dispose();
|
||||||
|
objMap.delete(id);
|
||||||
|
rtn.removed.push(id);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
if (!dataItem.full) {
|
||||||
|
console.log("cannot create object, dataitem is not full", dataItem);
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
obj = ctorFn(dataItem);
|
||||||
|
objMap.set(id, obj);
|
||||||
|
rtn.added.push(id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
obj.mergeData(dataItem);
|
||||||
|
}
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
function parseEnv0(envStr64 : string) : Map<string, string> {
|
function parseEnv0(envStr64 : string) : Map<string, string> {
|
||||||
let envStr = atob(envStr64);
|
let envStr = atob(envStr64);
|
||||||
let parts = envStr.split("\x00");
|
let parts = envStr.split("\x00");
|
||||||
@@ -182,4 +221,4 @@ function incObs(inum : mobx.IObservableValue<number>) {
|
|||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
export {handleJsonFetchResponse, base64ToArray, genMergeData, genMergeSimpleData, parseEnv0, boundInt, isModKeyPress, incObs};
|
export {handleJsonFetchResponse, base64ToArray, genMergeData, genMergeDataMap, genMergeSimpleData, parseEnv0, boundInt, isModKeyPress, incObs};
|
||||||
|
|||||||
Reference in New Issue
Block a user