diff --git a/src/model.ts b/src/model.ts
index aab2041b..06430365 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, BookmarksViewType, BookmarkType} 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, BookmarkType} from "./types";
import {WSControl} from "./ws";
import {ImageRendererModel} from "./imagerenderer";
@@ -1587,7 +1587,10 @@ class BookmarksModel {
bookmarks : OArr = mobx.observable.array([], {name: "Bookmarks"});
activeBookmark : OV = mobx.observable.box(null, {name: "activeBookmark"});
editingBookmark : OV = mobx.observable.box(null, {name: "editingBookmark"});
- pendingDelete : OV = mobx.observable.box(false, {name: "pendingDelete"});
+ pendingDelete : OV = mobx.observable.box(null, {name: "pendingDelete"});
+
+ tempDesc : OV = mobx.observable.box("", {name: "bookmarkEdit-tempDesc"});
+ tempCmd : OV = mobx.observable.box("", {name: "bookmarkEdit-tempCmd"});
closeView() : void {
mobx.action(() => {
@@ -1600,18 +1603,85 @@ class BookmarksModel {
mobx.action(() => this.pendingDelete.set(null))();
}
+ cancelEdit() : void {
+ mobx.action(() => {
+ this.pendingDelete.set(null);
+ this.editingBookmark.set(null);
+ this.tempDesc.set("");
+ this.tempCmd.set("");
+ })();
+ }
+
+ confirmEdit() : void {
+ if (this.editingBookmark.get() == null) {
+ return;
+ }
+ let bm = this.getBookmark(this.editingBookmark.get());
+ mobx.action(() => {
+ this.editingBookmark.set(null);
+ bm.description = this.tempDesc.get();
+ bm.cmdstr = this.tempCmd.get();
+ this.tempDesc.set("");
+ this.tempCmd.set("");
+ })();
+ GlobalCommandRunner.editBookmark(bm.bookmarkid, bm.description, bm.cmdstr);
+ }
+
handleDeleteBookmark(bookmarkId : string) : void {
if (this.pendingDelete.get() == null || this.pendingDelete.get() != this.activeBookmark.get()) {
mobx.action(() => this.pendingDelete.set(this.activeBookmark.get()))();
setTimeout(this.clearPendingDelete, 2000);
return;
}
- console.log("delete", bookmarkId);
+ GlobalCommandRunner.deleteBookmark(bookmarkId);
+ this.clearPendingDelete();
}
+ getBookmark(bookmarkId : string) : BookmarkType {
+ if (bookmarkId == null) {
+ return null;
+ }
+ for (let i=0; i {
+ this.pendingDelete.set(null);
+ this.activeBookmark.set(bookmarkId);
+ this.editingBookmark.set(bookmarkId);
+ this.tempDesc.set(bm.description ?? "");
+ this.tempCmd.set(bm.cmdstr ?? "");
+ })();
+ }
+
+ mergeBookmarks(bmArr : BookmarkType[]) : void {
+ mobx.action(() => {
+ genMergeSimpleData(this.bookmarks, bmArr, (bm : BookmarkType) => bm.bookmarkid, (bm : BookmarkType) => sprintf("%05d", bm.orderidx));
+ })();
+ }
+
handleDocKeyDown(e : any) : void {
if (e.code == "Escape") {
e.preventDefault();
+ if (this.editingBookmark.get() != null) {
+ this.cancelEdit();
+ return;
+ }
this.closeView();
return;
}
@@ -1631,6 +1701,18 @@ class BookmarksModel {
if (e.code == "ArrowDown") {
}
if (e.code == "Enter") {
+ if (this.activeBookmark.get() == null) {
+ return;
+ }
+ return;
+ }
+ if (e.code == "KeyE") {
+ if (this.activeBookmark.get() == null) {
+ return;
+ }
+ e.preventDefault();
+ this.handleEditBookmark(this.activeBookmark.get());
+ return;
}
}
return;
@@ -1972,7 +2054,10 @@ class Model {
this.updateRemotes(update.remotes);
}
if ("bookmarksview" in update) {
- this.showBookmarksView(update.bookmarksview);
+ this.showBookmarksView(update.bookmarks);
+ }
+ else if ("bookmarks" in update) {
+ this.bookmarksModel.mergeBookmarks(update.bookmarks);
}
if (interactive && "info" in update) {
let info : InfoType = update.info;
@@ -1993,10 +2078,10 @@ class Model {
// console.log("run-update>", Date.now(), interactive, update);
}
- showBookmarksView(bmview : BookmarksViewType) : void {
+ showBookmarksView(bmArr : BookmarkType[]) : void {
+ bmArr = bmArr ?? [];
mobx.action(() => {
this.activeMainView.set("bookmarks");
- let bmArr = bmview.bookmarks ?? [];
this.bookmarksModel.bookmarks.replace(bmArr);
this.bookmarksModel.activeBookmark.set(null);
if (bmArr.length > 0) {
@@ -2510,6 +2595,19 @@ class CommandRunner {
bookmarksView() {
GlobalModel.submitCommand("bookmarks", "show", null, {"nohist": "1"}, true);
}
+
+ editBookmark(bookmarkId : string, desc : string, cmdstr : string) {
+ let kwargs = {
+ "nohist": "1",
+ "description": desc,
+ "cmdstr": cmdstr,
+ };
+ GlobalModel.submitCommand("bookmark", "set", [bookmarkId], kwargs, true);
+ }
+
+ deleteBookmark(bookmarkId : string) : void {
+ GlobalModel.submitCommand("bookmark", "delete", [bookmarkId], {"nohist": "1"}, true);
+ }
};
function cmdPacketString(pk : FeCmdPacketType) : string {
diff --git a/src/sh2.less b/src/sh2.less
index 28ba7db7..08504b57 100644
--- a/src/sh2.less
+++ b/src/sh2.less
@@ -167,14 +167,48 @@ html, body, #main {
height: calc(100% - 4px);
}
+ &.is-editing {
+ padding-top: 8px;
+ padding-bottom: 12px;
+ }
+
&.pending-delete {
background-color: #522;
}
- .bookmark-content {
+ .bookmark-content, .bookmark-edit {
flex-grow: 1;
}
+ label {
+ color: white;
+ margin-bottom: 4px;
+ }
+
+ textarea {
+ width: 80%;
+ min-width: 50%;
+ color: white;
+ background-color: black;
+
+ &.mono-font {
+ .mono-font(12px);
+ }
+ }
+
+ .bookmark-id-div {
+ display: none;
+ position: absolute;
+ color: #666;
+ right: 5px;
+ bottom: 2px;
+ .mono-font(8px);
+ }
+
+ &:hover .bookmark-id-div {
+ display: block;
+ }
+
.bookmark-controls {
display: flex;
flex-direction: row;
diff --git a/src/types.ts b/src/types.ts
index 8cef8b4b..68b3d16b 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -282,11 +282,8 @@ type ModelUpdateType = {
history? : HistoryInfoType,
interactive : boolean,
connect? : boolean,
- bookmarksview? : BookmarksViewType,
-};
-
-type BookmarksViewType = {
- bookmarks: BookmarkType[],
+ bookmarksview? : boolean,
+ bookmarks : BookmarkType[],
};
type BookmarkType = {
@@ -298,6 +295,7 @@ type BookmarkType = {
description : string,
cmds : string[],
orderidx : number,
+ remove? : boolean,
};
type HistoryInfoType = {
@@ -382,4 +380,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, BookmarksViewType, BookmarkType};
+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, BookmarkType};