Pull in linting fixes from preact branch (#538)

* Pull in linting fixes from preact branch

* more consts

* one more const

* Revert PureComponent

* revert preact artifavt

* revert another change
This commit is contained in:
Evan Simkowitz 2024-04-02 12:30:17 -07:00 committed by GitHub
parent ca5117cda0
commit dc7fc2c823
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 312 additions and 309 deletions

View File

@ -8,7 +8,7 @@ import { sprintf } from "sprintf-js";
import { boundMethod } from "autobind-decorator"; import { boundMethod } from "autobind-decorator";
import dayjs from "dayjs"; import dayjs from "dayjs";
import localizedFormat from "dayjs/plugin/localizedFormat"; import localizedFormat from "dayjs/plugin/localizedFormat";
import { If } from "tsx-control-statements/components"; import { Choose, If, Otherwise, When } from "tsx-control-statements/components";
import { GlobalModel, GlobalCommandRunner, Cmd } from "@/models"; import { GlobalModel, GlobalCommandRunner, Cmd } from "@/models";
import { termHeightFromRows } from "@/util/textmeasure"; import { termHeightFromRows } from "@/util/textmeasure";
import cn from "classnames"; import cn from "classnames";
@ -25,23 +25,22 @@ import * as lineutil from "./lineutil";
import { ErrorBoundary } from "@/common/error/errorboundary"; import { ErrorBoundary } from "@/common/error/errorboundary";
import * as appconst from "@/app/appconst"; import * as appconst from "@/app/appconst";
import * as util from "@/util/util"; import * as util from "@/util/util";
import * as textmeasure from "@/util/textmeasure";
import "./line.less"; import "./line.less";
import { CenteredIcon, RotateIcon } from "../common/icons/icons"; import { RotateIcon } from "../common/icons/icons";
const DebugHeightProblems = false; const DebugHeightProblems = false;
const MinLine = 0; const MinLine = 0;
const MaxLine = 1000; const MaxLine = 1000;
let heightLog = {}; const heightLog = {};
(window as any).heightLog = heightLog; (window as any).heightLog = heightLog;
(window as any).findHeightProblems = function () { (window as any).findHeightProblems = function () {
for (let linenum in heightLog) { for (const linenum in heightLog) {
let lh = heightLog[linenum]; const lh = heightLog[linenum];
if (lh.heightArr == null || lh.heightArr.length < 2) { if (lh.heightArr == null || lh.heightArr.length < 2) {
continue; continue;
} }
let firstHeight = lh.heightArr[0]; const firstHeight = lh.heightArr[0];
for (let i = 1; i < lh.heightArr.length; i++) { for (let i = 1; i < lh.heightArr.length; i++) {
if (lh.heightArr[i] != firstHeight) { if (lh.heightArr[i] != firstHeight) {
console.log("line", linenum, "heights", lh.heightArr); console.log("line", linenum, "heights", lh.heightArr);
@ -57,7 +56,7 @@ function cmdShouldMarkError(cmd: Cmd): boolean {
if (cmd.getStatus() == "error") { if (cmd.getStatus() == "error") {
return true; return true;
} }
let exitCode = cmd.getExitCode(); const exitCode = cmd.getExitCode();
// 0, SIGINT, or SIGPIPE // 0, SIGINT, or SIGPIPE
if (exitCode == 0 || exitCode == 130 || exitCode == 141) { if (exitCode == 0 || exitCode == 130 || exitCode == 141) {
return false; return false;
@ -142,7 +141,7 @@ class LineActions extends React.Component<{ screen: LineContainerType; line: Lin
handleLineSettings(e: any): void { handleLineSettings(e: any): void {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
let { line } = this.props; const { line } = this.props;
if (line != null) { if (line != null) {
mobx.action(() => { mobx.action(() => {
GlobalModel.lineSettingsModal.set(line.linenum); GlobalModel.lineSettingsModal.set(line.linenum);
@ -152,74 +151,89 @@ class LineActions extends React.Component<{ screen: LineContainerType; line: Lin
} }
render() { render() {
let { line, screen } = this.props; const { line, screen } = this.props;
const isMinimized = line.linestate["wave:min"]; const isMinimized = line.linestate["wave:min"];
const containerType = screen.getContainerType(); const containerType = screen.getContainerType();
return ( return (
<div className="line-actions"> <div className="line-actions">
<If condition={containerType == appconst.LineContainer_Main}> <Choose>
<div key="restart" title="Restart Command" className="line-icon" onClick={this.clickRestart}> <When condition={containerType == appconst.LineContainer_Main}>
<i className="fa-sharp fa-regular fa-arrows-rotate fa-fw" /> <div key="restart" title="Restart Command" className="line-icon" onClick={this.clickRestart}>
</div> <i className="fa-sharp fa-regular fa-arrows-rotate fa-fw" />
<div key="delete" title="Delete Line (&#x2318;D)" className="line-icon" onClick={this.clickDelete}> </div>
<i className="fa-sharp fa-regular fa-trash fa-fw" /> <div
</div> key="delete"
<div title="Delete Line (&#x2318;D)"
key="bookmark" className="line-icon"
title="Bookmark" onClick={this.clickDelete}
className={cn("line-icon", "line-bookmark")} >
onClick={this.clickBookmark} <i className="fa-sharp fa-regular fa-trash fa-fw" />
> </div>
<i className="fa-sharp fa-regular fa-bookmark fa-fw" /> <div
</div> key="bookmark"
<div title="Bookmark"
key="minimize" className={cn("line-icon", "line-bookmark")}
title={`${isMinimized ? "Show Output" : "Hide Output"}`} onClick={this.clickBookmark}
className={cn("line-icon", isMinimized ? "active" : "")} >
onClick={this.clickMinimize} <i className="fa-sharp fa-regular fa-bookmark fa-fw" />
> </div>
<If condition={isMinimized}> <div
<i className="fa-sharp fa-regular fa-circle-plus fa-fw" /> key="minimize"
</If> title={`${isMinimized ? "Show Output" : "Hide Output"}`}
<If condition={!isMinimized}> className={cn("line-icon", isMinimized ? "active" : "")}
<i className="fa-sharp fa-regular fa-circle-minus fa-fw" /> onClick={this.clickMinimize}
</If> >
</div> <Choose>
<div className="line-icon line-sidebar" onClick={this.clickMoveToSidebar} title="Move to Sidebar"> <When condition={isMinimized}>
<i className="fa-sharp fa-solid fa-right-to-line fa-fw" /> <i className="fa-sharp fa-regular fa-circle-plus fa-fw" />
</div> </When>
<div <Otherwise>
key="settings" <i className="fa-sharp fa-regular fa-circle-minus fa-fw" />
title="Line Settings" </Otherwise>
className="line-icon line-icon-shrink-left" </Choose>
onClick={this.handleLineSettings} </div>
> <div
<i className="fa-sharp fa-regular fa-ellipsis-vertical fa-fw" /> className="line-icon line-sidebar"
</div> onClick={this.clickMoveToSidebar}
</If> title="Move to Sidebar"
<If condition={containerType == appconst.LineContainer_Sidebar}> >
<div key="restart" title="Restart Command" className="line-icon" onClick={this.clickRestart}> <i className="fa-sharp fa-solid fa-right-to-line fa-fw" />
<i className="fa-sharp fa-regular fa-arrows-rotate fa-fw" /> </div>
</div> <div
<div key="delete" title="Delete Line (&#x2318;D)" className="line-icon" onClick={this.clickDelete}> key="settings"
<i className="fa-sharp fa-regular fa-trash fa-fw" /> title="Line Settings"
</div> className="line-icon line-icon-shrink-left"
<div onClick={this.handleLineSettings}
key="bookmark" >
title="Bookmark" <i className="fa-sharp fa-regular fa-ellipsis-vertical fa-fw" />
className={cn("line-icon", "line-bookmark")} </div>
onClick={this.clickBookmark} </When>
> <When condition={containerType == appconst.LineContainer_Sidebar}>
<i className="fa-sharp fa-regular fa-bookmark fa-fw" /> <div
</div> key="delete"
<div title="Delete Line (&#x2318;D)"
className="line-icon line-sidebar" className="line-icon"
onClick={this.clickRemoveFromSidebar} onClick={this.clickDelete}
title="Move to Sidebar" >
> <i className="fa-sharp fa-regular fa-trash fa-fw" />
<i className="fa-sharp fa-solid fa-left-to-line fa-fw" /> </div>
</div> <div
</If> key="bookmark"
title="Bookmark"
className={cn("line-icon", "line-bookmark")}
onClick={this.clickBookmark}
>
<i className="fa-sharp fa-regular fa-bookmark fa-fw" />
</div>
<div
className="line-icon line-sidebar"
onClick={this.clickRemoveFromSidebar}
title="Move to Sidebar"
>
<i className="fa-sharp fa-solid fa-left-to-line fa-fw" />
</div>
</When>
</Choose>
</div> </div>
); );
} }
@ -254,9 +268,9 @@ class LineHeader extends React.Component<{ screen: LineContainerType; line: Line
} }
renderMeta1(cmd: Cmd) { renderMeta1(cmd: Cmd) {
let { line } = this.props; const { line } = this.props;
let formattedTime: string = ""; let formattedTime: string = "";
let restartTs = cmd.getRestartTs(); const restartTs = cmd.getRestartTs();
let timeTitle: string = null; let timeTitle: string = null;
if (restartTs != null && restartTs > 0) { if (restartTs != null && restartTs > 0) {
formattedTime = "restarted @ " + lineutil.getLineDateTimeStr(restartTs); formattedTime = "restarted @ " + lineutil.getLineDateTimeStr(restartTs);
@ -264,8 +278,8 @@ class LineHeader extends React.Component<{ screen: LineContainerType; line: Line
} else { } else {
formattedTime = lineutil.getLineDateTimeStr(line.ts); formattedTime = lineutil.getLineDateTimeStr(line.ts);
} }
let renderer = line.renderer; const renderer = line.renderer;
let durationMs = cmd.getDurationMs(); const durationMs = cmd.getDurationMs();
return ( return (
<div key="meta1" className="meta meta-line1"> <div key="meta1" className="meta meta-line1">
<SmallLineAvatar line={line} cmd={cmd} /> <SmallLineAvatar line={line} cmd={cmd} />
@ -287,7 +301,7 @@ class LineHeader extends React.Component<{ screen: LineContainerType; line: Line
} }
render() { render() {
let { line, cmd } = this.props; const { line, cmd } = this.props;
const hidePrompt = getIsHidePrompt(line); const hidePrompt = getIsHidePrompt(line);
return ( return (
<div key="header" className={cn("line-header", { "hide-prompt": hidePrompt })}> <div key="header" className={cn("line-header", { "hide-prompt": hidePrompt })}>
@ -303,7 +317,7 @@ class SmallLineAvatar extends React.Component<{ line: LineType; cmd: Cmd; onRigh
render() { render() {
const { line, cmd } = this.props; const { line, cmd } = this.props;
const lineNumStr = (line.linenumtemp ? "~" : "#") + String(line.linenum); const lineNumStr = (line.linenumtemp ? "~" : "#") + String(line.linenum);
let status = cmd != null ? cmd.getStatus() : "done"; const status = cmd != null ? cmd.getStatus() : "done";
const exitcode = cmd != null ? cmd.getExitCode() : 0; const exitcode = cmd != null ? cmd.getExitCode() : 0;
const isComment = line.linetype == "text"; const isComment = line.linetype == "text";
let icon = null; let icon = null;
@ -359,7 +373,7 @@ class RtnState extends React.Component<{ cmd: Cmd; line: LineType }> {
} }
checkStateDiffLoad(): void { checkStateDiffLoad(): void {
let cmd = this.props.cmd; const cmd = this.props.cmd;
if (cmd == null || !cmd.getRtnState() || this.rtnStateDiffFetched) { if (cmd == null || !cmd.getRtnState() || this.rtnStateDiffFetched) {
return; return;
} }
@ -406,7 +420,7 @@ class RtnState extends React.Component<{ cmd: Cmd; line: LineType }> {
} }
render() { render() {
let { cmd } = this.props; const { cmd } = this.props;
const rsdiff = this.rtnStateDiff.get(); const rsdiff = this.rtnStateDiff.get();
const termFontSize = GlobalModel.getTermFontSize(); const termFontSize = GlobalModel.getTermFontSize();
let rtnStateDiffSize = termFontSize - 2; let rtnStateDiffSize = termFontSize - 2;
@ -488,7 +502,7 @@ class LineCmd extends React.Component<
if (elem != null) { if (elem != null) {
curHeight = elem.offsetHeight; curHeight = elem.offsetHeight;
} }
let linenum = line.linenum; const linenum = line.linenum;
if (DebugHeightProblems && linenum >= MinLine && linenum <= MaxLine) { if (DebugHeightProblems && linenum >= MinLine && linenum <= MaxLine) {
heightLog[linenum] = heightLog[linenum] || {}; heightLog[linenum] = heightLog[linenum] || {};
heightLog[linenum].heightArr = heightLog[linenum].heightArr || []; heightLog[linenum].heightArr = heightLog[linenum].heightArr || [];
@ -685,7 +699,7 @@ class LineCmd extends React.Component<
const isFocused = mobx const isFocused = mobx
.computed( .computed(
() => { () => {
let screenFocusType = screen.getFocusType(); const screenFocusType = screen.getFocusType();
return isPhysicalFocused && screenFocusType == "cmd"; return isPhysicalFocused && screenFocusType == "cmd";
}, },
{ name: "computed-isFocused" } { name: "computed-isFocused" }
@ -694,7 +708,7 @@ class LineCmd extends React.Component<
const shouldCmdFocus = mobx const shouldCmdFocus = mobx
.computed( .computed(
() => { () => {
let screenFocusType = screen.getFocusType(); const screenFocusType = screen.getFocusType();
return isSelected && screenFocusType == "cmd"; return isSelected && screenFocusType == "cmd";
}, },
{ name: "computed-shouldCmdFocus" } { name: "computed-shouldCmdFocus" }
@ -725,16 +739,9 @@ class LineCmd extends React.Component<
rendererPlugin = PluginModel.getRendererPluginByName(line.renderer); rendererPlugin = PluginModel.getRendererPluginByName(line.renderer);
} }
const rendererType = lineutil.getRendererType(line); const rendererType = lineutil.getRendererType(line);
const hidePrompt = rendererPlugin?.hidePrompt;
const termFontSize = GlobalModel.getTermFontSize(); const termFontSize = GlobalModel.getTermFontSize();
const containerType = screen.getContainerType(); const containerType = screen.getContainerType();
const isMinimized = line.linestate["wave:min"] && containerType == appconst.LineContainer_Main; const isMinimized = line.linestate["wave:min"] && containerType == appconst.LineContainer_Main;
const lhv: LineChromeHeightVars = {
numCmdLines: lineutil.countCmdLines(cmd.getCmdStr()),
zeroHeight: isMinimized,
hasLine2: !hidePrompt,
};
const chromeHeight = textmeasure.calcLineChromeHeight(GlobalModel.lineHeightEnv, lhv);
return ( return (
<div <div
className={mainDivCn} className={mainDivCn}
@ -749,55 +756,64 @@ class LineCmd extends React.Component<
</If> </If>
<LineActions screen={screen} line={line} cmd={cmd} /> <LineActions screen={screen} line={line} cmd={cmd} />
<LineHeader screen={screen} line={line} cmd={cmd} /> <LineHeader screen={screen} line={line} cmd={cmd} />
<If condition={!isMinimized && isInSidebar}> <If condition={!isMinimized}>
<div className="sidebar-message" style={{ fontSize: termFontSize }}> <Choose>
&nbsp;&nbsp;showing in sidebar =&gt; <When condition={isInSidebar}>
</div> <div className="sidebar-message" style={{ fontSize: termFontSize }}>
</If> &nbsp;&nbsp;showing in sidebar =&gt;
<If condition={!isMinimized && !isInSidebar}> </div>
<ErrorBoundary plugin={rendererPlugin?.name} lineContext={lineutil.getRendererContext(line)}> </When>
<If condition={rendererPlugin == null && !isNoneRenderer}> <Otherwise>
<TerminalRenderer <ErrorBoundary
screen={screen} plugin={rendererPlugin?.name}
line={line} lineContext={lineutil.getRendererContext(line)}
width={width} >
staticRender={staticRender} <If condition={rendererPlugin == null && !isNoneRenderer}>
visible={visible} <TerminalRenderer
onHeightChange={this.handleHeightChange} screen={screen}
collapsed={false} line={line}
/> width={width}
</If> staticRender={staticRender}
<If condition={rendererPlugin != null && rendererPlugin.rendererType == "simple"}> visible={visible}
<SimpleBlobRenderer onHeightChange={this.handleHeightChange}
rendererContainer={screen} collapsed={false}
lineId={line.lineid} />
plugin={rendererPlugin} </If>
onHeightChange={this.handleHeightChange} <If condition={rendererPlugin != null && rendererPlugin.rendererType == "simple"}>
initParams={this.makeRendererModelInitializeParams()} <SimpleBlobRenderer
scrollToBringIntoViewport={this.scrollToBringIntoViewport} rendererContainer={screen}
isSelected={isSelected} lineId={line.lineid}
shouldFocus={shouldCmdFocus} plugin={rendererPlugin}
/> onHeightChange={this.handleHeightChange}
</If> initParams={this.makeRendererModelInitializeParams()}
<If condition={rendererPlugin != null && rendererPlugin.rendererType == "full"}> scrollToBringIntoViewport={this.scrollToBringIntoViewport}
<IncrementalRenderer isSelected={isSelected}
rendererContainer={screen} shouldFocus={shouldCmdFocus}
lineId={line.lineid} />
plugin={rendererPlugin} </If>
onHeightChange={this.handleHeightChange} <If condition={rendererPlugin != null && rendererPlugin.rendererType == "full"}>
initParams={this.makeRendererModelInitializeParams()} <IncrementalRenderer
isSelected={isSelected} rendererContainer={screen}
/> lineId={line.lineid}
</If> plugin={rendererPlugin}
</ErrorBoundary> onHeightChange={this.handleHeightChange}
<If condition={isRtnState}> initParams={this.makeRendererModelInitializeParams()}
<RtnState cmd={cmd} line={line} /> isSelected={isSelected}
</If> />
<If condition={isSelected && !isFocused && rendererType == "terminal"}> </If>
<div className="cmd-hints"> </ErrorBoundary>
<div className="hint-item color-nohover-white">focus line ({renderCmdText("L")})</div> <If condition={isRtnState}>
</div> <RtnState cmd={cmd} line={line} />
</If> </If>
<If condition={isSelected && !isFocused && rendererType == "terminal"}>
<div className="cmd-hints">
<div className="hint-item color-nohover-white">
focus line ({renderCmdText("L")})
</div>
</div>
</If>
</Otherwise>
</Choose>
</If> </If>
</div> </div>
); );
@ -877,11 +893,6 @@ class LineText extends React.Component<
name: "computed-isSelected", name: "computed-isSelected",
}) })
.get(); .get();
const isFocused = mobx
.computed(() => screen.getFocusType() == "cmd", {
name: "computed-isFocused",
})
.get();
const mainClass = cn("line", "line-text", "focus-parent", { selected: isSelected }); const mainClass = cn("line", "line-text", "focus-parent", { selected: isSelected });
return ( return (
<div <div

View File

@ -11,7 +11,6 @@ import cn from "classnames";
import { GlobalModel, GlobalCommandRunner, Screen } from "@/models"; import { GlobalModel, GlobalCommandRunner, Screen } from "@/models";
import { getMonoFontSize } from "@/util/textmeasure"; import { getMonoFontSize } from "@/util/textmeasure";
import * as appconst from "@/app/appconst"; import * as appconst from "@/app/appconst";
import { checkKeyPressed, adaptFromReactOrNativeKeyEvent, WaveKeyboardEvent } from "@/util/keyutil";
type OV<T> = mobx.IObservableValue<T>; type OV<T> = mobx.IObservableValue<T>;
@ -44,8 +43,8 @@ class HistoryKeybindings extends React.Component<{ inputObject: TextAreaInput },
if (GlobalModel.activeMainView != "session") { if (GlobalModel.activeMainView != "session") {
return; return;
} }
let inputModel = GlobalModel.inputModel; const inputModel = GlobalModel.inputModel;
let keybindManager = GlobalModel.keybindManager; const keybindManager = GlobalModel.keybindManager;
keybindManager.registerKeybinding("pane", "history", "generic:cancel", (waveEvent) => { keybindManager.registerKeybinding("pane", "history", "generic:cancel", (waveEvent) => {
inputModel.resetHistory(); inputModel.resetHistory();
return true; return true;
@ -109,15 +108,15 @@ class CmdInputKeybindings extends React.Component<{ inputObject: TextAreaInput }
if (GlobalModel.activeMainView != "session") { if (GlobalModel.activeMainView != "session") {
return; return;
} }
let inputObject = this.props.inputObject; const inputObject = this.props.inputObject;
this.lastTab = false; this.lastTab = false;
let keybindManager = GlobalModel.keybindManager; const keybindManager = GlobalModel.keybindManager;
let inputModel = GlobalModel.inputModel; const inputModel = GlobalModel.inputModel;
keybindManager.registerKeybinding("pane", "cmdinput", "cmdinput:autocomplete", (waveEvent) => { keybindManager.registerKeybinding("pane", "cmdinput", "cmdinput:autocomplete", (waveEvent) => {
let lastTab = this.lastTab; const lastTab = this.lastTab;
this.lastTab = true; this.lastTab = true;
this.curPress = "tab"; this.curPress = "tab";
let curLine = inputModel.getCurLine(); const curLine = inputModel.getCurLine();
if (lastTab) { if (lastTab) {
GlobalModel.submitCommand( GlobalModel.submitCommand(
"_compgen", "_compgen",
@ -140,8 +139,8 @@ class CmdInputKeybindings extends React.Component<{ inputObject: TextAreaInput }
keybindManager.registerKeybinding("pane", "cmdinput", "generic:confirm", (waveEvent) => { keybindManager.registerKeybinding("pane", "cmdinput", "generic:confirm", (waveEvent) => {
GlobalModel.closeTabSettings(); GlobalModel.closeTabSettings();
if (GlobalModel.inputModel.isEmpty()) { if (GlobalModel.inputModel.isEmpty()) {
let activeWindow = GlobalModel.getScreenLinesForActiveScreen(); const activeWindow = GlobalModel.getScreenLinesForActiveScreen();
let activeScreen = GlobalModel.getActiveScreen(); const activeScreen = GlobalModel.getActiveScreen();
if (activeScreen != null && activeWindow != null && activeWindow.lines.length > 0) { if (activeScreen != null && activeWindow != null && activeWindow.lines.length > 0) {
activeScreen.setSelectedLine(0); activeScreen.setSelectedLine(0);
GlobalCommandRunner.screenSelectLine("E"); GlobalCommandRunner.screenSelectLine("E");
@ -200,12 +199,12 @@ class CmdInputKeybindings extends React.Component<{ inputObject: TextAreaInput }
}); });
keybindManager.registerKeybinding("pane", "cmdinput", "generic:selectAbove", (waveEvent) => { keybindManager.registerKeybinding("pane", "cmdinput", "generic:selectAbove", (waveEvent) => {
this.curPress = "historyupdown"; this.curPress = "historyupdown";
let rtn = inputObject.arrowUpPressed(); const rtn = inputObject.arrowUpPressed();
return rtn; return rtn;
}); });
keybindManager.registerKeybinding("pane", "cmdinput", "generic:selectBelow", (waveEvent) => { keybindManager.registerKeybinding("pane", "cmdinput", "generic:selectBelow", (waveEvent) => {
this.curPress = "historyupdown"; this.curPress = "historyupdown";
let rtn = inputObject.arrowDownPressed(); const rtn = inputObject.arrowDownPressed();
return rtn; return rtn;
}); });
keybindManager.registerKeybinding("pane", "cmdinput", "generic:selectPageAbove", (waveEvent) => { keybindManager.registerKeybinding("pane", "cmdinput", "generic:selectPageAbove", (waveEvent) => {
@ -259,18 +258,18 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
historyFocused: OV<boolean> = mobx.observable.box(false); historyFocused: OV<boolean> = mobx.observable.box(false);
incVersion(): void { incVersion(): void {
let v = this.version.get(); const v = this.version.get();
mobx.action(() => this.version.set(v + 1))(); mobx.action(() => this.version.set(v + 1))();
} }
getCurSP(): StrWithPos { getCurSP(): StrWithPos {
let textarea = this.mainInputRef.current; const textarea = this.mainInputRef.current;
if (textarea == null) { if (textarea == null) {
return this.lastSP; return this.lastSP;
} }
let str = textarea.value; const str = textarea.value;
let pos = textarea.selectionStart; const pos = textarea.selectionStart;
let endPos = textarea.selectionEnd; const endPos = textarea.selectionEnd;
if (pos != endPos) { if (pos != endPos) {
return { str, pos: appconst.NoStrPos }; return { str, pos: appconst.NoStrPos };
} }
@ -278,7 +277,7 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
} }
updateSP(): void { updateSP(): void {
let curSP = this.getCurSP(); const curSP = this.getCurSP();
if (curSP.str == this.lastSP.str && curSP.pos == this.lastSP.pos) { if (curSP.str == this.lastSP.str && curSP.pos == this.lastSP.pos) {
return; return;
} }
@ -287,7 +286,7 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
} }
setFocus(): void { setFocus(): void {
let inputModel = GlobalModel.inputModel; const inputModel = GlobalModel.inputModel;
if (inputModel.historyShow.get()) { if (inputModel.historyShow.get()) {
this.historyInputRef.current.focus(); this.historyInputRef.current.focus();
} else { } else {
@ -296,25 +295,25 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
} }
getTextAreaMaxCols(): number { getTextAreaMaxCols(): number {
let taElem = this.mainInputRef.current; const taElem = this.mainInputRef.current;
if (taElem == null) { if (taElem == null) {
return 0; return 0;
} }
let cs = window.getComputedStyle(taElem); const cs = window.getComputedStyle(taElem);
let padding = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight); const padding = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight);
let borders = parseFloat(cs.borderLeft) + parseFloat(cs.borderRight); const borders = parseFloat(cs.borderLeft) + parseFloat(cs.borderRight);
let contentWidth = taElem.clientWidth - padding - borders; const contentWidth = taElem.clientWidth - padding - borders;
let fontSize = getMonoFontSize(parseInt(cs.fontSize)); const fontSize = getMonoFontSize(parseInt(cs.fontSize));
let maxCols = Math.floor(contentWidth / Math.ceil(fontSize.width)); const maxCols = Math.floor(contentWidth / Math.ceil(fontSize.width));
return maxCols; return maxCols;
} }
checkHeight(shouldFire: boolean): void { checkHeight(shouldFire: boolean): void {
let elem = this.controlRef.current; const elem = this.controlRef.current;
if (elem == null) { if (elem == null) {
return; return;
} }
let curHeight = elem.offsetHeight; const curHeight = elem.offsetHeight;
if (this.lastHeight == curHeight) { if (this.lastHeight == curHeight) {
return; return;
} }
@ -325,9 +324,9 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
} }
componentDidMount() { componentDidMount() {
let activeScreen = GlobalModel.getActiveScreen(); const activeScreen = GlobalModel.getActiveScreen();
if (activeScreen != null) { if (activeScreen != null) {
let focusType = activeScreen.focusType.get(); const focusType = activeScreen.focusType.get();
if (focusType == "input") { if (focusType == "input") {
this.setFocus(); this.setFocus();
} }
@ -338,16 +337,16 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
} }
componentDidUpdate() { componentDidUpdate() {
let activeScreen = GlobalModel.getActiveScreen(); const activeScreen = GlobalModel.getActiveScreen();
if (activeScreen != null) { if (activeScreen != null) {
let focusType = activeScreen.focusType.get(); const focusType = activeScreen.focusType.get();
if (this.lastFocusType != focusType && focusType == "input") { if (this.lastFocusType != focusType && focusType == "input") {
this.setFocus(); this.setFocus();
} }
this.lastFocusType = focusType; this.lastFocusType = focusType;
} }
let inputModel = GlobalModel.inputModel; const inputModel = GlobalModel.inputModel;
let fcpos = inputModel.forceCursorPos.get(); const fcpos = inputModel.forceCursorPos.get();
if (fcpos != null && fcpos != appconst.NoStrPos) { if (fcpos != null && fcpos != appconst.NoStrPos) {
if (this.mainInputRef.current != null) { if (this.mainInputRef.current != null) {
this.mainInputRef.current.selectionStart = fcpos; this.mainInputRef.current.selectionStart = fcpos;
@ -364,24 +363,24 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
} }
getLinePos(elem: any): { numLines: number; linePos: number } { getLinePos(elem: any): { numLines: number; linePos: number } {
let numLines = elem.value.split("\n").length; const numLines = elem.value.split("\n").length;
let linePos = elem.value.substr(0, elem.selectionStart).split("\n").length; const linePos = elem.value.substr(0, elem.selectionStart).split("\n").length;
return { numLines, linePos }; return { numLines, linePos };
} }
arrowUpPressed(): boolean { arrowUpPressed(): boolean {
let inputModel = GlobalModel.inputModel; const inputModel = GlobalModel.inputModel;
if (!inputModel.isHistoryLoaded()) { if (!inputModel.isHistoryLoaded()) {
this.lastHistoryUpDown = true; this.lastHistoryUpDown = true;
inputModel.loadHistory(false, 1, "screen"); inputModel.loadHistory(false, 1, "screen");
return true; return true;
} }
let currentRef = this.mainInputRef.current; const currentRef = this.mainInputRef.current;
if (currentRef == null) { if (currentRef == null) {
return true; return true;
} }
let linePos = this.getLinePos(currentRef); const linePos = this.getLinePos(currentRef);
let lastHist = this.lastHistoryUpDown; const lastHist = this.lastHistoryUpDown;
if (!lastHist && linePos.linePos > 1) { if (!lastHist && linePos.linePos > 1) {
// regular arrow // regular arrow
return false; return false;
@ -392,16 +391,16 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
} }
arrowDownPressed(): boolean { arrowDownPressed(): boolean {
let inputModel = GlobalModel.inputModel; const inputModel = GlobalModel.inputModel;
if (!inputModel.isHistoryLoaded()) { if (!inputModel.isHistoryLoaded()) {
return true; return true;
} }
let currentRef = this.mainInputRef.current; const currentRef = this.mainInputRef.current;
if (currentRef == null) { if (currentRef == null) {
return true; return true;
} }
let linePos = this.getLinePos(currentRef); const linePos = this.getLinePos(currentRef);
let lastHist = this.lastHistoryUpDown; const lastHist = this.lastHistoryUpDown;
if (!lastHist && linePos.linePos < linePos.numLines) { if (!lastHist && linePos.linePos < linePos.numLines) {
// regular arrow // regular arrow
return false; return false;
@ -412,17 +411,17 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
} }
scrollPage(up: boolean) { scrollPage(up: boolean) {
let inputModel = GlobalModel.inputModel; const inputModel = GlobalModel.inputModel;
let infoScroll = inputModel.hasScrollingInfoMsg(); const infoScroll = inputModel.hasScrollingInfoMsg();
if (infoScroll) { if (infoScroll) {
let div = document.querySelector(".cmd-input-info"); const div = document.querySelector(".cmd-input-info");
let amt = pageSize(div); const amt = pageSize(div);
scrollDiv(div, up ? -amt : amt); scrollDiv(div, up ? -amt : amt);
} }
} }
modEnter() { modEnter() {
let currentRef = this.mainInputRef.current; const currentRef = this.mainInputRef.current;
if (currentRef == null) { if (currentRef == null) {
return; return;
} }
@ -454,21 +453,21 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
if (this.mainInputRef.current == null) { if (this.mainInputRef.current == null) {
return; return;
} }
let selStart = this.mainInputRef.current.selectionStart; const selStart = this.mainInputRef.current.selectionStart;
let value = this.mainInputRef.current.value; const value = this.mainInputRef.current.value;
if (selStart > value.length) { if (selStart > value.length) {
return; return;
} }
let cutValue = value.substr(0, selStart); const cutValue = value.substring(0, selStart);
let restValue = value.substr(selStart); const restValue = value.substring(selStart);
let cmdLineUpdate = { str: restValue, pos: 0 }; const cmdLineUpdate = { str: restValue, pos: 0 };
navigator.clipboard.writeText(cutValue); navigator.clipboard.writeText(cutValue);
GlobalModel.inputModel.updateCmdLine(cmdLineUpdate); GlobalModel.inputModel.updateCmdLine(cmdLineUpdate);
} }
@boundMethod @boundMethod
controlP() { controlP() {
let inputModel = GlobalModel.inputModel; const inputModel = GlobalModel.inputModel;
if (!inputModel.isHistoryLoaded()) { if (!inputModel.isHistoryLoaded()) {
this.lastHistoryUpDown = true; this.lastHistoryUpDown = true;
inputModel.loadHistory(false, 1, "screen"); inputModel.loadHistory(false, 1, "screen");
@ -480,7 +479,7 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
@boundMethod @boundMethod
controlN() { controlN() {
let inputModel = GlobalModel.inputModel; const inputModel = GlobalModel.inputModel;
inputModel.moveHistorySelection(-1); inputModel.moveHistorySelection(-1);
this.lastHistoryUpDown = true; this.lastHistoryUpDown = true;
} }
@ -490,15 +489,15 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
if (this.mainInputRef.current == null) { if (this.mainInputRef.current == null) {
return; return;
} }
let selStart = this.mainInputRef.current.selectionStart; const selStart = this.mainInputRef.current.selectionStart;
let value = this.mainInputRef.current.value; const value = this.mainInputRef.current.value;
if (selStart > value.length) { if (selStart > value.length) {
return; return;
} }
let cutSpot = selStart - 1; let cutSpot = selStart - 1;
let initial = true; let initial = true;
for (; cutSpot >= 0; cutSpot--) { for (; cutSpot >= 0; cutSpot--) {
let ch = value[cutSpot]; const ch = value[cutSpot];
if (ch == " " && initial) { if (ch == " " && initial) {
continue; continue;
} }
@ -511,10 +510,10 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
if (cutSpot == -1) { if (cutSpot == -1) {
cutSpot = 0; cutSpot = 0;
} }
let cutValue = value.slice(cutSpot, selStart); const cutValue = value.slice(cutSpot, selStart);
let prevValue = value.slice(0, cutSpot); const prevValue = value.slice(0, cutSpot);
let restValue = value.slice(selStart); const restValue = value.slice(selStart);
let cmdLineUpdate = { str: prevValue + restValue, pos: prevValue.length }; const cmdLineUpdate = { str: prevValue + restValue, pos: prevValue.length };
navigator.clipboard.writeText(cutValue); navigator.clipboard.writeText(cutValue);
GlobalModel.inputModel.updateCmdLine(cmdLineUpdate); GlobalModel.inputModel.updateCmdLine(cmdLineUpdate);
} }
@ -524,26 +523,26 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
if (this.mainInputRef.current == null) { if (this.mainInputRef.current == null) {
return; return;
} }
let pastePromise = navigator.clipboard.readText(); const pastePromise = navigator.clipboard.readText();
pastePromise.then((clipText) => { pastePromise.then((clipText) => {
clipText = clipText ?? ""; clipText = clipText ?? "";
let selStart = this.mainInputRef.current.selectionStart; const selStart = this.mainInputRef.current.selectionStart;
let selEnd = this.mainInputRef.current.selectionEnd; const selEnd = this.mainInputRef.current.selectionEnd;
let value = this.mainInputRef.current.value; const value = this.mainInputRef.current.value;
if (selStart > value.length || selEnd > value.length) { if (selStart > value.length || selEnd > value.length) {
return; return;
} }
let newValue = value.substr(0, selStart) + clipText + value.substr(selEnd); const newValue = value.substr(0, selStart) + clipText + value.substr(selEnd);
let cmdLineUpdate = { str: newValue, pos: selStart + clipText.length }; const cmdLineUpdate = { str: newValue, pos: selStart + clipText.length };
GlobalModel.inputModel.updateCmdLine(cmdLineUpdate); GlobalModel.inputModel.updateCmdLine(cmdLineUpdate);
}); });
} }
@boundMethod @boundMethod
handleHistoryInput(e: any) { handleHistoryInput(e: any) {
let inputModel = GlobalModel.inputModel; const inputModel = GlobalModel.inputModel;
mobx.action(() => { mobx.action(() => {
let opts = mobx.toJS(inputModel.historyQueryOpts.get()); const opts = mobx.toJS(inputModel.historyQueryOpts.get());
opts.queryStr = e.target.value; opts.queryStr = e.target.value;
inputModel.setHistoryQueryOpts(opts); inputModel.setHistoryQueryOpts(opts);
})(); })();
@ -551,7 +550,7 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
@boundMethod @boundMethod
handleMainFocus(e: any) { handleMainFocus(e: any) {
let inputModel = GlobalModel.inputModel; const inputModel = GlobalModel.inputModel;
if (inputModel.historyShow.get()) { if (inputModel.historyShow.get()) {
e.preventDefault(); e.preventDefault();
if (this.historyInputRef.current != null) { if (this.historyInputRef.current != null) {
@ -578,7 +577,7 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
@boundMethod @boundMethod
handleHistoryFocus(e: any) { handleHistoryFocus(e: any) {
let inputModel = GlobalModel.inputModel; const inputModel = GlobalModel.inputModel;
if (!inputModel.historyShow.get()) { if (!inputModel.historyShow.get()) {
e.preventDefault(); e.preventDefault();
if (this.mainInputRef.current != null) { if (this.mainInputRef.current != null) {
@ -604,53 +603,51 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
} }
render() { render() {
let model = GlobalModel; const model = GlobalModel;
let inputModel = model.inputModel; const inputModel = model.inputModel;
let curLine = inputModel.getCurLine(); const curLine = inputModel.getCurLine();
let fcp = inputModel.forceCursorPos.get(); // for reaction
let displayLines = 1; let displayLines = 1;
let numLines = curLine.split("\n").length; const numLines = curLine.split("\n").length;
let maxCols = this.getTextAreaMaxCols(); const maxCols = this.getTextAreaMaxCols();
let longLine = false; let longLine = false;
let version = this.version.get(); // to force reactions
if (maxCols != 0 && curLine.length >= maxCols - 4) { if (maxCols != 0 && curLine.length >= maxCols - 4) {
longLine = true; longLine = true;
} }
if (numLines > 1 || longLine || inputModel.inputExpanded.get()) { if (numLines > 1 || longLine || inputModel.inputExpanded.get()) {
displayLines = 5; displayLines = 5;
} }
let disabled = inputModel.historyShow.get(); const disabled = inputModel.historyShow.get();
if (disabled) { if (disabled) {
displayLines = 1; displayLines = 1;
} }
let activeScreen = GlobalModel.getActiveScreen(); const activeScreen = GlobalModel.getActiveScreen();
if (activeScreen != null) { if (activeScreen != null) {
activeScreen.focusType.get(); // for reaction activeScreen.focusType.get(); // for reaction
} }
let termFontSize = GlobalModel.getTermFontSize(); const termFontSize = GlobalModel.getTermFontSize();
let fontSize = getMonoFontSize(termFontSize); const fontSize = getMonoFontSize(termFontSize);
let termPad = fontSize.pad; const termPad = fontSize.pad;
let computedInnerHeight = displayLines * fontSize.height + 2 * termPad; const computedInnerHeight = displayLines * fontSize.height + 2 * termPad;
let computedOuterHeight = computedInnerHeight + 2 * termPad; const computedOuterHeight = computedInnerHeight + 2 * termPad;
let shellType: string = ""; let shellType: string = "";
let screen = GlobalModel.getActiveScreen(); const screen = GlobalModel.getActiveScreen();
if (screen != null) { if (screen != null) {
let ri = screen.getCurRemoteInstance(); const ri = screen.getCurRemoteInstance();
if (ri != null && ri.shelltype != null) { if (ri != null && ri.shelltype != null) {
shellType = ri.shelltype; shellType = ri.shelltype;
} }
if (shellType == "") { if (shellType == "") {
let rptr = screen.curRemote.get(); const rptr = screen.curRemote.get();
if (rptr != null) { if (rptr != null) {
let remote = GlobalModel.getRemote(rptr.remoteid); const remote = GlobalModel.getRemote(rptr.remoteid);
if (remote != null) { if (remote != null) {
shellType = remote.defaultshelltype; shellType = remote.defaultshelltype;
} }
} }
} }
} }
let isMainInputFocused = this.mainInputFocused.get(); const isMainInputFocused = this.mainInputFocused.get();
let isHistoryFocused = this.historyFocused.get(); const isHistoryFocused = this.historyFocused.get();
return ( return (
<div <div
className="textareainput-div control is-expanded" className="textareainput-div control is-expanded"

View File

@ -6,7 +6,7 @@ import * as mobxReact from "mobx-react";
import * as mobx from "mobx"; import * as mobx from "mobx";
import { sprintf } from "sprintf-js"; import { sprintf } from "sprintf-js";
import { boundMethod } from "autobind-decorator"; import { boundMethod } from "autobind-decorator";
import { If, For } from "tsx-control-statements/components"; import { If } from "tsx-control-statements/components";
import cn from "classnames"; import cn from "classnames";
import { debounce } from "throttle-debounce"; import { debounce } from "throttle-debounce";
import dayjs from "dayjs"; import dayjs from "dayjs";
@ -18,7 +18,6 @@ import { LinesView } from "@/app/line/linesview";
import * as util from "@/util/util"; import * as util from "@/util/util";
import * as appconst from "@/app/appconst"; import * as appconst from "@/app/appconst";
import * as textmeasure from "@/util/textmeasure"; import * as textmeasure from "@/util/textmeasure";
import { NewTabSettings } from "./newtabsettings";
import "./screenview.less"; import "./screenview.less";
import "./tabs.less"; import "./tabs.less";
@ -38,18 +37,17 @@ class ScreenView extends React.Component<{ session: Session; screen: Screen }, {
constructor(props: { session: Session; screen: Screen }) { constructor(props: { session: Session; screen: Screen }) {
super(props); super(props);
this.handleResize_debounced = debounce(100, this.handleResize.bind(this)); this.handleResize_debounced = debounce(100, this.handleResize.bind(this));
let screen = this.props.screen; const screen = this.props.screen;
let hasSidebar = false; let hasSidebar = false;
if (screen != null) { if (screen != null) {
let viewOpts = screen.viewOpts.get(); const viewOpts = screen.viewOpts.get();
hasSidebar = viewOpts?.sidebar?.open; hasSidebar = viewOpts?.sidebar?.open;
} }
this.sidebarShowing = mobx.observable.box(hasSidebar, { name: "screenview-sidebarShowing" }); this.sidebarShowing = mobx.observable.box(hasSidebar, { name: "screenview-sidebarShowing" });
} }
componentDidMount(): void { componentDidMount(): void {
let { screen } = this.props; const elem = this.screenViewRef.current;
let elem = this.screenViewRef.current;
if (elem != null) { if (elem != null) {
this.rszObs = new ResizeObserver(this.handleResize_debounced); this.rszObs = new ResizeObserver(this.handleResize_debounced);
this.rszObs.observe(elem); this.rszObs.observe(elem);
@ -58,12 +56,12 @@ class ScreenView extends React.Component<{ session: Session; screen: Screen }, {
} }
componentDidUpdate(): void { componentDidUpdate(): void {
let { screen } = this.props; const { screen } = this.props;
if (screen == null) { if (screen == null) {
return; return;
} }
let viewOpts = screen.viewOpts.get(); const viewOpts = screen.viewOpts.get();
let hasSidebar = viewOpts?.sidebar?.open; const hasSidebar = viewOpts?.sidebar?.open;
if (hasSidebar && !this.sidebarShowing.get()) { if (hasSidebar && !this.sidebarShowing.get()) {
this.sidebarShowingTimeoutId = setTimeout(() => { this.sidebarShowingTimeoutId = setTimeout(() => {
mobx.action(() => { mobx.action(() => {
@ -87,7 +85,7 @@ class ScreenView extends React.Component<{ session: Session; screen: Screen }, {
} }
handleResize() { handleResize() {
let elem = this.screenViewRef.current; const elem = this.screenViewRef.current;
if (elem == null) { if (elem == null) {
return; return;
} }
@ -107,13 +105,13 @@ class ScreenView extends React.Component<{ session: Session; screen: Screen }, {
} }
render() { render() {
let { session, screen } = this.props; const { session, screen } = this.props;
let screenWidth = this.width.get(); const screenWidth = this.width.get();
if (screenWidth == null) { if (screenWidth == null) {
return <div className="screen-view" ref={this.screenViewRef}></div>; return <div className="screen-view" ref={this.screenViewRef}></div>;
} }
if (session == null) { if (session == null) {
let sessionCount = GlobalModel.sessionList.length; const sessionCount = GlobalModel.sessionList.length;
return ( return (
<div className="screen-view" ref={this.screenViewRef}> <div className="screen-view" ref={this.screenViewRef}>
<div className="window-view" style={{ width: "100%" }}> <div className="window-view" style={{ width: "100%" }}>
@ -133,7 +131,7 @@ class ScreenView extends React.Component<{ session: Session; screen: Screen }, {
); );
} }
if (screen == null) { if (screen == null) {
let screens = GlobalModel.getSessionScreens(session.sessionId); const screens = GlobalModel.getSessionScreens(session.sessionId);
return ( return (
<div className="screen-view" ref={this.screenViewRef}> <div className="screen-view" ref={this.screenViewRef}>
<div className="window-view" style={{ width: "100%" }}> <div className="window-view" style={{ width: "100%" }}>
@ -152,14 +150,14 @@ class ScreenView extends React.Component<{ session: Session; screen: Screen }, {
</div> </div>
); );
} }
let fontSize = GlobalModel.getTermFontSize(); const fontSize = GlobalModel.getTermFontSize();
let dprStr = sprintf("%0.3f", GlobalModel.devicePixelRatio.get()); const dprStr = sprintf("%0.3f", GlobalModel.devicePixelRatio.get());
let viewOpts = screen.viewOpts.get(); const viewOpts = screen.viewOpts.get();
let hasSidebar = viewOpts?.sidebar?.open; const hasSidebar = viewOpts?.sidebar?.open;
let winWidth = "100%"; let winWidth = "100%";
let sidebarWidth = "0px"; let sidebarWidth = "0px";
if (hasSidebar) { if (hasSidebar) {
let targetWidth = viewOpts?.sidebar?.width; const targetWidth = viewOpts?.sidebar?.width;
let realWidth = 0; let realWidth = 0;
if (util.isBlank(targetWidth) || screenWidth < MagicLayout.ScreenSidebarMinWidth * 2) { if (util.isBlank(targetWidth) || screenWidth < MagicLayout.ScreenSidebarMinWidth * 2) {
realWidth = Math.floor(screenWidth / 2) - MagicLayout.ScreenSidebarWidthPadding; realWidth = Math.floor(screenWidth / 2) - MagicLayout.ScreenSidebarWidthPadding;
@ -168,7 +166,6 @@ class ScreenView extends React.Component<{ session: Session; screen: Screen }, {
if (targetPercent > 100) { if (targetPercent > 100) {
targetPercent = 100; targetPercent = 100;
} }
let targetMul = targetPercent / 100;
realWidth = Math.floor((screenWidth * targetPercent) / 100); realWidth = Math.floor((screenWidth * targetPercent) / 100);
realWidth = util.boundInt( realWidth = util.boundInt(
realWidth, realWidth,
@ -177,7 +174,7 @@ class ScreenView extends React.Component<{ session: Session; screen: Screen }, {
); );
} else { } else {
// screen is at least 400px wide // screen is at least 400px wide
let targetWidthNum = parseInt(targetWidth); const targetWidthNum = parseInt(targetWidth);
realWidth = util.boundInt( realWidth = util.boundInt(
targetWidthNum, targetWidthNum,
MagicLayout.ScreenSidebarMinWidth, MagicLayout.ScreenSidebarMinWidth,
@ -382,9 +379,15 @@ class ScreenSidebar extends React.Component<{ screen: Screen; width: string }, {
} }
} }
interface ScreenWindowViewProps {
session: Session;
screen: Screen;
width: string;
}
// screen is not null // screen is not null
@mobxReact.observer @mobxReact.observer
class ScreenWindowView extends React.Component<{ session: Session; screen: Screen; width: string }, {}> { class ScreenWindowView extends React.Component<ScreenWindowViewProps, {}> {
rszObs: ResizeObserver; rszObs: ResizeObserver;
windowViewRef: React.RefObject<any>; windowViewRef: React.RefObject<any>;
@ -402,7 +405,7 @@ class ScreenWindowView extends React.Component<{ session: Session; screen: Scree
} }
setSize(width: number, height: number): void { setSize(width: number, height: number): void {
let { screen } = this.props; const { screen } = this.props;
if (screen == null) { if (screen == null) {
return; return;
} }
@ -418,10 +421,10 @@ class ScreenWindowView extends React.Component<{ session: Session; screen: Scree
componentDidMount() { componentDidMount() {
const { screen } = this.props; const { screen } = this.props;
let wvElem = this.windowViewRef.current; const wvElem = this.windowViewRef.current;
if (wvElem != null) { if (wvElem != null) {
let width = wvElem.offsetWidth; const width = wvElem.offsetWidth;
let height = wvElem.offsetHeight; const height = wvElem.offsetHeight;
this.setSize(width, height); this.setSize(width, height);
this.rszObs = new ResizeObserver(this.handleResize.bind(this)); this.rszObs = new ResizeObserver(this.handleResize.bind(this));
this.rszObs.observe(wvElem); this.rszObs.observe(wvElem);
@ -444,16 +447,16 @@ class ScreenWindowView extends React.Component<{ session: Session; screen: Scree
if (entries.length == 0) { if (entries.length == 0) {
return; return;
} }
let entry = entries[0]; const entry = entries[0];
let width = entry.target.offsetWidth; const width = entry.target.offsetWidth;
let height = entry.target.offsetHeight; const height = entry.target.offsetHeight;
mobx.action(() => { mobx.action(() => {
this.setSize_debounced(width, height); this.setSize_debounced(width, height);
})(); })();
} }
getScreenLines(): ScreenLines { getScreenLines(): ScreenLines {
let { screen } = this.props; const { screen } = this.props;
let win = GlobalModel.getScreenLinesById(screen.screenId); let win = GlobalModel.getScreenLinesById(screen.screenId);
if (win == null) { if (win == null) {
win = GlobalModel.loadScreenLines(screen.screenId); win = GlobalModel.loadScreenLines(screen.screenId);
@ -463,21 +466,16 @@ class ScreenWindowView extends React.Component<{ session: Session; screen: Scree
@boundMethod @boundMethod
toggleRenderMode() { toggleRenderMode() {
let renderMode = this.renderMode.get(); const renderMode = this.renderMode.get();
mobx.action(() => { mobx.action(() => {
this.renderMode.set(renderMode == "normal" ? "collapsed" : "normal"); this.renderMode.set(renderMode == "normal" ? "collapsed" : "normal");
})(); })();
} }
renderError(message: string, fade: boolean) { renderError(message: string, fade: boolean) {
let { screen } = this.props; const { screen, width } = this.props;
return ( return (
<div <div className="window-view" ref={this.windowViewRef} data-screenid={screen.screenId} style={{ width }}>
className="window-view"
ref={this.windowViewRef}
data-screenid={screen.screenId}
style={{ width: this.props.width }}
>
<div key="lines" className="lines"></div> <div key="lines" className="lines"></div>
<div key="window-empty" className={cn("window-empty", { "should-fade": fade })}> <div key="window-empty" className={cn("window-empty", { "should-fade": fade })}>
<div className="text-standard">{message}</div> <div className="text-standard">{message}</div>
@ -488,8 +486,8 @@ class ScreenWindowView extends React.Component<{ session: Session; screen: Scree
@boundMethod @boundMethod
copyShareLink(): void { copyShareLink(): void {
let { screen } = this.props; const { screen } = this.props;
let shareLink = screen.getWebShareUrl(); const shareLink = screen.getWebShareUrl();
if (shareLink == null) { if (shareLink == null) {
return; return;
} }
@ -506,22 +504,22 @@ class ScreenWindowView extends React.Component<{ session: Session; screen: Scree
@boundMethod @boundMethod
openScreenSettings(): void { openScreenSettings(): void {
let { screen } = this.props; const { screen } = this.props;
mobx.action(() => { mobx.action(() => {
GlobalModel.screenSettingsModal.set({ sessionId: screen.sessionId, screenId: screen.screenId }); GlobalModel.screenSettingsModal.set({ sessionId: screen.sessionId, screenId: screen.screenId });
})(); })();
} }
@boundMethod @boundMethod
buildLineComponent(lineProps: LineFactoryProps): JSX.Element { buildLineComponent(lineProps: LineFactoryProps): React.JSX.Element {
let { screen } = this.props; const { screen } = this.props;
let { line, ...restProps } = lineProps; const { line, ...restProps } = lineProps;
let realLine: LineType = line as LineType; const realLine: LineType = line as LineType;
return <Line key={realLine.lineid} screen={screen} line={realLine} {...restProps} />; return <Line key={realLine.lineid} screen={screen} line={realLine} {...restProps} />;
} }
determineVisibleLines(win: ScreenLines): LineType[] { determineVisibleLines(win: ScreenLines): LineType[] {
let { screen } = this.props; const { screen } = this.props;
if (screen.filterRunning.get()) { if (screen.filterRunning.get()) {
return win.getRunningCmdLines(); return win.getRunningCmdLines();
} }
@ -530,16 +528,16 @@ class ScreenWindowView extends React.Component<{ session: Session; screen: Scree
@boundMethod @boundMethod
disableFilter() { disableFilter() {
let { screen } = this.props; const { screen } = this.props;
mobx.action(() => { mobx.action(() => {
screen.filterRunning.set(false); screen.filterRunning.set(false);
})(); })();
} }
render() { render() {
let { session, screen } = this.props; const { session, screen, width } = this.props;
let win = this.getScreenLines(); const win = this.getScreenLines();
if (win == null || !win.loaded.get()) { if (!win.loaded.get()) {
return this.renderError("...", true); return this.renderError("...", true);
} }
if (win.loadError.get() != null) { if (win.loadError.get() != null) {
@ -548,28 +546,25 @@ class ScreenWindowView extends React.Component<{ session: Session; screen: Scree
if (this.width.get() == 0) { if (this.width.get() == 0) {
return this.renderError("", false); return this.renderError("", false);
} }
let cdata = GlobalModel.clientData.get(); const cdata = GlobalModel.clientData.get();
if (cdata == null) { if (cdata == null) {
return this.renderError("loading client data", true); return this.renderError("loading client data", true);
} }
let isActive = screen.isActive(); const lines = this.determineVisibleLines(win);
let lines = this.determineVisibleLines(win); const renderMode = this.renderMode.get();
let renderMode = this.renderMode.get();
return ( return (
<div className="window-view" ref={this.windowViewRef} style={{ width: this.props.width }}> <div className="window-view" ref={this.windowViewRef} style={{ width }}>
<If condition={lines.length == 0}> <If condition={lines.length == 0 && screen.nextLineNum.get() != 1}>
<If condition={screen.nextLineNum.get() != 1}> <div className="window-empty" ref={this.windowViewRef} data-screenid={screen.screenId}>
<div className="window-empty" ref={this.windowViewRef} data-screenid={screen.screenId}> <div key="lines" className="lines"></div>
<div key="lines" className="lines"></div> <div key="window-empty" className={cn("window-empty")}>
<div key="window-empty" className={cn("window-empty")}> <div>
<div> <code className="text-standard">
<code className="text-standard"> [workspace="{session.name.get()}" tab="{screen.name.get()}"]
[workspace="{session.name.get()}" tab="{screen.name.get()}"] </code>
</code>
</div>
</div> </div>
</div> </div>
</If> </div>
</If> </If>
<If condition={lines.length > 0}> <If condition={lines.length > 0}>
<LinesView <LinesView

View File

@ -24,7 +24,7 @@ class IncrementalRenderer extends React.Component<
constructor(props: any) { constructor(props: any) {
super(props); super(props);
let { rendererContainer, lineId, plugin, initParams } = this.props; const { rendererContainer, lineId, plugin, initParams } = this.props;
this.model = plugin.modelCtor(); this.model = plugin.modelCtor();
this.model.initialize(initParams); this.model.initialize(initParams);
rendererContainer.registerRenderer(lineId, this.model); rendererContainer.registerRenderer(lineId, this.model);
@ -40,7 +40,7 @@ class IncrementalRenderer extends React.Component<
this.props.onHeightChange(); this.props.onHeightChange();
} }
if (this.wrapperDivRef.current != null) { if (this.wrapperDivRef.current != null) {
let height = this.wrapperDivRef.current.offsetHeight; const height = this.wrapperDivRef.current.offsetHeight;
this.updateHeight_debounced(height); this.updateHeight_debounced(height);
} }
} }
@ -61,7 +61,7 @@ class IncrementalRenderer extends React.Component<
} }
componentWillUnmount() { componentWillUnmount() {
let { rendererContainer, lineId } = this.props; const { rendererContainer, lineId } = this.props;
rendererContainer.unloadRenderer(lineId); rendererContainer.unloadRenderer(lineId);
if (this.rszObs != null) { if (this.rszObs != null) {
this.rszObs.disconnect(); this.rszObs.disconnect();
@ -74,8 +74,8 @@ class IncrementalRenderer extends React.Component<
} }
render() { render() {
let { plugin } = this.props; const { plugin } = this.props;
let Comp = plugin.fullComponent; const Comp = plugin.fullComponent;
if (Comp == null) { if (Comp == null) {
<div ref={this.wrapperDivRef}>(no component found in plugin)</div>; <div ref={this.wrapperDivRef}>(no component found in plugin)</div>;
} }