diff --git a/src/app/line/lines.less b/src/app/line/lines.less
index 33da44989..66ebfc7e7 100644
--- a/src/app/line/lines.less
+++ b/src/app/line/lines.less
@@ -467,7 +467,7 @@
display: flex;
flex-direction: column;
overflow: auto;
- padding: 10px 0;
+ padding: 0 0 10px 0;
flex-grow: 1;
position: relative;
diff --git a/src/app/magiclayout.ts b/src/app/magiclayout.ts
new file mode 100644
index 000000000..df8c90daf
--- /dev/null
+++ b/src/app/magiclayout.ts
@@ -0,0 +1,34 @@
+// Copyright 2023, Command Line Inc.
+// SPDX-License-Identifier: Apache-2.0
+
+// magical layout constants to power TypeScript calculations
+// these need to match the CSS (usually margins, paddings, positions, etc.)
+let MagicLayout = {
+ CmdInputHeight: 92, // height of full cmd-input div
+ CmdInputBottom: 12, // .cmd-input
+
+ LineHeaderHeight: 46, // .line-header
+ LinePadding: 24, // .line-header (12px * 2)
+ WindowHeightOffset: 6, // .window-view, height is calc(100%-0.5rem)
+ LinesBottomPadding: 10, // .lines, padding
+ LineMarginTop: 12, // .line, margin
+
+ ScreenMaxContentWidthBuffer: 50,
+ ScreenMaxContentHeightBuffer: 0, // calc below
+ ScreenMinContentSize: 100,
+ ScreenMaxContentSize: 5000,
+
+ // the 3 is for descenders, which get cut off in the terminal without this
+ TermDescendersHeight: 3,
+ TermWidthBuffer: 15,
+
+};
+
+let m = MagicLayout;
+
+// add up all the line overhead + padding. subtract 2 so we don't see the border of neighboring line
+m.ScreenMaxContentHeightBuffer = m.LineHeaderHeight + m.LinePadding + m.WindowHeightOffset + m.LinesBottomPadding + m.LineMarginTop - 2;
+
+window.MagicLayout = MagicLayout;
+
+export { MagicLayout };
diff --git a/src/app/workspace/cmdinput/cmdInput.less b/src/app/workspace/cmdinput/cmdInput.less
index 772db8b22..6b5c63c07 100644
--- a/src/app/workspace/cmdinput/cmdInput.less
+++ b/src/app/workspace/cmdinput/cmdInput.less
@@ -6,10 +6,11 @@
display: flex;
flex-direction: column;
position: absolute;
- bottom: 16px;
- right: 16px;
- width: calc(100% - 28px);
+ bottom: 12px;
+ right: 12px;
+ width: calc(100% - 24px);
padding: 12px;
+ padding-bottom: 6px;
z-index: 100;
background: @background-session-components;
box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.5), 0px 3px 8px 0px rgba(0, 0, 0, 0.35),
diff --git a/src/app/workspace/screen/screenview.less b/src/app/workspace/screen/screenview.less
index 275b93e10..aa88b389d 100644
--- a/src/app/workspace/screen/screenview.less
+++ b/src/app/workspace/screen/screenview.less
@@ -11,7 +11,7 @@
flex-direction: column;
position: absolute;
width: 100%;
- height: calc(100% - 3em);
+ height: calc(100% - 0.5rem);
overflow-x: hidden;
.rendermode-tag {
diff --git a/src/app/workspace/workspace.less b/src/app/workspace/workspace.less
index 565a4639f..f8d4777a3 100644
--- a/src/app/workspace/workspace.less
+++ b/src/app/workspace/workspace.less
@@ -12,8 +12,8 @@
background: @background-session;
border: 1px solid @base-border;
border-radius: 8px;
- margin-bottom: 1em;
transition: width 0.2s ease;
+ margin-bottom: 0.5em;
}
.collapsed + .session-view {
max-width: calc(100% - 6.7em);
diff --git a/src/app/workspace/workspaceview.tsx b/src/app/workspace/workspaceview.tsx
index 9816ee7ef..d98685936 100644
--- a/src/app/workspace/workspaceview.tsx
+++ b/src/app/workspace/workspaceview.tsx
@@ -12,6 +12,7 @@ import { CmdInput } from "./cmdinput/cmdinput";
import { ScreenView } from "./screen/screenview";
import { ScreenTabs } from "./screen/tabs";
import { ErrorBoundary } from "../../app/common/error/errorboundary";
+import { MagicLayout } from "../magiclayout";
import "./workspace.less";
dayjs.extend(localizedFormat);
@@ -29,8 +30,9 @@ class WorkspaceView extends React.Component<{}, {}> {
let activeScreen = session.getActiveScreen();
let cmdInputHeight = model.inputModel.cmdInputHeight.get();
if (cmdInputHeight == 0) {
- cmdInputHeight = 110;
+ cmdInputHeight = MagicLayout.CmdInputHeight; // this is the base size of cmdInput (measured using devtools)
}
+ cmdInputHeight += MagicLayout.CmdInputBottom; // reference to .cmd-input, bottom: 12px
let isHidden = GlobalModel.activeMainView.get() != "session";
return (
@@ -38,7 +40,7 @@ class WorkspaceView extends React.Component<{}, {}> {
-
+
diff --git a/src/electron/emain.ts b/src/electron/emain.ts
index 5c9c581f0..527bad306 100644
--- a/src/electron/emain.ts
+++ b/src/electron/emain.ts
@@ -339,7 +339,7 @@ function mainResizeHandler(e, win) {
return;
}
let bounds = win.getBounds();
- console.log("resize/move", win.getBounds());
+ // console.log("resize/move", win.getBounds());
let winSize = { width: bounds.width, height: bounds.height, top: bounds.y, left: bounds.x };
let url = getBaseHostPort() + "/api/set-winsize";
let fetchHeaders = getFetchHeaders();
diff --git a/src/model/model.ts b/src/model/model.ts
index fc8f73b3e..b259f9b6a 100644
--- a/src/model/model.ts
+++ b/src/model/model.ts
@@ -76,6 +76,7 @@ import localizedFormat from "dayjs/plugin/localizedFormat";
import customParseFormat from "dayjs/plugin/customParseFormat";
import { getRendererContext, cmdStatusIsRunning } from "../app/line/lineutil";
import { sortAndFilterRemotes } from "../util/util";
+import { MagicLayout } from "../app/magiclayout";
dayjs.extend(customParseFormat);
dayjs.extend(localizedFormat);
@@ -644,10 +645,11 @@ class Screen {
let height = termHeightFromRows(25, GlobalModel.termFontSize.get());
return { width, height };
}
- // TODO calculate these sizes more deliberately
let winSize = this.lastScreenSize;
- let width = boundInt(winSize.width - 50, 100, 5000);
- let height = boundInt(winSize.height - 120, 100, 5000);
+ let minSize = MagicLayout.ScreenMinContentSize;
+ let maxSize = MagicLayout.ScreenMaxContentSize;
+ let width = boundInt(winSize.width - MagicLayout.ScreenMaxContentWidthBuffer, minSize, maxSize);
+ let height = boundInt(winSize.height - MagicLayout.ScreenMaxContentHeightBuffer, minSize, maxSize);
return { width, height };
}
diff --git a/src/plugins/image/image.tsx b/src/plugins/image/image.tsx
index 24b12d615..5859577b4 100644
--- a/src/plugins/image/image.tsx
+++ b/src/plugins/image/image.tsx
@@ -11,23 +11,6 @@ import "./image.less";
type OV = mobx.IObservableValue;
type CV = mobx.IComputedValue;
-// ctor(RendererContext, RenderOpts, isDone);
-// type RendererModel = {
-// dispose : () => void,
-// reload : (delayMs : number) => void,
-// receiveData : (pos : number, data : Uint8Array, reason? : string) => void,
-// cmdDone : () => void,
-// resizeWindow : (size : WindowSize) => void,
-// resizeCols : (cols : number) => void,
-// giveFocus : () => void,
-// getUsedRows : () => number,
-// };
-
-// two types of renderers
-// JSON
-// blob
-//
-
@mobxReact.observer
class SimpleImageRenderer extends React.Component<
{ data: Blob; context: RendererContext; opts: RendererOpts; savedHeight: number },
diff --git a/src/plugins/terminal/term.ts b/src/plugins/terminal/term.ts
index 056e5ed94..38e0571c1 100644
--- a/src/plugins/terminal/term.ts
+++ b/src/plugins/terminal/term.ts
@@ -188,6 +188,10 @@ class TermWrap {
let termNumLines = termBuf.lines.length;
let termYPos = termBuf.y;
if (termNumLines > term.rows) {
+ // TODO: there is a weird case here. for commands that output more than term.rows rows of output
+ // they get an "extra" blank line at the bottom because the cursor is positioned on the next line!
+ // hard problem to solve because the line is already written to the buffer. we only want to "fix"
+ // this when the command is no longer running.
return term.rows;
}
let usedRows = this.isRunning ? 1 : 0;
diff --git a/src/util/textmeasure.ts b/src/util/textmeasure.ts
index e6f35b3f3..0c37e9706 100644
--- a/src/util/textmeasure.ts
+++ b/src/util/textmeasure.ts
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import { boundInt } from "./util";
+import { MagicLayout } from "../app/magiclayout";
const MinTermCols = 10;
const MaxTermCols = 1024;
@@ -62,14 +63,14 @@ function measureText(
function windowWidthToCols(width: number, fontSize: number): number {
let dr = getMonoFontSize(fontSize);
- let cols = Math.trunc((width - 50) / dr.width) - 1;
+ let cols = Math.trunc((width - MagicLayout.ScreenMaxContentWidthBuffer) / dr.width) - 1;
cols = boundInt(cols, MinTermCols, MaxTermCols);
return cols;
}
function windowHeightToRows(height: number, fontSize: number): number {
let dr = getMonoFontSize(fontSize);
- let rows = Math.floor((height - 80) / dr.height) - 1;
+ let rows = Math.floor((height - MagicLayout.ScreenMaxContentHeightBuffer) / dr.height) - 1;
if (rows <= 0) {
rows = 1;
}
@@ -78,13 +79,13 @@ function windowHeightToRows(height: number, fontSize: number): number {
function termWidthFromCols(cols: number, fontSize: number): number {
let dr = getMonoFontSize(fontSize);
- return Math.ceil(dr.width * cols) + 15;
+ return Math.ceil(dr.width * cols) + MagicLayout.TermWidthBuffer;
}
function termHeightFromRows(rows: number, fontSize: number): number {
let dr = getMonoFontSize(fontSize);
- // TODO: replace the +3 with some calculation based on termFontSize. the +3 is for descenders, which get cut off without this.
- return Math.ceil(dr.height * rows) + 3;
+ // TODO: replace the TermDescendersHeight with some calculation based on termFontSize.
+ return Math.ceil(dr.height * rows) + MagicLayout.TermDescendersHeight;
}
export { measureText, getMonoFontSize, windowWidthToCols, windowHeightToRows, termWidthFromCols, termHeightFromRows };