mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-19 21:11:32 +01:00
terminal font-size updates (margins, paddings, etc.) (#315)
* reorganize line styles, split lines.less into lines.less and line.less * switch everyone to use termFontSize getter (easier to find usages) * better font-family font-size update logic * update line styles, clean up more * replace icons, fix line heights * make paddings/margins more consistent * fix more margins, make command completions use termfontfamily * updates for cmdinput margins, font sizes, etc. * fix more font sizes and margins (mostly command input) * add comment
This commit is contained in:
parent
b7539a26c7
commit
61de455b90
@ -2,6 +2,12 @@
|
|||||||
|
|
||||||
:root {
|
:root {
|
||||||
--fa-style-family: "Font Awesome 6 Sharp";
|
--fa-style-family: "Font Awesome 6 Sharp";
|
||||||
|
|
||||||
|
// these variables are overridden by user settings
|
||||||
|
--termfontfamily: "JetBrains Mono", monospace;
|
||||||
|
--termfontsize: 12px;
|
||||||
|
--termlineheight: 15px;
|
||||||
|
--termpad: 7px; // padding value (scaled to termfontsize)
|
||||||
}
|
}
|
||||||
|
|
||||||
html,
|
html,
|
||||||
|
@ -160,7 +160,7 @@ class Bookmark extends React.Component<BookmarkProps, {}> {
|
|||||||
<div className="bookmark-id-div">{bm.bookmarkid.substr(0, 8)}</div>
|
<div className="bookmark-id-div">{bm.bookmarkid.substr(0, 8)}</div>
|
||||||
<div className="bookmark-content">
|
<div className="bookmark-content">
|
||||||
<If condition={hasDesc}>
|
<If condition={hasDesc}>
|
||||||
<Markdown text={markdown} />
|
<Markdown text={markdown} extraClassName="bottom-margin" />
|
||||||
</If>
|
</If>
|
||||||
<CmdStrCode
|
<CmdStrCode
|
||||||
cmdstr={bm.cmdstr}
|
cmdstr={bm.cmdstr}
|
||||||
|
@ -27,7 +27,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
|||||||
@boundMethod
|
@boundMethod
|
||||||
handleChangeFontSize(fontSize: string): void {
|
handleChangeFontSize(fontSize: string): void {
|
||||||
const newFontSize = Number(fontSize);
|
const newFontSize = Number(fontSize);
|
||||||
if (GlobalModel.termFontSize.get() == newFontSize) {
|
if (GlobalModel.getTermFontSize() == newFontSize) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const prtn = GlobalCommandRunner.setTermFontSize(newFontSize, false);
|
const prtn = GlobalCommandRunner.setTermFontSize(newFontSize, false);
|
||||||
@ -144,7 +144,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
|||||||
const maxTokensStr = String(
|
const maxTokensStr = String(
|
||||||
openAIOpts.maxtokens == null || openAIOpts.maxtokens == 0 ? 1000 : openAIOpts.maxtokens
|
openAIOpts.maxtokens == null || openAIOpts.maxtokens == 0 ? 1000 : openAIOpts.maxtokens
|
||||||
);
|
);
|
||||||
const curFontSize = GlobalModel.termFontSize.get();
|
const curFontSize = GlobalModel.getTermFontSize();
|
||||||
const curFontFamily = GlobalModel.getTermFontFamily();
|
const curFontFamily = GlobalModel.getTermFontFamily();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
.markdown {
|
.markdown {
|
||||||
color: @term-white;
|
color: @term-white;
|
||||||
margin-bottom: 10px;
|
|
||||||
font-family: @markdown-font;
|
font-family: @markdown-font;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
|
|
||||||
|
&.bottom-margin {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
background-color: @markdown-highlight;
|
background-color: @markdown-highlight;
|
||||||
color: @term-white;
|
color: @term-white;
|
||||||
|
@ -41,7 +41,7 @@ class AlertModal extends React.Component<{}, {}> {
|
|||||||
<Modal.Header onClose={this.closeModal} title={title} />
|
<Modal.Header onClose={this.closeModal} title={title} />
|
||||||
<div className="wave-modal-body">
|
<div className="wave-modal-body">
|
||||||
<If condition={message?.markdown}>
|
<If condition={message?.markdown}>
|
||||||
<Markdown text={message?.message ?? ""} />
|
<Markdown text={message?.message ?? ""} extraClassName="bottom-margin" />
|
||||||
</If>
|
</If>
|
||||||
<If condition={!message?.markdown}>{message?.message}</If>
|
<If condition={!message?.markdown}>{message?.message}</If>
|
||||||
<If condition={message.confirmflag}>
|
<If condition={message.confirmflag}>
|
||||||
|
@ -59,7 +59,7 @@ export const UserInputModal = (userInputRequest: UserInputRequest) => {
|
|||||||
<div className="wave-modal-body">
|
<div className="wave-modal-body">
|
||||||
<div className="userinput-query">
|
<div className="userinput-query">
|
||||||
<If condition={userInputRequest.markdown}>
|
<If condition={userInputRequest.markdown}>
|
||||||
<Markdown text={userInputRequest.querytext} />
|
<Markdown text={userInputRequest.querytext} extraClassName="bottom-margin" />
|
||||||
</If>
|
</If>
|
||||||
<If condition={!userInputRequest.markdown}>{userInputRequest.querytext}</If>
|
<If condition={!userInputRequest.markdown}>{userInputRequest.querytext}</If>
|
||||||
</div>
|
</div>
|
||||||
|
@ -291,7 +291,7 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> {
|
|||||||
|
|
||||||
let model = this.model;
|
let model = this.model;
|
||||||
let isTermFocused = this.model.remoteTermWrapFocus.get();
|
let isTermFocused = this.model.remoteTermWrapFocus.get();
|
||||||
let termFontSize = GlobalModel.termFontSize.get();
|
let termFontSize = GlobalModel.getTermFontSize();
|
||||||
let termWidth = textmeasure.termWidthFromCols(appconst.RemotePtyCols, termFontSize);
|
let termWidth = textmeasure.termWidthFromCols(appconst.RemotePtyCols, termFontSize);
|
||||||
let remoteAliasText = util.isBlank(remote.remotealias) ? "(none)" : remote.remotealias;
|
let remoteAliasText = util.isBlank(remote.remotealias) ? "(none)" : remote.remotealias;
|
||||||
let selectedRemoteStatus = this.getSelectedRemote().status;
|
let selectedRemoteStatus = this.getSelectedRemote().status;
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
.term-prompt {
|
.term-prompt {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
font-size: var(--termfontsize);
|
||||||
|
line-height: var(--termlineheight);
|
||||||
font-family: var(--termfontfamily);
|
font-family: var(--termfontfamily);
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
@ -12,6 +14,10 @@
|
|||||||
fill: @wave-green;
|
fill: @wave-green;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: 0.25em; // em for relative sizing
|
||||||
|
}
|
||||||
|
|
||||||
.term-prompt-branch {
|
.term-prompt-branch {
|
||||||
color: @term-white;
|
color: @term-white;
|
||||||
}
|
}
|
||||||
@ -21,9 +27,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.term-prompt-remote {
|
.term-prompt-remote {
|
||||||
i {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.term-prompt-remote {
|
.term-prompt-remote {
|
||||||
|
@ -8,7 +8,6 @@ import localizedFormat from "dayjs/plugin/localizedFormat";
|
|||||||
import { GlobalModel } from "@/models";
|
import { GlobalModel } from "@/models";
|
||||||
import cn from "classnames";
|
import cn from "classnames";
|
||||||
import { isBlank } from "@/util/util";
|
import { isBlank } from "@/util/util";
|
||||||
import { ReactComponent as FolderIcon } from "@/assets/icons/folder.svg";
|
|
||||||
|
|
||||||
import "./prompt.less";
|
import "./prompt.less";
|
||||||
|
|
||||||
@ -76,6 +75,7 @@ class Prompt extends React.Component<{ rptr: RemotePtrType; festate: Record<stri
|
|||||||
if (rptr == null || isBlank(rptr.remoteid)) {
|
if (rptr == null || isBlank(rptr.remoteid)) {
|
||||||
return <span className={cn("term-prompt", "color-green")}> </span>;
|
return <span className={cn("term-prompt", "color-green")}> </span>;
|
||||||
}
|
}
|
||||||
|
let termFontSize = GlobalModel.getTermFontSize();
|
||||||
let remote = GlobalModel.getRemote(this.props.rptr.remoteid);
|
let remote = GlobalModel.getRemote(this.props.rptr.remoteid);
|
||||||
let remoteStr = getRemoteStr(rptr);
|
let remoteStr = getRemoteStr(rptr);
|
||||||
let festate = this.props.festate ?? {};
|
let festate = this.props.festate ?? {};
|
||||||
@ -96,7 +96,7 @@ class Prompt extends React.Component<{ rptr: RemotePtrType; festate: Record<stri
|
|||||||
}
|
}
|
||||||
let cwdElem = (
|
let cwdElem = (
|
||||||
<span title="current directory" className="term-prompt-cwd">
|
<span title="current directory" className="term-prompt-cwd">
|
||||||
<FolderIcon className="icon" />
|
<i className="fa-sharp fa-solid fa-folder" style={{ marginRight: Math.ceil(termFontSize / 4) }} />
|
||||||
{cwd}
|
{cwd}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
366
src/app/line/line.less
Normal file
366
src/app/line/line.less
Normal file
@ -0,0 +1,366 @@
|
|||||||
|
@import "@/common/themes/themes.less";
|
||||||
|
|
||||||
|
.line {
|
||||||
|
margin: 1rem 1rem 0 1rem;
|
||||||
|
padding: var(--termpad) var(--termpad) var(--termpad) var(--termpad);
|
||||||
|
border-radius: 6px;
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
flex-shrink: 0;
|
||||||
|
position: relative;
|
||||||
|
background: @base-background;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
|
||||||
|
&.line-cmd {
|
||||||
|
flex-direction: column;
|
||||||
|
scroll-margin-bottom: 20px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.line-text {
|
||||||
|
// old formatting for text lines (requires override)
|
||||||
|
flex-direction: row;
|
||||||
|
padding-top: 5px;
|
||||||
|
|
||||||
|
.line-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.line-invalid {
|
||||||
|
color: @term-white;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
border: 1px solid rgba(@base-color, 0.8) !important;
|
||||||
|
box-shadow: 0px 0px 0.5px 0px rgba(255, 255, 255, 0.5) inset, 0px 0.5px 0px 0px rgba(255, 255, 255, 0.2) inset;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
border: 1px solid rgba(@wave-green, 0.8) !important;
|
||||||
|
box-shadow: 0px 0px 0.5px 0px rgba(255, 255, 255, 0.5) inset, 0px 0.5px 0px 0px rgba(255, 255, 255, 0.2) inset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load-error-text {
|
||||||
|
color: @term-red;
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.renderer-loading {
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-message {
|
||||||
|
color: @term-yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
.focus-indicator {
|
||||||
|
height: calc(100% - 7px);
|
||||||
|
top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.line-simple {
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 1.2;
|
||||||
|
color: rgba(@base-color, 0.6);
|
||||||
|
|
||||||
|
.simple-line-header {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 5px;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ts {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.simple-line-status {
|
||||||
|
.linenum {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
display: inline-block;
|
||||||
|
height: 1em;
|
||||||
|
margin-left: 0.5em;
|
||||||
|
margin-right: 0.5em;
|
||||||
|
vertical-align: text-top;
|
||||||
|
fill: @base-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success {
|
||||||
|
color: @wave-green;
|
||||||
|
fill: @wave-green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fail {
|
||||||
|
color: @error-red;
|
||||||
|
fill: @error-red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning {
|
||||||
|
color: @warning-yellow;
|
||||||
|
fill: @warning-yellow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.top-border {
|
||||||
|
border-top: 1px solid #777;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(2) {
|
||||||
|
margin: 0px 5px 5px 5px;
|
||||||
|
padding: 0px 5px 5px 12px;
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .meta .termopts {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .meta .settings {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
width: 100%;
|
||||||
|
font-weight: normal;
|
||||||
|
font-family: var(--termfontfamily);
|
||||||
|
font-size: var(--termfontsize);
|
||||||
|
line-height: var(--termlineheight);
|
||||||
|
|
||||||
|
&.is-expanded {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-icon {
|
||||||
|
display: block;
|
||||||
|
visibility: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 3px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-icon-show {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-icon + .line-icon {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-icon.active {
|
||||||
|
visibility: visible;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .line-icon {
|
||||||
|
visibility: visible;
|
||||||
|
display: block;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta.meta-line1 {
|
||||||
|
color: rgba(@base-color, 0.6) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta.meta-line2 {
|
||||||
|
margin-left: -2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-header + div:not(.zero-height) {
|
||||||
|
margin-top: var(--termpad);
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-wrap {
|
||||||
|
flex: 1 1 0px;
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
.user {
|
||||||
|
color: lighten(@soft-blue, 10%);
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 1px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ts,
|
||||||
|
.termopts,
|
||||||
|
.renderer {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.renderer {
|
||||||
|
margin-left: 3px;
|
||||||
|
svg {
|
||||||
|
width: 1em;
|
||||||
|
margin-right: 0.5em;
|
||||||
|
fill: rgba(@base-color, 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings {
|
||||||
|
display: none;
|
||||||
|
margin-left: 0.5em;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
border-radius: 50%;
|
||||||
|
line-height: 1em;
|
||||||
|
svg {
|
||||||
|
fill: rgba(@base-color, 0.6);
|
||||||
|
&:hover {
|
||||||
|
fill: @base-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.termopts {
|
||||||
|
display: none;
|
||||||
|
.resize-button {
|
||||||
|
cursor: pointer;
|
||||||
|
padding-left: 3px;
|
||||||
|
padding-right: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.metapart-mono {
|
||||||
|
margin-left: 8px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmdtext {
|
||||||
|
overflow: hidden;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmdtext-overflow {
|
||||||
|
flex-shrink: 0;
|
||||||
|
padding-right: 2px;
|
||||||
|
color: @term-white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmdtext-expanded-wrapper {
|
||||||
|
padding-left: 6px;
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: 60px;
|
||||||
|
border-left: 2px solid #333;
|
||||||
|
margin-left: 3px;
|
||||||
|
|
||||||
|
.cmdtext-expanded {
|
||||||
|
white-space: pre;
|
||||||
|
|
||||||
|
color: @term-white;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-hints {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0px;
|
||||||
|
right: 0px;
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
.hint-item {
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-wrapper {
|
||||||
|
.loading-div {
|
||||||
|
height: 20px;
|
||||||
|
margin-left: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.has-rtnstate .terminal-wrapper {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-wrapper {
|
||||||
|
line-height: normal;
|
||||||
|
|
||||||
|
&.zero-height {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-connectelem {
|
||||||
|
overflow-y: hidden;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.cmd-done .terminal .xterm-cursor {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-loading-message {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(40% - 8px);
|
||||||
|
left: 50px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-rtnstate {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.cmd-rtnstate-label {
|
||||||
|
font-family: var(--termfontfamily);
|
||||||
|
position: relative;
|
||||||
|
font-size: 10px;
|
||||||
|
z-index: 2;
|
||||||
|
margin: 6px 0 2px 10px;
|
||||||
|
padding: 2px 5px 0px 5px;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 10px;
|
||||||
|
color: @term-white;
|
||||||
|
background-color: #151715;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-rtnstate-diff {
|
||||||
|
font-family: var(--termfontfamily);
|
||||||
|
color: @term-white;
|
||||||
|
white-space: pre;
|
||||||
|
margin-left: 10px;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-bottom: 1px;
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 1.2;
|
||||||
|
max-height: 50px;
|
||||||
|
overflow-y: auto;
|
||||||
|
direction: rtl;
|
||||||
|
|
||||||
|
.cmd-rtnstate-diff-inner {
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-rtnstate-sep {
|
||||||
|
height: 1px;
|
||||||
|
border-bottom: 1px solid #333;
|
||||||
|
position: relative;
|
||||||
|
top: -10px;
|
||||||
|
width: min(300px, 50%);
|
||||||
|
margin-bottom: -4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -25,17 +25,9 @@ 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 { ReactComponent as CheckIcon } from "@/assets/icons/line/check.svg";
|
|
||||||
import { ReactComponent as CommentIcon } from "@/assets/icons/line/comment.svg";
|
|
||||||
import { ReactComponent as QuestionIcon } from "@/assets/icons/line/question.svg";
|
|
||||||
import { ReactComponent as WarningIcon } from "@/assets/icons/line/triangle-exclamation.svg";
|
|
||||||
import { ReactComponent as XmarkIcon } from "@/assets/icons/line/xmark.svg";
|
|
||||||
import { ReactComponent as FillIcon } from "@/assets/icons/line/fill.svg";
|
import { ReactComponent as FillIcon } from "@/assets/icons/line/fill.svg";
|
||||||
import { ReactComponent as GearIcon } from "@/assets/icons/line/gear.svg";
|
|
||||||
|
|
||||||
import { RotateIcon } from "@/common/icons/icons";
|
import "./line.less";
|
||||||
|
|
||||||
import "./lines.less";
|
|
||||||
|
|
||||||
dayjs.extend(localizedFormat);
|
dayjs.extend(localizedFormat);
|
||||||
|
|
||||||
@ -44,41 +36,40 @@ 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);
|
||||||
const status = cmd != null ? cmd.getStatus() : "done";
|
let status = cmd != null ? cmd.getStatus() : "done";
|
||||||
const rtnstate = cmd != null ? cmd.getRtnState() : false;
|
|
||||||
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;
|
||||||
let iconTitle = null;
|
let iconTitle = null;
|
||||||
if (isComment) {
|
if (isComment) {
|
||||||
icon = <CommentIcon />;
|
icon = <i className="fa-sharp fa-solid fa-comment" />;
|
||||||
iconTitle = "comment";
|
iconTitle = "comment";
|
||||||
} else if (status == "done") {
|
} else if (status == "done") {
|
||||||
if (exitcode === 0) {
|
if (exitcode === 0) {
|
||||||
icon = <CheckIcon className="success" />;
|
icon = <i className="success fa-sharp fa-solid fa-check" />;
|
||||||
iconTitle = "success";
|
iconTitle = "success";
|
||||||
} else {
|
} else {
|
||||||
icon = <XmarkIcon className="fail" />;
|
icon = <i className="fail fa-sharp fa-solid fa-xmark" />;
|
||||||
iconTitle = "exitcode " + exitcode;
|
iconTitle = "exitcode " + exitcode;
|
||||||
}
|
}
|
||||||
} else if (status == "hangup") {
|
} else if (status == "hangup") {
|
||||||
icon = <WarningIcon className="warning" />;
|
icon = <i className="warning fa-sharp fa-solid fa-triangle-exclamation" />;
|
||||||
iconTitle = status;
|
iconTitle = status;
|
||||||
} else if (status == "error") {
|
} else if (status == "error") {
|
||||||
icon = <XmarkIcon className="fail" />;
|
icon = <i className="fail fa-sharp fa-solid fa-xmark" />;
|
||||||
iconTitle = "error";
|
iconTitle = "error";
|
||||||
} else if (status == "running" || "detached") {
|
} else if (status == "running" || status == "detached") {
|
||||||
icon = <RotateIcon className="warning spin" />;
|
icon = <i className="warning fa-sharp fa-solid fa-rotate fa-spin" />;
|
||||||
iconTitle = "running";
|
iconTitle = "running";
|
||||||
} else {
|
} else {
|
||||||
icon = <QuestionIcon />;
|
icon = <i className="fail fa-sharp fa-solid fa-question" />;
|
||||||
iconTitle = "unknown";
|
iconTitle = "unknown";
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
onContextMenu={this.props.onRightClick}
|
onContextMenu={this.props.onRightClick}
|
||||||
title={iconTitle}
|
title={iconTitle}
|
||||||
className={cn("simple-line-status", "status-" + status, rtnstate ? "has-rtnstate" : null)}
|
className={cn("simple-line-status", "status-" + status)}
|
||||||
>
|
>
|
||||||
<span className="linenum">{lineNumStr}</span>
|
<span className="linenum">{lineNumStr}</span>
|
||||||
<div className="avatar">{icon}</div>
|
<div className="avatar">{icon}</div>
|
||||||
@ -88,52 +79,22 @@ class SmallLineAvatar extends React.Component<{ line: LineType; cmd: Cmd; onRigh
|
|||||||
}
|
}
|
||||||
|
|
||||||
@mobxReact.observer
|
@mobxReact.observer
|
||||||
class LineCmd extends React.Component<
|
class RtnState extends React.Component<{ cmd: Cmd; line: LineType }> {
|
||||||
{
|
|
||||||
screen: LineContainerType;
|
|
||||||
line: LineType;
|
|
||||||
width: number;
|
|
||||||
staticRender: boolean;
|
|
||||||
visible: OV<boolean>;
|
|
||||||
onHeightChange: LineHeightChangeCallbackType;
|
|
||||||
renderMode: RenderModeType;
|
|
||||||
overrideCollapsed: OV<boolean>;
|
|
||||||
noSelect?: boolean;
|
|
||||||
showHints?: boolean;
|
|
||||||
},
|
|
||||||
{}
|
|
||||||
> {
|
|
||||||
lineRef: React.RefObject<any> = React.createRef();
|
|
||||||
cmdTextRef: React.RefObject<any> = React.createRef();
|
|
||||||
rtnStateDiff: mobx.IObservableValue<string> = mobx.observable.box(null, {
|
rtnStateDiff: mobx.IObservableValue<string> = mobx.observable.box(null, {
|
||||||
name: "linecmd-rtn-state-diff",
|
name: "linecmd-rtn-state-diff",
|
||||||
});
|
});
|
||||||
rtnStateDiffFetched: boolean = false;
|
rtnStateDiffFetched: boolean = false;
|
||||||
lastHeight: number;
|
|
||||||
isOverflow: OV<boolean> = mobx.observable.box(false, {
|
|
||||||
name: "line-overflow",
|
|
||||||
});
|
|
||||||
isCmdExpanded: OV<boolean> = mobx.observable.box(false, {
|
|
||||||
name: "cmd-expanded",
|
|
||||||
});
|
|
||||||
|
|
||||||
constructor(props) {
|
componentDidMount() {
|
||||||
super(props);
|
this.componentDidUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
this.checkStateDiffLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
checkStateDiffLoad(): void {
|
checkStateDiffLoad(): void {
|
||||||
const { screen, line, staticRender, visible } = this.props;
|
let cmd = this.props.cmd;
|
||||||
if (staticRender) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!visible.get()) {
|
|
||||||
if (this.rtnStateDiffFetched) {
|
|
||||||
this.rtnStateDiffFetched = false;
|
|
||||||
this.setRtnStateDiff(null);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const cmd = screen.getCmd(line);
|
|
||||||
if (cmd == null || !cmd.getRtnState() || this.rtnStateDiffFetched) {
|
if (cmd == null || !cmd.getRtnState() || this.rtnStateDiffFetched) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -179,6 +140,68 @@ class LineCmd extends React.Component<
|
|||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let { cmd } = this.props;
|
||||||
|
const rsdiff = this.rtnStateDiff.get();
|
||||||
|
const termFontSize = GlobalModel.getTermFontSize();
|
||||||
|
let rtnStateDiffSize = termFontSize - 2;
|
||||||
|
if (rtnStateDiffSize < 10) {
|
||||||
|
rtnStateDiffSize = Math.max(termFontSize, 10);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key="rtnstate"
|
||||||
|
className="cmd-rtnstate"
|
||||||
|
style={{
|
||||||
|
visibility: cmd.getStatus() == "done" ? "visible" : "hidden",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<If condition={rsdiff == null || rsdiff == ""}>
|
||||||
|
<div className="cmd-rtnstate-label">state unchanged</div>
|
||||||
|
<div className="cmd-rtnstate-sep"></div>
|
||||||
|
</If>
|
||||||
|
<If condition={rsdiff != null && rsdiff != ""}>
|
||||||
|
<div className="cmd-rtnstate-label">new state</div>
|
||||||
|
<div className="cmd-rtnstate-sep"></div>
|
||||||
|
<div className="cmd-rtnstate-diff" style={{ fontSize: rtnStateDiffSize }}>
|
||||||
|
<div className="cmd-rtnstate-diff-inner">{this.rtnStateDiff.get()}</div>
|
||||||
|
</div>
|
||||||
|
</If>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mobxReact.observer
|
||||||
|
class LineCmd extends React.Component<
|
||||||
|
{
|
||||||
|
screen: LineContainerType;
|
||||||
|
line: LineType;
|
||||||
|
width: number;
|
||||||
|
staticRender: boolean;
|
||||||
|
visible: OV<boolean>;
|
||||||
|
onHeightChange: LineHeightChangeCallbackType;
|
||||||
|
renderMode: RenderModeType;
|
||||||
|
overrideCollapsed: OV<boolean>;
|
||||||
|
noSelect?: boolean;
|
||||||
|
showHints?: boolean;
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
> {
|
||||||
|
lineRef: React.RefObject<any> = React.createRef();
|
||||||
|
cmdTextRef: React.RefObject<any> = React.createRef();
|
||||||
|
lastHeight: number;
|
||||||
|
isOverflow: OV<boolean> = mobx.observable.box(false, {
|
||||||
|
name: "line-overflow",
|
||||||
|
});
|
||||||
|
isCmdExpanded: OV<boolean> = mobx.observable.box(false, {
|
||||||
|
name: "cmd-expanded",
|
||||||
|
});
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.componentDidUpdate(null, null, null);
|
this.componentDidUpdate(null, null, null);
|
||||||
this.checkCmdText();
|
this.checkCmdText();
|
||||||
@ -241,7 +264,6 @@ class LineCmd extends React.Component<
|
|||||||
|
|
||||||
componentDidUpdate(prevProps, prevState, snapshot: { height: number }): void {
|
componentDidUpdate(prevProps, prevState, snapshot: { height: number }): void {
|
||||||
this.handleHeightChange();
|
this.handleHeightChange();
|
||||||
this.checkStateDiffLoad();
|
|
||||||
this.checkCmdText();
|
this.checkCmdText();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,7 +407,7 @@ class LineCmd extends React.Component<
|
|||||||
let height = 45 + 24; // height of zero height terminal
|
let height = 45 + 24; // height of zero height terminal
|
||||||
const usedRows = screen.getUsedRows(lineutil.getRendererContext(line), line, cmd, width);
|
const usedRows = screen.getUsedRows(lineutil.getRendererContext(line), line, cmd, width);
|
||||||
if (usedRows > 0) {
|
if (usedRows > 0) {
|
||||||
height = 48 + 24 + termHeightFromRows(usedRows, GlobalModel.termFontSize.get(), cmd.getTermMaxRows());
|
height = 48 + 24 + termHeightFromRows(usedRows, GlobalModel.getTermFontSize(), cmd.getTermMaxRows());
|
||||||
}
|
}
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
@ -452,7 +474,6 @@ class LineCmd extends React.Component<
|
|||||||
|
|
||||||
renderMeta1(cmd: Cmd) {
|
renderMeta1(cmd: Cmd) {
|
||||||
let { line } = this.props;
|
let { line } = this.props;
|
||||||
let termOpts = cmd.getTermOpts();
|
|
||||||
let formattedTime: string = "";
|
let formattedTime: string = "";
|
||||||
let restartTs = cmd.getRestartTs();
|
let restartTs = cmd.getRestartTs();
|
||||||
let timeTitle: string = null;
|
let timeTitle: string = null;
|
||||||
@ -472,16 +493,10 @@ class LineCmd extends React.Component<
|
|||||||
<div> </div>
|
<div> </div>
|
||||||
<If condition={!isBlank(renderer) && renderer != "terminal"}>
|
<If condition={!isBlank(renderer) && renderer != "terminal"}>
|
||||||
<div className="renderer">
|
<div className="renderer">
|
||||||
<FillIcon />
|
<i className="fa-sharp fa-solid fa-fill" />
|
||||||
{renderer}
|
{renderer}
|
||||||
</div>
|
</div>
|
||||||
</If>
|
</If>
|
||||||
<div className="termopts">
|
|
||||||
({termOpts.rows}x{termOpts.cols})
|
|
||||||
</div>
|
|
||||||
<div className="settings hoverEffect" onClick={this.handleLineSettings}>
|
|
||||||
<GearIcon />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -583,6 +598,7 @@ class LineCmd extends React.Component<
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
const isRtnState = cmd.getRtnState() && false; // turning off rtnstate for now
|
||||||
const isSelected = mobx
|
const isSelected = mobx
|
||||||
.computed(() => screen.getSelectedLine() == line.linenum, {
|
.computed(() => screen.getSelectedLine() == line.linenum, {
|
||||||
name: "computed-isSelected",
|
name: "computed-isSelected",
|
||||||
@ -621,14 +637,13 @@ class LineCmd extends React.Component<
|
|||||||
.get();
|
.get();
|
||||||
const isRunning = cmd.isRunning();
|
const isRunning = cmd.isRunning();
|
||||||
const isExpanded = this.isCmdExpanded.get();
|
const isExpanded = this.isCmdExpanded.get();
|
||||||
const rsdiff = this.rtnStateDiff.get();
|
|
||||||
const mainDivCn = cn(
|
const mainDivCn = cn(
|
||||||
"line",
|
"line",
|
||||||
"line-cmd",
|
"line-cmd",
|
||||||
{ selected: isSelected },
|
{ selected: isSelected },
|
||||||
{ active: isSelected && isFocused },
|
{ active: isSelected && isFocused },
|
||||||
{ "cmd-done": !isRunning },
|
{ "cmd-done": !isRunning },
|
||||||
{ "has-rtnstate": cmd.getRtnState() }
|
{ "has-rtnstate": isRtnState }
|
||||||
);
|
);
|
||||||
let rendererPlugin: RendererPluginType = null;
|
let rendererPlugin: RendererPluginType = null;
|
||||||
const isNoneRenderer = line.renderer == "none";
|
const isNoneRenderer = line.renderer == "none";
|
||||||
@ -637,11 +652,7 @@ class LineCmd extends React.Component<
|
|||||||
}
|
}
|
||||||
const rendererType = lineutil.getRendererType(line);
|
const rendererType = lineutil.getRendererType(line);
|
||||||
const hidePrompt = rendererPlugin?.hidePrompt;
|
const hidePrompt = rendererPlugin?.hidePrompt;
|
||||||
const termFontSize = GlobalModel.termFontSize.get();
|
const termFontSize = GlobalModel.getTermFontSize();
|
||||||
let rtnStateDiffSize = termFontSize - 2;
|
|
||||||
if (rtnStateDiffSize < 10) {
|
|
||||||
rtnStateDiffSize = Math.max(termFontSize, 10);
|
|
||||||
}
|
|
||||||
const containerType = screen.getContainerType();
|
const containerType = screen.getContainerType();
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -700,6 +711,14 @@ class LineCmd extends React.Component<
|
|||||||
>
|
>
|
||||||
<i className="fa-sharp fa-solid fa-right-to-line" />
|
<i className="fa-sharp fa-solid fa-right-to-line" />
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
key="settings"
|
||||||
|
title="Line Settings"
|
||||||
|
className="line-icon"
|
||||||
|
onClick={this.handleLineSettings}
|
||||||
|
>
|
||||||
|
<i className="fa-sharp fa-regular fa-ellipsis-vertical" />
|
||||||
|
</div>
|
||||||
</If>
|
</If>
|
||||||
<If condition={containerType == appconst.LineContainer_Sidebar}>
|
<If condition={containerType == appconst.LineContainer_Sidebar}>
|
||||||
<div
|
<div
|
||||||
@ -711,7 +730,7 @@ class LineCmd extends React.Component<
|
|||||||
</div>
|
</div>
|
||||||
</If>
|
</If>
|
||||||
</div>
|
</div>
|
||||||
<If condition={isInSidebar}>
|
<If condition={!isMinimized && isInSidebar}>
|
||||||
<div className="sidebar-message" style={{ fontSize: termFontSize }}>
|
<div className="sidebar-message" style={{ fontSize: termFontSize }}>
|
||||||
showing in sidebar =>
|
showing in sidebar =>
|
||||||
</div>
|
</div>
|
||||||
@ -752,26 +771,8 @@ class LineCmd extends React.Component<
|
|||||||
/>
|
/>
|
||||||
</If>
|
</If>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
<If condition={cmd.getRtnState()}>
|
<If condition={isRtnState}>
|
||||||
<div
|
<RtnState cmd={cmd} line={line} />
|
||||||
key="rtnstate"
|
|
||||||
className="cmd-rtnstate"
|
|
||||||
style={{
|
|
||||||
visibility: cmd.getStatus() == "done" ? "visible" : "hidden",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<If condition={rsdiff == null || rsdiff == ""}>
|
|
||||||
<div className="cmd-rtnstate-label">state unchanged</div>
|
|
||||||
<div className="cmd-rtnstate-sep"></div>
|
|
||||||
</If>
|
|
||||||
<If condition={rsdiff != null && rsdiff != ""}>
|
|
||||||
<div className="cmd-rtnstate-label">new state</div>
|
|
||||||
<div className="cmd-rtnstate-sep"></div>
|
|
||||||
<div className="cmd-rtnstate-diff" style={{ fontSize: rtnStateDiffSize }}>
|
|
||||||
<div className="cmd-rtnstate-diff-inner">{this.rtnStateDiff.get()}</div>
|
|
||||||
</div>
|
|
||||||
</If>
|
|
||||||
</div>
|
|
||||||
</If>
|
</If>
|
||||||
<If condition={isSelected && !isFocused && rendererType == "terminal"}>
|
<If condition={isSelected && !isFocused && rendererType == "terminal"}>
|
||||||
<div className="cmd-hints">
|
<div className="cmd-hints">
|
||||||
|
@ -1,462 +1,5 @@
|
|||||||
@import "@/common/themes/themes.less";
|
@import "@/common/themes/themes.less";
|
||||||
|
|
||||||
.line.line-text {
|
|
||||||
flex-direction: row;
|
|
||||||
padding-top: 5px;
|
|
||||||
|
|
||||||
.line-content {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
flex-grow: 1;
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.line .load-error-text {
|
|
||||||
color: @term-red;
|
|
||||||
padding-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.line .renderer-loading {
|
|
||||||
padding-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.line.line-cmd {
|
|
||||||
flex-direction: column;
|
|
||||||
scroll-margin-bottom: 20px;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.plus {
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
.plus {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-message {
|
|
||||||
color: @term-yellow;
|
|
||||||
}
|
|
||||||
|
|
||||||
.line-header {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
padding-bottom: 0.7rem;
|
|
||||||
width: 100%;
|
|
||||||
line-height: 1.2;
|
|
||||||
|
|
||||||
&.is-expanded {
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.hide-prompt {
|
|
||||||
height: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.line-icon {
|
|
||||||
display: block;
|
|
||||||
visibility: hidden;
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 3px;
|
|
||||||
border-radius: 50%;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.line-icon-show {
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.line-icon + .line-icon {
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.line-icon.active {
|
|
||||||
visibility: visible;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover .line-icon {
|
|
||||||
visibility: visible;
|
|
||||||
display: block;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.meta.meta-line1 {
|
|
||||||
color: rgba(@base-color, 0.6) !important;
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.meta.meta-line2 {
|
|
||||||
margin-left: -2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.has-rtnstate .terminal-wrapper {
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-wrapper {
|
|
||||||
.loading-div {
|
|
||||||
height: 20px;
|
|
||||||
margin-left: 50px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.terminal-wrapper {
|
|
||||||
line-height: normal;
|
|
||||||
|
|
||||||
&.zero-height {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.terminal-connectelem {
|
|
||||||
overflow-y: hidden;
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.cmd-done .terminal .xterm-cursor {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.terminal-loading-message {
|
|
||||||
position: absolute;
|
|
||||||
top: calc(40% - 8px);
|
|
||||||
left: 50px;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cmd-rtnstate {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.cmd-rtnstate-label {
|
|
||||||
font-family: var(--termfontfamily);
|
|
||||||
position: relative;
|
|
||||||
font-size: 10px;
|
|
||||||
z-index: 2;
|
|
||||||
margin: 6px 0 2px 10px;
|
|
||||||
padding: 2px 5px 0px 5px;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 10px;
|
|
||||||
color: @term-white;
|
|
||||||
background-color: #151715;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cmd-rtnstate-diff {
|
|
||||||
font-family: var(--termfontfamily);
|
|
||||||
color: @term-white;
|
|
||||||
white-space: pre;
|
|
||||||
margin-left: 10px;
|
|
||||||
padding-left: 10px;
|
|
||||||
padding-bottom: 1px;
|
|
||||||
font-size: 11px;
|
|
||||||
line-height: 1.2;
|
|
||||||
max-height: 50px;
|
|
||||||
overflow-y: auto;
|
|
||||||
direction: rtl;
|
|
||||||
|
|
||||||
.cmd-rtnstate-diff-inner {
|
|
||||||
direction: ltr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cmd-rtnstate-sep {
|
|
||||||
height: 1px;
|
|
||||||
border-bottom: 1px solid #333;
|
|
||||||
position: relative;
|
|
||||||
top: -10px;
|
|
||||||
width: min(300px, 50%);
|
|
||||||
margin-bottom: -4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.line {
|
|
||||||
margin: 1rem 1rem 0 1rem;
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 6px;
|
|
||||||
display: flex;
|
|
||||||
overflow: hidden;
|
|
||||||
flex-shrink: 0;
|
|
||||||
position: relative;
|
|
||||||
background: @base-background;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
|
|
||||||
&.selected {
|
|
||||||
border: 1px solid rgba(@base-color, 0.8) !important;
|
|
||||||
box-shadow: 0px 0px 0.5px 0px rgba(255, 255, 255, 0.5) inset, 0px 0.5px 0px 0px rgba(255, 255, 255, 0.2) inset;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
border: 1px solid rgba(@wave-green, 0.8) !important;
|
|
||||||
box-shadow: 0px 0px 0.5px 0px rgba(255, 255, 255, 0.5) inset, 0px 0.5px 0px 0px rgba(255, 255, 255, 0.2) inset;
|
|
||||||
}
|
|
||||||
|
|
||||||
.focus-indicator {
|
|
||||||
height: calc(100% - 7px);
|
|
||||||
top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.line-simple {
|
|
||||||
font-size: 11px;
|
|
||||||
line-height: 1.2;
|
|
||||||
color: rgba(@base-color, 0.6);
|
|
||||||
|
|
||||||
.simple-line-header {
|
|
||||||
display: flex;
|
|
||||||
margin-top: 5px;
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ts {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.simple-line-status {
|
|
||||||
.linenum {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.has-rtnstate {
|
|
||||||
.linenum {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar {
|
|
||||||
display: inline-block;
|
|
||||||
width: 1em;
|
|
||||||
height: 1em;
|
|
||||||
margin: 0 0.5em;
|
|
||||||
vertical-align: text-top;
|
|
||||||
fill: @base-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.success {
|
|
||||||
fill: @wave-green;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fail {
|
|
||||||
fill: @error-red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.warning {
|
|
||||||
fill: @warning-yellow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.top-border {
|
|
||||||
border-top: 1px solid #777;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(2) {
|
|
||||||
margin: 0px 5px 5px 5px;
|
|
||||||
padding: 0px 5px 5px 12px;
|
|
||||||
border-top: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover .meta .termopts {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover .meta .settings {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar {
|
|
||||||
max-height: 38px;
|
|
||||||
width: 38px;
|
|
||||||
display: flex;
|
|
||||||
flex-shrink: 0;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-weight: bold;
|
|
||||||
color: @term-white;
|
|
||||||
|
|
||||||
border-radius: 5px;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&.rtnstate {
|
|
||||||
border: 1px solid white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-icon {
|
|
||||||
position: absolute;
|
|
||||||
top: 2px;
|
|
||||||
right: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.comment-icon {
|
|
||||||
position: absolute;
|
|
||||||
top: 0px;
|
|
||||||
right: -4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.status-done {
|
|
||||||
background-color: #555;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.ephemeral {
|
|
||||||
opacity: 0.5;
|
|
||||||
outline: 1px solid white;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.status-error {
|
|
||||||
.status-icon {
|
|
||||||
color: @error-red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.status-hangup {
|
|
||||||
.status-icon {
|
|
||||||
color: @term-yellow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.status-running {
|
|
||||||
background-color: @soft-blue;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.status-waiting {
|
|
||||||
background-color: @term-yellow;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.status-detached {
|
|
||||||
background-color: @soft-blue;
|
|
||||||
.status-icon {
|
|
||||||
top: 3px;
|
|
||||||
right: 3px;
|
|
||||||
color: @term-white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.meta-wrap {
|
|
||||||
flex: 1 1 0px;
|
|
||||||
min-width: 0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
line-height: 1.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.meta {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
|
|
||||||
.simple-line-status {
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user {
|
|
||||||
color: lighten(@soft-blue, 10%);
|
|
||||||
font-weight: bold;
|
|
||||||
margin-top: 1px;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ts,
|
|
||||||
.termopts,
|
|
||||||
.renderer {
|
|
||||||
display: flex;
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.renderer {
|
|
||||||
margin-left: 3px;
|
|
||||||
margin-top: 5px;
|
|
||||||
svg {
|
|
||||||
width: 1em;
|
|
||||||
margin-right: 0.5em;
|
|
||||||
fill: rgba(@base-color, 0.6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.settings {
|
|
||||||
display: none;
|
|
||||||
margin-left: 0.5em;
|
|
||||||
margin-top: 0.65em;
|
|
||||||
cursor: pointer;
|
|
||||||
width: 1em;
|
|
||||||
height: 1em;
|
|
||||||
border-radius: 50%;
|
|
||||||
line-height: 1em;
|
|
||||||
svg {
|
|
||||||
fill: rgba(@base-color, 0.6);
|
|
||||||
&:hover {
|
|
||||||
fill: @base-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.termopts {
|
|
||||||
margin-top: 5px;
|
|
||||||
display: none;
|
|
||||||
.resize-button {
|
|
||||||
cursor: pointer;
|
|
||||||
padding-left: 3px;
|
|
||||||
padding-right: 3px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.metapart-mono {
|
|
||||||
margin-left: 8px;
|
|
||||||
margin-top: 4px;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cmdtext {
|
|
||||||
overflow: hidden;
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cmdtext-overflow {
|
|
||||||
flex-shrink: 0;
|
|
||||||
padding-right: 2px;
|
|
||||||
color: @term-white;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
margin-top: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cmdtext-expanded-wrapper {
|
|
||||||
margin-top: 2px;
|
|
||||||
padding-left: 6px;
|
|
||||||
overflow-y: auto;
|
|
||||||
max-height: 60px;
|
|
||||||
border-left: 2px solid #333;
|
|
||||||
margin-left: 3px;
|
|
||||||
|
|
||||||
.cmdtext-expanded {
|
|
||||||
white-space: pre;
|
|
||||||
|
|
||||||
color: @term-white;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cmd-hints {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0px;
|
|
||||||
right: 0px;
|
|
||||||
display: none;
|
|
||||||
|
|
||||||
.hint-item {
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.line.line-invalid {
|
|
||||||
color: @term-white;
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lines {
|
.lines {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -6,11 +6,10 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 12px;
|
bottom: var(--termfontsize);
|
||||||
right: 12px;
|
right: var(--termfontsize);
|
||||||
width: calc(100% - 24px);
|
width: calc(100% - 2 * var(--termfontsize));
|
||||||
padding: 12px;
|
padding: var(--termfontsize);
|
||||||
padding-bottom: 6px;
|
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
background: @background-session-components;
|
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),
|
box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.5), 0px 3px 8px 0px rgba(0, 0, 0, 0.35),
|
||||||
@ -24,7 +23,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.has-info {
|
&.has-info {
|
||||||
padding-top: 10px;
|
padding-top: var(--termpad);
|
||||||
}
|
}
|
||||||
|
|
||||||
.focus-indicator {
|
.focus-indicator {
|
||||||
@ -34,7 +33,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.has-history {
|
&.has-history {
|
||||||
padding-top: 5px;
|
padding-top: var(--termpad);
|
||||||
height: max(300px, 40%);
|
height: max(300px, 40%);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +100,11 @@
|
|||||||
|
|
||||||
.cmd-input-field {
|
.cmd-input-field {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-right: 17em;
|
padding-right: var(--termpad);
|
||||||
|
font-family: var(--termfontfamily);
|
||||||
|
font-weight: normal;
|
||||||
|
line-height: var(--termlineheight);
|
||||||
|
font-size: var(--termfontsize);
|
||||||
|
|
||||||
.cmd-hints {
|
.cmd-hints {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -115,10 +118,15 @@
|
|||||||
.textareainput-div {
|
.textareainput-div {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
&.control {
|
||||||
|
padding: var(--termpad) 0;
|
||||||
|
}
|
||||||
|
|
||||||
.shelltag {
|
.shelltag {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 4px;
|
// 13px = 10px height + 3px padding. subtract termpad to account for textareainput-div padding
|
||||||
right: 3px;
|
bottom: calc(-13px + var(--termpad));
|
||||||
|
right: 0px;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
color: @text-secondary;
|
color: @text-secondary;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
@ -131,14 +139,15 @@
|
|||||||
textarea {
|
textarea {
|
||||||
color: @term-bright-white;
|
color: @term-bright-white;
|
||||||
background-color: @textarea-background;
|
background-color: @textarea-background;
|
||||||
padding: 0.5em;
|
padding: var(--termpad);
|
||||||
resize: none;
|
resize: none;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
font-family: var(--termfontfamily);
|
line-height: var(--termlineheight);
|
||||||
font-weight: normal;
|
font-size: var(--termfontsize);
|
||||||
|
|
||||||
&.display-disabled {
|
&.display-disabled {
|
||||||
background-color: #444;
|
background-color: #444;
|
||||||
}
|
}
|
||||||
@ -350,7 +359,7 @@
|
|||||||
.cmd-input-info {
|
.cmd-input-info {
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
margin-bottom: 5px;
|
margin-bottom: var(--termpad);
|
||||||
|
|
||||||
.info-msg {
|
.info-msg {
|
||||||
color: @soft-blue;
|
color: @soft-blue;
|
||||||
@ -377,6 +386,9 @@
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
|
font-weight: normal;
|
||||||
|
font-family: var(--termfontfamily);
|
||||||
|
font-size: var(--termfontsize);
|
||||||
|
|
||||||
.info-comp {
|
.info-comp {
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
|
@ -214,37 +214,6 @@ class CmdInput extends React.Component<{}, {}> {
|
|||||||
screen={screen}
|
screen={screen}
|
||||||
onHeightChange={this.handleInnerHeightUpdate}
|
onHeightChange={this.handleInnerHeightUpdate}
|
||||||
/>
|
/>
|
||||||
<div className="control cmd-exec">
|
|
||||||
{/**<div onClick={inputModel.toggleExpandInput} className="hint-item color-white">
|
|
||||||
{inputModel.inputExpanded.get() ? "shrink" : "expand"} input ({renderCmdText("E")})
|
|
||||||
</div>**/}
|
|
||||||
{!focusVal && (
|
|
||||||
<div onClick={this.clickFocusInputHint} className="cmd-btn hoverEffect">
|
|
||||||
<div className="hint-elem">focus input ({renderCmdText("I")})</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{focusVal && (
|
|
||||||
<div className="cmd-btn hoverEffect">
|
|
||||||
<If condition={historyShow}>
|
|
||||||
<div className="hint-elem" onMouseDown={this.clickHistoryHint}>
|
|
||||||
close (esc)
|
|
||||||
</div>
|
|
||||||
</If>
|
|
||||||
<If condition={!historyShow}>
|
|
||||||
<div className="hint-elem" onMouseDown={this.clickHistoryHint}>
|
|
||||||
history (ctrl-r)
|
|
||||||
</div>
|
|
||||||
<div className="hint-elem" onMouseDown={this.clickAIHint}>
|
|
||||||
AI (ctrl-space)
|
|
||||||
</div>
|
|
||||||
</If>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<ExecIcon
|
|
||||||
onClick={inputModel.uiSubmitCommand}
|
|
||||||
className={`icon ${inputModel.getCurLine().trim() === "" ? "disabled" : "hoverEffect"}`}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -579,11 +579,11 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
|
|||||||
if (activeScreen != null) {
|
if (activeScreen != null) {
|
||||||
activeScreen.focusType.get(); // for reaction
|
activeScreen.focusType.get(); // for reaction
|
||||||
}
|
}
|
||||||
let termFontSize = 14;
|
let termFontSize = GlobalModel.getTermFontSize();
|
||||||
// fontSize*1.5 (line-height) + 2 * 0.5em padding
|
let fontSize = getMonoFontSize(termFontSize);
|
||||||
let computedInnerHeight = displayLines * (termFontSize * 1.5) + 2 * 0.5 * termFontSize;
|
let termPad = Math.floor(fontSize.height / 2);
|
||||||
// inner height + 2*1em padding
|
let computedInnerHeight = displayLines * fontSize.height + 2 * termPad;
|
||||||
let computedOuterHeight = computedInnerHeight + 2 * 1.0 * termFontSize;
|
let computedOuterHeight = computedInnerHeight + 2 * termPad;
|
||||||
let shellType: string = "";
|
let shellType: string = "";
|
||||||
let screen = GlobalModel.getActiveScreen();
|
let screen = GlobalModel.getActiveScreen();
|
||||||
if (screen != null) {
|
if (screen != null) {
|
||||||
|
@ -108,7 +108,7 @@ class ScreenView extends React.Component<{ session: Session; screen: Screen }, {
|
|||||||
if (screenWidth == null) {
|
if (screenWidth == null) {
|
||||||
return <div className="screen-view" ref={this.screenViewRef}></div>;
|
return <div className="screen-view" ref={this.screenViewRef}></div>;
|
||||||
}
|
}
|
||||||
let fontSize = GlobalModel.termFontSize.get();
|
let fontSize = GlobalModel.getTermFontSize();
|
||||||
let dprStr = sprintf("%0.3f", GlobalModel.devicePixelRatio.get());
|
let dprStr = sprintf("%0.3f", GlobalModel.devicePixelRatio.get());
|
||||||
let viewOpts = screen.viewOpts.get();
|
let viewOpts = screen.viewOpts.get();
|
||||||
let hasSidebar = viewOpts?.sidebar?.open;
|
let hasSidebar = viewOpts?.sidebar?.open;
|
||||||
|
@ -28,7 +28,7 @@ class ForwardLineContainer {
|
|||||||
this.winSize = winSize;
|
this.winSize = winSize;
|
||||||
let termWrap = this.getTermWrap(this.lineId);
|
let termWrap = this.getTermWrap(this.lineId);
|
||||||
if (termWrap != null) {
|
if (termWrap != null) {
|
||||||
let fontSize = this.globalModel.termFontSize.get();
|
let fontSize = this.globalModel.getTermFontSize();
|
||||||
let cols = windowWidthToCols(winSize.width, fontSize);
|
let cols = windowWidthToCols(winSize.width, fontSize);
|
||||||
let rows = windowHeightToRows(winSize.height, fontSize);
|
let rows = windowHeightToRows(winSize.height, fontSize);
|
||||||
termWrap.resizeCols(cols);
|
termWrap.resizeCols(cols);
|
||||||
|
@ -114,8 +114,8 @@ class HistoryViewModel {
|
|||||||
this.specialLineContainer = null;
|
this.specialLineContainer = null;
|
||||||
} else {
|
} else {
|
||||||
this.activeItem.set(hitem.historyid);
|
this.activeItem.set(hitem.historyid);
|
||||||
let width = termWidthFromCols(80, this.globalModel.termFontSize.get());
|
let width = termWidthFromCols(80, this.globalModel.getTermFontSize());
|
||||||
let height = termHeightFromRows(25, this.globalModel.termFontSize.get(), 25);
|
let height = termHeightFromRows(25, this.globalModel.getTermFontSize(), 25);
|
||||||
this.specialLineContainer = new SpecialLineContainer(
|
this.specialLineContainer = new SpecialLineContainer(
|
||||||
this,
|
this,
|
||||||
{ width, height },
|
{ width, height },
|
||||||
|
@ -33,7 +33,7 @@ import { MainSidebarModel } from "./mainsidebar";
|
|||||||
import { Screen } from "./screen";
|
import { Screen } from "./screen";
|
||||||
import { Cmd } from "./cmd";
|
import { Cmd } from "./cmd";
|
||||||
import { GlobalCommandRunner } from "./global";
|
import { GlobalCommandRunner } from "./global";
|
||||||
import { clearMonoFontCache } from "@/util/textmeasure";
|
import { clearMonoFontCache, getMonoFontSize } from "@/util/textmeasure";
|
||||||
import type { TermWrap } from "@/plugins/terminal/term";
|
import type { TermWrap } from "@/plugins/terminal/term";
|
||||||
|
|
||||||
type SWLinePtr = {
|
type SWLinePtr = {
|
||||||
@ -338,19 +338,29 @@ class Model {
|
|||||||
return this.termFontSize.get();
|
return this.termFontSize.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
setTermFontSize(fontSize: number) {
|
updateTermFontSizeVars(fontSize: number, force: boolean) {
|
||||||
|
if (!force && fontSize == this.termFontSize.get()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (fontSize < appconst.MinFontSize) {
|
if (fontSize < appconst.MinFontSize) {
|
||||||
fontSize = appconst.MinFontSize;
|
fontSize = appconst.MinFontSize;
|
||||||
}
|
}
|
||||||
if (fontSize > appconst.MaxFontSize) {
|
if (fontSize > appconst.MaxFontSize) {
|
||||||
fontSize = appconst.MaxFontSize;
|
fontSize = appconst.MaxFontSize;
|
||||||
}
|
}
|
||||||
|
const monoFontSize = getMonoFontSize(fontSize);
|
||||||
mobx.action(() => {
|
mobx.action(() => {
|
||||||
this.termFontSize.set(fontSize);
|
|
||||||
this.bumpRenderVersion();
|
this.bumpRenderVersion();
|
||||||
|
this.setStyleVar("--termfontsize", fontSize + "px");
|
||||||
|
this.setStyleVar("--termlineheight", monoFontSize.height + "px");
|
||||||
|
this.setStyleVar("--termpad", Math.floor(monoFontSize.height / 2) + "px");
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setStyleVar(name: string, value: string) {
|
||||||
|
document.documentElement.style.setProperty(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
getBaseWsHostPort(): string {
|
getBaseWsHostPort(): string {
|
||||||
if (this.isDev) {
|
if (this.isDev) {
|
||||||
return appconst.DevServerWsEndpoint;
|
return appconst.DevServerWsEndpoint;
|
||||||
@ -1131,6 +1141,16 @@ class Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setClientData(clientData: ClientDataType) {
|
setClientData(clientData: ClientDataType) {
|
||||||
|
let newFontFamily = clientData?.feopts?.termfontfamily;
|
||||||
|
if (newFontFamily == null) {
|
||||||
|
newFontFamily = "JetBrains Mono";
|
||||||
|
}
|
||||||
|
let newFontSize = clientData?.feopts?.termfontsize;
|
||||||
|
if (newFontSize == null) {
|
||||||
|
newFontSize = appconst.DefaultTermFontSize;
|
||||||
|
}
|
||||||
|
const ffUpdated = newFontFamily != this.getTermFontFamily();
|
||||||
|
const fsUpdated = newFontSize != this.getTermFontSize();
|
||||||
mobx.action(() => {
|
mobx.action(() => {
|
||||||
this.clientData.set(clientData);
|
this.clientData.set(clientData);
|
||||||
})();
|
})();
|
||||||
@ -1139,15 +1159,17 @@ class Model {
|
|||||||
shortcut = clientData?.clientopts?.globalshortcut;
|
shortcut = clientData?.clientopts?.globalshortcut;
|
||||||
}
|
}
|
||||||
getApi().reregisterGlobalShortcut(shortcut);
|
getApi().reregisterGlobalShortcut(shortcut);
|
||||||
let fontFamily = clientData?.feopts?.termfontfamily;
|
if (ffUpdated) {
|
||||||
if (fontFamily == null) {
|
// this also updates fontSize vars
|
||||||
fontFamily = "JetBrains Mono";
|
loadFonts(newFontFamily);
|
||||||
}
|
|
||||||
loadFonts(fontFamily);
|
|
||||||
document.fonts.ready.then(() => {
|
document.fonts.ready.then(() => {
|
||||||
clearMonoFontCache();
|
clearMonoFontCache();
|
||||||
|
this.updateTermFontSizeVars(this.termFontSize.get(), true); // forces an update of css vars
|
||||||
this.bumpRenderVersion();
|
this.bumpRenderVersion();
|
||||||
});
|
});
|
||||||
|
} else if (fsUpdated) {
|
||||||
|
this.updateTermFontSizeVars(newFontSize, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
submitCommandPacket(cmdPk: FeCmdPacketType, interactive: boolean): Promise<CommandRtnType> {
|
submitCommandPacket(cmdPk: FeCmdPacketType, interactive: boolean): Promise<CommandRtnType> {
|
||||||
|
@ -402,15 +402,15 @@ class Screen {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.lastScreenSize = winSize;
|
this.lastScreenSize = winSize;
|
||||||
let cols = windowWidthToCols(winSize.width, this.globalModel.termFontSize.get());
|
let cols = windowWidthToCols(winSize.width, this.globalModel.getTermFontSize());
|
||||||
let rows = windowHeightToRows(winSize.height, this.globalModel.termFontSize.get());
|
let rows = windowHeightToRows(winSize.height, this.globalModel.getTermFontSize());
|
||||||
this._termSizeCallback(rows, cols);
|
this._termSizeCallback(rows, cols);
|
||||||
}
|
}
|
||||||
|
|
||||||
getMaxContentSize(): WindowSize {
|
getMaxContentSize(): WindowSize {
|
||||||
if (this.lastScreenSize == null) {
|
if (this.lastScreenSize == null) {
|
||||||
let width = termWidthFromCols(80, this.globalModel.termFontSize.get());
|
let width = termWidthFromCols(80, this.globalModel.getTermFontSize());
|
||||||
let height = termHeightFromRows(25, this.globalModel.termFontSize.get(), 25);
|
let height = termHeightFromRows(25, this.globalModel.getTermFontSize(), 25);
|
||||||
return { width, height };
|
return { width, height };
|
||||||
}
|
}
|
||||||
let winSize = this.lastScreenSize;
|
let winSize = this.lastScreenSize;
|
||||||
@ -423,8 +423,8 @@ class Screen {
|
|||||||
|
|
||||||
getIdealContentSize(): WindowSize {
|
getIdealContentSize(): WindowSize {
|
||||||
if (this.lastScreenSize == null) {
|
if (this.lastScreenSize == null) {
|
||||||
let width = termWidthFromCols(80, this.globalModel.termFontSize.get());
|
let width = termWidthFromCols(80, this.globalModel.getTermFontSize());
|
||||||
let height = termHeightFromRows(25, this.globalModel.termFontSize.get(), 25);
|
let height = termHeightFromRows(25, this.globalModel.getTermFontSize(), 25);
|
||||||
return { width, height };
|
return { width, height };
|
||||||
}
|
}
|
||||||
let winSize = this.lastScreenSize;
|
let winSize = this.lastScreenSize;
|
||||||
|
@ -127,7 +127,7 @@ class SpecialLineContainer {
|
|||||||
}
|
}
|
||||||
let termWrap = this.getTermWrap(cmd.lineId);
|
let termWrap = this.getTermWrap(cmd.lineId);
|
||||||
if (termWrap == null) {
|
if (termWrap == null) {
|
||||||
let cols = windowWidthToCols(width, this.globalModel.termFontSize.get());
|
let cols = windowWidthToCols(width, this.globalModel.getTermFontSize());
|
||||||
let usedRows = this.globalModel.getContentHeight(context);
|
let usedRows = this.globalModel.getContentHeight(context);
|
||||||
if (usedRows != null) {
|
if (usedRows != null) {
|
||||||
return usedRows;
|
return usedRows;
|
||||||
|
@ -307,7 +307,7 @@ class SourceCodeRenderer extends React.Component<
|
|||||||
let allowEditing = this.getAllowEditing();
|
let allowEditing = this.getAllowEditing();
|
||||||
if (!allowEditing) {
|
if (!allowEditing) {
|
||||||
const noOfLines = Math.max(this.state.code.split("\n").length, 5);
|
const noOfLines = Math.max(this.state.code.split("\n").length, 5);
|
||||||
const lineHeight = Math.ceil(GlobalModel.termFontSize.get() * 1.5);
|
const lineHeight = Math.ceil(GlobalModel.getTermFontSize() * 1.5);
|
||||||
_editorHeight = Math.min(noOfLines * lineHeight + 10, fullWindowHeight);
|
_editorHeight = Math.min(noOfLines * lineHeight + 10, fullWindowHeight);
|
||||||
}
|
}
|
||||||
this.setState({ editorHeight: _editorHeight }, () => {
|
this.setState({ editorHeight: _editorHeight }, () => {
|
||||||
@ -434,7 +434,7 @@ class SourceCodeRenderer extends React.Component<
|
|||||||
<div
|
<div
|
||||||
className="code-renderer"
|
className="code-renderer"
|
||||||
style={{
|
style={{
|
||||||
fontSize: GlobalModel.termFontSize.get(),
|
fontSize: GlobalModel.getTermFontSize(),
|
||||||
color: "white",
|
color: "white",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -7,6 +7,7 @@ import * as mobx from "mobx";
|
|||||||
import { debounce } from "throttle-debounce";
|
import { debounce } from "throttle-debounce";
|
||||||
import * as util from "@/util/util";
|
import * as util from "@/util/util";
|
||||||
import { GlobalModel } from "@/models";
|
import { GlobalModel } from "@/models";
|
||||||
|
import cn from "classnames";
|
||||||
|
|
||||||
class SimpleBlobRendererModel {
|
class SimpleBlobRendererModel {
|
||||||
context: RendererContext;
|
context: RendererContext;
|
||||||
@ -246,7 +247,7 @@ class SimpleBlobRenderer extends React.Component<
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={this.wrapperDivRef}
|
ref={this.wrapperDivRef}
|
||||||
className="renderer-loading"
|
className={cn("renderer-loading", { "zero-height": height == 0 })}
|
||||||
style={{ minHeight: height, fontSize: model.opts.termFontSize }}
|
style={{ minHeight: height, fontSize: model.opts.termFontSize }}
|
||||||
>
|
>
|
||||||
loading content <i className="fa fa-ellipsis fa-fade" />
|
loading content <i className="fa fa-ellipsis fa-fade" />
|
||||||
@ -259,7 +260,7 @@ class SimpleBlobRenderer extends React.Component<
|
|||||||
}
|
}
|
||||||
let { festate, cmdstr, exitcode } = this.props.initParams.rawCmd;
|
let { festate, cmdstr, exitcode } = this.props.initParams.rawCmd;
|
||||||
return (
|
return (
|
||||||
<div ref={this.wrapperDivRef} className="sr-wrapper">
|
<div ref={this.wrapperDivRef} className={cn("sr-wrapper", { "zero-height": model.savedHeight == 0 })}>
|
||||||
<Comp
|
<Comp
|
||||||
cwd={festate.cwd}
|
cwd={festate.cwd}
|
||||||
cmdstr={cmdstr}
|
cmdstr={cmdstr}
|
||||||
|
@ -182,7 +182,7 @@ const CSVRenderer: FC<Props> = (props: Props) => {
|
|||||||
|
|
||||||
if (isFileTooLarge) {
|
if (isFileTooLarge) {
|
||||||
return (
|
return (
|
||||||
<div className="csv-renderer" style={{ fontSize: GlobalModel.termFontSize.get() }}>
|
<div className="csv-renderer" style={{ fontSize: GlobalModel.getTermFontSize() }}>
|
||||||
<div className="load-error-text">The file size exceeds 10MB and cannot be displayed.</div>
|
<div className="load-error-text">The file size exceeds 10MB and cannot be displayed.</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
@import "@/common/themes/themes.less";
|
@import "@/common/themes/themes.less";
|
||||||
|
|
||||||
.image-renderer {
|
.image-renderer {
|
||||||
padding: 10px;
|
|
||||||
img {
|
img {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
.markdown-renderer {
|
.markdown-renderer {
|
||||||
color: @term-white;
|
color: @term-white;
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
.scroller {
|
.scroller {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
@ -148,7 +148,7 @@ class TerminalRenderer extends React.Component<
|
|||||||
.get();
|
.get();
|
||||||
let cmd = screen.getCmd(line); // will not be null
|
let cmd = screen.getCmd(line); // will not be null
|
||||||
let usedRows = screen.getUsedRows(lineutil.getRendererContext(line), line, cmd, width);
|
let usedRows = screen.getUsedRows(lineutil.getRendererContext(line), line, cmd, width);
|
||||||
let termHeight = termHeightFromRows(usedRows, GlobalModel.termFontSize.get(), cmd.getTermMaxRows());
|
let termHeight = termHeightFromRows(usedRows, GlobalModel.getTermFontSize(), cmd.getTermMaxRows());
|
||||||
if (usedRows === 0) {
|
if (usedRows === 0) {
|
||||||
termHeight = 0;
|
termHeight = 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user