remove more references to window. also add 'archiving' to screen settings

This commit is contained in:
sawka
2023-03-14 20:09:59 -07:00
parent 78bd0d3788
commit b9f10fb9b6
6 changed files with 205 additions and 71 deletions
+20 -1
View File
@@ -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 (
<label className="checkbox-toggle">
<input type="checkbox" checked={this.props.checked} onChange={this.handleChange}/>
<span className="slider"/>
</label>
);
}
}
export {CmdStrCode, Toggle};
+1 -1
View File
@@ -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";
+11 -11
View File
@@ -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<{}, {}> {
</div>
<footer>
<If condition={isConfirm}>
<div onClick={this.handleOK} className="button is-primary is-outlined is-small">OK</div>
<div onClick={this.closeModal} className="button is-danger is-outlined is-small">Cancel</div>
<div onClick={this.closeModal} className="button is-prompt-cancel is-outlined is-small">Cancel</div>
<div onClick={this.handleOK} className="button is-prompt-green is-outlined is-small">OK</div>
</If>
<If condition={!isConfirm}>
<div onClick={this.handleOK} className="button is-primary is-small">OK</div>
<div onClick={this.handleOK} className="button is-prompt-green is-small">OK</div>
</If>
</footer>
</div>
+53 -50
View File
@@ -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<boolean> = mobx.observable.box(false, {name: "window-loaded"});
loaded : OV<boolean> = mobx.observable.box(false, {name: "slines-loaded"});
loadError : OV<string> = mobx.observable.box(null);
lines : OArr<LineType> = mobx.observable.array([], {name: "window-lines", deep: false});
lines : OArr<LineType> = mobx.observable.array([], {name: "slines-lines", deep: false});
cmds : Record<string, Cmd> = {};
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<RemoteType> = mobx.observable.array([], {name: "remotes", deep: false});
remotesLoaded : OV<boolean> = mobx.observable.box(false, {name: "remotesLoaded"});
windows : OMap<string, Window> = mobx.observable.map({}, {name: "windows", deep: false}); // key = "sessionid/screenid" (screenlines)
screenLines : OMap<string, ScreenLines> = mobx.observable.map({}, {name: "screenLines", deep: false}); // key = "sessionid/screenid" (screenlines)
termUsedRowsCache : Record<string, number> = {};
debugCmds : number = 0;
debugScreen : OV<boolean> = mobx.observable.box(false);
@@ -2587,7 +2586,7 @@ class Model {
for (let i=0; i<update.screens.length; i++) {
let screen = update.screens[i];
if (screen.remove) {
this.removeWindowByScreenId(screen.screenid);
this.removeScreenLinesByScreenId(screen.screenid);
}
}
}
@@ -2709,43 +2708,43 @@ class Model {
return null;
}
deactivateWindows() {
deactivateScreenLines() {
mobx.action(() => {
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};
+43 -8
View File
@@ -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<V> = mobx.IObservableValue<V>;
type OArr<V> = mobx.IObservableArray<V>;
@@ -16,6 +17,7 @@ type CV<V> = mobx.IComputedValue<V>;
class ScreenSettingsModal extends React.Component<{sessionId : string, screenId : string}, {}> {
tempName : OV<string>;
tempTabColor : OV<string>;
tempArchived : OV<boolean>;
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
</div>
</div>
</div>
<div className="settings-field">
<div className="settings-label">
Archived
</div>
<div className="settings-input">
<Toggle checked={this.tempArchived.get()} onChange={this.handleChangeArchived}/>
<div className="action-text">
<If condition={this.tempArchived.get() && this.tempArchived.get() != screen.archived.get()}>will be archived</If>
<If condition={!this.tempArchived.get() && this.tempArchived.get() != screen.archived.get()}>will be un-archived</If>
</div>
</div>
</div>
</div>
<footer>
<div onClick={this.handleOK} className="button is-primary is-outlined is-small">OK</div>
<div onClick={this.closeModal} className="button is-danger is-outlined is-small">Cancel</div>
<div onClick={this.closeModal} className="button is-prompt-cancel is-outlined is-small">Cancel</div>
<div onClick={this.handleOK} className="button is-prompt-green is-outlined is-small">OK</div>
</footer>
</div>
</div>
@@ -185,8 +220,8 @@ class SessionSettingsModal extends React.Component<{sessionId : string}, {}> {
</div>
</div>
<footer>
<div onClick={this.handleOK} className="button is-primary is-outlined is-small">OK</div>
<div onClick={this.closeModal} className="button is-danger is-outlined is-small">Cancel</div>
<div onClick={this.closeModal} className="button is-prompt-cancel is-outlined is-small">Cancel</div>
<div onClick={this.handleOK} className="button is-prompt-green is-outlined is-small">OK</div>
</footer>
</div>
</div>
+77
View File
@@ -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;
}
}