diff --git a/src/main.tsx b/src/main.tsx
index 9922f0c8..ba0d766f 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -9,7 +9,7 @@ import dayjs from "dayjs";
import {If, For, When, Otherwise, Choose} from "tsx-control-statements/components";
import cn from "classnames";
import {TermWrap} from "./term";
-import type {SessionDataType, LineType, CmdDataType, RemoteType, RemoteStateType, RemoteInstanceType, RemotePtrType, HistoryItem, HistoryQueryOpts, RemoteEditType, FeStateType, ContextMenuOpts} from "./types";
+import type {SessionDataType, LineType, CmdDataType, RemoteType, RemoteStateType, RemoteInstanceType, RemotePtrType, HistoryItem, HistoryQueryOpts, RemoteEditType, FeStateType, ContextMenuOpts, BookmarkType} from "./types";
import localizedFormat from 'dayjs/plugin/localizedFormat';
import {GlobalModel, GlobalCommandRunner, Session, Cmd, Window, Screen, ScreenWindow, riToRPtr, windowWidthToCols, windowHeightToRows, termHeightFromRows, termWidthFromCols} from "./model";
import {isModKeyPress} from "./util";
@@ -2751,7 +2751,7 @@ class SessionView extends React.Component<{}, {}> {
if (cmdInputHeight == 0) {
cmdInputHeight = 110;
}
- let isHidden = GlobalModel.historyViewActive.get();
+ let isHidden = (GlobalModel.activeMainView.get() != "session");
return (
@@ -2766,17 +2766,7 @@ class SessionView extends React.Component<{}, {}> {
@mobxReact.observer
class HistoryView extends React.Component<{}, {}> {
render() {
- let model = GlobalModel;
- let session = model.getActiveSession();
- if (session == null) {
- return (no active session)
;
- }
- let activeScreen = session.getActiveScreen();
- let cmdInputHeight = model.inputModel.cmdInputHeight.get();
- if (cmdInputHeight == 0) {
- cmdInputHeight = 110;
- }
- let isHidden = !GlobalModel.historyViewActive.get();
+ let isHidden = (GlobalModel.activeMainView.get() != "history");
return (
HISTORY
@@ -2785,6 +2775,26 @@ class HistoryView extends React.Component<{}, {}> {
}
}
+@mobxReact.observer
+class BookmarksView extends React.Component<{}, {}> {
+ render() {
+ let isHidden = (GlobalModel.activeMainView.get() != "bookmarks");
+ let bookmarks = GlobalModel.bookmarksModel.bookmarks;
+ let idx : number = 0;
+ let bookmark : BookmarkType = null;
+ return (
+
+
BOOKMARKS
+
+
+ bookmark {idx} -- {JSON.stringify(bookmark)}
+
+
+
+ );
+ }
+}
+
function getConnVal(r : RemoteType) : number {
if (r.status == "connected") {
return 1;
@@ -2868,15 +2878,18 @@ class MainSideBar extends React.Component<{}, {}> {
@boundMethod
handleHistoryClick() : void {
- mobx.action(() => {
- let isActive = GlobalModel.historyViewActive.get();
- GlobalModel.historyViewActive.set(!isActive);
- })();
+ console.log("history click");
}
@boundMethod
handleBookmarksClick() : void {
- console.log("click bookmarks");
+ if (GlobalModel.activeMainView.get() == "bookmarks") {
+ mobx.action(() => {
+ GlobalModel.activeMainView.set("session");
+ })();
+ return;
+ }
+ GlobalCommandRunner.bookmarksView();
}
render() {
@@ -2906,6 +2919,7 @@ class MainSideBar extends React.Component<{}, {}> {
}
}
let isCollapsed = this.collapsed.get();
+ let mainView = GlobalModel.activeMainView.get();
return (
diff --git a/src/model.ts b/src/model.ts
index 10f7fa4f..7d61f907 100644
--- a/src/model.ts
+++ b/src/model.ts
@@ -5,7 +5,7 @@ import {debounce} from "throttle-debounce";
import {handleJsonFetchResponse, base64ToArray, genMergeData, genMergeSimpleData, boundInt, isModKeyPress} from "./util";
import {TermWrap} from "./term";
import {v4 as uuidv4} from "uuid";
-import type {SessionDataType, WindowDataType, LineType, RemoteType, HistoryItem, RemoteInstanceType, RemotePtrType, CmdDataType, FeCmdPacketType, TermOptsType, RemoteStateType, ScreenDataType, ScreenWindowType, ScreenOptsType, LayoutType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, UIContextType, HistoryInfoType, HistoryQueryOpts, FeInputPacketType, TermWinSize, RemoteInputPacketType, FeStateType, ContextMenuOpts, RendererContext, RendererModel, PtyDataType} from "./types";
+import type {SessionDataType, WindowDataType, LineType, RemoteType, HistoryItem, RemoteInstanceType, RemotePtrType, CmdDataType, FeCmdPacketType, TermOptsType, RemoteStateType, ScreenDataType, ScreenWindowType, ScreenOptsType, LayoutType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, UIContextType, HistoryInfoType, HistoryQueryOpts, FeInputPacketType, TermWinSize, RemoteInputPacketType, FeStateType, ContextMenuOpts, RendererContext, RendererModel, PtyDataType, BookmarksViewType, BookmarkType} from "./types";
import {WSControl} from "./ws";
import {ImageRendererModel} from "./imagerenderer";
@@ -1583,6 +1583,10 @@ type LineFocusType = {
cmdid? : string,
};
+class BookmarksModel {
+ bookmarks : OArr = mobx.observable.array([], {name: "Bookmarks"});
+}
+
class Model {
clientId : string;
activeSessionId : OV = mobx.observable.box(null, {name: "activeSessionId"});
@@ -1592,14 +1596,16 @@ class Model {
remotes : OArr = mobx.observable.array([], {name: "remotes", deep: false});
remotesLoaded : OV = mobx.observable.box(false, {name: "remotesLoaded"});
windows : OMap = mobx.observable.map({}, {name: "windows", deep: false}); // key = "sessionid/windowid"
- inputModel : InputModel;
termUsedRowsCache : Record = {};
debugCmds : number = 0;
debugSW : OV = mobx.observable.box(false);
localServerRunning : OV;
authKey : string;
isDev : boolean;
- historyViewActive : OV = mobx.observable.box(false, {name: "historyViewActive"});
+ activeMainView : OV<"session" | "history" | "bookmarks"> = mobx.observable.box("session", {name: "activeMainView"});
+
+ inputModel : InputModel;
+ bookmarksModel : BookmarksModel;
constructor() {
this.clientId = getApi().getId();
@@ -1608,6 +1614,7 @@ class Model {
this.ws = new WSControl(this.getBaseWsHostPort(), this.clientId, this.authKey, (message : any) => this.runUpdate(message, false));
this.ws.reconnect();
this.inputModel = new InputModel();
+ this.bookmarksModel = new BookmarksModel();
let isLocalServerRunning = getApi().getLocalServerStatus();
this.localServerRunning = mobx.observable.box(isLocalServerRunning, {name: "model-local-server-running"});
getApi().onTCmd(this.onTCmd.bind(this));
@@ -1911,6 +1918,9 @@ class Model {
}
this.updateRemotes(update.remotes);
}
+ if ("bookmarksview" in update) {
+ this.showBookmarksView(update.bookmarksview);
+ }
if (interactive && "info" in update) {
let info : InfoType = update.info;
this.inputModel.flashInfoMsg(info, info.timeoutms);
@@ -1930,6 +1940,13 @@ class Model {
// console.log("run-update>", Date.now(), interactive, update);
}
+ showBookmarksView(bmview : BookmarksViewType) : void {
+ mobx.action(() => {
+ this.activeMainView.set("bookmarks");
+ this.bookmarksModel.bookmarks.replace(bmview.bookmarks || []);
+ })();
+ }
+
updateRemotes(remotes : RemoteType[]) : void {
genMergeSimpleData(this.remotes, remotes, (r) => r.remoteid, null);
}
@@ -2118,6 +2135,9 @@ class Model {
}
_activateSession(sessionId : string) {
+ mobx.action(() => {
+ this.activeMainView.set("session");
+ })();
let oldActiveSession = this.getActiveSession();
if (oldActiveSession != null && oldActiveSession.sessionId == sessionId) {
return;
@@ -2130,6 +2150,9 @@ class Model {
}
_activateScreen(sessionId : string, screenId : string, oldActiveScreen? : Screen) {
+ mobx.action(() => {
+ this.activeMainView.set("session");
+ })();
if (!oldActiveScreen) {
oldActiveScreen = this.getActiveScreen();
}
@@ -2425,6 +2448,10 @@ class CommandRunner {
linePin(lineId : string, val : boolean) {
GlobalModel.submitCommand("line", "pin", [lineId, (val ? "1" : "0")], {"nohist": "1"}, true);
}
+
+ bookmarksView() {
+ GlobalModel.submitCommand("bookmarks", "show", null, {"nohist": "1"}, true);
+ }
};
function cmdPacketString(pk : FeCmdPacketType) : string {
diff --git a/src/sh2.less b/src/sh2.less
index 181891e9..224d3136 100644
--- a/src/sh2.less
+++ b/src/sh2.less
@@ -51,7 +51,7 @@ html, body, #main {
background-color: black;
height: 100%;
- .session-view, .history-view {
+ .session-view, .history-view, .bookmarks-view {
flex-grow: 1;
display: flex;
flex-direction: column;
@@ -117,6 +117,14 @@ html, body, #main {
}
}
+.bookmarks-view {
+ .bookmarks-title {
+ margin: 10px 0 10px 15px;
+ .mono-font(1.5rem);
+ color: @term-bright-white;
+ }
+}
+
.screen-tabs {
height: 30px;
display: flex;
diff --git a/src/types.ts b/src/types.ts
index b10a578a..8cef8b4b 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -282,6 +282,22 @@ type ModelUpdateType = {
history? : HistoryInfoType,
interactive : boolean,
connect? : boolean,
+ bookmarksview? : BookmarksViewType,
+};
+
+type BookmarksViewType = {
+ bookmarks: BookmarkType[],
+};
+
+type BookmarkType = {
+ bookmarkid : string,
+ createdts : number,
+ cmdstr : string,
+ alias : string,
+ tags : string[],
+ description : string,
+ cmds : string[],
+ orderidx : number,
};
type HistoryInfoType = {
@@ -366,4 +382,4 @@ type PtyDataType = {
data : Uint8Array,
};
-export type {SessionDataType, LineType, RemoteType, RemoteStateType, RemoteInstanceType, WindowDataType, HistoryItem, CmdRemoteStateType, FeCmdPacketType, TermOptsType, CmdStartPacketType, CmdDataType, ScreenDataType, ScreenOptsType, ScreenWindowType, LayoutType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, RemotePtrType, UIContextType, HistoryInfoType, HistoryQueryOpts, WatchScreenPacketType, TermWinSize, FeInputPacketType, RemoteInputPacketType, RemoteEditType, FeStateType, ContextMenuOpts, RendererContext, WindowSize, RendererModel, PtyDataType};
+export type {SessionDataType, LineType, RemoteType, RemoteStateType, RemoteInstanceType, WindowDataType, HistoryItem, CmdRemoteStateType, FeCmdPacketType, TermOptsType, CmdStartPacketType, CmdDataType, ScreenDataType, ScreenOptsType, ScreenWindowType, LayoutType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, RemotePtrType, UIContextType, HistoryInfoType, HistoryQueryOpts, WatchScreenPacketType, TermWinSize, FeInputPacketType, RemoteInputPacketType, RemoteEditType, FeStateType, ContextMenuOpts, RendererContext, WindowSize, RendererModel, PtyDataType, BookmarksViewType, BookmarkType};