mirror of
https://github.com/wavetermdev/backup.git
synced 2026-04-22 15:26:58 -07:00
Compare commits
29 Commits
v0.7.2
...
sawka/ijson
| Author | SHA1 | Date | |
|---|---|---|---|
| f1a6dfb249 | |||
| 6319b26924 | |||
| 41fe49a54c | |||
| e044487489 | |||
| 0fdcd27fee | |||
| d923de412a | |||
| 15485d7235 | |||
| 59aef86e77 | |||
| 5353f40a20 | |||
| f86f010a34 | |||
| 73e5515e17 | |||
| 6919dbfb5f | |||
| 1f5309e097 | |||
| af7cc866d3 | |||
| 37e56acf63 | |||
| 70088afdb5 | |||
| 455790416d | |||
| eed234a131 | |||
| 5a6575a393 | |||
| 84cea373a8 | |||
| 181e14f55c | |||
| 1c23701181 | |||
| 0fe767cdf3 | |||
| 097623ab51 | |||
| 9de25e4869 | |||
| a139633375 | |||
| ccc63937b6 | |||
| dc7fc2c823 | |||
| ca5117cda0 |
+4
-1
@@ -18,6 +18,7 @@
|
||||
"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",
|
||||
@@ -31,6 +32,7 @@
|
||||
"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",
|
||||
@@ -41,6 +43,7 @@
|
||||
"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",
|
||||
@@ -50,8 +53,8 @@
|
||||
"uuid": "^9.0.0",
|
||||
"winston": "^3.8.2",
|
||||
"xterm": "^5.3.0",
|
||||
"xterm-addon-web-links": "^0.9.0",
|
||||
"xterm-addon-serialize": "^0.11.0",
|
||||
"xterm-addon-web-links": "^0.9.0",
|
||||
"xterm-addon-webgl": "^0.16.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
+17
-15
@@ -42,16 +42,19 @@
|
||||
--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: #333;
|
||||
--app-maincontent-bg-color: rgb(51, 51, 51);
|
||||
--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: #fff;
|
||||
--app-icon-hover-color: rgb(255, 255, 255);
|
||||
--app-selected-mask-color: rgba(255, 255, 255, 0.06);
|
||||
|
||||
/* global status colors */
|
||||
@@ -122,18 +125,18 @@
|
||||
|
||||
/* line colors */
|
||||
--line-sidebar-message-color: rgb(196, 160, 0);
|
||||
--line-background: rgba(21, 23, 21, 1);
|
||||
--line-avatar-color: #eceeec;
|
||||
--line-background: var(--app-panel-bg-color);
|
||||
--line-avatar-color: rgb(236, 238, 236);
|
||||
--line-text-color: rgb(211, 215, 207);
|
||||
--line-svg-fill-color: rgb(150, 152, 150);
|
||||
--line-svg-hover-fill-color: #eceeec;
|
||||
--line-svg-hover-fill-color: rgb(236, 238, 236);
|
||||
--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: #729fcf;
|
||||
--line-base-soft-blue-color: rgb(114, 159, 207);
|
||||
--line-active-border-color: var(--app-accent-color);
|
||||
--line-selected-bg-color: rgba(255, 255, 255, 0.05);
|
||||
--line-selected-border-left-color: #777777;
|
||||
--line-selected-border-left-color: rgb(119, 119, 119);
|
||||
--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);
|
||||
@@ -152,22 +155,21 @@
|
||||
/* 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: #ccc;
|
||||
--table-thead-bright-border-color: rgb(204, 204, 204);
|
||||
--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: #222;
|
||||
--table-tr-selected-hover-bg-color: #333;
|
||||
--table-tr-selected-bg-color: rgb(34, 34, 34);
|
||||
--table-tr-selected-hover-bg-color: var(--app-maincontent-bg-color);
|
||||
|
||||
/* cmdinput colors */
|
||||
--cmdinput-textarea-bg-color: #171717;
|
||||
--cmdinput-bg-color: var(--app-text-bg-color);
|
||||
--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: 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);
|
||||
--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);
|
||||
|
||||
/* screen view color */
|
||||
--screen-view-text-caption-color: rgb(139, 145, 138);
|
||||
|
||||
+15
-17
@@ -5,20 +5,20 @@
|
||||
@import url("./term-light.css");
|
||||
|
||||
:root {
|
||||
--app-bg-color: #fefefe;
|
||||
--app-bg-color: rgb(254, 254, 254);
|
||||
--app-accent-color: rgb(75, 166, 57);
|
||||
--app-accent-bg-color: rgba(75, 166, 57, 0.2);
|
||||
--app-text-color: #000;
|
||||
--app-text-color: rgb(0, 0, 0);
|
||||
--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: #e0e0e0;
|
||||
--app-panel-bg-color-dev: #e0e0e0;
|
||||
--app-icon-color: rgb(80, 80, 80);
|
||||
--app-icon-hover-color: rgb(100, 100, 100);
|
||||
--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-selected-mask-color: rgba(0, 0, 0, 0.06);
|
||||
|
||||
--input-bg-color: #eeeeee;
|
||||
--input-bg-color: rgb(238, 238, 238);
|
||||
|
||||
/* 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: #dddddd;
|
||||
--table-tr-selected-hover-bg-color: #cccccc;
|
||||
--table-tr-selected-bg-color: rgb(221, 221, 221);
|
||||
--table-tr-selected-hover-bg-color: rgb(204, 204, 204);
|
||||
|
||||
/* 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: #b7b7b7;
|
||||
--form-element-placeholder-color: #b7b7b7;
|
||||
--form-element-disabled-text-color: rgb(183, 183, 183);
|
||||
--form-element-placeholder-color: rgb(183, 183, 183);
|
||||
|
||||
--markdown-bg-color: rgb(0, 0, 0, 0.1);
|
||||
|
||||
@@ -50,8 +50,6 @@
|
||||
--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);
|
||||
@@ -64,15 +62,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: #f0f0f0;
|
||||
--logo-button-hover-bg-color: rgb(240, 240, 240);
|
||||
|
||||
--xterm-viewport-border-color: rgba(0, 0, 0, 0.3);
|
||||
|
||||
--datepicker-cell-hover-bg-color: #f0f0f0;
|
||||
--datepicker-cell-hover-bg-color: rgb(240, 240, 240);
|
||||
--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: #f5f5f5;
|
||||
--datepicker-year-header-border-color: #dcdcdc;
|
||||
--datepicker-year-header-bg-color: rgb(245, 245, 245);
|
||||
--datepicker-year-header-border-color: rgb(220, 220, 220);
|
||||
|
||||
/* toggle colors */
|
||||
--toggle-thumb-color: var(--app-bg-color);
|
||||
|
||||
+1
-1
@@ -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-regular fa-lightbulb"></i>
|
||||
<i className="fa-sharp fa-solid fa-sidebar-flip"></i>
|
||||
</Button>
|
||||
</div>
|
||||
</If>
|
||||
|
||||
@@ -64,3 +64,7 @@ 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";
|
||||
|
||||
@@ -6,9 +6,10 @@ 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, getApi } from "@/models";
|
||||
import { GlobalModel, GlobalCommandRunner, RemotesModel } 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";
|
||||
@@ -69,7 +70,20 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
||||
return;
|
||||
}
|
||||
const prtn = GlobalCommandRunner.setTheme(themeSource, false);
|
||||
getApi().setNativeThemeSource(themeSource);
|
||||
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);
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
}
|
||||
|
||||
@@ -93,7 +107,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
||||
prtn = GlobalCommandRunner.releaseCheckAutoOff(false);
|
||||
}
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
getApi().changeAutoUpdate(val);
|
||||
GlobalModel.getElectronApi().changeAutoUpdate(val);
|
||||
}
|
||||
|
||||
getFontSizes(): DropdownItem[] {
|
||||
@@ -193,6 +207,8 @@ 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}>
|
||||
@@ -233,6 +249,19 @@ 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>
|
||||
|
||||
@@ -6,7 +6,7 @@ import "./button.less";
|
||||
|
||||
interface ButtonProps {
|
||||
children: React.ReactNode;
|
||||
onClick?: () => void;
|
||||
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
||||
disabled?: boolean;
|
||||
leftIcon?: React.ReactNode;
|
||||
rightIcon?: React.ReactNode;
|
||||
@@ -14,6 +14,7 @@ interface ButtonProps {
|
||||
autoFocus?: boolean;
|
||||
className?: string;
|
||||
termInline?: boolean;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
class Button extends React.Component<ButtonProps> {
|
||||
@@ -23,14 +24,14 @@ class Button extends React.Component<ButtonProps> {
|
||||
};
|
||||
|
||||
@boundMethod
|
||||
handleClick() {
|
||||
handleClick(e) {
|
||||
if (this.props.onClick && !this.props.disabled) {
|
||||
this.props.onClick();
|
||||
this.props.onClick(e);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { leftIcon, rightIcon, children, disabled, style, autoFocus, termInline, className } = this.props;
|
||||
const { leftIcon, rightIcon, children, disabled, style, autoFocus, termInline, className, title } = this.props;
|
||||
|
||||
return (
|
||||
<button
|
||||
@@ -39,6 +40,7 @@ class Button extends React.Component<ButtonProps> {
|
||||
disabled={disabled}
|
||||
style={style}
|
||||
autoFocus={autoFocus}
|
||||
title={title}
|
||||
>
|
||||
{leftIcon && <span className="icon-left">{leftIcon}</span>}
|
||||
{children}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
.copy-button {
|
||||
padding: 5px 5px;
|
||||
|
||||
.fa-check {
|
||||
color: var(--app-success-color);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
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 };
|
||||
@@ -18,3 +18,4 @@ export { Toggle } from "./toggle";
|
||||
export { Tooltip } from "./tooltip";
|
||||
export { TabIcon } from "./tabicon";
|
||||
export { DatePicker } from "./datepicker";
|
||||
export { CopyButton } from "./copybutton";
|
||||
|
||||
@@ -7,8 +7,10 @@ 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);
|
||||
@@ -28,14 +30,17 @@ function CodeRenderer(props: any): any {
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class CodeBlockMarkdown extends React.Component<{ children: React.ReactNode; codeSelectSelectedIndex?: number }, {}> {
|
||||
class CodeBlockMarkdown extends React.Component<
|
||||
{ children: React.ReactNode; codeSelectSelectedIndex?: number; uuid: string },
|
||||
{}
|
||||
> {
|
||||
blockIndex: number;
|
||||
blockRef: React.RefObject<HTMLPreElement>;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.blockRef = React.createRef();
|
||||
this.blockIndex = GlobalModel.inputModel.addCodeBlockToCodeSelect(this.blockRef);
|
||||
this.blockIndex = GlobalModel.inputModel.addCodeBlockToCodeSelect(this.blockRef, this.props.uuid);
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -62,9 +67,21 @@ class Markdown extends React.Component<
|
||||
{ text: string; style?: any; extraClassName?: string; codeSelect?: boolean },
|
||||
{}
|
||||
> {
|
||||
CodeBlockRenderer(props: any, codeSelect: boolean, codeSelectIndex: number): any {
|
||||
curUuid: string;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.curUuid = uuidv4();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
CodeBlockRenderer(props: any, codeSelect: boolean, codeSelectIndex: number, curUuid: string): any {
|
||||
if (codeSelect) {
|
||||
return <CodeBlockMarkdown codeSelectSelectedIndex={codeSelectIndex}>{props.children}</CodeBlockMarkdown>;
|
||||
return (
|
||||
<CodeBlockMarkdown codeSelectSelectedIndex={codeSelectIndex} uuid={curUuid}>
|
||||
{props.children}
|
||||
</CodeBlockMarkdown>
|
||||
);
|
||||
} else {
|
||||
const clickHandler = (e: React.MouseEvent<HTMLElement>) => {
|
||||
let blockText = (e.target as HTMLElement).innerText;
|
||||
@@ -90,7 +107,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),
|
||||
pre: (props) => this.CodeBlockRenderer(props, codeSelect, curCodeSelectIndex, this.curUuid),
|
||||
};
|
||||
return (
|
||||
<div className={cn("markdown content", this.props.extraClassName)} style={this.props.style}>
|
||||
|
||||
@@ -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, getApi } from "@/models";
|
||||
import { GlobalModel } 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 {
|
||||
getApi().installAppUpdate();
|
||||
GlobalModel.getElectronApi().installAppUpdate();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
|
||||
@@ -312,7 +312,7 @@ class CreateRemoteConnModal extends React.Component<{}, {}> {
|
||||
endDecoration: (
|
||||
<InputDecoration>
|
||||
<Tooltip
|
||||
message={`(Required) The path to your ssh key file.`}
|
||||
message={`(Required) The path to your ssh private key file.`}
|
||||
icon={<i className="fa-sharp fa-regular fa-circle-question" />}
|
||||
>
|
||||
<i className="fa-sharp fa-regular fa-circle-question" />
|
||||
|
||||
@@ -338,7 +338,7 @@ class EditRemoteConnModal extends React.Component<{}, {}> {
|
||||
endDecoration: (
|
||||
<InputDecoration>
|
||||
<Tooltip
|
||||
message={`(Required) The path to your ssh key file.`}
|
||||
message={`(Required) The path to your ssh private key file.`}
|
||||
icon={<i className="fa-sharp fa-regular fa-circle-question" />}
|
||||
>
|
||||
<i className="fa-sharp fa-regular fa-circle-question" />
|
||||
|
||||
@@ -11,8 +11,9 @@ import { GlobalModel, GlobalCommandRunner, Screen } from "@/models";
|
||||
import { SettingsError, Modal, Dropdown, Tooltip } from "@/elements";
|
||||
import * as util from "@/util/util";
|
||||
import { Button } from "@/elements";
|
||||
import { ReactComponent as GlobeIcon } from "@/assets/icons/globe.svg";
|
||||
import { ReactComponent as StatusCircleIcon } from "@/assets/icons/statuscircle.svg";
|
||||
import { If } from "tsx-control-statements/components";
|
||||
import { commandRtnHandler } from "@/util/util";
|
||||
import { getTermThemes } from "@/util/themeutil";
|
||||
import {
|
||||
TabColorSelector,
|
||||
TabIconSelector,
|
||||
@@ -153,11 +154,34 @@ 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()})`} />
|
||||
@@ -186,6 +210,19 @@ 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>
|
||||
|
||||
@@ -6,8 +6,10 @@ import * as mobxReact from "mobx-react";
|
||||
import * as mobx from "mobx";
|
||||
import { boundMethod } from "autobind-decorator";
|
||||
import { GlobalModel, GlobalCommandRunner, Session } from "@/models";
|
||||
import { Button } from "@/elements";
|
||||
import { Toggle, InlineSettingsTextEdit, SettingsError, Modal, Tooltip } from "@/elements";
|
||||
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 * as util from "@/util/util";
|
||||
|
||||
import "./sessionsettings.less";
|
||||
@@ -76,6 +78,16 @@ 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(() => {
|
||||
@@ -87,6 +99,9 @@ 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()})`} />
|
||||
@@ -104,6 +119,19 @@ 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>
|
||||
|
||||
@@ -357,6 +357,10 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.wave-button {
|
||||
padding: 5px 5px;
|
||||
}
|
||||
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
|
||||
+14
-29
@@ -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, DatePicker } from "@/elements";
|
||||
import { TextField, Dropdown, Button, CopyButton } 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,8 +22,6 @@ 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";
|
||||
@@ -115,7 +113,6 @@ class HistoryCmdStr extends React.Component<
|
||||
cmdstr: string;
|
||||
onUse: () => void;
|
||||
onCopy: () => void;
|
||||
isCopied: boolean;
|
||||
fontSize: "normal" | "large";
|
||||
limitHeight: boolean;
|
||||
},
|
||||
@@ -138,24 +135,17 @@ class HistoryCmdStr extends React.Component<
|
||||
}
|
||||
|
||||
render() {
|
||||
const { isCopied, cmdstr, fontSize, limitHeight } = this.props;
|
||||
const { 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">
|
||||
<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>
|
||||
<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>
|
||||
</div>
|
||||
);
|
||||
@@ -190,7 +180,6 @@ 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() {
|
||||
@@ -308,7 +297,6 @@ class HistoryView extends React.Component<{}, {}> {
|
||||
hvm.setFromDate(null);
|
||||
return;
|
||||
}
|
||||
console.log;
|
||||
hvm.setFromDate(newDate);
|
||||
}
|
||||
|
||||
@@ -378,14 +366,6 @@ 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
|
||||
@@ -395,7 +375,7 @@ class HistoryView extends React.Component<{}, {}> {
|
||||
}
|
||||
mobx.action(() => {
|
||||
GlobalModel.showSessionView();
|
||||
GlobalModel.inputModel.setCurLine(item.cmdstr);
|
||||
GlobalModel.inputModel.updateCmdLine({ str: item.cmdstr, pos: item.cmdstr.length });
|
||||
setTimeout(() => GlobalModel.inputModel.giveFocus(), 50);
|
||||
})();
|
||||
}
|
||||
@@ -570,7 +550,6 @@ 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}
|
||||
/>
|
||||
@@ -670,6 +649,11 @@ 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;
|
||||
@@ -710,8 +694,9 @@ 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">
|
||||
<div className="line-container" key={termRenderVersion}>
|
||||
<If condition={canViewInContext}>
|
||||
<div className="line-context">
|
||||
<div title="View in Context" className="vic-btn" onClick={this.viewInContext}>
|
||||
|
||||
@@ -106,11 +106,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.top-border {
|
||||
border-top: 1px solid #777;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
&:hover .meta .termopts {
|
||||
display: block;
|
||||
}
|
||||
@@ -231,13 +226,12 @@
|
||||
}
|
||||
|
||||
.ts,
|
||||
.termopts,
|
||||
.renderer {
|
||||
.termopts {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.renderer .renderer-icon {
|
||||
margin-right: 0.5em;
|
||||
.renderer-icon {
|
||||
margin-right: 0.2em;
|
||||
}
|
||||
|
||||
.metapart-mono {
|
||||
|
||||
+236
-147
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user