working on refactoring out a 'renderer' type from TermWrap

This commit is contained in:
sawka
2023-02-03 18:12:50 -08:00
parent d6e0c038e4
commit a25deff1a2
4 changed files with 99 additions and 55 deletions
+18 -4
View File
@@ -213,6 +213,20 @@ class Prompt extends React.Component<{rptr : RemotePtrType, festate : FeStateTyp
} }
} }
@mobxReact.observer
class TerminalRenderer extends React.Component<{sw : ScreenWindow, line : LineType, width : number, staticRender : boolean, visible : OV<boolean>, onHeightChange : HeightChangeCallbackType}, {}> {
render() {
return null;
}
}
@mobxReact.observer
class MarkdownRenderer extends React.Component<{sw : ScreenWindow, line : LineType, width : number, staticRender : boolean, visible : OV<boolean>, onHeightChange : HeightChangeCallbackType}, {}> {
render() {
return null;
}
}
@mobxReact.observer @mobxReact.observer
class LineCmd extends React.Component<{sw : ScreenWindow, line : LineType, width : number, staticRender : boolean, visible : OV<boolean>, onHeightChange : HeightChangeCallbackType}, {}> { class LineCmd extends React.Component<{sw : ScreenWindow, line : LineType, width : number, staticRender : boolean, visible : OV<boolean>, onHeightChange : HeightChangeCallbackType}, {}> {
termLoaded : mobx.IObservableValue<boolean> = mobx.observable.box(false, {name: "linecmd-term-loaded"}); termLoaded : mobx.IObservableValue<boolean> = mobx.observable.box(false, {name: "linecmd-term-loaded"});
@@ -338,7 +352,7 @@ class LineCmd extends React.Component<{sw : ScreenWindow, line : LineType, width
doRefresh() { doRefresh() {
let {sw, line} = this.props; let {sw, line} = this.props;
let model = GlobalModel; let model = GlobalModel;
let termWrap = sw.getTermWrap(line.cmdid); let termWrap = sw.getRenderer(line.cmdid);
if (termWrap != null) { if (termWrap != null) {
termWrap.reload(500); termWrap.reload(500);
} }
@@ -365,9 +379,9 @@ class LineCmd extends React.Component<{sw : ScreenWindow, line : LineType, width
clickTermBlock(e : any) { clickTermBlock(e : any) {
let {sw, line} = this.props; let {sw, line} = this.props;
let model = GlobalModel; let model = GlobalModel;
let termWrap = sw.getTermWrap(line.cmdid); let termWrap = sw.getRenderer(line.cmdid);
if (termWrap != null) { if (termWrap != null) {
termWrap.focusTerminal(); termWrap.giveFocus();
} }
} }
@@ -1038,7 +1052,7 @@ class InfoRemoteShow extends React.Component<{}, {}> {
clickTermBlock(e : any) { clickTermBlock(e : any) {
let inputModel = GlobalModel.inputModel; let inputModel = GlobalModel.inputModel;
if (inputModel.remoteTermWrap != null) { if (inputModel.remoteTermWrap != null) {
inputModel.remoteTermWrap.focusTerminal(); inputModel.remoteTermWrap.giveFocus();
} }
} }
+33 -29
View File
@@ -5,7 +5,7 @@ import {debounce} from "throttle-debounce";
import {handleJsonFetchResponse, base64ToArray, genMergeData, genMergeSimpleData, boundInt, isModKeyPress} from "./util"; import {handleJsonFetchResponse, base64ToArray, genMergeData, genMergeSimpleData, boundInt, isModKeyPress} from "./util";
import {TermWrap} from "./term"; import {TermWrap} from "./term";
import {v4 as uuidv4} from "uuid"; 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, NormalTermContext} 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} from "./types";
import {WSControl} from "./ws"; import {WSControl} from "./ws";
var GlobalUser = "sawka"; var GlobalUser = "sawka";
@@ -306,7 +306,7 @@ class ScreenWindow {
termLineNumFocus : OV<number>; termLineNumFocus : OV<number>;
// cmdid => TermWrap // cmdid => TermWrap
terms : Record<string, TermWrap> = {}; renderers : Record<string, RendererModel> = {};
setAnchor_debounced : (anchorLine : number, anchorOffset : number) => void; setAnchor_debounced : (anchorLine : number, anchorOffset : number) => void;
@@ -366,9 +366,9 @@ class ScreenWindow {
(document.activeElement as HTMLElement).blur(); (document.activeElement as HTMLElement).blur();
} }
if (sline != null && sline.cmdid != null) { if (sline != null && sline.cmdid != null) {
let termWrap = this.getTermWrap(sline.cmdid); let termWrap = this.getRenderer(sline.cmdid);
if (termWrap != null && termWrap.terminal != null) { if (termWrap != null) {
termWrap.focusTerminal(); termWrap.giveFocus();
} }
} }
} }
@@ -455,12 +455,12 @@ class ScreenWindow {
updatePtyData(ptyMsg : PtyDataUpdateType) { updatePtyData(ptyMsg : PtyDataUpdateType) {
let cmdId = ptyMsg.cmdid; let cmdId = ptyMsg.cmdid;
let term = this.terms[cmdId]; let renderer = this.renderers[cmdId];
if (term == null) { if (renderer == null) {
return; return;
} }
let data = base64ToArray(ptyMsg.ptydata64); let data = base64ToArray(ptyMsg.ptydata64);
term.updatePtyData(ptyMsg.ptypos, data, "from-sw"); renderer.receiveData(ptyMsg.ptypos, data, "from-sw");
} }
isActive() : boolean { isActive() : boolean {
@@ -480,14 +480,14 @@ class ScreenWindow {
} }
this.lastRows = rows; this.lastRows = rows;
this.lastCols = cols; this.lastCols = cols;
for (let cmdid in this.terms) { for (let cmdid in this.renderers) {
this.terms[cmdid].resizeCols(cols); this.renderers[cmdid].resizeCols(cols);
} }
GlobalCommandRunner.resizeWindow(this.windowId, rows, cols); GlobalCommandRunner.resizeWindow(this.windowId, rows, cols);
} }
getTermWrap(cmdId : string) : TermWrap { getRenderer(cmdId : string) : RendererModel {
return this.terms[cmdId]; return this.renderers[cmdId];
} }
setTermFocus(lineNum : number, focus : boolean) : void { setTermFocus(lineNum : number, focus : boolean) : void {
@@ -547,7 +547,7 @@ class ScreenWindow {
connectElem(elem : Element, line : LineType, cmd : Cmd, width : number) { connectElem(elem : Element, line : LineType, cmd : Cmd, width : number) {
let cmdId = cmd.cmdId; let cmdId = cmd.cmdId;
let termWrap = this.getTermWrap(cmdId); let termWrap = this.getRenderer(cmdId);
if (termWrap != null) { if (termWrap != null) {
console.log("term-wrap already exists for", this.screenId, this.windowId, cmdId); console.log("term-wrap already exists for", this.screenId, this.windowId, cmdId);
return; return;
@@ -568,18 +568,18 @@ class ScreenWindow {
isRunning: cmd.isRunning(), isRunning: cmd.isRunning(),
customKeyHandler: this.termCustomKeyHandler.bind(this), customKeyHandler: this.termCustomKeyHandler.bind(this),
}); });
this.terms[cmdId] = termWrap; this.renderers[cmdId] = termWrap;
if ((this.focusType.get() == "cmd" || this.focusType.get() == "cmd-fg") && this.selectedLine.get() == line.linenum) { if ((this.focusType.get() == "cmd" || this.focusType.get() == "cmd-fg") && this.selectedLine.get() == line.linenum) {
termWrap.focusTerminal(); termWrap.giveFocus();
} }
return; return;
} }
disconnectElem(cmdId : string) { disconnectElem(cmdId : string) {
let termWrap = this.terms[cmdId]; let termWrap = this.renderers[cmdId];
if (termWrap != null) { if (termWrap != null) {
termWrap.dispose(); termWrap.dispose();
delete this.terms[cmdId]; delete this.renderers[cmdId];
} }
} }
@@ -588,7 +588,7 @@ class ScreenWindow {
if (!termOpts.flexrows) { if (!termOpts.flexrows) {
return termOpts.rows; return termOpts.rows;
} }
let termWrap = this.getTermWrap(cmd.cmdId); let termWrap = this.getRenderer(cmd.cmdId);
if (termWrap == null) { if (termWrap == null) {
let cols = widthToCols(width); let cols = widthToCols(width);
let usedRows = GlobalModel.getTUR(this.sessionId, cmd.cmdId, cols); let usedRows = GlobalModel.getTUR(this.sessionId, cmd.cmdId, cols);
@@ -600,7 +600,7 @@ class ScreenWindow {
} }
return (cmd.isRunning() ? 1 : 0); return (cmd.isRunning() ? 1 : 0);
} }
return termWrap.usedRows.get(); return termWrap.getUsedRows();
} }
getIsFocused(lineNum : number) : boolean { getIsFocused(lineNum : number) : boolean {
@@ -1669,7 +1669,7 @@ class Model {
return this.termUsedRowsCache[key]; return this.termUsedRowsCache[key];
} }
setTUR(termContext : NormalTermContext, size : TermWinSize, usedRows : number) : void { setTUR(termContext : RendererContext, size : TermWinSize, usedRows : number) : void {
let key = termContext.sessionId + "/" + termContext.cmdId + "/" + size.cols; let key = termContext.sessionId + "/" + termContext.cmdId + "/" + size.cols;
this.termUsedRowsCache[key] = usedRows; this.termUsedRowsCache[key] = usedRows;
GlobalCommandRunner.setTermUsedRows(termContext, usedRows); GlobalCommandRunner.setTermUsedRows(termContext, usedRows);
@@ -1754,13 +1754,17 @@ class Model {
} }
cmdStatusUpdate(sessionId : string, cmdId : string, origStatus : string, newStatus : string) { cmdStatusUpdate(sessionId : string, cmdId : string, origStatus : string, newStatus : string) {
// console.log("cmd status", sessionId, cmdId, origStatus, "=>", newStatus); let wasRunning = cmdStatusIsRunning(origStatus);
let lines = this.getActiveLinesByCmdId(sessionId, cmdId); let isRunning = cmdStatusIsRunning(newStatus);
for (let ptr of lines) { if (wasRunning && !isRunning) {
let sw = ptr.sw; // console.log("cmd status", sessionId, cmdId, origStatus, "=>", newStatus);
let term = sw.getTermWrap(cmdId); let lines = this.getActiveLinesByCmdId(sessionId, cmdId);
if (term != null) { for (let ptr of lines) {
term.setIsRunning(cmdStatusIsRunning(newStatus)); let sw = ptr.sw;
let renderer = sw.getRenderer(cmdId);
if (renderer != null) {
renderer.cmdDone();
}
} }
} }
} }
@@ -1829,7 +1833,7 @@ class Model {
return; return;
} }
let ptyData = base64ToArray(ptyMsg.ptydata64); let ptyData = base64ToArray(ptyMsg.ptydata64);
this.inputModel.remoteTermWrap.updatePtyData(ptyMsg.ptypos, ptyData); this.inputModel.remoteTermWrap.receiveData(ptyMsg.ptypos, ptyData);
return; return;
} }
} }
@@ -2360,7 +2364,7 @@ class CommandRunner {
GlobalModel.submitCommand("sw", "set", null, kwargs, true); GlobalModel.submitCommand("sw", "set", null, kwargs, true);
} }
setTermUsedRows(termContext : NormalTermContext, height : number) { setTermUsedRows(termContext : RendererContext, height : number) {
let kwargs : Record<string, string> = {}; let kwargs : Record<string, string> = {};
kwargs["session"] = termContext.sessionId; kwargs["session"] = termContext.sessionId;
kwargs["screen"] = termContext.screenId; kwargs["screen"] = termContext.screenId;
+28 -20
View File
@@ -3,26 +3,21 @@ import {Terminal} from 'xterm';
import {sprintf} from "sprintf-js"; import {sprintf} from "sprintf-js";
import {boundMethod} from "autobind-decorator"; import {boundMethod} from "autobind-decorator";
import {v4 as uuidv4} from "uuid"; import {v4 as uuidv4} from "uuid";
import {GlobalModel, widthToCols, GlobalCommandRunner} from "./model"; import {GlobalModel, widthToCols, GlobalCommandRunner, termHeightFromRows, termRowsFromHeight} from "./model";
import {boundInt} from "./util"; import {boundInt} from "./util";
import type {TermOptsType, TermWinSize, NormalTermContext} from "./types"; import type {TermOptsType, TermWinSize, RendererContext, WindowSize} from "./types";
type DataUpdate = { type DataUpdate = {
data : Uint8Array, data : Uint8Array,
pos : number, pos : number,
} }
type WindowSize = {
height : number,
width: number,
};
const MinTermCols = 10; const MinTermCols = 10;
const MaxTermCols = 1024; const MaxTermCols = 1024;
type RemoteTermContext = {remoteId : string}; type RemoteTermContext = {remoteId : string};
type TermContext = NormalTermContext | RemoteTermContext; type TermContext = RendererContext | RemoteTermContext;
type TermWrapOpts = { type TermWrapOpts = {
termContext : TermContext, termContext : TermContext,
@@ -112,6 +107,10 @@ class TermWrap {
this.reload(0); this.reload(0);
} }
getUsedRows() : number {
return this.usedRows.get();
}
@boundMethod @boundMethod
elemScrollHandler(e : any) { elemScrollHandler(e : any) {
// this stops a weird behavior in the terminal // this stops a weird behavior in the terminal
@@ -132,7 +131,7 @@ class TermWrap {
return null; return null;
} }
getNormalTermContext() : NormalTermContext { getRendererContext() : RendererContext {
if ("remoteId" in this.termContext) { if ("remoteId" in this.termContext) {
return null; return null;
} }
@@ -150,7 +149,10 @@ class TermWrap {
} }
} }
focusTerminal() { giveFocus() {
if (this.terminal == null) {
return;
}
this.terminal.focus(); this.terminal.focus();
setTimeout(() => this.terminal._core.viewport.syncScrollArea(true), 0) setTimeout(() => this.terminal._core.viewport.syncScrollArea(true), 0)
} }
@@ -191,7 +193,7 @@ class TermWrap {
if (!this.flexRows) { if (!this.flexRows) {
return; return;
} }
let termContext = this.getNormalTermContext(); let termContext = this.getRendererContext();
if ("remoteId" in termContext) { if ("remoteId" in termContext) {
return; return;
} }
@@ -218,11 +220,11 @@ class TermWrap {
})(); })();
} }
resizeCols(cols : number) { resizeCols(cols : number) : void {
this.resize({rows: this.termSize.rows, cols: cols}); this.resize({rows: this.termSize.rows, cols: cols});
} }
resize(size : TermWinSize) { resize(size : TermWinSize) : void {
if (this.terminal == null) { if (this.terminal == null) {
return; return;
} }
@@ -236,11 +238,17 @@ class TermWrap {
this.updateUsedRows(true, "resize"); this.updateUsedRows(true, "resize");
} }
resizeWindow(size : WindowSize) : void {
let cols = widthToCols(size.width);
let rows = termRowsFromHeight(size.height);
this.resize({rows, cols});
}
_getReloadUrl() : string { _getReloadUrl() : string {
if (this.getContextRemoteId() != null) { if (this.getContextRemoteId() != null) {
return sprintf(GlobalModel.getBaseHostPort() + "/api/remote-pty?remoteid=%s", this.getContextRemoteId()); return sprintf(GlobalModel.getBaseHostPort() + "/api/remote-pty?remoteid=%s", this.getContextRemoteId());
} }
let termContext = this.getNormalTermContext(); let termContext = this.getRendererContext();
return sprintf(GlobalModel.getBaseHostPort() + "/api/ptyout?sessionid=%s&cmdid=%s", termContext.sessionId, termContext.cmdId); return sprintf(GlobalModel.getBaseHostPort() + "/api/ptyout?sessionid=%s&cmdid=%s", termContext.sessionId, termContext.cmdId);
} }
@@ -268,9 +276,9 @@ class TermWrap {
setTimeout(() => { setTimeout(() => {
this.reloading = false; this.reloading = false;
this.ptyPos = ptyOffset; this.ptyPos = ptyOffset;
this.updatePtyData(ptyOffset, new Uint8Array(buf), "reload-main"); this.receiveData(ptyOffset, new Uint8Array(buf), "reload-main");
for (let i=0; i<this.dataUpdates.length; i++) { for (let i=0; i<this.dataUpdates.length; i++) {
this.updatePtyData(this.dataUpdates[i].pos, this.dataUpdates[i].data, "reload-update-" + i); this.receiveData(this.dataUpdates[i].pos, this.dataUpdates[i].data, "reload-update-" + i);
} }
this.dataUpdates = []; this.dataUpdates = [];
this.terminal.write(new Uint8Array(), () => { this.terminal.write(new Uint8Array(), () => {
@@ -282,7 +290,7 @@ class TermWrap {
}); });
} }
updatePtyData(pos : number, data : Uint8Array, reason? : string) { receiveData(pos : number, data : Uint8Array, reason? : string) {
// console.log("update-pty-data", pos, data.length, reason); // console.log("update-pty-data", pos, data.length, reason);
if (this.terminal == null) { if (this.terminal == null) {
return; return;
@@ -313,9 +321,9 @@ class TermWrap {
}); });
} }
setIsRunning(isRunning : boolean) { cmdDone() : void {
this.isRunning = isRunning; this.isRunning = false;
this.updateUsedRows(true, "cmd-status"); this.updateUsedRows(true, "cmd-done");
} }
} }
+20 -2
View File
@@ -333,7 +333,7 @@ type ContextMenuOpts = {
type UpdateMessage = PtyDataUpdateType | ModelUpdateType; type UpdateMessage = PtyDataUpdateType | ModelUpdateType;
type NormalTermContext = { type RendererContext = {
sessionId : string, sessionId : string,
screenId : string, screenId : string,
windowId : string, windowId : string,
@@ -342,4 +342,22 @@ type NormalTermContext = {
lineNum : number, lineNum : number,
}; };
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, NormalTermContext}; type RendererModel = {
reload : (delayMs : number) => void,
dispose : () => void,
receiveData : (pos : number, data : Uint8Array, reason? : string) => void,
cmdDone : () => void,
resizeWindow : (size : WindowSize) => void,
resizeCols : (cols : number) => void,
giveFocus : () => void,
getUsedRows : () => number,
focusHandler : (focus : boolean) => void;
};
type WindowSize = {
height : number,
width: number,
};
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};