get renderers working, updates to remove globalmodel dependencies on simplerender.

This commit is contained in:
sawka
2023-03-31 00:34:39 -07:00
parent ab0852b574
commit 6af8aec315
6 changed files with 141 additions and 60 deletions
+37 -3
View File
@@ -6,9 +6,9 @@ import {boundMethod} from "autobind-decorator";
import dayjs from "dayjs";
import localizedFormat from 'dayjs/plugin/localizedFormat';
import {If, For, When, Otherwise, Choose} from "tsx-control-statements/components";
import {GlobalModel, GlobalCommandRunner, Session, Cmd, ScreenLines, Screen} from "./model";
import {GlobalModel, GlobalCommandRunner, Session, Cmd, ScreenLines, Screen, getTermPtyData} from "./model";
import {windowWidthToCols, windowHeightToRows, termHeightFromRows, termWidthFromCols} from "./textmeasure";
import type {LineType, CmdDataType, FeStateType, RemoteType, RemotePtrType, RenderModeType, RendererContext, RendererOpts, SimpleBlobRendererComponent, RendererPluginType, LineHeightChangeCallbackType} from "./types";
import type {LineType, CmdDataType, FeStateType, RemoteType, RemotePtrType, RenderModeType, RendererContext, RendererOpts, SimpleBlobRendererComponent, RendererPluginType, LineHeightChangeCallbackType, RendererModelInitializeParams, RendererModel} from "./types";
import cn from "classnames";
import {TermWrap} from "./term";
import type {LineContainerModel} from "./model";
@@ -441,6 +441,40 @@ class LineCmd extends React.Component<{screen : LineContainerModel, line : LineT
termFontSize: GlobalModel.termFontSize.get(),
};
}
makeRendererModelInitializeParams() : RendererModelInitializeParams {
let {screen, line} = this.props;
let context = lineutil.getRendererContext(line);
let cmd = screen.getCmd(line); // won't be null
let savedHeight = screen.getContentHeight(context);
if (savedHeight == null) {
if (line.contentheight != null && line.contentheight != -1) {
savedHeight = line.contentheight;
}
else {
savedHeight = 0;
}
}
let api = {
saveHeight: (height : number) => {
screen.setContentHeight(lineutil.getRendererContext(line), height);
},
onFocusChanged: (focus : boolean) => {
screen.setTermFocus(line.linenum, focus);
},
dataHandler: (data : string, model : RendererModel) => {
cmd.handleDataFromRenderer(data, model);
},
};
return {
context: context,
isDone: !cmd.isRunning(),
savedHeight: savedHeight,
opts: this.getRendererOpts(cmd),
ptyDataSource: getTermPtyData,
api: api,
};
}
render() {
let {screen, line, width, staticRender, visible, topBorder, renderMode} = this.props;
@@ -517,7 +551,7 @@ class LineCmd extends React.Component<{screen : LineContainerModel, line : LineT
<TerminalRenderer screen={screen} line={line} width={width} staticRender={staticRender} visible={visible} onHeightChange={this.handleHeightChange} collapsed={isCollapsed}/>
</If>
<If condition={rendererPlugin != null}>
<SimpleBlobRenderer lcm={screen} line={line} cmd={cmd} plugin={rendererPlugin} onHeightChange={this.handleHeightChange} rendererOpts={this.getRendererOpts(cmd)}/>
<SimpleBlobRenderer rendererContainer={screen} cmdId={line.cmdid} plugin={rendererPlugin} onHeightChange={this.handleHeightChange} initParams={this.makeRendererModelInitializeParams()}/>
</If>
<If condition={!isCollapsed && cmd.getRtnState()}>
<div key="rtnstate" className="cmd-rtnstate" style={{visibility: ((cmd.getStatus() == "done") ? "visible" : "hidden")}}>
+1 -1
View File
@@ -322,11 +322,11 @@ class LineSettingsModal extends React.Component<{line : LineType}, {}> {
</div>
<div className="dropdown-menu" role="menu">
<div className="dropdown-content has-background-black">
<div onClick={() => this.clickSetRenderer("none") } key="none" className="dropdown-item">none</div>
<div onClick={() => this.clickSetRenderer(null) } key="terminal" className="dropdown-item">terminal</div>
<For each="plugin" of={plugins}>
<div onClick={() => this.clickSetRenderer(plugin.name) } key={plugin.name} className="dropdown-item">{plugin.name}</div>
</For>
<div onClick={() => this.clickSetRenderer("none") } key="none" className="dropdown-item">none</div>
</div>
</div>
</div>
+11 -52
View File
@@ -4,8 +4,7 @@ import * as mobx from "mobx";
import {sprintf} from "sprintf-js";
import {boundMethod} from "autobind-decorator";
import {If, For, When, Otherwise, Choose} from "tsx-control-statements/components";
import type {RendererModelInitializeParams, TermOptsType, RendererContext, RendererOpts, SimpleBlobRendererComponent, RendererModelContainerApi, RendererPluginType, PtyDataType, RendererModel, RendererOptsUpdate, LineType} from "./types";
import {LineContainerModel, getTermPtyData, Cmd} from "./model";
import type {RendererModelInitializeParams, TermOptsType, RendererContext, RendererOpts, SimpleBlobRendererComponent, RendererModelContainerApi, RendererPluginType, PtyDataType, RendererModel, RendererOptsUpdate, LineType, TermContextUnion, RendererContainerType} from "./types";
import {PtyDataBuffer} from "./ptydata";
import {debounce, throttle} from "throttle-debounce";
@@ -21,7 +20,8 @@ class SimpleBlobRendererModel {
loading : OV<boolean>;
loadError : OV<string> = mobx.observable.box(null, {name: "renderer-loadError"});
ptyData : PtyDataType;
updateHeight_debounced : (newHeight : number) => void
updateHeight_debounced : (newHeight : number) => void;
ptyDataSource : (termContext : TermContextUnion) => Promise<PtyDataType>;
constructor() {
this.updateHeight_debounced = debounce(1000, this.updateHeight.bind(this));
@@ -34,6 +34,7 @@ class SimpleBlobRendererModel {
this.opts = params.opts;
this.api = params.api;
this.savedHeight = params.savedHeight;
this.ptyDataSource = params.ptyDataSource;
if (this.isDone.get()) {
this.reload(0);
}
@@ -72,7 +73,7 @@ class SimpleBlobRendererModel {
mobx.action(() => {
this.loading.set(true);
})();
let rtnp = getTermPtyData(this.context);
let rtnp = this.ptyDataSource(this.context);
rtnp.then((ptydata) => {
setTimeout(() => {
this.ptyData = ptydata;
@@ -94,60 +95,18 @@ class SimpleBlobRendererModel {
}
}
function contextFromLine(line : LineType) : RendererContext {
return {
screenId: line.screenid,
cmdId: line.cmdid,
lineId: line.lineid,
lineNum: line.linenum,
};
}
function apiAdapter(lcm : LineContainerModel, line : LineType, cmd : Cmd) : RendererModelContainerApi {
return {
saveHeight: (height : number) => {
lcm.setContentHeight(contextFromLine(line), height);
},
onFocusChanged: (focus : boolean) => {
lcm.setTermFocus(line.linenum, focus);
},
dataHandler: (data : string, model : RendererModel) => {
cmd.handleDataFromRenderer(data, model);
},
};
}
@mobxReact.observer
class SimpleBlobRenderer extends React.Component<{lcm : LineContainerModel, line : LineType, cmd : Cmd, rendererOpts : RendererOpts, plugin : RendererPluginType, onHeightChange : () => void}, {}> {
class SimpleBlobRenderer extends React.Component<{rendererContainer : RendererContainerType, cmdId : string, plugin : RendererPluginType, onHeightChange : () => void, initParams : RendererModelInitializeParams}, {}> {
model : SimpleBlobRendererModel;
wrapperDivRef : React.RefObject<any> = React.createRef();
rszObs : ResizeObserver;
constructor(props : any) {
super(props);
let {lcm, line, cmd, rendererOpts} = this.props;
let context = contextFromLine(line);
let savedHeight = lcm.getContentHeight(context);
if (savedHeight == null) {
if (line.contentheight != null && line.contentheight != -1) {
savedHeight = line.contentheight;
}
else {
savedHeight = 0;
}
}
let initOpts = {
context: context,
isDone: !cmd.isRunning(),
savedHeight: savedHeight,
opts: rendererOpts,
api: apiAdapter(lcm, line, cmd),
};
let {rendererContainer, cmdId, initParams} = this.props;
this.model = new SimpleBlobRendererModel();
this.model.initialize(initOpts);
lcm.registerRenderer(line.cmdid, this.model);
this.model.initialize(initParams);
rendererContainer.registerRenderer(cmdId, this.model);
}
handleResize(entries : ResizeObserverEntry[]) : void {
@@ -179,8 +138,8 @@ class SimpleBlobRenderer extends React.Component<{lcm : LineContainerModel, line
}
componentWillUnmount() {
let {lcm, line} = this.props;
lcm.unloadRenderer(line.cmdid);
let {rendererContainer, cmdId} = this.props;
rendererContainer.unloadRenderer(cmdId);
if (this.rszObs != null) {
this.rszObs.disconnect();
this.rszObs = null;
+7 -1
View File
@@ -399,6 +399,7 @@ type RendererModelInitializeParams = {
savedHeight : number,
opts : RendererOpts,
api : RendererModelContainerApi,
ptyDataSource: (termContext : TermContextUnion) => Promise<PtyDataType>,
};
type RendererModel = {
@@ -581,6 +582,11 @@ type LineFactoryProps = {
noSelect? : boolean,
}
type RendererContainerType = {
registerRenderer : (cmdId : string, model : RendererModel) => void,
unloadRenderer : (cmdId : string) => void,
};
type LineHeightChangeCallbackType = (lineNum : number, newHeight : number, oldHeight : number) => void;
export type {SessionDataType, LineType, RemoteType, RemoteStateType, RemoteInstanceType, HistoryItem, CmdRemoteStateType, FeCmdPacketType, TermOptsType, CmdStartPacketType, CmdDataType, ScreenDataType, ScreenOptsType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, RemotePtrType, UIContextType, HistoryInfoType, HistoryQueryOpts, WatchScreenPacketType, TermWinSize, FeInputPacketType, RemoteInputPacketType, RemoteEditType, FeStateType, ContextMenuOpts, RendererContext, WindowSize, RendererModel, PtyDataType, BookmarkType, ClientDataType, PlaybookType, PlaybookEntryType, HistoryViewDataType, RenderModeType, AlertMessageType, HistorySearchParams, ScreenLinesType, FocusTypeStrs, HistoryTypeStrs, RendererOpts, RendererPluginType, SimpleBlobRendererComponent, RendererModelContainerApi, RendererModelInitializeParams, RendererOptsUpdate, ClientMigrationInfo, WebShareOpts, RemoteStatusTypeStrs, WebFullScreen, WebScreen, WebLine, WebCmd, RemoteTermContext, TermContextUnion, WebRemote, WebScreenUpdate, PtyDataUpdate, WebShareWSMessage, LineHeightChangeCallbackType, LineFactoryProps, LineInterface};
export type {SessionDataType, LineType, RemoteType, RemoteStateType, RemoteInstanceType, HistoryItem, CmdRemoteStateType, FeCmdPacketType, TermOptsType, CmdStartPacketType, CmdDataType, ScreenDataType, ScreenOptsType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, RemotePtrType, UIContextType, HistoryInfoType, HistoryQueryOpts, WatchScreenPacketType, TermWinSize, FeInputPacketType, RemoteInputPacketType, RemoteEditType, FeStateType, ContextMenuOpts, RendererContext, WindowSize, RendererModel, PtyDataType, BookmarkType, ClientDataType, PlaybookType, PlaybookEntryType, HistoryViewDataType, RenderModeType, AlertMessageType, HistorySearchParams, ScreenLinesType, FocusTypeStrs, HistoryTypeStrs, RendererOpts, RendererPluginType, SimpleBlobRendererComponent, RendererModelContainerApi, RendererModelInitializeParams, RendererOptsUpdate, ClientMigrationInfo, WebShareOpts, RemoteStatusTypeStrs, WebFullScreen, WebScreen, WebLine, WebCmd, RemoteTermContext, TermContextUnion, WebRemote, WebScreenUpdate, PtyDataUpdate, WebShareWSMessage, LineHeightChangeCallbackType, LineFactoryProps, LineInterface, RendererContainerType};
+80 -2
View File
@@ -5,7 +5,7 @@ import {sprintf} from "sprintf-js";
import {boundMethod} from "autobind-decorator";
import {If, For, When, Otherwise, Choose} from "tsx-control-statements/components";
import cn from "classnames";
import {WebShareModel} from "./webshare-model";
import {WebShareModel, getTermPtyData} from "./webshare-model";
import * as T from "./types";
import {isBlank} from "./util";
import {PluginModel} from "./plugins";
@@ -15,6 +15,7 @@ import {windowWidthToCols, windowHeightToRows, termHeightFromRows, termWidthFrom
import {debounce, throttle} from "throttle-debounce";
import {LinesView} from "./linesview";
import {Toggle} from "./elements";
import {SimpleBlobRendererModel, SimpleBlobRenderer} from "./simplerenderer";
type OV<V> = mobx.IObservableValue<V>;
type OArr<V> = mobx.IObservableArray<V>;
@@ -122,6 +123,7 @@ class WebLineCmdView extends React.Component<{line : T.WebLine, cmd : T.WebCmd,
cmdTextRef : React.RefObject<any> = React.createRef();
copiedIndicator : OV<boolean> = mobx.observable.box(false, {name: "copiedIndicator"});
lastHeight : number;
lastScreenSize : T.WindowSize;
componentDidMount() : void {
this.checkCmdText();
@@ -234,9 +236,14 @@ class WebLineCmdView extends React.Component<{line : T.WebLine, cmd : T.WebCmd,
handleHeightChange() : void {
let {line} = this.props;
let curHeight = 0;
let curWidth = 0;
let elem = this.lineRef.current;
if (elem != null) {
curHeight = elem.offsetHeight;
curWidth = elem.offsetWidth;
if (curHeight != 0 && curWidth != 0) {
this.lastScreenSize = {height: curHeight, width: curWidth};
}
}
if (this.lastHeight == curHeight) {
return;
@@ -294,6 +301,72 @@ class WebLineCmdView extends React.Component<{line : T.WebLine, cmd : T.WebCmd,
})();
}, 600);
}
getMaxContentSize() : T.WindowSize {
if (this.lastScreenSize == null) {
let width = termWidthFromCols(80, WebShareModel.getTermFontSize());
let height = termHeightFromRows(25, WebShareModel.getTermFontSize());
return {width, height};
}
let winSize = this.lastScreenSize;
let width = util.boundInt(winSize.width-50, 100, 5000);
let height = util.boundInt(winSize.height-100, 100, 5000);
return {width, height};
}
getIdealContentSize() : T.WindowSize {
if (this.lastScreenSize == null) {
let width = termWidthFromCols(80, WebShareModel.getTermFontSize());
let height = termHeightFromRows(25, WebShareModel.getTermFontSize());
return {width, height};
}
let winSize = this.lastScreenSize;
let width = util.boundInt(Math.ceil((winSize.width-50)*0.7), 100, 5000);
let height = util.boundInt(Math.ceil((winSize.height-100)*0.5), 100, 5000);
return {width, height};
}
getRendererOpts(cmd : T.WebCmd) : T.RendererOpts {
return {
maxSize: this.getMaxContentSize(),
idealSize: this.getIdealContentSize(),
termOpts: cmd.termopts,
termFontSize: WebShareModel.getTermFontSize(),
};
}
makeRendererModelInitializeParams() : T.RendererModelInitializeParams {
let {line, cmd} = this.props;
let context = lineutil.getWebRendererContext(line);
let savedHeight = WebShareModel.getContentHeight(context);
if (savedHeight == null) {
if (line.contentheight != null && line.contentheight != -1) {
savedHeight = line.contentheight;
}
else {
savedHeight = 0;
}
}
let api = {
saveHeight: (height : number) => {
WebShareModel.setContentHeight(lineutil.getWebRendererContext(line), height);
},
onFocusChanged: (focus : boolean) => {
// nothing
},
dataHandler: (data : string, model : T.RendererModel) => {
// nothing
},
};
return {
context: context,
isDone: !lineutil.cmdStatusIsRunning(cmd.status),
savedHeight: savedHeight,
opts: this.getRendererOpts(cmd),
ptyDataSource: getTermPtyData,
api: api,
};
}
render() {
let {line, cmd, topBorder, staticRender, visible} = this.props;
@@ -334,7 +407,12 @@ class WebLineCmdView extends React.Component<{line : T.WebLine, cmd : T.WebCmd,
</div>
</If>
</div>
<TerminalRenderer line={line} cmd={cmd} width={width} staticRender={false} visible={visObs} onHeightChange={this.handleHeightChange}/>
<If condition={rendererPlugin == null && !isNoneRenderer}>
<TerminalRenderer line={line} cmd={cmd} width={width} staticRender={staticRender} visible={visible} onHeightChange={this.handleHeightChange}/>
</If>
<If condition={rendererPlugin != null}>
<SimpleBlobRenderer rendererContainer={WebShareModel} cmdId={line.lineid} plugin={rendererPlugin} onHeightChange={this.handleHeightChange} initParams={this.makeRendererModelInitializeParams()}/>
</If>
</div>
);
}
+5 -1
View File
@@ -358,6 +358,10 @@ class WebShareModelClass {
return this.renderers[lineId];
}
registerRenderer(cmdId : string, renderer : T.RendererModel) {
this.renderers[cmdId] = renderer;
}
loadFullScreenData() : void {
if (isBlank(this.screenId)) {
this.setErrMessage("No ScreenId Specified, Cannot Load.");
@@ -455,4 +459,4 @@ if ((window as any).WebShareModel == null) {
(window as any).WebShareModel = WebShareModel;
}
export {WebShareModel};
export {WebShareModel, getTermPtyData};