Compare commits

..

1 Commits

Author SHA1 Message Date
sawka f29e277f96 add Shift:Cmd '[' and ']' for switching tabs 2024-04-01 10:56:38 -07:00
92 changed files with 1779 additions and 4780 deletions
+2 -2
View File
@@ -194,11 +194,11 @@
},
{
"command": "app:selectTabLeft",
"keys": ["Cmd:["]
"keys": ["Cmd:[", "Shift:Cmd:["]
},
{
"command": "app:selectTabRight",
"keys": ["Cmd:]"]
"keys": ["Cmd:]", "Shift:Cmd:]"]
},
{
"command": "app:selectWorkspace-1",
+1 -4
View File
@@ -18,7 +18,6 @@
"appId": "dev.commandline.waveterm"
},
"dependencies": {
"@lexical/react": "^0.14.3",
"@monaco-editor/react": "^4.5.1",
"@table-nav/core": "^0.0.7",
"@table-nav/react": "^0.0.7",
@@ -32,7 +31,6 @@
"electron-squirrel-startup": "^1.0.0",
"electron-updater": "^6.1.8",
"framer-motion": "^10.16.16",
"lexical": "^0.14.3",
"mobx": "6.12",
"mobx-react": "^7.5.0",
"monaco-editor": "^0.44.0",
@@ -43,7 +41,6 @@
"papaparse": "^5.4.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-frame-component": "^5.2.6",
"react-markdown": "^9.0.0",
"remark": "^15.0.1",
"remark-gfm": "^4.0.0",
@@ -53,8 +50,8 @@
"uuid": "^9.0.0",
"winston": "^3.8.2",
"xterm": "^5.3.0",
"xterm-addon-serialize": "^0.11.0",
"xterm-addon-web-links": "^0.9.0",
"xterm-addon-serialize": "^0.11.0",
"xterm-addon-webgl": "^0.16.0"
},
"devDependencies": {
+15 -17
View File
@@ -42,19 +42,16 @@
--app-bg-color: black;
--app-accent-color: rgb(88, 193, 66);
--app-accent-bg-color: rgba(88, 193, 66, 0.25);
--app-accent-bg-darker-color: rgba(88, 193, 66, 0.5);
--app-text-color: rgb(211, 215, 207);
--app-text-primary-color: rgb(255, 255, 255);
--app-text-secondary-color: rgb(195, 200, 194);
--app-text-disabled-color: rgb(173, 173, 173);
--app-text-bg-color: rgb(23, 23, 23);
--app-text-bg-disabled-color: rgb(51, 51, 51);
--app-border-color: rgb(51, 51, 51);
--app-maincontent-bg-color: rgb(51, 51, 51);
--app-maincontent-bg-color: #333;
--app-panel-bg-color: rgba(21, 23, 21, 1);
--app-panel-bg-color-dev: rgb(21, 23, 48);
--app-icon-color: rgb(139, 145, 138);
--app-icon-hover-color: rgb(255, 255, 255);
--app-icon-hover-color: #fff;
--app-selected-mask-color: rgba(255, 255, 255, 0.06);
/* global status colors */
@@ -125,18 +122,18 @@
/* line colors */
--line-sidebar-message-color: rgb(196, 160, 0);
--line-background: var(--app-panel-bg-color);
--line-avatar-color: rgb(236, 238, 236);
--line-background: rgba(21, 23, 21, 1);
--line-avatar-color: #eceeec;
--line-text-color: rgb(211, 215, 207);
--line-svg-fill-color: rgb(150, 152, 150);
--line-svg-hover-fill-color: rgb(236, 238, 236);
--line-svg-hover-fill-color: #eceeec;
--line-separator-color: rgb(126, 126, 126);
--line-error-color: var(--app-error-color);
--line-warning-color: var(--app-warning-color);
--line-base-soft-blue-color: rgb(114, 159, 207);
--line-base-soft-blue-color: #729fcf;
--line-active-border-color: var(--app-accent-color);
--line-selected-bg-color: rgba(255, 255, 255, 0.05);
--line-selected-border-left-color: rgb(119, 119, 119);
--line-selected-border-left-color: #777777;
--line-selected-error-border-color: rgba(204, 0, 0, 0.8);
--line-selected-error-bg-color: rgb(19, 4, 3);
--line-error-bg-color: rgba(200, 0, 0, 0.1);
@@ -155,21 +152,22 @@
/* table colors */
--table-border-color: rgba(241, 246, 243, 0.15);
--table-thead-border-top-color: rgba(250, 250, 250, 0.1);
--table-thead-bright-border-color: rgb(204, 204, 204);
--table-thead-bright-border-color: #ccc;
--table-thead-bg-color: rgba(250, 250, 250, 0.02);
--table-tr-border-bottom-color: rgba(241, 246, 243, 0.15);
--table-tr-hover-bg-color: rgba(255, 255, 255, 0.06);
--table-tr-selected-bg-color: rgb(34, 34, 34);
--table-tr-selected-hover-bg-color: var(--app-maincontent-bg-color);
--table-tr-selected-bg-color: #222;
--table-tr-selected-hover-bg-color: #333;
/* cmdinput colors */
--cmdinput-bg-color: var(--app-text-bg-color);
--cmdinput-textarea-bg-color: #171717;
--cmdinput-text-error-color: var(--term-red);
--cmdinput-history-item-error-color: var(--term-bright-red);
--cmdinput-history-item-selected-error-color: var(--term-bright-red);
--cmdinput-button-bg-color: var(--tab-green);
--cmdinput-disabled-bg-color: var(--app-text-bg-disabled-color);
--cmdinput-history-bg-color: var(--app-bg-color);
--cmdinput-button-bg-color: rgb(88, 193, 66);
--cmdinput-comment-button-bg-color: rgb(57, 113, 255);
--cmdinput-disabled-icon-color: rgb(76, 81, 75, 1);
--cmdinput-history-bg-color: rgb(21, 23, 21, 1);
/* screen view color */
--screen-view-text-caption-color: rgb(139, 145, 138);
+17 -15
View File
@@ -5,20 +5,20 @@
@import url("./term-light.css");
:root {
--app-bg-color: rgb(254, 254, 254);
--app-bg-color: #fefefe;
--app-accent-color: rgb(75, 166, 57);
--app-accent-bg-color: rgba(75, 166, 57, 0.2);
--app-text-color: rgb(0, 0, 0);
--app-text-color: #000;
--app-text-primary-color: rgb(0, 0, 0, 0.9);
--app-text-secondary-color: rgb(0, 0, 0, 0.7);
--app-border-color: rgb(139 145 138);
--app-panel-bg-color: rgb(224, 224, 224);
--app-panel-bg-color-dev: rgb(224, 224, 224);
--app-icon-color: rgb(110, 110, 110);
--app-icon-hover-color: rgb(80, 80, 80);
--app-panel-bg-color: #e0e0e0;
--app-panel-bg-color-dev: #e0e0e0;
--app-icon-color: rgb(80, 80, 80);
--app-icon-hover-color: rgb(100, 100, 100);
--app-selected-mask-color: rgba(0, 0, 0, 0.06);
--input-bg-color: rgb(238, 238, 238);
--input-bg-color: #eeeeee;
/* tab color */
--tab-white: rgb(0, 0, 0, 0.6);
@@ -30,8 +30,8 @@
--table-thead-bg-color: rgba(250, 250, 250, 0.15);
--table-tr-border-bottom-color: rgba(0, 0, 0, 0.15);
--table-tr-hover-bg-color: rgba(0, 0, 0, 0.15);
--table-tr-selected-bg-color: rgb(221, 221, 221);
--table-tr-selected-hover-bg-color: rgb(204, 204, 204);
--table-tr-selected-bg-color: #dddddd;
--table-tr-selected-hover-bg-color: #cccccc;
/* form colors */
--form-element-border-color: rgba(0, 0, 0, 0.3);
@@ -41,8 +41,8 @@
--form-element-label-color: rgba(0, 0, 0, 0.6);
--form-element-secondary-color: rgba(0, 0, 0, 0.09);
--form-element-icon-color: rgb(0, 0, 0, 0.6);
--form-element-disabled-text-color: rgb(183, 183, 183);
--form-element-placeholder-color: rgb(183, 183, 183);
--form-element-disabled-text-color: #b7b7b7;
--form-element-placeholder-color: #b7b7b7;
--markdown-bg-color: rgb(0, 0, 0, 0.1);
@@ -50,6 +50,8 @@
--modal-header-bottom-border-color: rgba(0, 0, 0, 0.3);
/* cmd input */
--cmdinput-textarea-bg-color: rgba(0, 0, 0, 0.1);
--cmdinput-textarea-border-color: var(--form-element-border-color);
/* scroll colors */
--scrollbar-background-color: var(--app-bg-color);
@@ -62,15 +64,15 @@
--line-actions-inactive-color: rgba(0, 0, 0, 0.3);
--line-actions-active-color: rgba(0, 0, 0, 1);
--logo-button-hover-bg-color: rgb(240, 240, 240);
--logo-button-hover-bg-color: #f0f0f0;
--xterm-viewport-border-color: rgba(0, 0, 0, 0.3);
--datepicker-cell-hover-bg-color: rgb(240, 240, 240);
--datepicker-cell-hover-bg-color: #f0f0f0;
--datepicker-cell-other-text-color: rgba(0, 0, 0, 0.3);
--datepicker-header-fade-color: rgba(0, 0, 0, 0.4);
--datepicker-year-header-bg-color: rgb(245, 245, 245);
--datepicker-year-header-border-color: rgb(220, 220, 220);
--datepicker-year-header-bg-color: #f5f5f5;
--datepicker-year-header-border-color: #dcdcdc;
/* toggle colors */
--toggle-thumb-color: var(--app-bg-color);
+1 -1
View File
@@ -146,7 +146,7 @@ class App extends React.Component<{}, {}> {
<If condition={GlobalModel.isDev && rightSidebarCollapsed && activeMainView == "session"}>
<div className="right-sidebar-triggers">
<Button className="secondary ghost right-sidebar-trigger" onClick={this.openRightSidebar}>
<i className="fa-sharp fa-solid fa-sidebar-flip"></i>
<i className="fa-sharp fa-regular fa-lightbulb"></i>
</Button>
</div>
</If>
-4
View File
@@ -64,7 +64,3 @@ export enum StatusIndicatorLevel {
// matches packet.go
export const ErrorCode_InvalidCwd = "ERRCWD";
export const InputAuxView_History = "history";
export const InputAuxView_Info = "info";
export const InputAuxView_AIChat = "aichat";
+3 -32
View File
@@ -6,10 +6,9 @@ import * as mobxReact from "mobx-react";
import * as mobx from "mobx";
import { boundMethod } from "autobind-decorator";
import { If } from "tsx-control-statements/components";
import { GlobalModel, GlobalCommandRunner, RemotesModel } from "@/models";
import { GlobalModel, GlobalCommandRunner, RemotesModel, getApi } from "@/models";
import { Toggle, InlineSettingsTextEdit, SettingsError, Dropdown } from "@/common/elements";
import { commandRtnHandler, isBlank } from "@/util/util";
import { getTermThemes } from "@/util/themeutil";
import * as appconst from "@/app/appconst";
import "./clientsettings.less";
@@ -70,20 +69,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
return;
}
const prtn = GlobalCommandRunner.setTheme(themeSource, false);
GlobalModel.getElectronApi().setNativeThemeSource(themeSource);
commandRtnHandler(prtn, this.errorMessage);
}
@boundMethod
handleChangeTermTheme(theme: string): void {
// For global terminal theme, the key is global, otherwise it's either
// sessionId or screenId.
const currTheme = GlobalModel.getTermTheme()["global"];
if (currTheme == theme) {
return;
}
const prtn = GlobalCommandRunner.setGlobalTermTheme(theme, false);
getApi().setNativeThemeSource(themeSource);
commandRtnHandler(prtn, this.errorMessage);
}
@@ -107,7 +93,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
prtn = GlobalCommandRunner.releaseCheckAutoOff(false);
}
commandRtnHandler(prtn, this.errorMessage);
GlobalModel.getElectronApi().changeAutoUpdate(val);
getApi().changeAutoUpdate(val);
}
getFontSizes(): DropdownItem[] {
@@ -207,8 +193,6 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
const curFontSize = GlobalModel.getTermFontSize();
const curFontFamily = GlobalModel.getTermFontFamily();
const curTheme = GlobalModel.getThemeSource();
const termThemes = getTermThemes(GlobalModel.termThemes, "Wave Default");
const currTermTheme = GlobalModel.getTermTheme()["global"] ?? termThemes[0].label;
return (
<MainView className="clientsettings-view" title="Client Settings" onClose={this.handleClose}>
@@ -249,19 +233,6 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
/>
</div>
</div>
<If condition={termThemes.length > 0}>
<div className="settings-field">
<div className="settings-label">Terminal Theme</div>
<div className="settings-input">
<Dropdown
className="terminal-theme-dropdown"
options={termThemes}
defaultValue={currTermTheme}
onChange={this.handleChangeTermTheme}
/>
</div>
</div>
</If>
<div className="settings-field">
<div className="settings-label">Client ID</div>
<div className="settings-input">{cdata.clientid}</div>
+4 -6
View File
@@ -6,7 +6,7 @@ import "./button.less";
interface ButtonProps {
children: React.ReactNode;
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
onClick?: () => void;
disabled?: boolean;
leftIcon?: React.ReactNode;
rightIcon?: React.ReactNode;
@@ -14,7 +14,6 @@ interface ButtonProps {
autoFocus?: boolean;
className?: string;
termInline?: boolean;
title?: string;
}
class Button extends React.Component<ButtonProps> {
@@ -24,14 +23,14 @@ class Button extends React.Component<ButtonProps> {
};
@boundMethod
handleClick(e) {
handleClick() {
if (this.props.onClick && !this.props.disabled) {
this.props.onClick(e);
this.props.onClick();
}
}
render() {
const { leftIcon, rightIcon, children, disabled, style, autoFocus, termInline, className, title } = this.props;
const { leftIcon, rightIcon, children, disabled, style, autoFocus, termInline, className } = this.props;
return (
<button
@@ -40,7 +39,6 @@ class Button extends React.Component<ButtonProps> {
disabled={disabled}
style={style}
autoFocus={autoFocus}
title={title}
>
{leftIcon && <span className="icon-left">{leftIcon}</span>}
{children}
-7
View File
@@ -1,7 +0,0 @@
.copy-button {
padding: 5px 5px;
.fa-check {
color: var(--app-success-color);
}
}
-51
View File
@@ -1,51 +0,0 @@
import * as React from "react";
import { Button } from "./button";
import { boundMethod } from "autobind-decorator";
import * as mobxReact from "mobx-react";
import * as mobx from "mobx";
import "./copybutton.less";
type CopyButtonProps = {
title: string;
onClick: (e: React.MouseEvent<HTMLButtonElement>) => void;
};
@mobxReact.observer
class CopyButton extends React.Component<CopyButtonProps, {}> {
isCopied: OV<boolean> = mobx.observable.box(false, { name: "isCopied" });
@boundMethod
handleOnClick(e: React.MouseEvent<HTMLButtonElement>) {
if (this.isCopied.get()) {
return;
}
mobx.action(() => {
this.isCopied.set(true);
})();
setTimeout(() => {
mobx.action(() => {
this.isCopied.set(false);
})();
}, 2000);
if (this.props.onClick) {
this.props.onClick(e);
}
}
render() {
const { title, onClick } = this.props;
const isCopied = this.isCopied.get();
return (
<Button onClick={this.handleOnClick} className="copy-button secondary ghost" title={title}>
{isCopied ? (
<i className="fa-sharp fa-solid fa-check"></i>
) : (
<i className="fa-sharp fa-solid fa-copy"></i>
)}
</Button>
);
}
}
export { CopyButton };
-1
View File
@@ -18,4 +18,3 @@ export { Toggle } from "./toggle";
export { Tooltip } from "./tooltip";
export { TabIcon } from "./tabicon";
export { DatePicker } from "./datepicker";
export { CopyButton } from "./copybutton";
+5 -22
View File
@@ -7,10 +7,8 @@ import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import cn from "classnames";
import { GlobalModel } from "@/models";
import { v4 as uuidv4 } from "uuid";
import "./markdown.less";
import { boundMethod } from "autobind-decorator";
function LinkRenderer(props: any): any {
let newUrl = "https://extern?" + encodeURIComponent(props.href);
@@ -30,17 +28,14 @@ function CodeRenderer(props: any): any {
}
@mobxReact.observer
class CodeBlockMarkdown extends React.Component<
{ children: React.ReactNode; codeSelectSelectedIndex?: number; uuid: string },
{}
> {
class CodeBlockMarkdown extends React.Component<{ children: React.ReactNode; codeSelectSelectedIndex?: number }, {}> {
blockIndex: number;
blockRef: React.RefObject<HTMLPreElement>;
constructor(props) {
super(props);
this.blockRef = React.createRef();
this.blockIndex = GlobalModel.inputModel.addCodeBlockToCodeSelect(this.blockRef, this.props.uuid);
this.blockIndex = GlobalModel.inputModel.addCodeBlockToCodeSelect(this.blockRef);
}
render() {
@@ -67,21 +62,9 @@ class Markdown extends React.Component<
{ text: string; style?: any; extraClassName?: string; codeSelect?: boolean },
{}
> {
curUuid: string;
constructor(props) {
super(props);
this.curUuid = uuidv4();
}
@boundMethod
CodeBlockRenderer(props: any, codeSelect: boolean, codeSelectIndex: number, curUuid: string): any {
CodeBlockRenderer(props: any, codeSelect: boolean, codeSelectIndex: number): any {
if (codeSelect) {
return (
<CodeBlockMarkdown codeSelectSelectedIndex={codeSelectIndex} uuid={curUuid}>
{props.children}
</CodeBlockMarkdown>
);
return <CodeBlockMarkdown codeSelectSelectedIndex={codeSelectIndex}>{props.children}</CodeBlockMarkdown>;
} else {
const clickHandler = (e: React.MouseEvent<HTMLElement>) => {
let blockText = (e.target as HTMLElement).innerText;
@@ -107,7 +90,7 @@ class Markdown extends React.Component<
h5: (props) => HeaderRenderer(props, 5),
h6: (props) => HeaderRenderer(props, 6),
code: (props) => CodeRenderer(props),
pre: (props) => this.CodeBlockRenderer(props, codeSelect, curCodeSelectIndex, this.curUuid),
pre: (props) => this.CodeBlockRenderer(props, codeSelect, curCodeSelectIndex),
};
return (
<div className={cn("markdown content", this.props.extraClassName)} style={this.props.style}>
+2 -2
View File
@@ -5,7 +5,7 @@ import * as React from "react";
import * as mobxReact from "mobx-react";
import * as mobx from "mobx";
import { boundMethod } from "autobind-decorator";
import { GlobalModel } from "@/models";
import { GlobalModel, getApi } from "@/models";
import { Modal, LinkButton } from "@/elements";
import * as util from "@/util/util";
import * as appconst from "@/app/appconst";
@@ -26,7 +26,7 @@ class AboutModal extends React.Component<{}, {}> {
@boundMethod
updateApp(): void {
GlobalModel.getElectronApi().installAppUpdate();
getApi().installAppUpdate();
}
@boundMethod
+1 -1
View File
@@ -312,7 +312,7 @@ class CreateRemoteConnModal extends React.Component<{}, {}> {
endDecoration: (
<InputDecoration>
<Tooltip
message={`(Required) The path to your ssh private key file.`}
message={`(Required) The path to your ssh key file.`}
icon={<i className="fa-sharp fa-regular fa-circle-question" />}
>
<i className="fa-sharp fa-regular fa-circle-question" />
+1 -1
View File
@@ -338,7 +338,7 @@ class EditRemoteConnModal extends React.Component<{}, {}> {
endDecoration: (
<InputDecoration>
<Tooltip
message={`(Required) The path to your ssh private key file.`}
message={`(Required) The path to your ssh key file.`}
icon={<i className="fa-sharp fa-regular fa-circle-question" />}
>
<i className="fa-sharp fa-regular fa-circle-question" />
+2 -39
View File
@@ -11,9 +11,8 @@ import { GlobalModel, GlobalCommandRunner, Screen } from "@/models";
import { SettingsError, Modal, Dropdown, Tooltip } from "@/elements";
import * as util from "@/util/util";
import { Button } from "@/elements";
import { If } from "tsx-control-statements/components";
import { commandRtnHandler } from "@/util/util";
import { getTermThemes } from "@/util/themeutil";
import { ReactComponent as GlobeIcon } from "@/assets/icons/globe.svg";
import { ReactComponent as StatusCircleIcon } from "@/assets/icons/statuscircle.svg";
import {
TabColorSelector,
TabIconSelector,
@@ -154,34 +153,11 @@ class ScreenSettingsModal extends React.Component<{}, {}> {
});
}
@boundMethod
handleChangeTermTheme(theme: string): void {
const currTheme = GlobalModel.getTermTheme()[this.screenId];
if (currTheme == theme) {
return;
}
const prtn = GlobalCommandRunner.setScreenTermTheme(this.screenId, theme, false);
commandRtnHandler(prtn, this.errorMessage);
}
@boundMethod
selectRemote(cname: string): void {
let prtn = GlobalCommandRunner.screenSetRemote(cname, true, false);
util.commandRtnHandler(prtn, this.errorMessage);
}
render() {
const screen = this.screen;
if (screen == null) {
return null;
}
let color: string = null;
let icon: string = null;
let index: number = 0;
const curRemote = GlobalModel.getRemote(GlobalModel.getActiveScreen().getCurRemoteInstance().remoteid);
const termThemes = getTermThemes(GlobalModel.termThemes);
const currTermTheme = GlobalModel.getTermTheme()[this.screenId] ?? termThemes[0].label;
return (
<Modal className="screen-settings-modal">
<Modal.Header onClose={this.closeModal} title={`Tab Settings (${screen.name.get()})`} />
@@ -210,19 +186,6 @@ class ScreenSettingsModal extends React.Component<{}, {}> {
<TabIconSelector screen={screen} errorMessage={this.errorMessage} />
</div>
</div>
<If condition={termThemes.length > 0}>
<div className="settings-field">
<div className="settings-label">Terminal Theme</div>
<div className="settings-input">
<Dropdown
className="terminal-theme-dropdown"
options={termThemes}
defaultValue={currTermTheme}
onChange={this.handleChangeTermTheme}
/>
</div>
</div>
</If>
<div className="settings-field">
<div className="settings-label actions-label">
<div>Actions</div>
+2 -30
View File
@@ -6,10 +6,8 @@ import * as mobxReact from "mobx-react";
import * as mobx from "mobx";
import { boundMethod } from "autobind-decorator";
import { GlobalModel, GlobalCommandRunner, Session } from "@/models";
import { If } from "tsx-control-statements/components";
import { Toggle, InlineSettingsTextEdit, SettingsError, Modal, Tooltip, Button, Dropdown } from "@/elements";
import { commandRtnHandler } from "@/util/util";
import { getTermThemes } from "@/util/themeutil";
import { Button } from "@/elements";
import { Toggle, InlineSettingsTextEdit, SettingsError, Modal, Tooltip } from "@/elements";
import * as util from "@/util/util";
import "./sessionsettings.less";
@@ -78,16 +76,6 @@ class SessionSettingsModal extends React.Component<{}, {}> {
});
}
@boundMethod
handleChangeTermTheme(theme: string): void {
const currTheme = GlobalModel.getTermTheme()[this.sessionId];
if (currTheme == theme) {
return;
}
const prtn = GlobalCommandRunner.setSessionTermTheme(this.sessionId, theme, false);
commandRtnHandler(prtn, this.errorMessage);
}
@boundMethod
dismissError(): void {
mobx.action(() => {
@@ -99,9 +87,6 @@ class SessionSettingsModal extends React.Component<{}, {}> {
if (this.session == null) {
return null;
}
const termThemes = getTermThemes(GlobalModel.termThemes);
const currTermTheme = GlobalModel.getTermTheme()[this.sessionId] ?? termThemes[0].label;
return (
<Modal className="session-settings-modal">
<Modal.Header onClose={this.closeModal} title={`Workspace Settings (${this.session.name.get()})`} />
@@ -119,19 +104,6 @@ class SessionSettingsModal extends React.Component<{}, {}> {
/>
</div>
</div>
<If condition={termThemes.length > 0}>
<div className="settings-field">
<div className="settings-label">Terminal Theme</div>
<div className="settings-input">
<Dropdown
className="terminal-theme-dropdown"
options={termThemes}
defaultValue={currTermTheme}
onChange={this.handleChangeTermTheme}
/>
</div>
</div>
</If>
<div className="settings-field">
<div className="settings-label">
<div>Archived</div>
-4
View File
@@ -357,10 +357,6 @@
cursor: pointer;
}
.wave-button {
padding: 5px 5px;
}
visibility: hidden;
}
+29 -14
View File
@@ -14,7 +14,7 @@ import localizedFormat from "dayjs/plugin/localizedFormat";
import customParseFormat from "dayjs/plugin/customParseFormat";
import { Line } from "@/app/line/linecomps";
import { checkKeyPressed, adaptFromReactOrNativeKeyEvent } from "@/util/keyutil";
import { TextField, Dropdown, Button, CopyButton } from "@/elements";
import { TextField, Dropdown, Button, DatePicker } from "@/elements";
import { ReactComponent as ChevronLeftIcon } from "@/assets/icons/history/chevron-left.svg";
import { ReactComponent as ChevronRightIcon } from "@/assets/icons/history/chevron-right.svg";
@@ -22,6 +22,8 @@ import { ReactComponent as RightIcon } from "@/assets/icons/history/right.svg";
import { ReactComponent as SearchIcon } from "@/assets/icons/history/search.svg";
import { ReactComponent as TrashIcon } from "@/assets/icons/trash.svg";
import { ReactComponent as CheckedCheckbox } from "@/assets/icons/checked-checkbox.svg";
import { ReactComponent as CheckIcon } from "@/assets/icons/line/check.svg";
import { ReactComponent as CopyIcon } from "@/assets/icons/history/copy.svg";
import "./history.less";
import { MainView } from "../common/elements/mainview";
@@ -113,6 +115,7 @@ class HistoryCmdStr extends React.Component<
cmdstr: string;
onUse: () => void;
onCopy: () => void;
isCopied: boolean;
fontSize: "normal" | "large";
limitHeight: boolean;
},
@@ -135,17 +138,24 @@ class HistoryCmdStr extends React.Component<
}
render() {
const { cmdstr, fontSize, limitHeight } = this.props;
const { isCopied, cmdstr, fontSize, limitHeight } = this.props;
return (
<div className={cn("cmdstr-code", { "is-large": fontSize == "large" }, { "limit-height": limitHeight })}>
<If condition={isCopied}>
<div key="copied" className="copied-indicator">
<div>copied</div>
</div>
</If>
<div key="code" className="code-div">
<code>{cmdstr}</code>
</div>
<div key="copy" className="actions-block">
<CopyButton onClick={this.handleCopy} title="Copy" />
<Button className="secondary ghost" title="Use Command" onClick={this.handleUse}>
<i className="fa-sharp fa-solid fa-play"></i>
</Button>
<div className="action-item" onClick={this.handleCopy} title="copy">
<CopyIcon className="icon" />
</div>
<div key="use" className="action-item" title="Use Command" onClick={this.handleUse}>
<CheckIcon className="icon" />
</div>
</div>
</div>
);
@@ -180,6 +190,7 @@ class HistoryView extends React.Component<{}, {}> {
tableRszObs: ResizeObserver;
sessionDropdownActive: OV<boolean> = mobx.observable.box(false, { name: "sessionDropdownActive" });
remoteDropdownActive: OV<boolean> = mobx.observable.box(false, { name: "remoteDropdownActive" });
copiedItemId: OV<string> = mobx.observable.box(null, { name: "copiedItemId" });
@boundMethod
handleNext() {
@@ -297,6 +308,7 @@ class HistoryView extends React.Component<{}, {}> {
hvm.setFromDate(null);
return;
}
console.log;
hvm.setFromDate(newDate);
}
@@ -366,6 +378,14 @@ class HistoryView extends React.Component<{}, {}> {
return;
}
navigator.clipboard.writeText(item.cmdstr);
mobx.action(() => {
this.copiedItemId.set(item.historyid);
})();
setTimeout(() => {
mobx.action(() => {
this.copiedItemId.set(null);
})();
}, 600);
}
@boundMethod
@@ -375,7 +395,7 @@ class HistoryView extends React.Component<{}, {}> {
}
mobx.action(() => {
GlobalModel.showSessionView();
GlobalModel.inputModel.updateCmdLine({ str: item.cmdstr, pos: item.cmdstr.length });
GlobalModel.inputModel.setCurLine(item.cmdstr);
setTimeout(() => GlobalModel.inputModel.giveFocus(), 50);
})();
}
@@ -550,6 +570,7 @@ class HistoryView extends React.Component<{}, {}> {
cmdstr={item.cmdstr}
onUse={() => this.handleUse(item)}
onCopy={() => this.handleCopy(item)}
isCopied={this.copiedItemId.get() == item.historyid}
fontSize="normal"
limitHeight={true}
/>
@@ -649,11 +670,6 @@ class LineContainer extends React.Component<{ historyId: string; width: number }
this.line = hvm.getLineById(this.historyItem.lineid);
}
componentDidMount(): void {
GlobalModel.bumpTermRenderVersion();
GlobalModel.termThemeSrcEl.set(null);
}
@boundMethod
handleHeightChange(lineNum: number, newHeight: number, oldHeight: number): void {
return;
@@ -694,9 +710,8 @@ class LineContainer extends React.Component<{ historyId: string; width: number }
ssStr = sprintf("#%s[%s]", session.name.get(), screen.name.get());
canViewInContext = true;
}
const termRenderVersion = GlobalModel.termRenderVersion.get();
return (
<div className="line-container" key={termRenderVersion}>
<div className="line-container">
<If condition={canViewInContext}>
<div className="line-context">
<div title="View in Context" className="vic-btn" onClick={this.viewInContext}>
+9 -3
View File
@@ -106,6 +106,11 @@
}
}
&.top-border {
border-top: 1px solid #777;
padding: 10px;
}
&:hover .meta .termopts {
display: block;
}
@@ -226,12 +231,13 @@
}
.ts,
.termopts {
.termopts,
.renderer {
display: flex;
}
.renderer-icon {
margin-right: 0.2em;
.renderer .renderer-icon {
margin-right: 0.5em;
}
.metapart-mono {

Some files were not shown because too many files have changed in this diff Show More