move width from ScreenWindowView to ScreenWindow. pass termopts.cols in uicontext to cmdrunner

This commit is contained in:
sawka 2022-09-03 23:39:50 -07:00
parent 4a2b3cc381
commit 225f120fbe
4 changed files with 62 additions and 40 deletions

View File

@ -887,15 +887,19 @@ class CmdInput extends React.Component<{}, {}> {
} }
} }
// sw is not null
@mobxReact.observer @mobxReact.observer
class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> { class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
mutObs : any; mutObs : any;
rszObs : any; rszObs : any;
interObs : IntersectionObserver; interObs : IntersectionObserver;
randomId : string; randomId : string;
width : mobx.IObservableValue<number> = mobx.observable.box(0);
lastHeight : number = null; lastHeight : number = null;
constructor(props : any) {
super(props);
}
scrollToBottom(reason : string) { scrollToBottom(reason : string) {
let elem = document.getElementById(this.getLinesDOMId()); let elem = document.getElementById(this.getLinesDOMId());
if (elem == null) { if (elem == null) {
@ -911,7 +915,7 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
let {sw} = this.props; let {sw} = this.props;
let target = event.target; let target = event.target;
let atBottom = (target.scrollTop + 30 > (target.scrollHeight - target.offsetHeight)); let atBottom = (target.scrollTop + 30 > (target.scrollHeight - target.offsetHeight));
if (sw && sw.shouldFollow.get() != atBottom) { if (sw.shouldFollow.get() != atBottom) {
mobx.action(() => sw.shouldFollow.set(atBottom))(); mobx.action(() => sw.shouldFollow.set(atBottom))();
} }
// console.log("scroll-handler (sw)>", atBottom, target.scrollTop, target.scrollHeight, event); // console.log("scroll-handler (sw)>", atBottom, target.scrollTop, target.scrollHeight, event);
@ -924,7 +928,7 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
this.mutObs.observe(elem, {childList: true}); this.mutObs.observe(elem, {childList: true});
elem.addEventListener("termresize", this.handleTermResize); elem.addEventListener("termresize", this.handleTermResize);
let {sw} = this.props; let {sw} = this.props;
if (sw && sw.shouldFollow.get()) { if (sw.shouldFollow.get()) {
setTimeout(() => this.scrollToBottom("mount"), 0); setTimeout(() => this.scrollToBottom("mount"), 0);
} }
this.interObs = new IntersectionObserver(interObsCallback, { this.interObs = new IntersectionObserver(interObsCallback, {
@ -940,12 +944,6 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
} }
} }
updateWidth(width : number) {
mobx.action(() => {
this.width.set(width);
})();
}
componentWillUnmount() { componentWillUnmount() {
if (this.mutObs) { if (this.mutObs) {
this.mutObs.disconnect(); this.mutObs.disconnect();
@ -956,6 +954,7 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
if (this.interObs) { if (this.interObs) {
this.interObs.disconnect(); this.interObs.disconnect();
} }
this.props.sw.setWidth(0);
} }
handleResize(entries : any) { handleResize(entries : any) {
@ -964,7 +963,7 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
} }
let entry = entries[0]; let entry = entries[0];
let width = entry.target.offsetWidth; let width = entry.target.offsetWidth;
this.updateWidth(width); this.props.sw.setWidth(width);
if (this.lastHeight == null) { if (this.lastHeight == null) {
this.lastHeight = entry.target.offsetHeight; this.lastHeight = entry.target.offsetHeight;
return; return;
@ -981,16 +980,13 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
doConditionalScrollToBottom(reason : string) { doConditionalScrollToBottom(reason : string) {
let {sw} = this.props; let {sw} = this.props;
if (sw && sw.shouldFollow.get()) { if (sw.shouldFollow.get()) {
setTimeout(() => this.scrollToBottom(reason), 0); setTimeout(() => this.scrollToBottom(reason), 0);
} }
} }
getWindow() : Window { getWindow() : Window {
let {sw} = this.props; let {sw} = this.props;
if (sw == null) {
return null;
}
let win = GlobalModel.getWindowById(sw.sessionId, sw.windowId); let win = GlobalModel.getWindowById(sw.sessionId, sw.windowId);
if (win == null) { if (win == null) {
win = GlobalModel.loadWindow(sw.sessionId, sw.windowId); win = GlobalModel.loadWindow(sw.sessionId, sw.windowId);
@ -1005,7 +1001,7 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
@boundMethod @boundMethod
handleTermResize(e : any) { handleTermResize(e : any) {
let {sw} = this.props; let {sw} = this.props;
if (sw && sw.shouldFollow.get()) { if (sw.shouldFollow.get()) {
setTimeout(() => this.scrollToBottom("termresize"), 0); setTimeout(() => this.scrollToBottom("termresize"), 0);
} }
} }
@ -1017,12 +1013,6 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
getWindowId() : string { getWindowId() : string {
let {sw} = this.props; let {sw} = this.props;
if (sw == null) {
if (!this.randomId) {
this.randomId = uuidv4();
}
return this.randomId;
}
return sw.windowId; return sw.windowId;
} }
@ -1035,9 +1025,7 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
return ( return (
<div className="window-view" style={this.getWindowViewStyle()} id={this.getWindowViewDOMId()}> <div className="window-view" style={this.getWindowViewStyle()} id={this.getWindowViewDOMId()}>
<div key="window-tag" className="window-tag"> <div key="window-tag" className="window-tag">
<If condition={sw != null}>
<span>{sw.name.get()}{sw.shouldFollow.get() ? "*" : ""}</span> <span>{sw.name.get()}{sw.shouldFollow.get() ? "*" : ""}</span>
</If>
</div> </div>
<div key="lines" className="lines" id={this.getLinesDOMId()}></div> <div key="lines" className="lines" id={this.getLinesDOMId()}></div>
<div key="window-empty" className="window-empty"> <div key="window-empty" className="window-empty">
@ -1049,9 +1037,6 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
render() { render() {
let {sw} = this.props; let {sw} = this.props;
if (sw == null) {
return this.renderError("(no screen window)");
}
let win = this.getWindow(); let win = this.getWindow();
if (win == null || !win.loaded.get()) { if (win == null || !win.loaded.get()) {
return this.renderError("(loading)"); return this.renderError("(loading)");
@ -1059,7 +1044,7 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
if (win.loadError.get() != null) { if (win.loadError.get() != null) {
return this.renderError(sprintf("(%s)", win.loadError.get())); return this.renderError(sprintf("(%s)", win.loadError.get()));
} }
if (this.width.get() == 0) { if (sw.width.get() == 0) {
return this.renderError(""); return this.renderError("");
} }
let idx = 0; let idx = 0;
@ -1087,7 +1072,7 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
<div key="lines" className="lines" onScroll={this.scrollHandler} id={this.getLinesDOMId()} style={linesStyle}> <div key="lines" className="lines" onScroll={this.scrollHandler} id={this.getLinesDOMId()} style={linesStyle}>
<div className="lines-spacer"></div> <div className="lines-spacer"></div>
<For each="line" of={win.lines} index="idx"> <For each="line" of={win.lines} index="idx">
<Line key={line.lineid} line={line} sw={sw} width={this.width.get()} interObs={this.interObs} initVis={idx > win.lines.length-1-7} cmdRefNum={cmdRefMap[line.lineid] ?? 0}/> <Line key={line.lineid} line={line} sw={sw} width={sw.width.get()} interObs={this.interObs} initVis={idx > win.lines.length-1-7} cmdRefNum={cmdRefMap[line.lineid] ?? 0}/>
</For> </For>
</div> </div>
<If condition={win.lines.length == 0}> <If condition={win.lines.length == 0}>
@ -1104,14 +1089,17 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
class ScreenView extends React.Component<{screen : Screen}, {}> { class ScreenView extends React.Component<{screen : Screen}, {}> {
render() { render() {
let {screen} = this.props; let {screen} = this.props;
if (screen == null) { let sw : ScreenWindow = null;
if (screen != null) {
sw = screen.getActiveSW();
}
if (screen == null || sw == null) {
return ( return (
<div className="screen-view"> <div className="screen-view">
(no screen) (no screen or window)
</div> </div>
); );
} }
let sw = screen.getActiveSW();
return ( return (
<div className="screen-view"> <div className="screen-view">
<ScreenWindowView key={sw.windowId} sw={sw}/> <ScreenWindowView key={sw.windowId} sw={sw}/>

View File

@ -8,6 +8,16 @@ import type {SessionDataType, WindowDataType, LineType, RemoteType, HistoryItem,
import {WSControl} from "./ws"; import {WSControl} from "./ws";
var GlobalUser = "sawka"; var GlobalUser = "sawka";
const DefaultCellWidth = 8;
const DefaultCellHeight = 16;
function widthToCols(width : number) : number {
let cols = Math.trunc((width - 25) / DefaultCellWidth) - 1;
if (cols < 0) {
return 0;
}
return cols;
}
type OV<V> = mobx.IObservableValue<V>; type OV<V> = mobx.IObservableValue<V>;
type OArr<V> = mobx.IObservableArray<V>; type OArr<V> = mobx.IObservableArray<V>;
@ -242,6 +252,7 @@ class ScreenWindow {
name : OV<string>; name : OV<string>;
layout : OV<LayoutType>; layout : OV<LayoutType>;
shouldFollow : OV<boolean> = mobx.observable.box(true); shouldFollow : OV<boolean> = mobx.observable.box(true);
width : OV<number> = mobx.observable.box(0);
// cmdid => TermWrap // cmdid => TermWrap
terms : Record<string, TermWrap> = {}; terms : Record<string, TermWrap> = {};
@ -264,6 +275,12 @@ class ScreenWindow {
term.updatePtyData(ptyMsg.ptypos, data); term.updatePtyData(ptyMsg.ptypos, data);
} }
setWidth(width : number) : void {
mobx.action(() => {
this.width.set(width);
})();
}
getTermWrap(cmdId : string) : TermWrap { getTermWrap(cmdId : string) : TermWrap {
return this.terms[cmdId]; return this.terms[cmdId];
} }
@ -275,7 +292,8 @@ class ScreenWindow {
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;
} }
let usedRows = GlobalModel.getTUR(this.sessionId, cmdId, width); let cols = widthToCols(width);
let usedRows = GlobalModel.getTUR(this.sessionId, cmdId, cols);
termWrap = new TermWrap(elem, this.sessionId, cmdId, usedRows, cmd.getTermOpts(), {height: 0, width: width}, cmd.handleKey.bind(cmd)); termWrap = new TermWrap(elem, this.sessionId, cmdId, usedRows, cmd.getTermOpts(), {height: 0, width: width}, cmd.handleKey.bind(cmd));
this.terms[cmdId] = termWrap; this.terms[cmdId] = termWrap;
return; return;
@ -296,7 +314,8 @@ class ScreenWindow {
} }
let termWrap = this.getTermWrap(cmd.cmdId); let termWrap = this.getTermWrap(cmd.cmdId);
if (termWrap == null) { if (termWrap == null) {
let usedRows = GlobalModel.getTUR(this.sessionId, cmd.cmdId, width); let cols = widthToCols(width);
let usedRows = GlobalModel.getTUR(this.sessionId, cmd.cmdId, cols);
if (usedRows != null) { if (usedRows != null) {
return usedRows; return usedRows;
} }
@ -1127,13 +1146,13 @@ class Model {
getApi().onDigitCmd(this.onDigitCmd.bind(this)); getApi().onDigitCmd(this.onDigitCmd.bind(this));
} }
getTUR(sessionId : string, cmdId : string, width : number) : number { getTUR(sessionId : string, cmdId : string, cols : number) : number {
let key = sessionId + "/" + cmdId + "/" + width; let key = sessionId + "/" + cmdId + "/" + cols;
return this.termUsedRowsCache[key]; return this.termUsedRowsCache[key];
} }
setTUR(sessionId : string, cmdId : string, width : number, usedRows : number) : void { setTUR(sessionId : string, cmdId : string, cols : number, usedRows : number) : void {
let key = sessionId + "/" + cmdId + "/" + width; let key = sessionId + "/" + cmdId + "/" + cols;
this.termUsedRowsCache[key] = usedRows; this.termUsedRowsCache[key] = usedRows;
} }
@ -1148,6 +1167,7 @@ class Model {
screenid : null, screenid : null,
windowid : null, windowid : null,
remote : null, remote : null,
termopts : {},
}; };
let session = this.getActiveSession(); let session = this.getActiveSession();
if (session != null) { if (session != null) {
@ -1160,6 +1180,10 @@ class Model {
rtn.windowid = win.windowId; rtn.windowid = win.windowId;
rtn.remote = win.curRemote.get(); rtn.remote = win.curRemote.get();
} }
let sw = screen.getActiveSW();
if (sw != null) {
rtn.termopts.cols = widthToCols(sw.width.get());
}
} }
} }
return rtn; return rtn;
@ -1731,6 +1755,6 @@ if ((window as any).GlobalModal == null) {
GlobalModel = (window as any).GlobalModel; GlobalModel = (window as any).GlobalModel;
GlobalCommandRunner = (window as any).GlobalCommandRunner; GlobalCommandRunner = (window as any).GlobalCommandRunner;
export {Model, Session, Window, GlobalModel, GlobalCommandRunner, Cmd, Screen, ScreenWindow, riToRPtr}; export {Model, Session, Window, GlobalModel, GlobalCommandRunner, Cmd, Screen, ScreenWindow, riToRPtr, widthToCols};

View File

@ -48,6 +48,7 @@ class TermWrap {
loadError : mobx.IObservableValue<boolean> = mobx.observable.box(false); loadError : mobx.IObservableValue<boolean> = mobx.observable.box(false);
winSize : WindowSize; winSize : WindowSize;
numParseErrors : number = 0; numParseErrors : number = 0;
termCols : number;
constructor(elem : Element, sessionId : string, cmdId : string, usedRows : number, termOpts : TermOptsType, winSize : WindowSize, keyHandler : (event : any) => void) { constructor(elem : Element, sessionId : string, cmdId : string, usedRows : number, termOpts : TermOptsType, winSize : WindowSize, keyHandler : (event : any) => void) {
this.sessionId = sessionId; this.sessionId = sessionId;
@ -68,6 +69,7 @@ class TermWrap {
if (maxCols > cols) { if (maxCols > cols) {
cols = maxCols; cols = maxCols;
} }
this.termCols = maxCols;
this.terminal = new Terminal({rows: termOpts.rows, cols: maxCols, fontSize: 14, theme: {foreground: "#d3d7cf"}}); this.terminal = new Terminal({rows: termOpts.rows, cols: maxCols, fontSize: 14, theme: {foreground: "#d3d7cf"}});
this.terminal._core._inputHandler._parser.setErrorHandler((state) => { this.terminal._core._inputHandler._parser.setErrorHandler((state) => {
this.numParseErrors++; this.numParseErrors++;
@ -155,7 +157,7 @@ class TermWrap {
mobx.action(() => { mobx.action(() => {
let oldUsedRows = this.usedRows.get(); let oldUsedRows = this.usedRows.get();
this.usedRows.set(tur); this.usedRows.set(tur);
GlobalModel.setTUR(this.sessionId, this.cmdId, this.winSize.width, tur); GlobalModel.setTUR(this.sessionId, this.cmdId, this.termCols, tur);
if (this.connectedElem) { if (this.connectedElem) {
let resizeEvent = new CustomEvent("termresize", { let resizeEvent = new CustomEvent("termresize", {
bubbles: true, bubbles: true,

View File

@ -139,11 +139,19 @@ type CmdRemoteStateType = {
cwd : string, cwd : string,
}; };
type UIContextTermOptsType = {
rows? : number,
cols? : number,
term? : string,
maxptysize? : number,
};
type UIContextType = { type UIContextType = {
sessionid : string, sessionid : string,
screenid : string, screenid : string,
windowid : string, windowid : string,
remote : RemotePtrType, remote : RemotePtrType,
termopts : UIContextTermOptsType,
}; };
type FeCmdPacketType = { type FeCmdPacketType = {