bookmark editing/delete

This commit is contained in:
sawka 2023-02-21 18:02:28 -08:00
parent 9bb9e1fd5d
commit cc5f8f81e7
4 changed files with 207 additions and 17 deletions

View File

@ -2805,7 +2805,39 @@ class Bookmark extends React.Component<{bookmark : BookmarkType}, {}> {
@boundMethod
handleEditClick() : void {
console.log("do edit");
let {bookmark} = this.props;
let model = GlobalModel.bookmarksModel;
model.handleEditBookmark(bookmark.bookmarkid);
}
@boundMethod
handleEditCancel() : void {
let model = GlobalModel.bookmarksModel;
model.cancelEdit();
return;
}
@boundMethod
handleEditUpdate() : void {
let model = GlobalModel.bookmarksModel;
model.confirmEdit();
return;
}
@boundMethod
handleDescChange(e : any) : void {
let model = GlobalModel.bookmarksModel;
mobx.action(() => {
model.tempDesc.set(e.target.value);
})();
}
@boundMethod
handleCmdChange(e : any) : void {
let model = GlobalModel.bookmarksModel;
mobx.action(() => {
model.tempCmd.set(e.target.value);
})();
}
render() {
@ -2823,13 +2855,41 @@ class Bookmark extends React.Component<{bookmark : BookmarkType}, {}> {
h6: (props) => HeaderRenderer(props, 6),
code: CodeRenderer,
};
if (bm.cmdstr.startsWith("git")) {
markdown = "Use to modify the code repo\n1. git pull\n2. git push\n3. git commit\n\n> one\n> more blockquote\n>\n> more";
}
let hasDesc = markdown != "";
let isEditing = (model.editingBookmark.get() == bm.bookmarkid);
if (isEditing) {
return (
<div className={cn("bookmark focus-parent is-editing", {"pending-delete": model.pendingDelete.get() == bm.bookmarkid})}>
<div className={cn("focus-indicator", {"active": isSelected})}/>
<div className="bookmark-edit">
<div className="field">
<label className="label">Description (markdown)</label>
<div className="control">
<textarea className="textarea mono-font" rows={6} value={model.tempDesc.get()} onChange={this.handleDescChange}/>
</div>
</div>
<div className="field">
<label className="label">Command</label>
<div className="control">
<textarea className="textarea mono-font" rows={3} value={model.tempCmd.get()} onChange={this.handleCmdChange}/>
</div>
</div>
<div className="field is-grouped">
<div className="control">
<button className="button is-link" onClick={this.handleEditUpdate}>Update</button>
</div>
<div className="control">
<button className="button" onClick={this.handleEditCancel}>Cancel</button>
</div>
</div>
</div>
</div>
);
}
return (
<div className={cn("bookmark focus-parent", {"pending-delete": model.pendingDelete.get() == bm.bookmarkid})}>
<div className={cn("focus-indicator", {"active": isSelected})}/>
<div className="bookmark-id-div">{bm.bookmarkid.substr(0, 8)}</div>
<div className="bookmark-content">
<If condition={hasDesc}>
<div className="markdown">

View File

@ -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<BookmarkType> = mobx.observable.array([], {name: "Bookmarks"});
activeBookmark : OV<string> = mobx.observable.box(null, {name: "activeBookmark"});
editingBookmark : OV<string> = mobx.observable.box(null, {name: "editingBookmark"});
pendingDelete : OV<string> = mobx.observable.box(false, {name: "pendingDelete"});
pendingDelete : OV<string> = mobx.observable.box(null, {name: "pendingDelete"});
tempDesc : OV<string> = mobx.observable.box("", {name: "bookmarkEdit-tempDesc"});
tempCmd : OV<string> = 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.bookmarks.length; i++) {
let bm = this.bookmarks[i];
if (bm.bookmarkid == bookmarkId) {
return bm;
}
}
return null;
}
getActiveBookmark() : BookmarkType {
let activeBookmarkId = this.activeBookmark.get();
return this.getBookmark(activeBookmarkId);
}
handleEditBookmark(bookmarkId : string) : void {
let bm = this.getBookmark(bookmarkId);
if (bm == null) {
return;
}
mobx.action(() => {
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 {

View File

@ -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;

View File

@ -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};