From b9f10fb9b6dfa6d29b14405c659e713e66fbc6d8 Mon Sep 17 00:00:00 2001 From: sawka Date: Tue, 14 Mar 2023 20:09:59 -0700 Subject: [PATCH] remove more references to window. also add 'archiving' to screen settings --- src/elements.tsx | 21 +++++++++- src/linecomps.tsx | 2 +- src/main.tsx | 22 +++++----- src/model.ts | 103 ++++++++++++++++++++++++---------------------- src/settings.tsx | 51 +++++++++++++++++++---- src/sh2.less | 77 ++++++++++++++++++++++++++++++++++ 6 files changed, 205 insertions(+), 71 deletions(-) diff --git a/src/elements.tsx b/src/elements.tsx index 482af38e..5f5e21af 100644 --- a/src/elements.tsx +++ b/src/elements.tsx @@ -46,4 +46,23 @@ class CmdStrCode extends React.Component<{cmdstr : string, onUse : () => void, o } } -export {CmdStrCode}; +class Toggle extends React.Component<{checked : boolean, onChange : (value : boolean) => void}, {}> { + @boundMethod + handleChange(e : any) : void { + let {onChange} = this.props; + if (onChange != null) { + onChange(e.target.checked); + } + } + + render() { + return ( + + ); + } +} + +export {CmdStrCode, Toggle}; diff --git a/src/linecomps.tsx b/src/linecomps.tsx index 22a160db..c45fa294 100644 --- a/src/linecomps.tsx +++ b/src/linecomps.tsx @@ -7,7 +7,7 @@ import dayjs from "dayjs"; import localizedFormat from 'dayjs/plugin/localizedFormat'; import {ImageRendererModel} from "./imagerenderer"; import {If, For, When, Otherwise, Choose} from "tsx-control-statements/components"; -import {GlobalModel, GlobalCommandRunner, Session, Cmd, Window, Screen, windowWidthToCols, windowHeightToRows, termHeightFromRows, termWidthFromCols} from "./model"; +import {GlobalModel, GlobalCommandRunner, Session, Cmd, ScreenLines, Screen, windowWidthToCols, windowHeightToRows, termHeightFromRows, termWidthFromCols} from "./model"; import type {LineType, CmdDataType, FeStateType, RemoteType, RemotePtrType, RenderModeType} from "./types"; import cn from "classnames"; import {TermWrap} from "./term"; diff --git a/src/main.tsx b/src/main.tsx index 20ddfb8f..6c82e0ce 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -11,7 +11,7 @@ import dayjs from "dayjs"; import type {SessionDataType, LineType, CmdDataType, RemoteType, RemoteStateType, RemoteInstanceType, RemotePtrType, HistoryItem, HistoryQueryOpts, RemoteEditType, FeStateType, ContextMenuOpts, BookmarkType, RenderModeType} from "./types"; import type * as T from "./types"; import localizedFormat from 'dayjs/plugin/localizedFormat'; -import {GlobalModel, GlobalCommandRunner, Session, Cmd, Window, Screen, riToRPtr, windowWidthToCols, windowHeightToRows, termHeightFromRows, termWidthFromCols, TabColors, RemoteColors} from "./model"; +import {GlobalModel, GlobalCommandRunner, Session, Cmd, ScreenLines, Screen, riToRPtr, windowWidthToCols, windowHeightToRows, termHeightFromRows, termWidthFromCols, TabColors, RemoteColors} from "./model"; import {isModKeyPress} from "./util"; import ReactMarkdown from 'react-markdown' import remarkGfm from 'remark-gfm' @@ -172,7 +172,7 @@ class TextAreaInput extends React.Component<{onHeightChange : () => void}, {}> { } let model = GlobalModel; let inputModel = model.inputModel; - let win = model.getActiveWindow(); + let win = model.getScreenLinesForActiveScreen(); let ctrlMod = e.getModifierState("Control") || e.getModifierState("Meta") || e.getModifierState("Shift"); let curLine = inputModel.getCurLine(); @@ -196,7 +196,7 @@ class TextAreaInput extends React.Component<{onHeightChange : () => void}, {}> { e.preventDefault(); if (!ctrlMod) { if (GlobalModel.inputModel.isEmpty()) { - let activeWindow = GlobalModel.getActiveWindow(); + let activeWindow = GlobalModel.getScreenLinesForActiveScreen(); let activeScreen = GlobalModel.getActiveScreen(); if (activeScreen != null && activeWindow != null && activeWindow.lines.length > 0) { activeScreen.setSelectedLine(0); @@ -1981,11 +1981,11 @@ class ScreenWindowView extends React.Component<{screen : Screen}, {}> { this.setSize_debounced(width, height); } - getWindow() : Window { + getScreenLines() : ScreenLines { let {screen} = this.props; - let win = GlobalModel.getWindowById(screen.sessionId, screen.screenId); + let win = GlobalModel.getScreenLinesById(screen.sessionId, screen.screenId); if (win == null) { - win = GlobalModel.loadWindow(screen.sessionId, screen.screenId); + win = GlobalModel.loadScreenLines(screen.sessionId, screen.screenId); } return win; } @@ -2016,7 +2016,7 @@ class ScreenWindowView extends React.Component<{screen : Screen}, {}> { render() { let {screen} = this.props; - let win = this.getWindow(); + let win = this.getScreenLines(); if (win == null || !win.loaded.get()) { return this.renderError("...", true); } @@ -2356,7 +2356,7 @@ class MainSideBar extends React.Component<{}, {}> { render() { let model = GlobalModel; let activeSessionId = model.activeSessionId.get(); - let activeWindow = model.getActiveWindow(); + let activeWindow = model.getScreenLinesForActiveScreen(); let activeScreen = model.getActiveScreen(); let activeRemoteId : string = null; if (activeScreen != null) { @@ -2623,11 +2623,11 @@ class AlertModal extends React.Component<{}, {}> { diff --git a/src/model.ts b/src/model.ts index 1f213bb0..7b762842 100644 --- a/src/model.ts +++ b/src/model.ts @@ -52,7 +52,7 @@ type LineContainerModel = { type SWLinePtr = { line : LineType, - win : Window, + slines : ScreenLines, screen : Screen, }; @@ -301,7 +301,7 @@ class Screen { this.setAnchorFields(sdata.selectedline, 0, "init"); } this.termLineNumFocus = mobx.observable.box(0, {name: "termLineNumFocus"}); - this.curRemote = mobx.observable.box(sdata.curremote, {name: "window-curRemote"}); + this.curRemote = mobx.observable.box(sdata.curremote, {name: "screen-curRemote"}); } dispose() { @@ -394,7 +394,7 @@ class Screen { } getMaxLineNum() : number { - let win = this.getWindow(); + let win = this.getScreenLines(); if (win == null) { return null; } @@ -409,7 +409,7 @@ class Screen { if (lineNum == null) { return null; } - let win = this.getWindow(); + let win = this.getScreenLines(); if (win == null) { return null; } @@ -426,7 +426,7 @@ class Screen { } isLastLine(lineNum : number) : boolean { - let win = this.getWindow(); + let win = this.getScreenLines(); if (win == null) { return false; } @@ -439,7 +439,7 @@ class Screen { } getPresentLineNum(lineNum : number) : number { - let win = this.getWindow(); + let win = this.getScreenLines(); if (win == null || !win.loaded.get()) { return lineNum; } @@ -648,8 +648,8 @@ class Screen { return this.selectedLine.get(); } - getWindow() : Window { - return GlobalModel.getWindowById(this.sessionId, this.screenId); + getScreenLines() : ScreenLines { + return GlobalModel.getScreenLinesById(this.sessionId, this.screenId); } getFocusType() : FocusTypeStrs { @@ -679,13 +679,12 @@ class Screen { } } -// fake window for now (this is really ScreenLines) -class Window { +class ScreenLines { sessionId : string; screenId : string; - loaded : OV = mobx.observable.box(false, {name: "window-loaded"}); + loaded : OV = mobx.observable.box(false, {name: "slines-loaded"}); loadError : OV = mobx.observable.box(null); - lines : OArr = mobx.observable.array([], {name: "window-lines", deep: false}); + lines : OArr = mobx.observable.array([], {name: "slines-lines", deep: false}); cmds : Record = {}; constructor(sessionId : string, screenId : string) { @@ -705,7 +704,7 @@ class Window { return rtn; } - updateWindow(slines : ScreenLinesType, load : boolean) { + updateData(slines : ScreenLinesType, load : boolean) { mobx.action(() => { if (load) { this.loaded.set(true); @@ -718,7 +717,7 @@ class Window { })(); } - setWindowLoadError(errStr : string) { + setLoadError(errStr : string) { mobx.action(() => { this.loaded.set(true); this.loadError.set(errStr); @@ -2233,7 +2232,7 @@ class Model { ws : WSControl; 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/screenid" (screenlines) + screenLines : OMap = mobx.observable.map({}, {name: "screenLines", deep: false}); // key = "sessionid/screenid" (screenlines) termUsedRowsCache : Record = {}; debugCmds : number = 0; debugScreen : OV = mobx.observable.box(false); @@ -2587,7 +2586,7 @@ class Model { for (let i=0; i { - this.windows.clear(); + this.screenLines.clear(); })(); } - getWindowById(sessionId : string, screenId : string) : Window { - return this.windows.get(sessionId + "/" + screenId); + getScreenLinesById(sessionId : string, screenId : string) : ScreenLines { + return this.screenLines.get(sessionId + "/" + screenId); } updateScreenLines(slines : ScreenLinesType, load : boolean) { mobx.action(() => { let winKey = slines.sessionid + "/" + slines.screenid; - let existingWin = this.windows.get(winKey); + let existingWin = this.screenLines.get(winKey); if (existingWin == null) { if (!load) { - console.log("cannot update window that does not exist", winKey); + console.log("cannot update screen-lines that does not exist", winKey); return; } - let newWindow = new Window(slines.sessionid, slines.screenid); - this.windows.set(winKey, newWindow); - newWindow.updateWindow(slines, load); + let newWindow = new ScreenLines(slines.sessionid, slines.screenid); + this.screenLines.set(winKey, newWindow); + newWindow.updateData(slines, load); return; } else { - existingWin.updateWindow(slines, load); + existingWin.updateData(slines, load); existingWin.loaded.set(true); } })(); } - removeWindowByScreenId(screenId : string) { + removeScreenLinesByScreenId(screenId : string) { mobx.action(() => { - for (let winKey of this.windows.keys()) { - let win = this.windows.get(winKey); + for (let winKey of this.screenLines.keys()) { + let win = this.screenLines.get(winKey); if (win.screenId == screenId) { - this.windows.delete(winKey); + this.screenLines.delete(winKey); return; } } @@ -2773,12 +2772,12 @@ class Model { return rtn; } - getActiveWindow() : Window { + getScreenLinesForActiveScreen() : ScreenLines { let screen = this.getActiveScreen(); if (screen == null) { return null; } - return this.windows.get(screen.sessionId + "/" + screen.screenId); + return this.screenLines.get(screen.sessionId + "/" + screen.screenId); } getActiveScreen() : Screen { @@ -2790,7 +2789,7 @@ class Model { } addLineCmd(line : LineType, cmd : CmdDataType, interactive : boolean) { - let win = this.getWindowById(line.sessionid, line.screenid); + let win = this.getScreenLinesById(line.sessionid, line.screenid); if (win == null) { return; } @@ -2798,7 +2797,7 @@ class Model { } updateCmd(cmd : CmdDataType) { - this.windows.forEach((win : Window) => { + this.screenLines.forEach((win : ScreenLines) => { win.updateCmd(cmd); }); } @@ -2906,7 +2905,7 @@ class Model { return; } mobx.action(() => { - this.deactivateWindows(); + this.deactivateScreenLines(); let curSessionId = this.activeSessionId.get(); if (curSessionId != sessionId) { this.activeSessionId.set(sessionId); @@ -2921,27 +2920,27 @@ class Model { this.ws.watchScreen(curScreen.sessionId, curScreen.screenId); } - _loadWindowAsync(newWin : Window) { - this.windows.set(newWin.sessionId + "/" + newWin.screenId, newWin); + _loadScreenLinesAsync(newWin : ScreenLines) { + this.screenLines.set(newWin.sessionId + "/" + newWin.screenId, newWin); let usp = new URLSearchParams({screenid: newWin.screenId}); let url = new URL(GlobalModel.getBaseHostPort() + "/api/get-screen-lines?" + usp.toString()); let fetchHeaders = GlobalModel.getFetchHeaders(); fetch(url, {headers: fetchHeaders}).then((resp) => handleJsonFetchResponse(url, resp)).then((data) => { if (data.data == null) { - console.log("null window returned from get-window"); + console.log("null screen-lines returned from get-screen-lines"); return; } let slines : ScreenLinesType = data.data; this.updateScreenLines(slines, true); return; }).catch((err) => { - this.errorHandler(sprintf("getting window=%s", newWin.screenId), err, false); + this.errorHandler(sprintf("getting screen-lines=%s", newWin.screenId), err, false); }); } - loadWindow(sessionId : string, screenId : string) : Window { - let newWin = new Window(sessionId, screenId); - setTimeout(() => this._loadWindowAsync(newWin), 0); + loadScreenLines(sessionId : string, screenId : string) : ScreenLines { + let newWin = new ScreenLines(sessionId, screenId); + setTimeout(() => this._loadScreenLinesAsync(newWin), 0); return newWin; } @@ -2982,15 +2981,15 @@ class Model { if (session == null) { return null; } - let window = this.getWindowById(line.sessionid, line.screenid); - if (window == null) { + let slines = this.getScreenLinesById(line.sessionid, line.screenid); + if (slines == null) { return null; } - return window.getCmd(line.cmdid); + return slines.getCmd(line.cmdid); } getCmdByIds(sessionid : string, cmdid : string) : Cmd { - for (let win of this.windows.values()) { + for (let win of this.screenLines.values()) { if (win.sessionId != sessionid) { continue; } @@ -3008,7 +3007,7 @@ class Model { if (session == null) { return []; } - for (let win of this.windows.values()) { + for (let win of this.screenLines.values()) { if (win.sessionId != sessionid) { continue; } @@ -3028,7 +3027,7 @@ class Model { } if (winLine != null) { let screen = this.getScreenById(win.sessionId, win.screenId); - rtn.push({line : winLine, win: win, screen: screen}); + rtn.push({line : winLine, slines: win, screen: screen}); } } return rtn; @@ -3081,7 +3080,7 @@ class CommandRunner { if (!show) { kwargs["noshow"] = "1"; } - if (htype != null && htype != "window") { + if (htype != null && htype != "screen") { kwargs["type"] = htype; } GlobalModel.submitCommand("history", null, null, kwargs, true); @@ -3124,6 +3123,10 @@ class CommandRunner { GlobalModel.submitCommand("screen", "resize", null, {"nohist": "1", "screen": screenId, "cols": String(cols), "rows": String(rows)}, false); } + screenArchive(screenId : string, shouldArchive : boolean) { + GlobalModel.submitCommand("screen", "archive", [screenId, (shouldArchive ? "1" : "0")], {"nohist": "1"}, false); + } + showRemote(remoteid : string) { GlobalModel.submitCommand("remote", "show", null, {"nohist": "1", "remote": remoteid}, true); } @@ -3332,7 +3335,7 @@ if ((window as any).GlobalModel == null) { GlobalModel = (window as any).GlobalModel; GlobalCommandRunner = (window as any).GlobalCommandRunner; -export {Model, Session, Window, GlobalModel, GlobalCommandRunner, Cmd, Screen, riToRPtr, windowWidthToCols, windowHeightToRows, termWidthFromCols, termHeightFromRows, getPtyData, getRemotePtyData, TabColors, RemoteColors}; +export {Model, Session, ScreenLines, GlobalModel, GlobalCommandRunner, Cmd, Screen, riToRPtr, windowWidthToCols, windowHeightToRows, termWidthFromCols, termHeightFromRows, getPtyData, getRemotePtyData, TabColors, RemoteColors}; export type {LineContainerModel}; diff --git a/src/settings.tsx b/src/settings.tsx index e616b57b..d392e0c8 100644 --- a/src/settings.tsx +++ b/src/settings.tsx @@ -6,6 +6,7 @@ import {boundMethod} from "autobind-decorator"; import {If, For, When, Otherwise, Choose} from "tsx-control-statements/components"; import cn from "classnames"; import {GlobalModel, GlobalCommandRunner, TabColors} from "./model"; +import {Toggle} from "./elements"; type OV = mobx.IObservableValue; type OArr = mobx.IObservableArray; @@ -16,6 +17,7 @@ type CV = mobx.IComputedValue; class ScreenSettingsModal extends React.Component<{sessionId : string, screenId : string}, {}> { tempName : OV; tempTabColor : OV; + tempArchived : OV; constructor(props : any) { super(props); @@ -26,6 +28,7 @@ class ScreenSettingsModal extends React.Component<{sessionId : string, screenId } this.tempName = mobx.observable.box(screen.name.get(), {name: "screenSettings-tempName"}); this.tempTabColor = mobx.observable.box(screen.getTabColor(), {name: "screenSettings-tempTabColor"}); + this.tempArchived = mobx.observable.box(screen.archived.get(), {name: "screenSettings-tempArchived"}); } @boundMethod @@ -39,11 +42,24 @@ class ScreenSettingsModal extends React.Component<{sessionId : string, screenId handleOK() : void { mobx.action(() => { GlobalModel.screenSettingsModal.set(null); - GlobalCommandRunner.screenSetSettings({ - "tabcolor": this.tempTabColor.get(), - "name": this.tempName.get(), - }); })(); + let screen = GlobalModel.getScreenById(this.props.sessionId, this.props.screenId); + if (screen == null) { + return; + } + let settings : {tabcolor? : string, name? : string} = {}; + if (this.tempTabColor.get() != screen.getTabColor()) { + settings.tabcolor = this.tempTabColor.get(); + } + if (this.tempName.get() != screen.name.get()) { + settings.name = this.tempName.get(); + } + if (Object.keys(settings).length > 0) { + GlobalCommandRunner.screenSetSettings(settings); + } + if (this.tempArchived.get() != screen.archived.get()) { + GlobalCommandRunner.screenArchive(screen.screenId, this.tempArchived.get()); + } } @boundMethod @@ -60,6 +76,13 @@ class ScreenSettingsModal extends React.Component<{sessionId : string, screenId })(); } + @boundMethod + handleChangeArchived(val : boolean) : void { + mobx.action(() => { + this.tempArchived.set(val); + })(); + } + render() { let {sessionId, screenId} = this.props; let screen = GlobalModel.getScreenById(sessionId, screenId); @@ -109,10 +132,22 @@ class ScreenSettingsModal extends React.Component<{sessionId : string, screenId +
+
+ Archived +
+
+ +
+ will be archived + will be un-archived +
+
+
-
OK
-
Cancel
+
Cancel
+
OK
@@ -185,8 +220,8 @@ class SessionSettingsModal extends React.Component<{sessionId : string}, {}> { diff --git a/src/sh2.less b/src/sh2.less index e95f7394..53a24122 100644 --- a/src/sh2.less +++ b/src/sh2.less @@ -2805,6 +2805,10 @@ input[type=checkbox] { } .settings-input { + display: flex; + flex-direction: row; + align-items: center; + input { padding: 4px; border-radius: 3px; @@ -2862,9 +2866,82 @@ input[type=checkbox] { } } } + + .action-text { + margin-left: 20px; + font-size: 12px; + color: @term-red; + } } &:not(:first-child) { margin-top: 10px; } } + +.checkbox-toggle { + position: relative; + display: inline-block; + width: 40px; + height: 23px; + + input { + opacity: 0; + width: 0; + height: 0; + } + + .slider { + position: absolute; + content: ""; + cursor: pointer; + top: 0; + bottom: 0; + left: 0; + right: 0; + background-color: #333; + transition: 0.5s; + border-radius: 33px; + } + + .slider:before { + position: absolute; + content: ""; + height: 18px; + width: 18px; + left: 3px; + bottom: 3px; + background-color: white; + transition: 0.5s; + border-radius: 50%; + } + + input:checked + .slider { + background-color: @term-green; + } + + input:checked + .slider:before { + transform: translateX(18px); + } +} + +.button.is-prompt-green { + background-color: #222; + color: @term-white; + + &:hover { + background-color: @term-green; + font-weight: bold; + } +} + +.button.is-prompt-cancel { + background-color: #222; + color: #777; + border-color: #777; + + &:hover { + background-color: #777; + color: #fff; + } +}