mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-03-09 13:00:53 +01:00
big update to support screen consolidation
This commit is contained in:
parent
ed6737157b
commit
0afacbd6d2
@ -545,7 +545,7 @@ class LineContainer extends React.Component<{historyId : string, width : number}
|
||||
<If condition={session == null}>
|
||||
<div className="no-line-context"/>
|
||||
</If>
|
||||
<Line sw={hvm.specialLineContainer} line={this.line} width={width} staticRender={false} visible={this.visible} onHeightChange={this.handleHeightChange} overrideCollapsed={this.overrideCollapsed} topBorder={false} renderMode="normal"/>
|
||||
<Line screen={hvm.specialLineContainer} line={this.line} width={width} staticRender={false} visible={this.visible} onHeightChange={this.handleHeightChange} overrideCollapsed={this.overrideCollapsed} topBorder={false} renderMode="normal"/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -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, ScreenWindow, windowWidthToCols, windowHeightToRows, termHeightFromRows, termWidthFromCols} from "./model";
|
||||
import {GlobalModel, GlobalCommandRunner, Session, Cmd, Window, 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";
|
||||
@ -20,7 +20,7 @@ type OArr<V> = mobx.IObservableArray<V>;
|
||||
type OMap<K,V> = mobx.ObservableMap<K,V>;
|
||||
|
||||
type HeightChangeCallbackType = (lineNum : number, newHeight : number, oldHeight : number) => void;
|
||||
type RendererComponentProps = {sw : LineContainerModel, line : LineType, width : number, staticRender : boolean, visible : OV<boolean>, onHeightChange : HeightChangeCallbackType, collapsed : boolean};
|
||||
type RendererComponentProps = {screen : LineContainerModel, line : LineType, width : number, staticRender : boolean, visible : OV<boolean>, onHeightChange : HeightChangeCallbackType, collapsed : boolean};
|
||||
type RendererComponentType = { new(props : RendererComponentProps) : React.Component<RendererComponentProps, {}> };
|
||||
|
||||
function isBlank(s : string) : boolean {
|
||||
@ -125,7 +125,7 @@ class LineAvatar extends React.Component<{line : LineType, cmd : Cmd}, {}> {
|
||||
|
||||
|
||||
@mobxReact.observer
|
||||
class LineCmd extends React.Component<{sw : LineContainerModel, line : LineType, width : number, staticRender : boolean, visible : OV<boolean>, onHeightChange : HeightChangeCallbackType, topBorder : boolean, renderMode : RenderModeType, overrideCollapsed : OV<boolean>, noSelect? : boolean}, {}> {
|
||||
class LineCmd extends React.Component<{screen : LineContainerModel, line : LineType, width : number, staticRender : boolean, visible : OV<boolean>, onHeightChange : HeightChangeCallbackType, topBorder : boolean, renderMode : RenderModeType, overrideCollapsed : OV<boolean>, noSelect? : boolean}, {}> {
|
||||
lineRef : React.RefObject<any> = React.createRef();
|
||||
cmdTextRef : React.RefObject<any> = React.createRef();
|
||||
rtnStateDiff : mobx.IObservableValue<string> = mobx.observable.box(null, {name: "linecmd-rtn-state-diff"});
|
||||
@ -139,7 +139,7 @@ class LineCmd extends React.Component<{sw : LineContainerModel, line : LineType,
|
||||
}
|
||||
|
||||
checkStateDiffLoad() : void {
|
||||
let {sw, line, staticRender, visible} = this.props;
|
||||
let {screen, line, staticRender, visible} = this.props;
|
||||
if (staticRender || this.isCollapsed()) {
|
||||
return;
|
||||
}
|
||||
@ -150,7 +150,7 @@ class LineCmd extends React.Component<{sw : LineContainerModel, line : LineType,
|
||||
}
|
||||
return;
|
||||
}
|
||||
let cmd = sw.getCmd(line);
|
||||
let cmd = screen.getCmd(line);
|
||||
if (cmd == null || !cmd.getRtnState() || this.rtnStateDiffFetched) {
|
||||
return;
|
||||
}
|
||||
@ -200,9 +200,9 @@ class LineCmd extends React.Component<{sw : LineContainerModel, line : LineType,
|
||||
|
||||
@boundMethod
|
||||
doRefresh() {
|
||||
let {sw, line} = this.props;
|
||||
let {screen, line} = this.props;
|
||||
let model = GlobalModel;
|
||||
let termWrap = sw.getRenderer(line.cmdid);
|
||||
let termWrap = screen.getRenderer(line.cmdid);
|
||||
if (termWrap != null) {
|
||||
termWrap.reload(500);
|
||||
}
|
||||
@ -321,7 +321,7 @@ class LineCmd extends React.Component<{sw : LineContainerModel, line : LineType,
|
||||
return;
|
||||
}
|
||||
}
|
||||
GlobalCommandRunner.swSelectLine(String(line.linenum), "cmd");
|
||||
GlobalCommandRunner.screenSelectLine(String(line.linenum), "cmd");
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
@ -377,8 +377,8 @@ class LineCmd extends React.Component<{sw : LineContainerModel, line : LineType,
|
||||
}
|
||||
|
||||
renderSimple() {
|
||||
let {sw, line, width, topBorder, renderMode} = this.props;
|
||||
let cmd = sw.getCmd(line);
|
||||
let {screen, line, width, topBorder, renderMode} = this.props;
|
||||
let cmd = screen.getCmd(line);
|
||||
let isCollapsed = this.isCollapsed();
|
||||
let mainDivCn = cn(
|
||||
"line",
|
||||
@ -394,7 +394,7 @@ class LineCmd extends React.Component<{sw : LineContainerModel, line : LineType,
|
||||
// else: 53+(lines*lineheight)
|
||||
let height = (isCollapsed ? 30 : 42); // height of zero height terminal
|
||||
if (!isCollapsed) {
|
||||
let usedRows = sw.getUsedRows(line, cmd, width);
|
||||
let usedRows = screen.getUsedRows(line, cmd, width);
|
||||
if (usedRows > 0) {
|
||||
height = 53 + termHeightFromRows(usedRows, GlobalModel.termFontSize.get());
|
||||
}
|
||||
@ -427,7 +427,7 @@ class LineCmd extends React.Component<{sw : LineContainerModel, line : LineType,
|
||||
}
|
||||
|
||||
render() {
|
||||
let {sw, line, width, staticRender, visible, topBorder, renderMode} = this.props;
|
||||
let {screen, line, width, staticRender, visible, topBorder, renderMode} = this.props;
|
||||
let model = GlobalModel;
|
||||
let lineid = line.lineid;
|
||||
let isVisible = visible.get();
|
||||
@ -435,7 +435,7 @@ class LineCmd extends React.Component<{sw : LineContainerModel, line : LineType,
|
||||
return this.renderSimple();
|
||||
}
|
||||
let formattedTime = getLineDateTimeStr(line.ts);
|
||||
let cmd = sw.getCmd(line);
|
||||
let cmd = screen.getCmd(line);
|
||||
if (cmd == null) {
|
||||
return (
|
||||
<div className="line line-invalid" id={this.getLineDomId()} ref={this.lineRef} data-lineid={line.lineid} data-linenum={line.linenum} data-windowid={line.windowid}>
|
||||
@ -445,15 +445,15 @@ class LineCmd extends React.Component<{sw : LineContainerModel, line : LineType,
|
||||
}
|
||||
let status = cmd.getStatus();
|
||||
let lineNumStr = (line.linenumtemp ? "~" : "") + String(line.linenum);
|
||||
let isSelected = mobx.computed(() => (sw.getSelectedLine() == line.linenum), {name: "computed-isSelected"}).get();
|
||||
let isPhysicalFocused = mobx.computed(() => sw.getIsFocused(line.linenum), {name: "computed-getIsFocused"}).get();
|
||||
let isSelected = mobx.computed(() => (screen.getSelectedLine() == line.linenum), {name: "computed-isSelected"}).get();
|
||||
let isPhysicalFocused = mobx.computed(() => screen.getIsFocused(line.linenum), {name: "computed-getIsFocused"}).get();
|
||||
let isFocused = mobx.computed(() => {
|
||||
let swFocusType = sw.getFocusType();
|
||||
return isPhysicalFocused && (swFocusType == "cmd" || swFocusType == "cmd-fg")
|
||||
let screenFocusType = screen.getFocusType();
|
||||
return isPhysicalFocused && (screenFocusType == "cmd" || screenFocusType == "cmd-fg")
|
||||
}, {name: "computed-isFocused"}).get();
|
||||
let isFgFocused = mobx.computed(() => {
|
||||
let swFocusType = sw.getFocusType();
|
||||
return isPhysicalFocused && swFocusType == "cmd-fg"
|
||||
let screenFocusType = screen.getFocusType();
|
||||
return isPhysicalFocused && screenFocusType == "cmd-fg"
|
||||
}, {name: "computed-isFgFocused"}).get();
|
||||
let isStatic = staticRender;
|
||||
let isRunning = cmd.isRunning()
|
||||
@ -500,7 +500,7 @@ class LineCmd extends React.Component<{sw : LineContainerModel, line : LineType,
|
||||
</If>
|
||||
</div>
|
||||
</div>
|
||||
<RendererComponent sw={sw} line={line} width={width} staticRender={staticRender} visible={visible} onHeightChange={this.handleHeightChange} collapsed={isCollapsed}/>
|
||||
<RendererComponent screen={screen} line={line} width={width} staticRender={staticRender} visible={visible} onHeightChange={this.handleHeightChange} collapsed={isCollapsed}/>
|
||||
<If condition={!isCollapsed && cmd.getRtnState()}>
|
||||
<div key="rtnstate" className="cmd-rtnstate" style={{visibility: ((cmd.getStatus() == "done") ? "visible" : "hidden")}}>
|
||||
<If condition={rsdiff == null || rsdiff == ""}>
|
||||
@ -520,7 +520,7 @@ class LineCmd extends React.Component<{sw : LineContainerModel, line : LineType,
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class Line extends React.Component<{sw : LineContainerModel, line : LineType, width : number, staticRender : boolean, visible : OV<boolean>, onHeightChange : HeightChangeCallbackType, overrideCollapsed : OV<boolean>, topBorder : boolean, renderMode : RenderModeType, noSelect? : boolean}, {}> {
|
||||
class Line extends React.Component<{screen : LineContainerModel, line : LineType, width : number, staticRender : boolean, visible : OV<boolean>, onHeightChange : HeightChangeCallbackType, overrideCollapsed : OV<boolean>, topBorder : boolean, renderMode : RenderModeType, noSelect? : boolean}, {}> {
|
||||
render() {
|
||||
let line = this.props.line;
|
||||
if (line.archived) {
|
||||
@ -537,7 +537,7 @@ class Line extends React.Component<{sw : LineContainerModel, line : LineType, wi
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class MarkdownRenderer extends React.Component<{sw : ScreenWindow, line : LineType, width : number, staticRender : boolean, visible : OV<boolean>, onHeightChange : HeightChangeCallbackType}, {}> {
|
||||
class MarkdownRenderer extends React.Component<{s : Screen, line : LineType, width : number, staticRender : boolean, visible : OV<boolean>, onHeightChange : HeightChangeCallbackType}, {}> {
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
@ -574,21 +574,21 @@ class Prompt extends React.Component<{rptr : RemotePtrType, festate : FeStateTyp
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class LineText extends React.Component<{sw : LineContainerModel, line : LineType, renderMode : RenderModeType, topBorder : boolean, noSelect? : boolean}, {}> {
|
||||
class LineText extends React.Component<{screen : LineContainerModel, line : LineType, renderMode : RenderModeType, topBorder : boolean, noSelect? : boolean}, {}> {
|
||||
@boundMethod
|
||||
clickHandler() {
|
||||
let {line, noSelect} = this.props;
|
||||
if (noSelect) {
|
||||
return;
|
||||
}
|
||||
GlobalCommandRunner.swSelectLine(String(line.linenum));
|
||||
GlobalCommandRunner.screenSelectLine(String(line.linenum));
|
||||
}
|
||||
|
||||
render() {
|
||||
let {sw, line, topBorder, renderMode} = this.props;
|
||||
let {screen, line, topBorder, renderMode} = this.props;
|
||||
let formattedTime = getLineDateTimeStr(line.ts);
|
||||
let isSelected = mobx.computed(() => (sw.getSelectedLine() == line.linenum), {name: "computed-isSelected"}).get();
|
||||
let isFocused = mobx.computed(() => (sw.getFocusType() == "cmd"), {name: "computed-isFocused"}).get();
|
||||
let isSelected = mobx.computed(() => (screen.getSelectedLine() == line.linenum), {name: "computed-isSelected"}).get();
|
||||
let isFocused = mobx.computed(() => (screen.getFocusType() == "cmd"), {name: "computed-isFocused"}).get();
|
||||
let isCollapsed = (renderMode == "collapsed");
|
||||
let mainClass = cn(
|
||||
"line",
|
||||
@ -615,7 +615,7 @@ class LineText extends React.Component<{sw : LineContainerModel, line : LineType
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class ImageRenderer extends React.Component<{sw : LineContainerModel, line : LineType, width : number, staticRender : boolean, visible : OV<boolean>, onHeightChange : () => void, collapsed : boolean}, {}> {
|
||||
class ImageRenderer extends React.Component<{screen : LineContainerModel, line : LineType, width : number, staticRender : boolean, visible : OV<boolean>, onHeightChange : () => void, collapsed : boolean}, {}> {
|
||||
elemRef : React.RefObject<any> = React.createRef();
|
||||
imageDivRef : React.RefObject<any> = React.createRef();
|
||||
imageLoaded : mobx.IObservableValue<boolean> = mobx.observable.box(false, {name: "imageLoaded"});
|
||||
@ -679,9 +679,9 @@ class ImageRenderer extends React.Component<{sw : LineContainerModel, line : Lin
|
||||
}
|
||||
|
||||
loadImage() : void {
|
||||
let {sw, line} = this.props;
|
||||
let {screen, line} = this.props;
|
||||
let model = GlobalModel;
|
||||
let cmd = sw.getCmd(line);
|
||||
let cmd = screen.getCmd(line);
|
||||
if (cmd == null) {
|
||||
return;
|
||||
}
|
||||
@ -690,13 +690,13 @@ class ImageRenderer extends React.Component<{sw : LineContainerModel, line : Lin
|
||||
console.log("cannot load image, no elem found");
|
||||
return;
|
||||
}
|
||||
this.imageModel = sw.loadImageRenderer(this.imageDivRef.current, line, cmd);
|
||||
this.imageModel = screen.loadImageRenderer(this.imageDivRef.current, line, cmd);
|
||||
mobx.action(() => this.imageLoaded.set(true))();
|
||||
}
|
||||
|
||||
unloadImage(unmount : boolean) : void {
|
||||
let {sw, line} = this.props;
|
||||
sw.unloadRenderer(line.cmdid);
|
||||
let {screen, line} = this.props;
|
||||
screen.unloadRenderer(line.cmdid);
|
||||
this.imageModel = null;
|
||||
if (!unmount) {
|
||||
mobx.action(() => this.imageLoaded.set(false))();
|
||||
@ -724,7 +724,7 @@ class ImageRenderer extends React.Component<{sw : LineContainerModel, line : Lin
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class TerminalRenderer extends React.Component<{sw : LineContainerModel, line : LineType, width : number, staticRender : boolean, visible : OV<boolean>, onHeightChange : () => void, collapsed : boolean}, {}> {
|
||||
class TerminalRenderer extends React.Component<{screen : LineContainerModel, line : LineType, width : number, staticRender : boolean, visible : OV<boolean>, onHeightChange : () => void, collapsed : boolean}, {}> {
|
||||
termLoaded : mobx.IObservableValue<boolean> = mobx.observable.box(false, {name: "linecmd-term-loaded"});
|
||||
elemRef : React.RefObject<any> = React.createRef();
|
||||
|
||||
@ -786,9 +786,9 @@ class TerminalRenderer extends React.Component<{sw : LineContainerModel, line :
|
||||
}
|
||||
|
||||
loadTerminal() : void {
|
||||
let {sw, line} = this.props;
|
||||
let {screen, line} = this.props;
|
||||
let model = GlobalModel;
|
||||
let cmd = sw.getCmd(line);
|
||||
let cmd = screen.getCmd(line);
|
||||
if (cmd == null) {
|
||||
return;
|
||||
}
|
||||
@ -798,13 +798,13 @@ class TerminalRenderer extends React.Component<{sw : LineContainerModel, line :
|
||||
console.log("cannot load terminal, no term elem found", termId);
|
||||
return;
|
||||
}
|
||||
sw.loadTerminalRenderer(termElem, line, cmd, this.props.width);
|
||||
screen.loadTerminalRenderer(termElem, line, cmd, this.props.width);
|
||||
mobx.action(() => this.termLoaded.set(true))();
|
||||
}
|
||||
|
||||
unloadTerminal(unmount : boolean) : void {
|
||||
let {sw, line} = this.props;
|
||||
sw.unloadRenderer(line.cmdid);
|
||||
let {screen, line} = this.props;
|
||||
screen.unloadRenderer(line.cmdid);
|
||||
if (!unmount) {
|
||||
mobx.action(() => this.termLoaded.set(false))();
|
||||
let termId = "term-" + getLineId(line);
|
||||
@ -817,24 +817,24 @@ class TerminalRenderer extends React.Component<{sw : LineContainerModel, line :
|
||||
|
||||
@boundMethod
|
||||
clickTermBlock(e : any) {
|
||||
let {sw, line} = this.props;
|
||||
let {screen, line} = this.props;
|
||||
let model = GlobalModel;
|
||||
let termWrap = sw.getRenderer(line.cmdid);
|
||||
let termWrap = screen.getRenderer(line.cmdid);
|
||||
if (termWrap != null) {
|
||||
termWrap.giveFocus();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let {sw, line, width, staticRender, visible, collapsed} = this.props;
|
||||
let {screen, line, width, staticRender, visible, collapsed} = this.props;
|
||||
let isVisible = visible.get(); // for reaction
|
||||
let isPhysicalFocused = mobx.computed(() => sw.getIsFocused(line.linenum), {name: "computed-getIsFocused"}).get();
|
||||
let isPhysicalFocused = mobx.computed(() => screen.getIsFocused(line.linenum), {name: "computed-getIsFocused"}).get();
|
||||
let isFocused = mobx.computed(() => {
|
||||
let swFocusType = sw.getFocusType();
|
||||
return isPhysicalFocused && (swFocusType == "cmd" || swFocusType == "cmd-fg")
|
||||
let screenFocusType = screen.getFocusType();
|
||||
return isPhysicalFocused && (screenFocusType == "cmd" || screenFocusType == "cmd-fg")
|
||||
}, {name: "computed-isFocused"}).get();
|
||||
let cmd = sw.getCmd(line); // will not be null
|
||||
let usedRows = sw.getUsedRows(line, cmd, width);
|
||||
let cmd = screen.getCmd(line); // will not be null
|
||||
let usedRows = screen.getUsedRows(line, cmd, width);
|
||||
let termHeight = termHeightFromRows(usedRows, GlobalModel.termFontSize.get());
|
||||
let termLoaded = this.termLoaded.get();
|
||||
return (
|
||||
|
164
src/main.tsx
164
src/main.tsx
@ -11,7 +11,7 @@ import cn from "classnames";
|
||||
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, ScreenWindow, riToRPtr, windowWidthToCols, windowHeightToRows, termHeightFromRows, termWidthFromCols} from "./model";
|
||||
import {GlobalModel, GlobalCommandRunner, Session, Cmd, Window, Screen, riToRPtr, windowWidthToCols, windowHeightToRows, termHeightFromRows, termWidthFromCols} from "./model";
|
||||
import {isModKeyPress} from "./util";
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
import remarkGfm from 'remark-gfm'
|
||||
@ -125,9 +125,9 @@ class TextAreaInput extends React.Component<{onHeightChange : () => void}, {}> {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
let activeSW = GlobalModel.getActiveSW();
|
||||
if (activeSW != null) {
|
||||
let focusType = activeSW.focusType.get();
|
||||
let activeScreen = GlobalModel.getActiveScreen();
|
||||
if (activeScreen != null) {
|
||||
let focusType = activeScreen.focusType.get();
|
||||
if (focusType == "input") {
|
||||
this.setFocus();
|
||||
}
|
||||
@ -137,9 +137,9 @@ class TextAreaInput extends React.Component<{onHeightChange : () => void}, {}> {
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
let activeSW = GlobalModel.getActiveSW();
|
||||
if (activeSW != null) {
|
||||
let focusType = activeSW.focusType.get();
|
||||
let activeScreen = GlobalModel.getActiveScreen();
|
||||
if (activeScreen != null) {
|
||||
let focusType = activeScreen.focusType.get();
|
||||
if (this.lastFocusType != focusType && focusType == "input") {
|
||||
this.setFocus();
|
||||
}
|
||||
@ -195,10 +195,10 @@ class TextAreaInput extends React.Component<{onHeightChange : () => void}, {}> {
|
||||
if (!ctrlMod) {
|
||||
if (GlobalModel.inputModel.isEmpty()) {
|
||||
let activeWindow = GlobalModel.getActiveWindow();
|
||||
let activeSW = GlobalModel.getActiveSW();
|
||||
if (activeSW != null && activeWindow != null && activeWindow.lines.length > 0) {
|
||||
activeSW.setSelectedLine(0);
|
||||
GlobalCommandRunner.swSelectLine("E");
|
||||
let activeScreen = GlobalModel.getActiveScreen();
|
||||
if (activeScreen != null && activeWindow != null && activeWindow.lines.length > 0) {
|
||||
activeScreen.setSelectedLine(0);
|
||||
GlobalCommandRunner.screenSelectLine("E");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -477,9 +477,9 @@ class TextAreaInput extends React.Component<{onHeightChange : () => void}, {}> {
|
||||
if (disabled) {
|
||||
displayLines = 1;
|
||||
}
|
||||
let activeSW = GlobalModel.getActiveSW();
|
||||
if (activeSW != null) {
|
||||
activeSW.focusType.get(); // for reaction
|
||||
let activeScreen = GlobalModel.getActiveScreen();
|
||||
if (activeScreen != null) {
|
||||
activeScreen.focusType.get(); // for reaction
|
||||
}
|
||||
return (
|
||||
<div className="control cmd-input-control is-expanded" ref={this.controlRef}>
|
||||
@ -1448,12 +1448,12 @@ class CmdInput extends React.Component<{}, {}> {
|
||||
render() {
|
||||
let model = GlobalModel;
|
||||
let inputModel = model.inputModel;
|
||||
let win = GlobalModel.getActiveWindow();
|
||||
let screen = GlobalModel.getActiveScreen();
|
||||
let ri : RemoteInstanceType = null;
|
||||
let rptr : RemotePtrType = null;
|
||||
if (win != null) {
|
||||
ri = win.getCurRemoteInstance();
|
||||
rptr = win.curRemote.get();
|
||||
if (screen != null) {
|
||||
ri = screen.getCurRemoteInstance();
|
||||
rptr = screen.curRemote.get();
|
||||
}
|
||||
let remote : RemoteType = null;
|
||||
let remoteState : FeStateType = null;
|
||||
@ -1538,7 +1538,7 @@ function getLineDateStr(todayDate : string, yesterdayDate : string, ts : number)
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class LinesView extends React.Component<{sw : ScreenWindow, width : number, lines : LineType[], renderMode : RenderModeType}, {}> {
|
||||
class LinesView extends React.Component<{screen : Screen, width : number, lines : LineType[], renderMode : RenderModeType}, {}> {
|
||||
rszObs : any;
|
||||
linesRef : React.RefObject<any>;
|
||||
staticRender : OV<boolean> = mobx.observable.box(true, {name: "static-render"});
|
||||
@ -1574,15 +1574,15 @@ class LinesView extends React.Component<{sw : ScreenWindow, width : number, line
|
||||
}
|
||||
|
||||
computeAnchorLine() : void {
|
||||
let {sw} = this.props;
|
||||
let {screen} = this.props;
|
||||
let linesElem = this.linesRef.current;
|
||||
if (linesElem == null) {
|
||||
sw.setAnchorFields(null, 0, "no-lines");
|
||||
screen.setAnchorFields(null, 0, "no-lines");
|
||||
return;
|
||||
}
|
||||
let lineElemArr = linesElem.querySelectorAll(".line");
|
||||
if (lineElemArr == null || lineElemArr.length == 0) {
|
||||
sw.setAnchorFields(null, 0, "no-line");
|
||||
screen.setAnchorFields(null, 0, "no-line");
|
||||
return;
|
||||
}
|
||||
let scrollTop = linesElem.scrollTop;
|
||||
@ -1599,7 +1599,7 @@ class LinesView extends React.Component<{sw : ScreenWindow, width : number, line
|
||||
if (anchorElem == null) {
|
||||
anchorElem = lineElemArr[0];
|
||||
}
|
||||
sw.setAnchorFields(parseInt(anchorElem.dataset.linenum), containerBottom - (anchorElem.offsetTop + anchorElem.offsetHeight), "computeAnchorLine");
|
||||
screen.setAnchorFields(parseInt(anchorElem.dataset.linenum), containerBottom - (anchorElem.offsetTop + anchorElem.offsetHeight), "computeAnchorLine");
|
||||
}
|
||||
|
||||
computeVisibleMap() : void {
|
||||
@ -1649,40 +1649,40 @@ class LinesView extends React.Component<{sw : ScreenWindow, width : number, line
|
||||
}
|
||||
|
||||
restoreAnchorOffset(reason : string) : void {
|
||||
let {sw} = this.props;
|
||||
let {screen} = this.props;
|
||||
let linesElem = this.linesRef.current;
|
||||
if (linesElem == null) {
|
||||
return;
|
||||
}
|
||||
if (sw.anchorLine == null || sw.anchorLine == 0) {
|
||||
if (screen.anchorLine == null || screen.anchorLine == 0) {
|
||||
return;
|
||||
}
|
||||
let anchorElem = linesElem.querySelector(sprintf(".line[data-linenum=\"%d\"]", sw.anchorLine));
|
||||
let anchorElem = linesElem.querySelector(sprintf(".line[data-linenum=\"%d\"]", screen.anchorLine));
|
||||
if (anchorElem == null) {
|
||||
return;
|
||||
}
|
||||
let isLastLine = sw.isLastLine(sw.anchorLine);
|
||||
let isLastLine = screen.isLastLine(screen.anchorLine);
|
||||
let scrollTop = linesElem.scrollTop;
|
||||
let height = linesElem.clientHeight;
|
||||
let containerBottom = scrollTop + height;
|
||||
let curAnchorOffset = containerBottom - (anchorElem.offsetTop + anchorElem.offsetHeight);
|
||||
let newAnchorOffset = sw.anchorOffset;
|
||||
let newAnchorOffset = screen.anchorOffset;
|
||||
if (isLastLine && newAnchorOffset == 0) {
|
||||
newAnchorOffset = 10;
|
||||
}
|
||||
if (curAnchorOffset != newAnchorOffset) {
|
||||
let offsetDiff = curAnchorOffset - newAnchorOffset;
|
||||
let newScrollTop = scrollTop - offsetDiff;
|
||||
// console.log("update scrolltop", reason, "line=" + sw.anchorLine, -offsetDiff, linesElem.scrollTop, "=>", newScrollTop);
|
||||
// console.log("update scrolltop", reason, "line=" + screen.anchorLine, -offsetDiff, linesElem.scrollTop, "=>", newScrollTop);
|
||||
linesElem.scrollTop = newScrollTop;
|
||||
this.ignoreNextScroll = true;
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() : void {
|
||||
let {sw, lines} = this.props;
|
||||
let {screen, lines} = this.props;
|
||||
let linesElem = this.linesRef.current;
|
||||
let anchorLineObj = sw.getLineByNum(sw.anchorLine);
|
||||
let anchorLineObj = screen.getLineByNum(screen.anchorLine);
|
||||
if (anchorLineObj == null) {
|
||||
// scroll to bottom
|
||||
if (linesElem != null) {
|
||||
@ -1693,7 +1693,7 @@ class LinesView extends React.Component<{sw : ScreenWindow, width : number, line
|
||||
else {
|
||||
this.restoreAnchorOffset("re-mount");
|
||||
}
|
||||
this.lastSelectedLine = sw.getSelectedLine();
|
||||
this.lastSelectedLine = screen.getSelectedLine();
|
||||
this.lastLinesLength = lines.length;
|
||||
|
||||
if (linesElem != null) {
|
||||
@ -1754,35 +1754,35 @@ class LinesView extends React.Component<{sw : ScreenWindow, width : number, line
|
||||
}
|
||||
|
||||
updateSelectedLine() : void {
|
||||
let {sw, lines} = this.props;
|
||||
let {screen, lines} = this.props;
|
||||
let linesElem = this.linesRef.current;
|
||||
if (linesElem == null) {
|
||||
return null;
|
||||
}
|
||||
let newLine = sw.getSelectedLine();
|
||||
let newLine = screen.getSelectedLine();
|
||||
if (newLine == 0) {
|
||||
return;
|
||||
}
|
||||
this.setLineVisible(newLine, true);
|
||||
// console.log("update selected line", this.lastSelectedLine, "=>", newLine, sprintf("anchor=%d:%d", sw.anchorLine, sw.anchorOffset));
|
||||
// console.log("update selected line", this.lastSelectedLine, "=>", newLine, sprintf("anchor=%d:%d", screen.anchorLine, screen.anchorOffset));
|
||||
let viewInfo = this.getLineViewInfo(newLine);
|
||||
if (viewInfo == null) {
|
||||
return;
|
||||
}
|
||||
sw.setAnchorFields(newLine, viewInfo.anchorOffset, "updateSelectedLine");
|
||||
screen.setAnchorFields(newLine, viewInfo.anchorOffset, "updateSelectedLine");
|
||||
let isFirst = (newLine == lines[0].linenum);
|
||||
let isLast = (newLine == lines[lines.length-1].linenum);
|
||||
if (viewInfo.botOffset > 0) {
|
||||
linesElem.scrollTop = linesElem.scrollTop + viewInfo.botOffset + (isLast ? 10 : 0);
|
||||
this.ignoreNextScroll = true;
|
||||
sw.anchorOffset = (isLast ? 10 : 0);
|
||||
screen.anchorOffset = (isLast ? 10 : 0);
|
||||
}
|
||||
else if (viewInfo.topOffset < 0) {
|
||||
linesElem.scrollTop = linesElem.scrollTop + viewInfo.topOffset + (isFirst ? -10 : 0);
|
||||
this.ignoreNextScroll = true;
|
||||
sw.anchorOffset = linesElem.clientHeight - viewInfo.height;
|
||||
screen.anchorOffset = linesElem.clientHeight - viewInfo.height;
|
||||
}
|
||||
// console.log("new anchor", sw.getAnchorStr());
|
||||
// console.log("new anchor", screen.getAnchorStr());
|
||||
}
|
||||
|
||||
setLineVisible(lineNum : number, vis : boolean) : void {
|
||||
@ -1800,10 +1800,10 @@ class LinesView extends React.Component<{sw : ScreenWindow, width : number, line
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) : void {
|
||||
let {sw, lines} = this.props;
|
||||
if (sw.getSelectedLine() != this.lastSelectedLine) {
|
||||
let {screen, lines} = this.props;
|
||||
if (screen.getSelectedLine() != this.lastSelectedLine) {
|
||||
this.updateSelectedLine();
|
||||
this.lastSelectedLine = sw.getSelectedLine();
|
||||
this.lastSelectedLine = screen.getSelectedLine();
|
||||
} else if (lines.length != this.lastLinesLength) {
|
||||
this.restoreAnchorOffset("line-length-change");
|
||||
}
|
||||
@ -1861,8 +1861,8 @@ class LinesView extends React.Component<{sw : ScreenWindow, width : number, line
|
||||
}
|
||||
|
||||
render() {
|
||||
let {sw, width, lines, renderMode} = this.props;
|
||||
let selectedLine = sw.getSelectedLine(); // for re-rendering
|
||||
let {screen, width, lines, renderMode} = this.props;
|
||||
let selectedLine = screen.getSelectedLine(); // for re-rendering
|
||||
let line : LineType = null;
|
||||
for (let i=0; i<lines.length; i++) {
|
||||
let key = String(lines[i].linenum);
|
||||
@ -1893,7 +1893,7 @@ class LinesView extends React.Component<{sw : ScreenWindow, width : number, line
|
||||
lineElements.push(sepElem);
|
||||
}
|
||||
let topBorder = (dateSepStr == null) && this.hasTopBorder(lines, idx);
|
||||
let lineElem = <Line key={line.lineid} line={line} sw={sw} width={width} visible={this.visibleMap.get(lineNumStr)} staticRender={this.staticRender.get()} onHeightChange={this.onHeightChange} overrideCollapsed={this.collapsedMap.get(lineNumStr)} topBorder={topBorder} renderMode={renderMode}/>;
|
||||
let lineElem = <Line key={line.lineid} line={line} screen={screen} width={width} visible={this.visibleMap.get(lineNumStr)} staticRender={this.staticRender.get()} onHeightChange={this.onHeightChange} overrideCollapsed={this.collapsedMap.get(lineNumStr)} topBorder={topBorder} renderMode={renderMode}/>;
|
||||
lineElements.push(lineElem);
|
||||
}
|
||||
return (
|
||||
@ -1905,9 +1905,9 @@ class LinesView extends React.Component<{sw : ScreenWindow, width : number, line
|
||||
}
|
||||
}
|
||||
|
||||
// sw is not null
|
||||
// screen is not null
|
||||
@mobxReact.observer
|
||||
class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
|
||||
class ScreenWindowView extends React.Component<{screen : Screen}, {}> {
|
||||
rszObs : any;
|
||||
windowViewRef : React.RefObject<any>;
|
||||
|
||||
@ -1924,8 +1924,8 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
|
||||
}
|
||||
|
||||
setSize(width : number, height : number) : void {
|
||||
let {sw} = this.props;
|
||||
if (sw == null) {
|
||||
let {screen} = this.props;
|
||||
if (screen == null) {
|
||||
return;
|
||||
}
|
||||
mobx.action(() => {
|
||||
@ -1934,10 +1934,10 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
|
||||
let cols = windowWidthToCols(width, GlobalModel.termFontSize.get());
|
||||
let rows = windowHeightToRows(height, GlobalModel.termFontSize.get());
|
||||
if (cols == 0 || rows == 0) {
|
||||
console.log("cannot set sw size", rows, cols);
|
||||
console.log("cannot set screen size", rows, cols);
|
||||
return;
|
||||
}
|
||||
sw.termSizeCallback(rows, cols);
|
||||
screen.termSizeCallback(rows, cols);
|
||||
})();
|
||||
}
|
||||
|
||||
@ -1969,10 +1969,10 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
|
||||
}
|
||||
|
||||
getWindow() : Window {
|
||||
let {sw} = this.props;
|
||||
let win = GlobalModel.getWindowById(sw.sessionId, sw.windowId);
|
||||
let {screen} = this.props;
|
||||
let win = GlobalModel.getWindowById(screen.sessionId, screen.windowId);
|
||||
if (win == null) {
|
||||
win = GlobalModel.loadWindow(sw.sessionId, sw.windowId);
|
||||
win = GlobalModel.loadWindow(screen.sessionId, screen.screenId, screen.windowId);
|
||||
}
|
||||
return win;
|
||||
}
|
||||
@ -1990,11 +1990,11 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
|
||||
}
|
||||
|
||||
renderError(message : string, fade : boolean) {
|
||||
let {sw} = this.props;
|
||||
let {screen} = this.props;
|
||||
return (
|
||||
<div className="window-view" style={this.getWindowViewStyle()} ref={this.windowViewRef} data-windowid={sw.windowId}>
|
||||
<div className="window-view" style={this.getWindowViewStyle()} ref={this.windowViewRef} data-windowid={screen.windowId}>
|
||||
<div key="window-tag" className="window-tag">
|
||||
<span>{sw.name.get()}</span>
|
||||
<span>{screen.name.get()}</span>
|
||||
</div>
|
||||
<div key="lines" className="lines"></div>
|
||||
<div key="window-empty" className={cn("window-empty", {"should-fade": fade})}>
|
||||
@ -2005,7 +2005,7 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
|
||||
}
|
||||
|
||||
render() {
|
||||
let {sw} = this.props;
|
||||
let {screen} = this.props;
|
||||
let win = this.getWindow();
|
||||
if (win == null || !win.loaded.get()) {
|
||||
return this.renderError("...", true);
|
||||
@ -2022,16 +2022,15 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
|
||||
}
|
||||
let idx = 0;
|
||||
let line : LineType = null;
|
||||
let screen = GlobalModel.getScreenById(sw.sessionId, sw.screenId);
|
||||
let session = GlobalModel.getSessionById(sw.sessionId);
|
||||
let isActive = sw.isActive();
|
||||
let selectedLine = sw.getSelectedLine();
|
||||
let session = GlobalModel.getSessionById(screen.sessionId);
|
||||
let isActive = screen.isActive();
|
||||
let selectedLine = screen.getSelectedLine();
|
||||
let lines = win.getNonArchivedLines();
|
||||
let renderMode = this.renderMode.get();
|
||||
return (
|
||||
<div className="window-view" style={this.getWindowViewStyle()} ref={this.windowViewRef}>
|
||||
<div key="window-tag" className={cn("window-tag", {"is-active": isActive})}>
|
||||
<div className="window-name">{sw.name.get()}</div>
|
||||
<div className="window-name">{screen.name.get()}</div>
|
||||
<div className="render-mode" onClick={this.toggleRenderMode}>
|
||||
<If condition={renderMode == "normal"}>
|
||||
<i title="collapse" className="fa-sharp fa-solid fa-arrows-to-line"/>
|
||||
@ -2042,11 +2041,11 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
|
||||
</div>
|
||||
</div>
|
||||
<If condition={lines.length > 0}>
|
||||
<LinesView sw={sw} width={this.width.get()} lines={lines} renderMode={renderMode}/>
|
||||
<LinesView screen={screen} width={this.width.get()} lines={lines} renderMode={renderMode}/>
|
||||
</If>
|
||||
<If condition={lines.length == 0}>
|
||||
<div key="window-empty" className="window-empty">
|
||||
<div><code>[session="{session.name.get()}" screen="{screen.name.get()}" window="{sw.name.get()}"]</code></div>
|
||||
<div><code>[session="{session.name.get()}" screen="{screen.name.get()}" window="{screen.name.get()}"]</code></div>
|
||||
</div>
|
||||
</If>
|
||||
</div>
|
||||
@ -2058,22 +2057,17 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
|
||||
class ScreenView extends React.Component<{screen : Screen}, {}> {
|
||||
render() {
|
||||
let {screen} = this.props;
|
||||
let sw : ScreenWindow = null;
|
||||
if (screen != null) {
|
||||
sw = screen.getActiveSW();
|
||||
}
|
||||
if (screen == null || sw == null) {
|
||||
if (screen == null) {
|
||||
return (
|
||||
<div className="screen-view">
|
||||
(no screen or window)
|
||||
(no screen found)
|
||||
</div>
|
||||
);
|
||||
}
|
||||
let fontSize = GlobalModel.termFontSize.get();
|
||||
let swKey = sw.windowId + "-fs" + fontSize;
|
||||
return (
|
||||
<div className="screen-view" data-screenid={sw.screenId}>
|
||||
<ScreenWindowView key={swKey} sw={sw}/>
|
||||
<div className="screen-view" data-screenid={screen.screenId}>
|
||||
<ScreenWindowView key={screen.screenId} screen={screen}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -2160,7 +2154,8 @@ class ScreenTabs extends React.Component<{session : Session}, {}> {
|
||||
let index = 0;
|
||||
let showingScreens = [];
|
||||
let activeScreenId = session.activeScreenId.get();
|
||||
for (let screen of session.screens) {
|
||||
let screens = GlobalModel.getSessionScreens(session.sessionId);
|
||||
for (let screen of screens) {
|
||||
if (!screen.archived.get() || activeScreenId == screen.screenId) {
|
||||
showingScreens.push(screen);
|
||||
}
|
||||
@ -2328,17 +2323,14 @@ class MainSideBar extends React.Component<{}, {}> {
|
||||
let model = GlobalModel;
|
||||
let activeSessionId = model.activeSessionId.get();
|
||||
let activeWindow = model.getActiveWindow();
|
||||
let activeScreen = model.getActiveScreen();
|
||||
let activeRemoteId : string = null;
|
||||
if (activeWindow != null) {
|
||||
let rptr = activeWindow.curRemote.get();
|
||||
if (activeScreen != null) {
|
||||
let rptr = activeScreen.curRemote.get();
|
||||
if (rptr != null && !isBlank(rptr.remoteid)) {
|
||||
activeRemoteId = rptr.remoteid;
|
||||
}
|
||||
}
|
||||
let sw : ScreenWindow = null;
|
||||
if (GlobalModel.debugSW.get()) {
|
||||
sw = GlobalModel.getActiveSW();
|
||||
}
|
||||
let session : Session = null;
|
||||
let remotes = model.remotes ?? [];
|
||||
let remote : RemoteType = null;
|
||||
@ -2397,7 +2389,7 @@ class MainSideBar extends React.Component<{}, {}> {
|
||||
<li className="menu-history"><a onClick={this.handleHistoryClick} className={cn({"is-active": (mainView == "history")})}><i className="fa-sharp fa-solid fa-clock"/> HISTORY</a></li>
|
||||
</ul>
|
||||
<ul className="menu-list">
|
||||
<li className="menu-bookmarks"><a onClick={this.handleBookmarksClick} className={cn({"is-active": (mainView == "bookmarks")})}><i className="fa-sharp fa-solid fa-bookmark"/> BOOKMARKS</a></li>
|
||||
<li className="menu-bookmarks"><a onClick={this.handleBookmarksClick} className={cn({"is-active": (mainView == "bookmarks")})}><i className="fa-sharp fa-solid fa-bookmark"/> BOOKMARKS <span>⌘B</span></a></li>
|
||||
</ul>
|
||||
<p className="menu-label display-none">
|
||||
Playbooks
|
||||
@ -2407,11 +2399,11 @@ class MainSideBar extends React.Component<{}, {}> {
|
||||
<li key="prompt-dev"><a onClick={this.handlePlaybookClick}><i className="fa-sharp fa-solid fa-file-lines"/> prompt-dev</a></li>
|
||||
</ul>
|
||||
<div className="spacer"></div>
|
||||
<If condition={GlobalModel.debugSW.get() && sw != null}>
|
||||
<If condition={GlobalModel.debugScreen.get() && activeScreen != null}>
|
||||
<div>
|
||||
focus={sw.focusType.get()}<br/>
|
||||
sline={sw.getSelectedLine()}<br/>
|
||||
termfocus={sw.termLineNumFocus.get()}<br/>
|
||||
focus={activeScreen.focusType.get()}<br/>
|
||||
sline={activeScreen.getSelectedLine()}<br/>
|
||||
termfocus={activeScreen.termLineNumFocus.get()}<br/>
|
||||
</div>
|
||||
</If>
|
||||
<ul className="menu-list">
|
||||
|
433
src/model.ts
433
src/model.ts
@ -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, BookmarkType, ClientDataType, HistoryViewDataType, AlertMessageType, HistorySearchParams} from "./types";
|
||||
import type {SessionDataType, LineType, RemoteType, HistoryItem, RemoteInstanceType, RemotePtrType, CmdDataType, FeCmdPacketType, TermOptsType, RemoteStateType, ScreenDataType, ScreenOptsType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, UIContextType, HistoryInfoType, HistoryQueryOpts, FeInputPacketType, TermWinSize, RemoteInputPacketType, FeStateType, ContextMenuOpts, RendererContext, RendererModel, PtyDataType, BookmarkType, ClientDataType, HistoryViewDataType, AlertMessageType, HistorySearchParams, FocusTypeStrs, ScreenLinesType} from "./types";
|
||||
import {WSControl} from "./ws";
|
||||
import {ImageRendererModel} from "./imagerenderer";
|
||||
import {measureText, getMonoFontSize} from "./textmeasure";
|
||||
@ -28,6 +28,7 @@ const DevServerWsEndpoint = "ws://localhost:8091";
|
||||
const DefaultTermFontSize = 12;
|
||||
const MinFontSize = 8;
|
||||
const MaxFontSize = 15;
|
||||
const InputChunkSize = 500;
|
||||
|
||||
// @ts-ignore
|
||||
const VERSION = __PROMPT_VERSION__;
|
||||
@ -50,7 +51,7 @@ type LineContainerModel = {
|
||||
type SWLinePtr = {
|
||||
line : LineType,
|
||||
win : Window,
|
||||
sw : ScreenWindow,
|
||||
screen : Screen,
|
||||
};
|
||||
|
||||
function windowWidthToCols(width : number, fontSize : number) : number {
|
||||
@ -249,6 +250,13 @@ class Cmd {
|
||||
if (!this.isRunning()) {
|
||||
return;
|
||||
}
|
||||
for (let pos=0; pos<data.length; pos += InputChunkSize) {
|
||||
let dataChunk = data.slice(pos, pos+InputChunkSize);
|
||||
this.handleInputChunk(dataChunk);
|
||||
}
|
||||
}
|
||||
|
||||
handleInputChunk(data : string) : void {
|
||||
let inputPacket : FeInputPacketType = {
|
||||
type: "feinput",
|
||||
ck: this.sessionId + "/" + this.cmdId,
|
||||
@ -262,28 +270,38 @@ class Cmd {
|
||||
class Screen {
|
||||
sessionId : string;
|
||||
screenId : string;
|
||||
windowId : string;
|
||||
screenIdx : OV<number>;
|
||||
opts : OV<ScreenOptsType>;
|
||||
name : OV<string>;
|
||||
activeWindowId : OV<string>;
|
||||
windows : OArr<ScreenWindow>;
|
||||
archived : OV<boolean>;
|
||||
curRemote : OV<RemotePtrType>;
|
||||
lastCols : number;
|
||||
lastRows : number;
|
||||
selectedLine : OV<number>;
|
||||
focusType : OV<FocusTypeStrs>;
|
||||
anchorLine : number = null;
|
||||
anchorOffset : number = 0;
|
||||
termLineNumFocus : OV<number>;
|
||||
setAnchor_debounced : (anchorLine : number, anchorOffset : number) => void;
|
||||
renderers : Record<string, RendererModel> = {}; // cmdid => TermWrap
|
||||
|
||||
constructor(sdata : ScreenDataType) {
|
||||
this.sessionId = sdata.sessionid;
|
||||
this.screenId = sdata.screenid;
|
||||
this.windowId = sdata.windowid;
|
||||
this.name = mobx.observable.box(sdata.name, {name: "screen-name"});
|
||||
this.screenIdx = mobx.observable.box(sdata.screenidx, {name: "screen-screenidx"});
|
||||
this.opts = mobx.observable.box(sdata.screenopts, {name: "screen-opts"});
|
||||
this.activeWindowId = mobx.observable.box(ces(sdata.activewindowid), {name: "screen-activewindowid"});
|
||||
this.archived = mobx.observable.box(!!sdata.archived, {name: "screen-archived"});
|
||||
let swArr : ScreenWindow[] = [];
|
||||
let wins = sdata.windows || [];
|
||||
for (let i=0; i<wins.length; i++) {
|
||||
let sw = new ScreenWindow(wins[i]);
|
||||
swArr.push(sw);
|
||||
this.focusType = mobx.observable.box(sdata.focustype, {name: "focusType"});
|
||||
this.selectedLine = mobx.observable.box(sdata.selectedline == 0 ? null : sdata.selectedline, {name: "selectedLine"});
|
||||
this.setAnchor_debounced = debounce(1000, this.setAnchor.bind(this));
|
||||
if (sdata.selectedline != 0) {
|
||||
this.setAnchorFields(sdata.selectedline, 0, "init");
|
||||
}
|
||||
this.windows = mobx.observable.array(swArr, {deep: false})
|
||||
this.termLineNumFocus = mobx.observable.box(0, {name: "termLineNumFocus"});
|
||||
this.curRemote = mobx.observable.box(sdata.curremote, {name: "window-curRemote"});
|
||||
}
|
||||
|
||||
dispose() {
|
||||
@ -294,83 +312,19 @@ class Screen {
|
||||
throw new Error("invalid screen update, ids don't match")
|
||||
}
|
||||
mobx.action(() => {
|
||||
if (data.screenidx != 0) {
|
||||
this.screenIdx.set(data.screenidx);
|
||||
}
|
||||
if (data.screenopts != null) {
|
||||
this.opts.set(data.screenopts);
|
||||
}
|
||||
if (!isBlank(data.name)) {
|
||||
this.name.set(data.name);
|
||||
}
|
||||
if (!isBlank(data.activewindowid)) {
|
||||
this.activeWindowId.set(data.activewindowid);
|
||||
}
|
||||
this.archived.set(!!data.archived);
|
||||
// TODO merge windows
|
||||
let oldSelectedLine = this.selectedLine.get();
|
||||
let oldFocusType = this.focusType.get();
|
||||
this.selectedLine.set(data.selectedline);
|
||||
this.focusType.set(data.focustype);
|
||||
this.refocusLine(data, oldFocusType, oldSelectedLine);
|
||||
// do not update anchorLine/anchorOffset (only stored)
|
||||
})();
|
||||
}
|
||||
|
||||
getActiveSW() : ScreenWindow {
|
||||
return this.getSW(this.activeWindowId.get());
|
||||
}
|
||||
|
||||
getTabColor() : string {
|
||||
let tabColor = "green";
|
||||
let screenOpts = this.opts.get();
|
||||
if (screenOpts != null && !isBlank(screenOpts.tabcolor)) {
|
||||
tabColor = screenOpts.tabcolor;
|
||||
}
|
||||
return tabColor;
|
||||
}
|
||||
|
||||
getSW(windowId : string) : ScreenWindow {
|
||||
if (windowId == null) {
|
||||
return null;
|
||||
}
|
||||
for (let i=0; i<this.windows.length; i++) {
|
||||
if (this.windows[i].windowId == windowId) {
|
||||
return this.windows[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class ScreenWindow {
|
||||
sessionId : string;
|
||||
screenId : string;
|
||||
windowId : string;
|
||||
name : OV<string>;
|
||||
layout : OV<LayoutType>;
|
||||
lastCols : number;
|
||||
lastRows : number;
|
||||
selectedLine : OV<number>;
|
||||
focusType : OV<"input"|"cmd"|"cmd-fg">;
|
||||
anchorLine : number = null;
|
||||
anchorOffset : number = 0;
|
||||
termLineNumFocus : OV<number>;
|
||||
|
||||
// cmdid => TermWrap
|
||||
renderers : Record<string, RendererModel> = {};
|
||||
|
||||
setAnchor_debounced : (anchorLine : number, anchorOffset : number) => void;
|
||||
|
||||
constructor(swdata : ScreenWindowType) {
|
||||
this.sessionId = swdata.sessionid;
|
||||
this.screenId = swdata.screenid;
|
||||
this.windowId = swdata.windowid;
|
||||
this.name = mobx.observable.box(swdata.name, {name: "name"});
|
||||
this.layout = mobx.observable.box(swdata.layout, {name: "layout"});
|
||||
this.focusType = mobx.observable.box(swdata.focustype, {name: "focusType"});
|
||||
this.selectedLine = mobx.observable.box(swdata.selectedline == 0 ? null : swdata.selectedline, {name: "selectedLine"});
|
||||
this.setAnchor_debounced = debounce(1000, this.setAnchor.bind(this));
|
||||
if (swdata.selectedline != 0) {
|
||||
this.setAnchorFields(swdata.selectedline, 0, "init");
|
||||
}
|
||||
this.termLineNumFocus = mobx.observable.box(0, {name: "termLineNumFocus"});
|
||||
}
|
||||
|
||||
getCmd(line : LineType) : Cmd {
|
||||
return GlobalModel.getCmd(line);
|
||||
}
|
||||
@ -382,37 +336,46 @@ class ScreenWindow {
|
||||
return sprintf("%d:%d", this.anchorLine, this.anchorOffset);
|
||||
}
|
||||
|
||||
getWindowId() : string {
|
||||
return this.windowId;
|
||||
}
|
||||
|
||||
getTabColor() : string {
|
||||
let tabColor = "green";
|
||||
let screenOpts = this.opts.get();
|
||||
if (screenOpts != null && !isBlank(screenOpts.tabcolor)) {
|
||||
tabColor = screenOpts.tabcolor;
|
||||
}
|
||||
return tabColor;
|
||||
}
|
||||
|
||||
getCurRemoteInstance() : RemoteInstanceType {
|
||||
let session = GlobalModel.getSessionById(this.sessionId);
|
||||
let rptr = this.curRemote.get();
|
||||
if (rptr == null) {
|
||||
return null;
|
||||
}
|
||||
return session.getRemoteInstance(this.windowId, rptr);
|
||||
}
|
||||
|
||||
setAnchorFields(anchorLine : number, anchorOffset : number, reason : string) {
|
||||
this.anchorLine = anchorLine;
|
||||
this.anchorOffset = anchorOffset;
|
||||
// console.log("set-anchor-fields", anchorLine, anchorOffset, reason);
|
||||
}
|
||||
|
||||
updateSelf(swdata : ScreenWindowType) {
|
||||
mobx.action(() => {
|
||||
this.name.set(swdata.name);
|
||||
this.layout.set(swdata.layout);
|
||||
let oldSelectedLine = this.selectedLine.get();
|
||||
let oldFocusType = this.focusType.get();
|
||||
this.selectedLine.set(swdata.selectedline);
|
||||
this.focusType.set(swdata.focustype);
|
||||
this.refocusLine(swdata, oldFocusType, oldSelectedLine);
|
||||
// do not update anchorLine/anchorOffset (only stored)
|
||||
})();
|
||||
}
|
||||
|
||||
refocusLine(swdata : ScreenWindowType, oldFocusType : string, oldSelectedLine : number) : void {
|
||||
let isCmdFocus = (swdata.focustype == "cmd" || swdata.focustype == "cmd-fg");
|
||||
refocusLine(sdata : ScreenDataType, oldFocusType : string, oldSelectedLine : number) : void {
|
||||
let isCmdFocus = (sdata.focustype == "cmd" || sdata.focustype == "cmd-fg");
|
||||
if (!isCmdFocus) {
|
||||
return;
|
||||
}
|
||||
let curLineFocus = GlobalModel.getFocusedLine();
|
||||
let sline : LineType = null;
|
||||
if (swdata.selectedline != 0) {
|
||||
sline = this.getLineByNum(swdata.selectedline);
|
||||
if (sdata.selectedline != 0) {
|
||||
sline = this.getLineByNum(sdata.selectedline);
|
||||
}
|
||||
// console.log("refocus", curLineFocus.linenum, "=>", swdata.selectedline, sline.cmdid);
|
||||
if (curLineFocus.cmdInputFocus || (curLineFocus.linenum != null && curLineFocus.linenum != swdata.selectedline)) {
|
||||
// console.log("refocus", curLineFocus.linenum, "=>", sdata.selectedline, sline.cmdid);
|
||||
if (curLineFocus.cmdInputFocus || (curLineFocus.linenum != null && curLineFocus.linenum != sdata.selectedline)) {
|
||||
(document.activeElement as HTMLElement).blur();
|
||||
}
|
||||
if (sline != null && sline.cmdid != null) {
|
||||
@ -423,19 +386,15 @@ class ScreenWindow {
|
||||
}
|
||||
}
|
||||
|
||||
setFocusType(ftype : "input" | "cmd" | "cmd-fg") : void {
|
||||
setFocusType(ftype : FocusTypeStrs) : void {
|
||||
mobx.action(() => {
|
||||
this.focusType.set(ftype);
|
||||
})();
|
||||
}
|
||||
|
||||
getFocusType() : "input" | "cmd" | "cmd-fg" {
|
||||
return this.focusType.get();
|
||||
}
|
||||
|
||||
setAnchor(anchorLine : number, anchorOffset : number) : void {
|
||||
let setVal = ((anchorLine == null || anchorLine == 0) ? "0" : sprintf("%d:%d", anchorLine, anchorOffset));
|
||||
GlobalCommandRunner.swSetAnchor(this.sessionId, this.screenId, this.windowId, setVal);
|
||||
GlobalCommandRunner.screenSetAnchor(this.sessionId, this.screenId, this.windowId, setVal);
|
||||
}
|
||||
|
||||
getMaxLineNum() : number {
|
||||
@ -564,10 +523,10 @@ class ScreenWindow {
|
||||
// console.log("SW setTermFocus", lineNum, focus);
|
||||
mobx.action(() => this.termLineNumFocus.set(focus ? lineNum : 0))();
|
||||
if (focus && this.selectedLine.get() != lineNum) {
|
||||
GlobalCommandRunner.swSelectLine(String(lineNum), "cmd");
|
||||
GlobalCommandRunner.screenSelectLine(String(lineNum), "cmd");
|
||||
}
|
||||
else if (focus && this.focusType.get() == "input") {
|
||||
GlobalCommandRunner.swSetFocus("cmd");
|
||||
GlobalCommandRunner.screenSetFocus("cmd");
|
||||
}
|
||||
}
|
||||
|
||||
@ -697,6 +656,10 @@ class ScreenWindow {
|
||||
return GlobalModel.getWindowById(this.sessionId, this.windowId);
|
||||
}
|
||||
|
||||
getFocusType() : FocusTypeStrs {
|
||||
return this.focusType.get();
|
||||
}
|
||||
|
||||
giveFocus() : void {
|
||||
if (!this.isActive()) {
|
||||
return;
|
||||
@ -720,17 +683,19 @@ class ScreenWindow {
|
||||
}
|
||||
}
|
||||
|
||||
// fake window for now (this is really ScreenLines)
|
||||
class Window {
|
||||
sessionId : string;
|
||||
screenId : string;
|
||||
windowId : string;
|
||||
curRemote : OV<RemotePtrType> = mobx.observable.box(null, {name: "window-curRemote"});
|
||||
loaded : OV<boolean> = mobx.observable.box(false, {name: "window-loaded"});
|
||||
loadError : OV<string> = mobx.observable.box(null);
|
||||
lines : OArr<LineType> = mobx.observable.array([], {name: "window-lines", deep: false});
|
||||
cmds : Record<string, Cmd> = {};
|
||||
|
||||
constructor(sessionId : string, windowId : string) {
|
||||
constructor(sessionId : string, screenId : string, windowId : string) {
|
||||
this.sessionId = sessionId;
|
||||
this.screenId = screenId;
|
||||
this.windowId = windowId;
|
||||
}
|
||||
|
||||
@ -746,17 +711,13 @@ class Window {
|
||||
return rtn;
|
||||
}
|
||||
|
||||
updateWindow(win : WindowDataType, load : boolean) {
|
||||
updateWindow(slines : ScreenLinesType, load : boolean) {
|
||||
mobx.action(() => {
|
||||
if (win.curremote != null && win.curremote.remoteid != "") {
|
||||
this.curRemote.set(win.curremote);
|
||||
}
|
||||
if (load) {
|
||||
this.loaded.set(true);
|
||||
}
|
||||
genMergeSimpleData(this.lines, win.lines, (l : LineType) => String(l.lineid), (l : LineType) => sprintf("%013d:%s", l.ts, l.lineid));
|
||||
|
||||
let cmds = win.cmds || [];
|
||||
genMergeSimpleData(this.lines, slines.lines, (l : LineType) => String(l.lineid), (l : LineType) => sprintf("%013d:%s", l.ts, l.lineid));
|
||||
let cmds = slines.cmds || [];
|
||||
for (let i=0; i<cmds.length; i++) {
|
||||
this.cmds[cmds[i].cmdid] = new Cmd(cmds[i]);
|
||||
}
|
||||
@ -796,15 +757,6 @@ class Window {
|
||||
return rtn;
|
||||
}
|
||||
|
||||
getCurRemoteInstance() : RemoteInstanceType {
|
||||
let session = GlobalModel.getSessionById(this.sessionId);
|
||||
let rptr = this.curRemote.get();
|
||||
if (rptr == null) {
|
||||
return null;
|
||||
}
|
||||
return session.getRemoteInstance(this.windowId, this.curRemote.get());
|
||||
}
|
||||
|
||||
updateCmd(cmd : CmdDataType) : void {
|
||||
if (cmd.remove) {
|
||||
throw new Error("cannot remove cmd with updateCmd call [" + cmd.cmdid + "]");
|
||||
@ -876,7 +828,6 @@ class Session {
|
||||
name : OV<string>;
|
||||
activeScreenId : OV<string>;
|
||||
sessionIdx : OV<number>;
|
||||
screens : OArr<Screen>;
|
||||
notifyNum : OV<number> = mobx.observable.box(0);
|
||||
remoteInstances : OArr<RemoteInstanceType>;
|
||||
archived : OV<boolean>;
|
||||
@ -886,13 +837,6 @@ class Session {
|
||||
this.name = mobx.observable.box(sdata.name);
|
||||
this.sessionIdx = mobx.observable.box(sdata.sessionidx);
|
||||
this.archived = mobx.observable.box(!!sdata.archived);
|
||||
let screenData = sdata.screens || [];
|
||||
let screens : Screen[] = [];
|
||||
for (let i=0; i<screenData.length; i++) {
|
||||
let screen = new Screen(screenData[i]);
|
||||
screens.push(screen);
|
||||
}
|
||||
this.screens = mobx.observable.array(screens, {deep: false});
|
||||
this.activeScreenId = mobx.observable.box(ces(sdata.activescreenid));
|
||||
let remotes = sdata.remotes || [];
|
||||
this.remoteInstances = mobx.observable.array(remotes);
|
||||
@ -917,7 +861,6 @@ class Session {
|
||||
this.notifyNum.set(sdata.notifynum);
|
||||
}
|
||||
this.archived.set(!!sdata.archived);
|
||||
genMergeData(this.screens, sdata.screens, (s : Screen) => s.screenId, (s : ScreenDataType) => s.screenid, (data : ScreenDataType) => new Screen(data), (s : Screen) => s.screenIdx.get());
|
||||
if (!isBlank(sdata.activescreenid)) {
|
||||
let screen = this.getScreenById(sdata.activescreenid);
|
||||
if (screen == null) {
|
||||
@ -943,12 +886,7 @@ class Session {
|
||||
if (screenId == null) {
|
||||
return null;
|
||||
}
|
||||
for (let i=0; i<this.screens.length; i++) {
|
||||
if (this.screens[i].screenId == screenId) {
|
||||
return this.screens[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return GlobalModel.getScreenById(this.sessionId, screenId);
|
||||
}
|
||||
|
||||
getRemoteInstance(windowId : string, rptr : RemotePtrType) : RemoteInstanceType {
|
||||
@ -968,17 +906,6 @@ class Session {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
getSWs(windowId : string) : ScreenWindow[] {
|
||||
let rtn : ScreenWindow[] = [];
|
||||
for (let screen of this.screens) {
|
||||
let sw = screen.getSW(windowId);
|
||||
if (sw != null) {
|
||||
rtn.push(sw);
|
||||
}
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
}
|
||||
|
||||
function getDefaultHistoryQueryOpts() : HistoryQueryOpts {
|
||||
@ -1114,10 +1041,10 @@ class InputModel {
|
||||
this.physicalInputFocused.set(isFocused);
|
||||
})();
|
||||
if (isFocused) {
|
||||
let sw = GlobalModel.getActiveSW();
|
||||
if (sw != null) {
|
||||
if (sw.focusType.get() != "input") {
|
||||
GlobalCommandRunner.swSetFocus("input");
|
||||
let screen = GlobalModel.getActiveScreen();
|
||||
if (screen != null) {
|
||||
if (screen.focusType.get() != "input") {
|
||||
GlobalCommandRunner.screenSetFocus("input");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2308,13 +2235,14 @@ class Model {
|
||||
activeSessionId : OV<string> = mobx.observable.box(null, {name: "activeSessionId"});
|
||||
sessionListLoaded : OV<boolean> = mobx.observable.box(false, {name: "sessionListLoaded"});
|
||||
sessionList : OArr<Session> = mobx.observable.array([], {name: "SessionList", deep: false});
|
||||
screenList : OArr<Screen> = mobx.observable.array([], {name: "ScreenList", deep: false});
|
||||
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/windowid"
|
||||
windows : OMap<string, Window> = mobx.observable.map({}, {name: "windows", deep: false}); // key = "sessionid/windowid" (screenlines)
|
||||
termUsedRowsCache : Record<string, number> = {};
|
||||
debugCmds : number = 0;
|
||||
debugSW : OV<boolean> = mobx.observable.box(false);
|
||||
debugScreen : OV<boolean> = mobx.observable.box(false);
|
||||
localServerRunning : OV<boolean>;
|
||||
authKey : string;
|
||||
isDev : boolean;
|
||||
@ -2492,21 +2420,6 @@ class Model {
|
||||
})();
|
||||
}
|
||||
|
||||
dumpStructure() : void {
|
||||
for (let i=0; i<this.sessionList.length; i++) {
|
||||
let session = this.sessionList[i];
|
||||
console.log("SESSION", session.sessionId);
|
||||
for (let j=0; j<session.screens.length; j++) {
|
||||
let screen = session.screens[j];
|
||||
console.log(" SCREEN", screen.sessionId, screen.screenId);
|
||||
for (let k=0; k<screen.windows.length; k++) {
|
||||
let win = screen.windows[k];
|
||||
console.log(" WINDOW", win.sessionId, win.screenId, win.windowId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getTUR(sessionId : string, cmdId : string, cols : number) : number {
|
||||
let key = sessionId + "/" + cmdId + "/" + cols;
|
||||
return this.termUsedRowsCache[key];
|
||||
@ -2542,16 +2455,10 @@ class Model {
|
||||
let screen = session.getActiveScreen();
|
||||
if (screen != null) {
|
||||
rtn.screenid = screen.screenId;
|
||||
let win = this.getActiveWindow();
|
||||
if (win != null) {
|
||||
rtn.windowid = win.windowId;
|
||||
rtn.remote = win.curRemote.get();
|
||||
}
|
||||
let sw = screen.getActiveSW();
|
||||
if (sw != null) {
|
||||
rtn.winsize = {rows: sw.lastRows, cols: sw.lastCols};
|
||||
rtn.linenum = sw.selectedLine.get();
|
||||
}
|
||||
rtn.windowid = screen.windowId;
|
||||
rtn.remote = screen.curRemote.get();
|
||||
rtn.winsize = {rows: screen.lastRows, cols: screen.lastCols};
|
||||
rtn.linenum = screen.selectedLine.get();
|
||||
}
|
||||
}
|
||||
return rtn;
|
||||
@ -2566,9 +2473,9 @@ class Model {
|
||||
}
|
||||
|
||||
onLCmd(e : any, mods : KeyModsType) {
|
||||
let sw = this.getActiveSW();
|
||||
if (sw != null) {
|
||||
GlobalCommandRunner.swSetFocus("cmd");
|
||||
let screen = this.getActiveScreen();
|
||||
if (screen != null) {
|
||||
GlobalCommandRunner.screenSetFocus("cmd");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2604,8 +2511,8 @@ class Model {
|
||||
// console.log("cmd status", sessionId, cmdId, origStatus, "=>", newStatus);
|
||||
let lines = this.getActiveLinesByCmdId(sessionId, cmdId);
|
||||
for (let ptr of lines) {
|
||||
let sw = ptr.sw;
|
||||
let renderer = sw.getRenderer(cmdId);
|
||||
let screen = ptr.screen;
|
||||
let renderer = screen.getRenderer(cmdId);
|
||||
if (renderer != null) {
|
||||
renderer.cmdDone();
|
||||
}
|
||||
@ -2614,19 +2521,19 @@ class Model {
|
||||
}
|
||||
|
||||
onMetaPageUp() : void {
|
||||
GlobalCommandRunner.swSelectLine("-1");
|
||||
GlobalCommandRunner.screenSelectLine("-1");
|
||||
}
|
||||
|
||||
onMetaPageDown() : void {
|
||||
GlobalCommandRunner.swSelectLine("+1");
|
||||
GlobalCommandRunner.screenSelectLine("+1");
|
||||
}
|
||||
|
||||
onMetaArrowUp() : void {
|
||||
GlobalCommandRunner.swSelectLine("-1");
|
||||
GlobalCommandRunner.screenSelectLine("-1");
|
||||
}
|
||||
|
||||
onMetaArrowDown() : void {
|
||||
GlobalCommandRunner.swSelectLine("+1");
|
||||
GlobalCommandRunner.screenSelectLine("+1");
|
||||
}
|
||||
|
||||
onBracketCmd(e : any, arg : {relative: number}, mods : KeyModsType) {
|
||||
@ -2700,6 +2607,18 @@ class Model {
|
||||
}
|
||||
}
|
||||
}
|
||||
if ("screens" in update) {
|
||||
if (update.connect) {
|
||||
this.screenList.clear();
|
||||
}
|
||||
genMergeData(this.screenList, update.screens, (s : Screen) => s.screenId, (sdata : ScreenDataType) => sdata.screenid, (sdata : ScreenDataType) => new Screen(sdata), null);
|
||||
for (let i=0; i<update.screens.length; i++) {
|
||||
let screen = update.screens[i];
|
||||
if (screen.remove) {
|
||||
this.removeWindowByScreenId(screen.screenid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ("activesessionid" in update) {
|
||||
this._activateSession(update.activesessionid);
|
||||
}
|
||||
@ -2714,15 +2633,8 @@ class Model {
|
||||
this.addLineCmd(update.lines[i], null, interactive);
|
||||
}
|
||||
}
|
||||
if ("windows" in update) {
|
||||
for (let i=0; i<update.windows.length; i++) {
|
||||
this.updateWindow(update.windows[i], false);
|
||||
}
|
||||
}
|
||||
if ("screenwindows" in update) {
|
||||
for (let i=0; i<update.screenwindows.length; i++) {
|
||||
this.updateSW(update.screenwindows[i]);
|
||||
}
|
||||
if ("screenlines" in update) {
|
||||
this.updateScreenLines(update.screenlines, false);
|
||||
}
|
||||
if ("remotes" in update) {
|
||||
if (update.connect) {
|
||||
@ -2788,13 +2700,10 @@ class Model {
|
||||
|
||||
getScreenNames() : Record<string, string> {
|
||||
let rtn : Record<string, string> = {};
|
||||
for (let i=0; i<this.sessionList.length; i++) {
|
||||
let session = this.sessionList[i];
|
||||
for (let j=0; j<session.screens.length; j++) {
|
||||
let screen = session.screens[j];
|
||||
for (let i=0; i<this.screenList.length; i++) {
|
||||
let screen = this.screenList[i];
|
||||
rtn[screen.screenId] = screen.name.get();
|
||||
}
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
@ -2820,45 +2729,58 @@ class Model {
|
||||
return this.windows.get(sessionId + "/" + windowId);
|
||||
}
|
||||
|
||||
updateWindow(win : WindowDataType, load : boolean) {
|
||||
updateScreenLines(slines : ScreenLinesType, load : boolean) {
|
||||
mobx.action(() => {
|
||||
let winKey = win.sessionid + "/" + win.windowid;
|
||||
if (win.remove) {
|
||||
this.windows.delete(winKey);
|
||||
return;
|
||||
}
|
||||
let winKey = slines.sessionid + "/" + slines.windowid;
|
||||
let existingWin = this.windows.get(winKey);
|
||||
if (existingWin == null) {
|
||||
if (!load) {
|
||||
console.log("cannot update window that does not exist", winKey);
|
||||
return;
|
||||
}
|
||||
let newWindow = new Window(win.sessionid, win.windowid);
|
||||
let newWindow = new Window(slines.sessionid, slines.screenid, slines.windowid);
|
||||
this.windows.set(winKey, newWindow);
|
||||
newWindow.updateWindow(win, load);
|
||||
newWindow.updateWindow(slines, load);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
existingWin.updateWindow(win, load);
|
||||
existingWin.updateWindow(slines, load);
|
||||
existingWin.loaded.set(true);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
updateSW(swdata : ScreenWindowType) {
|
||||
let sw = this.getSWByIds(swdata.sessionid, swdata.screenid, swdata.windowid);
|
||||
if (sw == null) {
|
||||
removeWindowByScreenId(screenId : string) {
|
||||
mobx.action(() => {
|
||||
for (let winKey of this.windows.keys()) {
|
||||
let win = this.windows.get(winKey);
|
||||
if (win.screenId == screenId) {
|
||||
this.windows.delete(winKey);
|
||||
return;
|
||||
}
|
||||
sw.updateSelf(swdata);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
getScreenById(sessionId : string, screenId : string) : Screen {
|
||||
let session = this.getSessionById(sessionId);
|
||||
if (session == null) {
|
||||
for (let i=0; i<this.screenList.length; i++) {
|
||||
let screen = this.screenList[i];
|
||||
if (screen.screenId == screenId) {
|
||||
return screen;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return session.getScreenById(screenId);
|
||||
|
||||
getSessionScreens(sessionId : string) : Screen[] {
|
||||
let rtn : Screen[] = [];
|
||||
for (let i=0; i<this.screenList.length; i++) {
|
||||
let screen = this.screenList[i];
|
||||
if (screen.sessionId == sessionId) {
|
||||
rtn.push(screen);
|
||||
}
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
getActiveWindow() : Window {
|
||||
@ -2866,32 +2788,7 @@ class Model {
|
||||
if (screen == null) {
|
||||
return null;
|
||||
}
|
||||
let activeWindowId = screen.activeWindowId.get();
|
||||
return this.windows.get(screen.sessionId + "/" + activeWindowId);
|
||||
}
|
||||
|
||||
getActiveSW() : ScreenWindow {
|
||||
let screen = this.getActiveScreen();
|
||||
if (screen == null) {
|
||||
return null;
|
||||
}
|
||||
return screen.getActiveSW();
|
||||
}
|
||||
|
||||
getSWByWindowId(windowId : string) : ScreenWindow {
|
||||
let screen = this.getActiveScreen();
|
||||
if (screen == null) {
|
||||
return null;
|
||||
}
|
||||
return screen.getSW(windowId);
|
||||
}
|
||||
|
||||
getSWByIds(sessionId : string, screenId : string, windowId : string) : ScreenWindow {
|
||||
let screen = this.getScreenById(sessionId, screenId);
|
||||
if (screen == null) {
|
||||
return null;
|
||||
}
|
||||
return screen.getSW(windowId);
|
||||
return this.windows.get(screen.sessionId + "/" + screen.windowId);
|
||||
}
|
||||
|
||||
getActiveScreen() : Screen {
|
||||
@ -3036,23 +2933,24 @@ class Model {
|
||||
|
||||
_loadWindowAsync(newWin : Window) {
|
||||
this.windows.set(newWin.sessionId + "/" + newWin.windowId, newWin);
|
||||
let usp = new URLSearchParams({sessionid: newWin.sessionId, windowid: newWin.windowId});
|
||||
let url = new URL(GlobalModel.getBaseHostPort() + "/api/get-window?" + usp.toString());
|
||||
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");
|
||||
return;
|
||||
}
|
||||
this.updateWindow(data.data, true);
|
||||
let slines : ScreenLinesType = data.data;
|
||||
this.updateScreenLines(slines, true);
|
||||
return;
|
||||
}).catch((err) => {
|
||||
this.errorHandler(sprintf("getting window=%s", newWin.windowId), err, false);
|
||||
});
|
||||
}
|
||||
|
||||
loadWindow(sessionId : string, windowId : string) : Window {
|
||||
let newWin = new Window(sessionId, windowId);
|
||||
loadWindow(sessionId : string, screenId : string, windowId : string) : Window {
|
||||
let newWin = new Window(sessionId, screenId, windowId);
|
||||
setTimeout(() => this._loadWindowAsync(newWin), 0);
|
||||
return newWin;
|
||||
}
|
||||
@ -3139,10 +3037,8 @@ class Model {
|
||||
}
|
||||
}
|
||||
if (winLine != null) {
|
||||
let sws = session.getSWs(win.windowId);
|
||||
for (let sw of sws) {
|
||||
rtn.push({line : winLine, win: win, sw: sw});
|
||||
}
|
||||
let screen = this.getScreenById(win.sessionId, win.screenId);
|
||||
rtn.push({line : winLine, win: win, screen: screen});
|
||||
}
|
||||
}
|
||||
return rtn;
|
||||
@ -3151,7 +3047,7 @@ class Model {
|
||||
updatePtyData(ptyMsg : PtyDataUpdateType) : void {
|
||||
let activeLinePtrs = this.getActiveLinesByCmdId(ptyMsg.sessionid, ptyMsg.cmdid);
|
||||
for (let lineptr of activeLinePtrs) {
|
||||
lineptr.sw.updatePtyData(ptyMsg);
|
||||
lineptr.screen.updatePtyData(ptyMsg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3217,10 +3113,7 @@ class CommandRunner {
|
||||
lineView(sessionId : string, screenId : string, lineNum : number) {
|
||||
let screen = GlobalModel.getScreenById(sessionId, screenId);
|
||||
if (screen != null) {
|
||||
let sw = screen.getActiveSW();
|
||||
if (sw != null) {
|
||||
sw.setAnchorFields(lineNum, 0, "line:view");
|
||||
}
|
||||
screen.setAnchorFields(lineNum, 0, "line:view");
|
||||
}
|
||||
GlobalModel.submitCommand("line", "view", [sessionId, screenId, String(lineNum)], {"nohist": "1"}, false);
|
||||
}
|
||||
@ -3238,7 +3131,7 @@ class CommandRunner {
|
||||
}
|
||||
|
||||
resizeWindow(windowId : string, rows : number, cols : number) {
|
||||
GlobalModel.submitCommand("sw", "resize", null, {"nohist": "1", "window": windowId, "cols": String(cols), "rows": String(rows)}, false);
|
||||
GlobalModel.submitCommand("screen", "resize", null, {"nohist": "1", "window": windowId, "cols": String(cols), "rows": String(rows)}, false);
|
||||
}
|
||||
|
||||
showRemote(remoteid : string) {
|
||||
@ -3290,7 +3183,7 @@ class CommandRunner {
|
||||
GlobalModel.submitCommand("remote", "archive", null, {"remote": remoteid, "nohist": "1"}, true);
|
||||
}
|
||||
|
||||
swSelectLine(lineArg : string, focusVal? : string) {
|
||||
screenSelectLine(lineArg : string, focusVal? : string) {
|
||||
let kwargs : Record<string, string> = {
|
||||
"nohist": "1",
|
||||
"line": lineArg,
|
||||
@ -3298,7 +3191,7 @@ class CommandRunner {
|
||||
if (focusVal != null) {
|
||||
kwargs["focus"] = focusVal;
|
||||
}
|
||||
GlobalModel.submitCommand("sw", "set", null, kwargs, true);
|
||||
GlobalModel.submitCommand("screen", "set", null, kwargs, false);
|
||||
}
|
||||
|
||||
setTermUsedRows(termContext : RendererContext, height : number) {
|
||||
@ -3311,7 +3204,7 @@ class CommandRunner {
|
||||
GlobalModel.submitCommand("line", "setheight", posargs, kwargs, false);
|
||||
}
|
||||
|
||||
swSetAnchor(sessionId : string, screenId : string, windowId : string, anchorVal : string) : void {
|
||||
screenSetAnchor(sessionId : string, screenId : string, windowId : string, anchorVal : string) : void {
|
||||
let kwargs = {
|
||||
"nohist": "1",
|
||||
"anchor": anchorVal,
|
||||
@ -3319,11 +3212,11 @@ class CommandRunner {
|
||||
"screen": screenId,
|
||||
"window": windowId,
|
||||
};
|
||||
GlobalModel.submitCommand("sw", "set", null, kwargs, true);
|
||||
GlobalModel.submitCommand("screen", "set", null, kwargs, false);
|
||||
}
|
||||
|
||||
swSetFocus(focusVal : string) : void {
|
||||
GlobalModel.submitCommand("sw", "set", null, {"focus": focusVal, "nohist": "1"}, true);
|
||||
screenSetFocus(focusVal : string) : void {
|
||||
GlobalModel.submitCommand("screen", "set", null, {"focus": focusVal, "nohist": "1"}, false);
|
||||
}
|
||||
|
||||
lineStar(lineId : string, starVal : number) {
|
||||
@ -3439,7 +3332,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, ScreenWindow, riToRPtr, windowWidthToCols, windowHeightToRows, termWidthFromCols, termHeightFromRows, getPtyData, getRemotePtyData};
|
||||
export {Model, Session, Window, GlobalModel, GlobalCommandRunner, Cmd, Screen, riToRPtr, windowWidthToCols, windowHeightToRows, termWidthFromCols, termHeightFromRows, getPtyData, getRemotePtyData};
|
||||
export type {LineContainerModel};
|
||||
|
||||
|
||||
|
62
src/types.ts
62
src/types.ts
@ -1,6 +1,7 @@
|
||||
import * as mobx from "mobx";
|
||||
|
||||
type ShareModeType = "local" | "private" | "view" | "shared";
|
||||
type FocusTypeStrs = "input"|"cmd"|"cmd-fg";
|
||||
|
||||
type SessionDataType = {
|
||||
sessionid : string,
|
||||
@ -10,7 +11,6 @@ type SessionDataType = {
|
||||
sessionidx : number,
|
||||
sharemode : ShareModeType,
|
||||
archived? : boolean,
|
||||
screens : ScreenDataType[],
|
||||
remotes : RemoteInstanceType[],
|
||||
|
||||
// for updates
|
||||
@ -42,47 +42,25 @@ type LineType = {
|
||||
|
||||
type ScreenOptsType = {
|
||||
tabcolor? : string,
|
||||
pterm? : string,
|
||||
}
|
||||
|
||||
type ScreenDataType = {
|
||||
sessionid : string,
|
||||
screenid : string,
|
||||
windowid : string,
|
||||
screenidx : number,
|
||||
activewindowid : string,
|
||||
name : string,
|
||||
archived? : boolean,
|
||||
windows : ScreenWindowType[],
|
||||
screenopts : ScreenOptsType,
|
||||
|
||||
// for updates
|
||||
remove? : boolean,
|
||||
full? : boolean,
|
||||
};
|
||||
|
||||
type LayoutType = {
|
||||
type : string,
|
||||
parent? : string,
|
||||
zindex? : number,
|
||||
float? : boolean,
|
||||
top? : string,
|
||||
bottom? : string,
|
||||
left? : string,
|
||||
right? : string,
|
||||
width? : string,
|
||||
height? : string,
|
||||
};
|
||||
|
||||
type ScreenWindowType = {
|
||||
sessionid : string,
|
||||
screenid : string,
|
||||
windowid : string,
|
||||
name : string,
|
||||
layout : LayoutType,
|
||||
curremote : RemotePtrType,
|
||||
nextlinenum : number,
|
||||
selectedline : number,
|
||||
focustype : "input"|"cmd"|"cmd-fg",
|
||||
focustype : FocusTypeStrs,
|
||||
anchor : {anchorline : number, anchoroffset : number},
|
||||
|
||||
// for updates
|
||||
full? : boolean,
|
||||
remove? : boolean,
|
||||
};
|
||||
|
||||
@ -142,18 +120,6 @@ type RemotePtrType = {
|
||||
name? : string,
|
||||
};
|
||||
|
||||
type WindowDataType = {
|
||||
sessionid : string,
|
||||
windowid : string,
|
||||
curremote : RemotePtrType,
|
||||
nextlinenum : number,
|
||||
lines : LineType[],
|
||||
cmds : CmdDataType[],
|
||||
|
||||
// for updates
|
||||
remove? : boolean,
|
||||
};
|
||||
|
||||
type HistoryItem = {
|
||||
historyid : string,
|
||||
ts : number,
|
||||
@ -273,12 +239,20 @@ type PtyDataUpdateType = {
|
||||
ptydatalen : number,
|
||||
};
|
||||
|
||||
type ScreenLinesType = {
|
||||
sessionid : string,
|
||||
screenid : string,
|
||||
windowid : string,
|
||||
lines : LineType[],
|
||||
cmds : CmdDataType[],
|
||||
};
|
||||
|
||||
type ModelUpdateType = {
|
||||
interactive : boolean,
|
||||
sessions? : SessionDataType[],
|
||||
activesessionid? : string,
|
||||
windows? : WindowDataType[],
|
||||
screenwindows? : ScreenWindowType[],
|
||||
screens? : ScreenDataType[],
|
||||
screenlines? : ScreenLinesType,
|
||||
line? : LineType,
|
||||
lines? : LineType[],
|
||||
cmd? : CmdDataType,
|
||||
@ -445,4 +419,4 @@ type HistorySearchParams = {
|
||||
|
||||
type RenderModeType = "normal" | "collapsed";
|
||||
|
||||
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, ClientDataType, PlaybookType, PlaybookEntryType, HistoryViewDataType, RenderModeType, AlertMessageType, HistorySearchParams};
|
||||
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};
|
||||
|
Loading…
Reference in New Issue
Block a user