mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
More Prompt Updates / Line Action Implementation (#357)
* termfontsize-sm (for meta1). add some small margin. remove rootIndicator. switch cwd/remote to red if root * break LineHeader out into its own react component * actual set our --term colors as the *theme* for xtermjs * move line-actions into its own div (absolute position). hover/background colors * add duration, format renderer, spacing, remove meta-wrap * simplify cmdtext output. simpler multi-line rendering. * adjust position/height of line actions for better interaction with long lines * fix horiz scrolling * remove unused * quick fix for text lines
This commit is contained in:
+3
-3
@@ -17,12 +17,12 @@ body {
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
&.is-dev .sidebar {
|
&.is-dev .sidebar {
|
||||||
background-color: var(--sidebar-dev-bg-color);
|
background-color: var(--app-panel-bg-color-dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
body .sidebar {
|
body .sidebar {
|
||||||
background-color: var(--sidebar-bg-color);
|
background-color: var(--app-panel-bg-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
@@ -117,7 +117,7 @@ svg.icon {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hideScrollbarUntillHover {
|
.scrollbar-hide-until-hover {
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb,
|
&::-webkit-scrollbar-thumb,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import cn from "classnames";
|
|||||||
|
|
||||||
class TabIcon extends React.Component<{ icon: string; color: string }> {
|
class TabIcon extends React.Component<{ icon: string; color: string }> {
|
||||||
render() {
|
render() {
|
||||||
let { icon, color, className } = this.props;
|
let { icon, color } = this.props;
|
||||||
let iconClass = "";
|
let iconClass = "";
|
||||||
if (icon === "default" || icon === "square") {
|
if (icon === "default" || icon === "square") {
|
||||||
iconClass = "fa-solid fa-square fa-fw";
|
iconClass = "fa-solid fa-square fa-fw";
|
||||||
|
|||||||
@@ -2,10 +2,9 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
.term-prompt {
|
.term-prompt {
|
||||||
font-weight: normal;
|
// we are explicitly *not* setting font size properties here so prompt will inherit from caller
|
||||||
font-size: var(--termfontsize);
|
|
||||||
line-height: var(--termlineheight);
|
|
||||||
font-family: var(--termfontfamily);
|
font-family: var(--termfontfamily);
|
||||||
|
font-weight: normal;
|
||||||
color: var(--term-gray);
|
color: var(--term-gray);
|
||||||
|
|
||||||
i {
|
i {
|
||||||
@@ -62,11 +61,7 @@
|
|||||||
color: var(--term-bright-green);
|
color: var(--term-bright-green);
|
||||||
}
|
}
|
||||||
|
|
||||||
.term-prompt-end-user {
|
&.term-prompt-isroot .term-prompt-cwd {
|
||||||
color: var(--term-bright-green);
|
|
||||||
}
|
|
||||||
|
|
||||||
.term-prompt-end-root {
|
|
||||||
color: var(--term-bright-red);
|
color: var(--term-bright-red);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,11 +94,7 @@ class Prompt extends React.Component<{ rptr: RemotePtrType; festate: Record<stri
|
|||||||
if (remote && remote.remotecanonicalname) {
|
if (remote && remote.remotecanonicalname) {
|
||||||
remoteTitle = "connected to " + remote.remotecanonicalname;
|
remoteTitle = "connected to " + remote.remotecanonicalname;
|
||||||
}
|
}
|
||||||
let cwdElem = (
|
let cwdElem = <span className="term-prompt-cwd">{cwd}</span>;
|
||||||
<span title="current directory" className="term-prompt-cwd">
|
|
||||||
{cwd}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
let remoteElem = null;
|
let remoteElem = null;
|
||||||
if (remoteStr != "local") {
|
if (remoteStr != "local") {
|
||||||
remoteElem = (
|
remoteElem = (
|
||||||
@@ -107,12 +103,6 @@ class Prompt extends React.Component<{ rptr: RemotePtrType; festate: Record<stri
|
|||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let rootIndicatorElem = null;
|
|
||||||
if (isRoot) {
|
|
||||||
rootIndicatorElem = <span className="term-prompt-end-root">#</span>;
|
|
||||||
} else {
|
|
||||||
rootIndicatorElem = <span className="term-prompt-end-user">$</span>;
|
|
||||||
}
|
|
||||||
let branchElem = null;
|
let branchElem = null;
|
||||||
let pythonElem = null;
|
let pythonElem = null;
|
||||||
let condaElem = null;
|
let condaElem = null;
|
||||||
@@ -142,9 +132,14 @@ class Prompt extends React.Component<{ rptr: RemotePtrType; festate: Record<stri
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<span className={cn("term-prompt", { "term-prompt-color": this.props.color })}>
|
<span
|
||||||
{remoteElem} {condaElem} {pythonElem}
|
className={cn(
|
||||||
{cwdElem} {branchElem} {rootIndicatorElem}
|
"term-prompt",
|
||||||
|
{ "term-prompt-color": this.props.color },
|
||||||
|
{ "term-prompt-isroot": isRoot }
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{remoteElem} {cwdElem} {branchElem} {condaElem} {pythonElem}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
// Copyright 2023, Command Line Inc.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The file contains barebones of styling to appy themes to Prompt.
|
|
||||||
* @TODO: Find a way to change the theme system-wide. atm, we are captruing colors in main.less
|
|
||||||
*/
|
|
||||||
|
|
||||||
const themes = [
|
|
||||||
{
|
|
||||||
id: "default",
|
|
||||||
terminal: { foreground: "#eceeec", background: "black" },
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const getTheme = (_id = "default") => themes.find(({ id }) => id === _id);
|
|
||||||
|
|
||||||
export { getTheme };
|
|
||||||
+95
-147
@@ -2,30 +2,13 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: calc(var(--termpad) * 2) var(--termpad) calc(var(--termpad) * 2 + 1px) calc(var(--termpad) * 3);
|
padding: calc(var(--termpad) * 2) var(--termpad) calc(var(--termpad) * 2 + 1px) calc(var(--termpad) * 3);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-family: var(--termfontfamily);
|
font-family: var(--termfontfamily);
|
||||||
|
scroll-margin-bottom: 20px;
|
||||||
&.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 {
|
&.line-invalid {
|
||||||
color: var(--term-text-white);
|
color: var(--term-text-white);
|
||||||
@@ -118,7 +101,6 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
margin-left: 0.5em;
|
margin-left: 0.5em;
|
||||||
margin-right: 0.5em;
|
|
||||||
vertical-align: text-top;
|
vertical-align: text-top;
|
||||||
fill: var(--primary-background-color);
|
fill: var(--primary-background-color);
|
||||||
}
|
}
|
||||||
@@ -152,152 +134,118 @@
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.line-header {
|
.line-header + div:not(.zero-height) {
|
||||||
|
margin-top: calc(var(--termpad) + 2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .line-actions {
|
||||||
|
background-color: var(--app-panel-bg-color);
|
||||||
|
.line-icon {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-actions {
|
||||||
|
position: absolute;
|
||||||
|
right: calc(var(--termpad) * 2);
|
||||||
|
top: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--line-actions-inactive-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding-left: 4px;
|
||||||
|
padding-right: 4px;
|
||||||
|
line-height: 1.2;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.line-icon {
|
||||||
|
visibility: hidden;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--line-actions-active-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
padding: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-icon + .line-icon:not(.line-icon-shrink-left) {
|
||||||
|
margin-left: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-family: var(--termfontfamily);
|
font-family: var(--termfontfamily);
|
||||||
font-size: var(--termfontsize);
|
font-size: var(--termfontsize);
|
||||||
line-height: var(--termlineheight);
|
line-height: var(--termlineheight);
|
||||||
|
|
||||||
&.is-expanded {
|
.meta + .meta {
|
||||||
height: auto;
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.line-icon {
|
.meta {
|
||||||
display: block;
|
|
||||||
visibility: hidden;
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 3px;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.line-icon-show {
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.line-icon + .line-icon {p
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.line-icon.active {
|
|
||||||
visibility: visible;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover .line-icon {
|
|
||||||
visibility: visible;
|
|
||||||
display: block;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.meta.meta-line1 {
|
|
||||||
color: var(--term-gray);
|
|
||||||
}
|
|
||||||
|
|
||||||
.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: var(--line-meta-user-color);
|
|
||||||
font-weight: bold;
|
|
||||||
margin-top: 1px;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ts,
|
|
||||||
.termopts,
|
|
||||||
.renderer {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
flex-direction: row;
|
||||||
|
|
||||||
.renderer {
|
.user {
|
||||||
margin-left: 3px;
|
color: var(--line-meta-user-color);
|
||||||
svg {
|
font-weight: bold;
|
||||||
width: 1em;
|
margin-top: 1px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.meta-line1 {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
font-size: var(--termfontsize-sm);
|
||||||
|
line-height: var(--termlineheight-sm);
|
||||||
|
color: var(--term-gray);
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-divider {
|
||||||
|
margin-left: var(--termpad);
|
||||||
|
margin-right: var(--termpad);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ts,
|
||||||
|
.termopts,
|
||||||
|
.renderer {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.renderer .renderer-icon {
|
||||||
margin-right: 0.5em;
|
margin-right: 0.5em;
|
||||||
fill: var(--line-svg-fill-color);
|
}
|
||||||
|
|
||||||
|
.metapart-mono {
|
||||||
|
margin-left: 8px;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings {
|
|
||||||
display: none;
|
|
||||||
margin-left: 0.5em;
|
|
||||||
cursor: pointer;
|
|
||||||
width: 1em;
|
|
||||||
height: 1em;
|
|
||||||
border-radius: 50%;
|
|
||||||
line-height: 1em;
|
|
||||||
svg {
|
|
||||||
fill: var(--line-svg-fill-color);
|
|
||||||
&:hover {
|
|
||||||
fill: var(--line-svg-hover-fill-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: var(--term-text-white);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.meta-cmdtext {
|
|
||||||
color: var(--term-bright-white);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cmdtext-expanded-wrapper {
|
|
||||||
padding-left: 6px;
|
|
||||||
overflow-y: auto;
|
|
||||||
max-height: 60px;
|
|
||||||
border-left: 2px solid #333;
|
|
||||||
margin-left: 3px;
|
|
||||||
|
|
||||||
.cmdtext-expanded {
|
.cmdtext-expanded {
|
||||||
|
overflow: auto;
|
||||||
|
max-height: calc(var(--termlineheight) * 3.3);
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
|
color: var(--term-bright-white);
|
||||||
|
font-weight: bold;
|
||||||
|
width: calc(100% - var(--termpad) * 2);
|
||||||
|
|
||||||
color: var(--term-text-white);
|
&.is-multiline {
|
||||||
padding-bottom: 5px;
|
border-left: 2px solid #333;
|
||||||
|
margin-left: 3px;
|
||||||
|
padding-left: 6px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+234
-273
File diff suppressed because it is too large
Load Diff
@@ -28,12 +28,16 @@
|
|||||||
font-size: var(--termfontsize);
|
font-size: var(--termfontsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.lines-spacer + .line-sep-labeled {
|
||||||
|
margin-top: var(--termpad);
|
||||||
|
}
|
||||||
|
|
||||||
.line-sep-labeled::before,
|
.line-sep-labeled::before,
|
||||||
.line-sep-labeled::after {
|
.line-sep-labeled::after {
|
||||||
content: "";
|
content: "";
|
||||||
height: 1px;
|
height: 1px;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
background-color: var(--app-text-color);
|
background-color: var(--term-gray);
|
||||||
}
|
}
|
||||||
|
|
||||||
.line-sep-labeled::before {
|
.line-sep-labeled::before {
|
||||||
|
|||||||
+6
-2
@@ -9,6 +9,8 @@
|
|||||||
--termfontsize: 12px;
|
--termfontsize: 12px;
|
||||||
--termlineheight: 15px;
|
--termlineheight: 15px;
|
||||||
--termpad: 7px; // padding value (scaled to termfontsize)
|
--termpad: 7px; // padding value (scaled to termfontsize)
|
||||||
|
--termfontsize-sm: 10px;
|
||||||
|
--termlineheight-sm: 13px;
|
||||||
|
|
||||||
// other fonts
|
// other fonts
|
||||||
--fixed-font: "Martian Mono", sans-serif;
|
--fixed-font: "Martian Mono", sans-serif;
|
||||||
@@ -43,6 +45,8 @@
|
|||||||
--app-border-color: rgb(51, 51, 51);
|
--app-border-color: rgb(51, 51, 51);
|
||||||
--app-maincontent-bg-color: #333;
|
--app-maincontent-bg-color: #333;
|
||||||
--app-border-radius: 10px;
|
--app-border-radius: 10px;
|
||||||
|
--app-panel-bg-color: rgba(21, 23, 21, 1);
|
||||||
|
--app-panel-bg-color-dev: rgb(21, 23, 48);
|
||||||
|
|
||||||
// global generic colors
|
// global generic colors
|
||||||
--app-black: rgb(0, 0, 0);
|
--app-black: rgb(0, 0, 0);
|
||||||
@@ -150,8 +154,6 @@
|
|||||||
--hotkey-text-color: rgb(195, 200, 194);
|
--hotkey-text-color: rgb(195, 200, 194);
|
||||||
|
|
||||||
// sidebar colors
|
// sidebar colors
|
||||||
--sidebar-bg-color: rgba(21, 23, 21, 1);
|
|
||||||
--sidebar-dev-bg-color: rgb(21, 23, 48);
|
|
||||||
--sidebar-settings-color: rgb(255, 255, 255);
|
--sidebar-settings-color: rgb(255, 255, 255);
|
||||||
--sidebar-separator-color: var(--app-border-color);
|
--sidebar-separator-color: var(--app-border-color);
|
||||||
--sidebar-highlight-color: rgba(241, 246, 243, 0.08);
|
--sidebar-highlight-color: rgba(241, 246, 243, 0.08);
|
||||||
@@ -186,6 +188,8 @@
|
|||||||
--line-status-success-fill: rgb(88, 193, 66);
|
--line-status-success-fill: rgb(88, 193, 66);
|
||||||
--line-status-error-fill: #cc0000;
|
--line-status-error-fill: #cc0000;
|
||||||
--line-status-warning-fill: #ffa500;
|
--line-status-warning-fill: #ffa500;
|
||||||
|
--line-actions-inactive-color: rgba(255, 255, 255, 0.5);
|
||||||
|
--line-actions-active-color: rgba(255, 255, 255, 1);
|
||||||
|
|
||||||
// view colors
|
// view colors
|
||||||
// todo: bookmarks is a view, colors must be unified with --view* colors
|
// todo: bookmarks is a view, colors must be unified with --view* colors
|
||||||
|
|||||||
@@ -324,7 +324,7 @@ class MainSideBar extends React.Component<MainSideBarProps, {}> {
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
className="middle hideScrollbarUntillHover"
|
className="middle scrollbar-hide-until-hover"
|
||||||
id="sidebar-middle"
|
id="sidebar-middle"
|
||||||
style={{
|
style={{
|
||||||
maxHeight: `calc(100vh - ${this.middleHeightSubtractor.get()}px)`,
|
maxHeight: `calc(100vh - ${this.middleHeightSubtractor.get()}px)`,
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ class ScreenTabs extends React.Component<
|
|||||||
{/* Inner container ensures that hovering over the scrollbar doesn't trigger the hover effect on the tabs. This prevents weird flickering of the icons when the mouse is moved over the scrollbar. */}
|
{/* Inner container ensures that hovering over the scrollbar doesn't trigger the hover effect on the tabs. This prevents weird flickering of the icons when the mouse is moved over the scrollbar. */}
|
||||||
<div
|
<div
|
||||||
key="container-inner"
|
key="container-inner"
|
||||||
className="screen-tabs-container-inner no-highlight-scrollbar hideScrollbarUntillHover"
|
className="screen-tabs-container-inner no-highlight-scrollbar scrollbar-hide-until-hover"
|
||||||
>
|
>
|
||||||
<Reorder.Group
|
<Reorder.Group
|
||||||
className="screen-tabs"
|
className="screen-tabs"
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ class Cmd {
|
|||||||
return this.data.get().restartts;
|
return this.data.get().restartts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getDurationMs(): number {
|
||||||
|
return this.data.get().durationms;
|
||||||
|
}
|
||||||
|
|
||||||
getAsWebCmd(lineid: string): WebCmd {
|
getAsWebCmd(lineid: string): WebCmd {
|
||||||
let cmd = this.data.get();
|
let cmd = this.data.get();
|
||||||
let remote = this.model.getRemote(this.remote.remoteid);
|
let remote = this.model.getRemote(this.remote.remoteid);
|
||||||
|
|||||||
+5
-1
@@ -353,12 +353,16 @@ class Model {
|
|||||||
if (fontSize > appconst.MaxFontSize) {
|
if (fontSize > appconst.MaxFontSize) {
|
||||||
fontSize = appconst.MaxFontSize;
|
fontSize = appconst.MaxFontSize;
|
||||||
}
|
}
|
||||||
|
const fontSizeSm = fontSize - 2;
|
||||||
const monoFontSize = getMonoFontSize(fontSize);
|
const monoFontSize = getMonoFontSize(fontSize);
|
||||||
|
const monoFontSizeSm = getMonoFontSize(fontSizeSm);
|
||||||
mobx.action(() => {
|
mobx.action(() => {
|
||||||
this.bumpRenderVersion();
|
this.bumpRenderVersion();
|
||||||
this.setStyleVar("--termfontsize", fontSize + "px");
|
this.setStyleVar("--termfontsize", fontSize + "px");
|
||||||
this.setStyleVar("--termlineheight", monoFontSize.height + "px");
|
this.setStyleVar("--termlineheight", monoFontSize.height + "px");
|
||||||
this.setStyleVar("--termpad", Math.floor(monoFontSize.height / 2) + "px");
|
this.setStyleVar("--termpad", monoFontSize.pad + "px");
|
||||||
|
this.setStyleVar("--termfontsize-sm", fontSizeSm + "px");
|
||||||
|
this.setStyleVar("--termlineheight-sm", monoFontSizeSm.height + "px");
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
import * as mobx from "mobx";
|
import * as mobx from "mobx";
|
||||||
import { Terminal } from "xterm";
|
import { Terminal } from "xterm";
|
||||||
|
import type { ITheme } from "xterm";
|
||||||
//TODO: replace with `@xterm/addon-web-links` when it's available as stable
|
//TODO: replace with `@xterm/addon-web-links` when it's available as stable
|
||||||
import { WebLinksAddon } from "xterm-addon-web-links";
|
import { WebLinksAddon } from "xterm-addon-web-links";
|
||||||
import { sprintf } from "sprintf-js";
|
import { sprintf } from "sprintf-js";
|
||||||
@@ -10,7 +11,6 @@ import { boundMethod } from "autobind-decorator";
|
|||||||
import { windowWidthToCols, windowHeightToRows } from "@/util/textmeasure";
|
import { windowWidthToCols, windowHeightToRows } from "@/util/textmeasure";
|
||||||
import { boundInt } from "@/util/util";
|
import { boundInt } from "@/util/util";
|
||||||
import { GlobalModel } from "@/models";
|
import { GlobalModel } from "@/models";
|
||||||
import { getTheme } from "@/common/themes/themes";
|
|
||||||
|
|
||||||
type DataUpdate = {
|
type DataUpdate = {
|
||||||
data: Uint8Array;
|
data: Uint8Array;
|
||||||
@@ -36,6 +36,30 @@ type TermWrapOpts = {
|
|||||||
onUpdateContentHeight: (termContext: RendererContext, height: number) => void;
|
onUpdateContentHeight: (termContext: RendererContext, height: number) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getThemeFromCSSVars(): ITheme {
|
||||||
|
let theme: ITheme = {};
|
||||||
|
let rootStyle = getComputedStyle(document.documentElement);
|
||||||
|
theme.foreground = rootStyle.getPropertyValue("--term-white");
|
||||||
|
theme.background = rootStyle.getPropertyValue("--term-black");
|
||||||
|
theme.black = rootStyle.getPropertyValue("--term-black");
|
||||||
|
theme.red = rootStyle.getPropertyValue("--term-red");
|
||||||
|
theme.green = rootStyle.getPropertyValue("--term-green");
|
||||||
|
theme.yellow = rootStyle.getPropertyValue("--term-yellow");
|
||||||
|
theme.blue = rootStyle.getPropertyValue("--term-blue");
|
||||||
|
theme.magenta = rootStyle.getPropertyValue("--term-magenta");
|
||||||
|
theme.cyan = rootStyle.getPropertyValue("--term-cyan");
|
||||||
|
theme.white = rootStyle.getPropertyValue("--term-white");
|
||||||
|
theme.brightBlack = rootStyle.getPropertyValue("--term-bright-black");
|
||||||
|
theme.brightRed = rootStyle.getPropertyValue("--term-bright-red");
|
||||||
|
theme.brightGreen = rootStyle.getPropertyValue("--term-bright-green");
|
||||||
|
theme.brightYellow = rootStyle.getPropertyValue("--term-bright-yellow");
|
||||||
|
theme.brightBlue = rootStyle.getPropertyValue("--term-bright-blue");
|
||||||
|
theme.brightMagenta = rootStyle.getPropertyValue("--term-bright-magenta");
|
||||||
|
theme.brightCyan = rootStyle.getPropertyValue("--term-bright-cyan");
|
||||||
|
theme.brightWhite = rootStyle.getPropertyValue("--term-bright-white");
|
||||||
|
return theme;
|
||||||
|
}
|
||||||
|
|
||||||
// cmd-instance
|
// cmd-instance
|
||||||
class TermWrap {
|
class TermWrap {
|
||||||
terminal: any;
|
terminal: any;
|
||||||
@@ -86,13 +110,13 @@ class TermWrap {
|
|||||||
let cols = windowWidthToCols(opts.winSize.width, opts.fontSize);
|
let cols = windowWidthToCols(opts.winSize.width, opts.fontSize);
|
||||||
this.termSize = { rows: opts.termOpts.rows, cols: cols };
|
this.termSize = { rows: opts.termOpts.rows, cols: cols };
|
||||||
}
|
}
|
||||||
const { terminal } = getTheme();
|
let theme = getThemeFromCSSVars();
|
||||||
this.terminal = new Terminal({
|
this.terminal = new Terminal({
|
||||||
rows: this.termSize.rows,
|
rows: this.termSize.rows,
|
||||||
cols: this.termSize.cols,
|
cols: this.termSize.cols,
|
||||||
fontSize: opts.fontSize,
|
fontSize: opts.fontSize,
|
||||||
fontFamily: opts.fontFamily,
|
fontFamily: opts.fontFamily,
|
||||||
theme: { foreground: terminal.foreground, background: terminal.background },
|
theme: theme,
|
||||||
});
|
});
|
||||||
this.terminal.loadAddon(
|
this.terminal.loadAddon(
|
||||||
new WebLinksAddon((e, uri) => {
|
new WebLinksAddon((e, uri) => {
|
||||||
|
|||||||
@@ -268,6 +268,26 @@ function getDateStr(d: Date): string {
|
|||||||
return dowStr + " " + yearStr + "-" + monthStr + "-" + dayStr;
|
return dowStr + " " + yearStr + "-" + monthStr + "-" + dayStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatDuration(ms: number): string {
|
||||||
|
if (ms < 1000) {
|
||||||
|
return ms + "ms";
|
||||||
|
}
|
||||||
|
if (ms < 10000) {
|
||||||
|
return (ms / 1000).toFixed(2) + "s";
|
||||||
|
}
|
||||||
|
if (ms < 100000) {
|
||||||
|
return (ms / 1000).toFixed(1) + "s";
|
||||||
|
}
|
||||||
|
if (ms < 60 * 60 * 1000) {
|
||||||
|
let mins = Math.floor(ms / 60000);
|
||||||
|
let secs = Math.floor((ms % 60000) / 1000);
|
||||||
|
return mins + "m" + secs + "s";
|
||||||
|
}
|
||||||
|
let hours = Math.floor(ms / (60 * 60 * 1000));
|
||||||
|
let mins = Math.floor((ms % (60 * 60 * 1000)) / 60000);
|
||||||
|
return hours + "h" + mins + "m";
|
||||||
|
}
|
||||||
|
|
||||||
function getRemoteConnVal(r: RemoteType): number {
|
function getRemoteConnVal(r: RemoteType): number {
|
||||||
switch (r.status) {
|
switch (r.status) {
|
||||||
case "connected":
|
case "connected":
|
||||||
@@ -400,4 +420,5 @@ export {
|
|||||||
getRemoteName,
|
getRemoteName,
|
||||||
ces,
|
ces,
|
||||||
fireAndForget,
|
fireAndForget,
|
||||||
|
formatDuration,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user