mirror of
https://github.com/wavetermdev/backup.git
synced 2026-04-22 15:26:58 -07:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4d95d45a45 |
+1
-5
@@ -18,13 +18,11 @@
|
||||
"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",
|
||||
"@tanstack/match-sorter-utils": "^8.8.4",
|
||||
"@tanstack/react-table": "^8.10.3",
|
||||
"@withfig/autocomplete": "^2.652.3",
|
||||
"autobind-decorator": "^2.4.0",
|
||||
"base64-js": "^1.5.1",
|
||||
"classnames": "^2.3.1",
|
||||
@@ -33,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",
|
||||
@@ -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": {
|
||||
@@ -80,7 +77,6 @@
|
||||
"@types/throttle-debounce": "^5.0.1",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"@types/webpack-env": "^1.18.3",
|
||||
"@withfig/autocomplete-types": "^1.30.0",
|
||||
"babel-loader": "^9.1.3",
|
||||
"babel-plugin-jsx-control-statements": "^4.1.2",
|
||||
"copy-webpack-plugin": "^12.0.0",
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
--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-primary-color: rgb(23, 23, 23);
|
||||
--app-text-secondary-color: rgb(76, 76, 76);
|
||||
--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);
|
||||
|
||||
+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-solid fa-sidebar-flip"></i>
|
||||
<i className="fa-sharp fa-regular fa-lightbulb"></i>
|
||||
</Button>
|
||||
</div>
|
||||
</If>
|
||||
|
||||
@@ -64,8 +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";
|
||||
export const InputAuxView_Suggestions = "suggestions";
|
||||
|
||||
@@ -6,14 +6,14 @@ 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 { MainView } from "@/common/elements/mainview";
|
||||
|
||||
import "./clientsettings.less";
|
||||
import { MainView } from "../common/elements/mainview";
|
||||
|
||||
class ClientSettingsKeybindings extends React.Component<{}, {}> {
|
||||
componentDidMount() {
|
||||
@@ -70,7 +70,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
||||
return;
|
||||
}
|
||||
const prtn = GlobalCommandRunner.setTheme(themeSource, false);
|
||||
GlobalModel.getElectronApi().setNativeThemeSource(themeSource);
|
||||
getApi().setNativeThemeSource(themeSource);
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
}
|
||||
|
||||
@@ -107,13 +107,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
||||
prtn = GlobalCommandRunner.releaseCheckAutoOff(false);
|
||||
}
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
GlobalModel.getElectronApi().changeAutoUpdate(val);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleChangeAutocompleteEnabled(val: boolean): void {
|
||||
const prtn: Promise<CommandRtnType> = GlobalCommandRunner.setAutocompleteEnabled(val);
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
getApi().changeAutoUpdate(val);
|
||||
}
|
||||
|
||||
getFontSizes(): DropdownItem[] {
|
||||
@@ -360,15 +354,6 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Command Autocomplete</div>
|
||||
<div className="settings-input">
|
||||
<Toggle
|
||||
checked={cdata.clientopts.autocompleteenabled ?? false}
|
||||
onChange={this.handleChangeAutocompleteEnabled}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<SettingsError errorMessage={this.errorMessage} />
|
||||
</div>
|
||||
</MainView>
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
.copy-button {
|
||||
padding: 5px 5px;
|
||||
|
||||
.fa-check {
|
||||
color: var(--app-success-color);
|
||||
}
|
||||
}
|
||||
@@ -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 };
|
||||
@@ -18,4 +18,3 @@ export { Toggle } from "./toggle";
|
||||
export { Tooltip } from "./tooltip";
|
||||
export { TabIcon } from "./tabicon";
|
||||
export { DatePicker } from "./datepicker";
|
||||
export { CopyButton } from "./copybutton";
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { OverlayScrollbarsComponentProps, useOverlayScrollbars } from "overlayscrollbars-react";
|
||||
import React from "react";
|
||||
|
||||
export const ScrollbarsComponent = (props: {
|
||||
options?: OverlayScrollbarsComponentProps["options"];
|
||||
children: React.ReactNode;
|
||||
childrenRef: React.RefObject<any>;
|
||||
}) => {
|
||||
const [initialize, instance] = useOverlayScrollbars({ options: props.options });
|
||||
|
||||
React.useEffect(() => {
|
||||
initialize(props.childrenRef.current);
|
||||
}, [initialize, props.childrenRef.current]);
|
||||
|
||||
return <div ref={props.childrenRef}>{props.children}</div>;
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -58,8 +58,4 @@
|
||||
.term-prompt-python {
|
||||
color: var(--term-magenta);
|
||||
}
|
||||
|
||||
.term-prompt-k8s {
|
||||
color: var(--term-magenta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +146,6 @@ class Prompt extends React.Component<
|
||||
let branchElem = null;
|
||||
let pythonElem = null;
|
||||
let condaElem = null;
|
||||
let k8sElem = null;
|
||||
if (!isBlank(festate["PROMPTVAR_GITBRANCH"])) {
|
||||
const branchName = festate["PROMPTVAR_GITBRANCH"];
|
||||
branchElem = (
|
||||
@@ -172,19 +171,9 @@ class Prompt extends React.Component<
|
||||
</span>
|
||||
);
|
||||
}
|
||||
if (!isBlank(festate["K8SCONTEXT"])) {
|
||||
const k8sContext = festate["K8SCONTEXT"];
|
||||
const k8sNs = festate["K8SNAMESPACE"];
|
||||
k8sElem = (
|
||||
<span title="k8s context:namespace" className="term-prompt-k8s">
|
||||
k8s:({k8sContext}
|
||||
{isBlank(k8sNs) ? "" : ":" + k8sNs}){" "}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<span className={termClassNames}>
|
||||
{remoteElem} {cwdElem} {branchElem} {condaElem} {pythonElem} {k8sElem}
|
||||
{remoteElem} {cwdElem} {branchElem} {condaElem} {pythonElem}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -357,10 +357,6 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.wave-button {
|
||||
padding: 5px 5px;
|
||||
}
|
||||
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
|
||||
@@ -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() {
|
||||
@@ -366,6 +377,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 +394,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 +569,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}
|
||||
/>
|
||||
|
||||
@@ -665,83 +665,6 @@ class LineCmd extends React.Component<
|
||||
};
|
||||
};
|
||||
|
||||
@boundMethod
|
||||
handleContextMenu(e: React.MouseEvent) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
let { line, screen } = this.props;
|
||||
const containerType = screen.getContainerType();
|
||||
const isMainContainer = containerType == appconst.LineContainer_Main;
|
||||
const cmd = screen.getCmd(line);
|
||||
let menu: ContextMenuItem[] = [
|
||||
{ role: "copy", label: "Copy", type: "normal" },
|
||||
{ role: "paste", label: "Paste", type: "normal" },
|
||||
{ type: "separator" },
|
||||
{ label: "Copy Command", click: () => this.copyCommandStr() },
|
||||
];
|
||||
const isTerminal = isBlank(line.renderer) || line.renderer == "terminal";
|
||||
if (isTerminal) {
|
||||
menu.push({ label: "Copy Visible Output", click: () => this.copyOutput(false) });
|
||||
menu.push({ label: "Copy Full Output", click: () => this.copyOutput(true) });
|
||||
}
|
||||
if (isMainContainer) {
|
||||
menu.push({ type: "separator" });
|
||||
const isMinimized = line.linestate["wave:min"];
|
||||
if (isMinimized) {
|
||||
menu.push({
|
||||
label: "Show Block Output",
|
||||
click: () => GlobalCommandRunner.lineMinimize(line.lineid, false, true),
|
||||
});
|
||||
} else {
|
||||
menu.push({
|
||||
label: "Hide Block Output",
|
||||
click: () => GlobalCommandRunner.lineMinimize(line.lineid, true, true),
|
||||
});
|
||||
}
|
||||
if (cmd?.isRunning()) {
|
||||
menu.push({ type: "separator" });
|
||||
menu.push({
|
||||
label: "Send Signal",
|
||||
type: "submenu",
|
||||
submenu: [
|
||||
{ label: "SIGINT", click: () => GlobalCommandRunner.lineSignal(line.lineid, "SIGINT", true) },
|
||||
{ label: "SIGTERM", click: () => GlobalCommandRunner.lineSignal(line.lineid, "SIGTERM", true) },
|
||||
{ label: "SIGKILL", click: () => GlobalCommandRunner.lineSignal(line.lineid, "SIGKILL", true) },
|
||||
{ type: "separator" },
|
||||
{ label: "SIGUSR1", click: () => GlobalCommandRunner.lineSignal(line.lineid, "SIGUSR1", true) },
|
||||
{ label: "SIGUSR2", click: () => GlobalCommandRunner.lineSignal(line.lineid, "SIGUSR2", true) },
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
menu.push({ type: "separator" });
|
||||
menu.push({ label: "Restart Line", click: () => GlobalCommandRunner.lineRestart(line.lineid, true) });
|
||||
menu.push({ type: "separator" });
|
||||
menu.push({ label: "Delete Block", click: () => GlobalCommandRunner.lineDelete(line.lineid, true) });
|
||||
}
|
||||
GlobalModel.contextMenuModel.showContextMenu(menu, { x: e.clientX, y: e.clientY });
|
||||
}
|
||||
|
||||
copyCommandStr() {
|
||||
const { line, screen } = this.props;
|
||||
const cmd: Cmd = screen.getCmd(line);
|
||||
if (cmd != null) {
|
||||
navigator.clipboard.writeText(cmd.getCmdStr());
|
||||
}
|
||||
}
|
||||
|
||||
copyOutput(fullOutput: boolean) {
|
||||
const { line, screen } = this.props;
|
||||
let termWrap = screen.getTermWrap(line.lineid);
|
||||
if (termWrap == null) {
|
||||
return;
|
||||
}
|
||||
let outputStr = termWrap.getOutput(fullOutput);
|
||||
if (fullOutput != null) {
|
||||
navigator.clipboard.writeText(outputStr);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { screen, line, width, staticRender, visible } = this.props;
|
||||
const isVisible = visible.get();
|
||||
@@ -827,7 +750,6 @@ class LineCmd extends React.Component<
|
||||
data-lineid={line.lineid}
|
||||
data-linenum={line.linenum}
|
||||
data-screenid={line.screenid}
|
||||
onContextMenu={this.handleContextMenu}
|
||||
>
|
||||
<If condition={isSelected || cmdError}>
|
||||
<div key="mask" className={cn("line-mask", { "error-mask": cmdError })}></div>
|
||||
|
||||
@@ -22,23 +22,6 @@
|
||||
border-bottom: 1px solid var(--app-border-color);
|
||||
}
|
||||
|
||||
.rsb-modes {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 5px 10px;
|
||||
gap: 5px;
|
||||
border-bottom: 1px solid var(--app-border-color);
|
||||
|
||||
.icon-container {
|
||||
padding: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.icon-container:hover {
|
||||
background-color: var(--app-selected-mask-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
// Copyright 2023-2024, Command Line Inc.
|
||||
// Copyright 2023, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import * as React from "react";
|
||||
import * as mobxReact from "mobx-react";
|
||||
import * as mobx from "mobx";
|
||||
import dayjs from "dayjs";
|
||||
import { If, For } from "tsx-control-statements/components";
|
||||
|
||||
import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||
import { GlobalModel } from "@/models";
|
||||
import { ResizableSidebar, Button } from "@/elements";
|
||||
import { WaveBookDisplay } from "./wavebook";
|
||||
|
||||
import "./right.less";
|
||||
|
||||
@@ -57,14 +55,6 @@ class KeybindDevPane extends React.Component<{}, {}> {
|
||||
|
||||
@mobxReact.observer
|
||||
class RightSideBar extends React.Component<RightSideBarProps, {}> {
|
||||
mode: OV<string> = mobx.observable.box(null, { name: "RightSideBar-mode" });
|
||||
|
||||
setMode(mode: string) {
|
||||
mobx.action(() => {
|
||||
this.mode.set(mode);
|
||||
})();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ResizableSidebar
|
||||
@@ -81,31 +71,9 @@ class RightSideBar extends React.Component<RightSideBarProps, {}> {
|
||||
<i className="fa-sharp fa-regular fa-xmark"></i>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="rsb-modes">
|
||||
<div className="flex-spacer" />
|
||||
<If condition={GlobalModel.isDev}>
|
||||
<div
|
||||
className="icon-container"
|
||||
title="Show Keybinding Debugger"
|
||||
onClick={() => this.setMode("keybind")}
|
||||
>
|
||||
<i className="fa-fw fa-sharp fa-keyboard fa-solid" />
|
||||
</div>
|
||||
</If>
|
||||
<div
|
||||
className="icon-container"
|
||||
title="Show Keybinding Debugger"
|
||||
onClick={() => this.setMode("wavebook")}
|
||||
>
|
||||
<i className="fa-sharp fa-solid fa-book-sparkles"></i>
|
||||
</div>
|
||||
</div>
|
||||
<If condition={this.mode.get() == "keybind"}>
|
||||
<If condition={GlobalModel.isDev}>
|
||||
<KeybindDevPane></KeybindDevPane>
|
||||
</If>
|
||||
<If condition={this.mode.get() == "wavebook"}>
|
||||
<WaveBookDisplay></WaveBookDisplay>
|
||||
</If>
|
||||
</React.Fragment>
|
||||
)}
|
||||
</ResizableSidebar>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user