Compare commits

..

26 Commits

Author SHA1 Message Date
Red Adaya 15d02f3357 remove styles not related to Tooltip 2024-02-06 13:42:09 +08:00
Red Adaya 39d371681c remove styles not related to Toggle 2024-02-06 13:41:23 +08:00
Red Adaya 412c3ac5a2 remove styles not related to TextField 2024-02-06 13:37:15 +08:00
Red Adaya 36484621ec remove styles not related to Status 2024-02-06 13:35:15 +08:00
Red Adaya 72231ead1d SettingsError doesn't need styles cos it uses classnames in app.less 2024-02-06 13:33:42 +08:00
Red Adaya 81c1fd43f7 remove styles not related to ResizableSidebar 2024-02-06 13:31:20 +08:00
Red Adaya c9a73c2204 RemoteStatusLight no longer used. It's replaced by Status component. 2024-02-06 13:27:58 +08:00
Red Adaya 434f980b49 remove styles not related to PasswordField 2024-02-06 13:26:22 +08:00
Red Adaya 75d462764d NumberField doesn't need styles cos it extends TextField 2024-02-06 13:24:50 +08:00
Red Adaya c58c88af4e remove styles not related to modal 2024-02-06 13:23:32 +08:00
Red Adaya 05be301ea2 remove styles not related to markdown 2024-02-06 13:22:04 +08:00
Red Adaya 27e5a9154d LinkButton doesn't need styles cos it's extends Button component 2024-02-06 13:19:31 +08:00
Red Adaya a7d2148bc0 remove styles not related to InputDecoration 2024-02-06 10:28:39 +08:00
Red Adaya ead75880e1 remove styles not related to InlineSettingsTextEdit 2024-02-06 10:17:18 +08:00
Red Adaya 0bdb50cf91 fix import error 2024-02-06 10:12:32 +08:00
Red Adaya abf3448f07 InfoMessage conmponent no longer needed 2024-02-06 10:09:01 +08:00
Red Adaya 8988d26867 remove old connections 2024-02-06 09:50:57 +08:00
Red Adaya a084ca4801 IconButton doesn't need styles because it extends Button 2024-02-06 09:30:10 +08:00
Red Adaya 36e2578a03 remove styles not related to dropdown 2024-02-06 09:26:46 +08:00
Red Adaya a49487c035 renderCmdText doesn't need styles 2024-02-06 09:15:51 +08:00
Red Adaya 03296043fb remove styles not related to CmdStrCode 2024-02-06 09:10:35 +08:00
Red Adaya ec797f55ff remove styles not related to checkbox 2024-02-06 09:05:18 +08:00
Red Adaya 550461167b init 2024-02-05 23:08:59 +08:00
Red Adaya cf5d2ecddf Merge branch 'main' of github.com:wavetermdev/waveterm into split-components-in-common 2024-02-05 23:07:48 +08:00
Red Adaya c4128cd266 init 2024-02-02 23:26:33 +08:00
Red Adaya 17bb07a47d split settings modals 2024-02-02 16:50:44 +08:00
155 changed files with 2191 additions and 8740 deletions
+1 -3
View File
@@ -10,7 +10,7 @@
# Wave Terminal # Wave Terminal
A open-source, cross-platform, AI-integrated, modern terminal for seamless workflows. A open-source, cross-platform, modern terminal for seamless workflows.
Wave isn't just another terminal emulator; it's a rethink on how terminals are built. Wave combines command line with the power of the open web to help veteran CLI users and new developers alike. Wave isn't just another terminal emulator; it's a rethink on how terminals are built. Wave combines command line with the power of the open web to help veteran CLI users and new developers alike.
@@ -18,7 +18,6 @@ Wave isn't just another terminal emulator; it's a rethink on how terminals are b
* Persistent sessions that can restore state across network disconnections and reboots * Persistent sessions that can restore state across network disconnections and reboots
* Searchable contextual command history across all remote sessions (saved locally) * Searchable contextual command history across all remote sessions (saved locally)
* Workspaces, tabs, and command blocks to keep you organized * Workspaces, tabs, and command blocks to keep you organized
* AI Integration with ChatGPT (or ChatGPT compatible APIs) to help write commands and get answers inline
## Installation ## Installation
@@ -36,7 +35,6 @@ brew install --cask wave
* Homepage — https://www.waveterm.dev * Homepage — https://www.waveterm.dev
* Download Page — https://www.waveterm.dev/download * Download Page — https://www.waveterm.dev/download
* Documentation — https://docs.waveterm.dev/ * Documentation — https://docs.waveterm.dev/
* Blog — https://blog.waveterm.dev/
* Quick Start Guide — https://docs.waveterm.dev/quickstart/ * Quick Start Guide — https://docs.waveterm.dev/quickstart/
* Discord Community — https://discord.gg/XfvZ334gwU * Discord Community — https://discord.gg/XfvZ334gwU
+6 -3
View File
@@ -7,9 +7,10 @@ import * as mobx from "mobx";
import { boundMethod } from "autobind-decorator"; import { boundMethod } from "autobind-decorator";
import { If } from "tsx-control-statements/components"; import { If } from "tsx-control-statements/components";
import dayjs from "dayjs"; import dayjs from "dayjs";
import type { ContextMenuOpts } from "../types/types";
import localizedFormat from "dayjs/plugin/localizedFormat"; import localizedFormat from "dayjs/plugin/localizedFormat";
import { GlobalModel } from "@/models"; import { GlobalModel } from "../model/model";
import { isBlank } from "@/util/util"; import { isBlank } from "../util/util";
import { WorkspaceView } from "./workspace/workspaceview"; import { WorkspaceView } from "./workspace/workspaceview";
import { PluginsView } from "./pluginsview/pluginsview"; import { PluginsView } from "./pluginsview/pluginsview";
import { BookmarksView } from "./bookmarks/bookmarks"; import { BookmarksView } from "./bookmarks/bookmarks";
@@ -24,12 +25,14 @@ import "./app.less";
dayjs.extend(localizedFormat); dayjs.extend(localizedFormat);
type OV<V> = mobx.IObservableValue<V>;
@mobxReact.observer @mobxReact.observer
class App extends React.Component<{}, {}> { class App extends React.Component<{}, {}> {
dcWait: OV<boolean> = mobx.observable.box(false, { name: "dcWait" }); dcWait: OV<boolean> = mobx.observable.box(false, { name: "dcWait" });
mainContentRef: React.RefObject<HTMLDivElement> = React.createRef(); mainContentRef: React.RefObject<HTMLDivElement> = React.createRef();
constructor(props: {}) { constructor(props: any) {
super(props); super(props);
if (GlobalModel.isDev) document.body.className = "is-dev"; if (GlobalModel.isDev) document.body.className = "is-dev";
} }
-41
View File
@@ -8,7 +8,6 @@ export const SESSION_SETTINGS = "sessionSettings";
export const LINE_SETTINGS = "lineSettings"; export const LINE_SETTINGS = "lineSettings";
export const CLIENT_SETTINGS = "clientSettings"; export const CLIENT_SETTINGS = "clientSettings";
export const TAB_SWITCHER = "tabSwitcher"; export const TAB_SWITCHER = "tabSwitcher";
export const USER_INPUT = "userInput";
export const LineContainer_Main = "main"; export const LineContainer_Main = "main";
export const LineContainer_History = "history"; export const LineContainer_History = "history";
@@ -17,43 +16,3 @@ export const LineContainer_Sidebar = "sidebar";
export const ConfirmKey_HideShellPrompt = "hideshellprompt"; export const ConfirmKey_HideShellPrompt = "hideshellprompt";
export const NoStrPos = -1; export const NoStrPos = -1;
export const RemotePtyRows = 8; // also in main.tsx
export const RemotePtyCols = 80;
export const ProdServerEndpoint = "http://127.0.0.1:1619";
export const ProdServerWsEndpoint = "ws://127.0.0.1:1623";
export const DevServerEndpoint = "http://127.0.0.1:8090";
export const DevServerWsEndpoint = "ws://127.0.0.1:8091";
export const DefaultTermFontSize = 12;
export const MinFontSize = 8;
export const MaxFontSize = 24;
export const InputChunkSize = 500;
export const RemoteColors = ["red", "green", "yellow", "blue", "magenta", "cyan", "white", "orange"];
export const TabColors = ["red", "orange", "yellow", "green", "mint", "cyan", "blue", "violet", "pink", "white"];
export const TabIcons = [
"sparkle",
"fire",
"ghost",
"cloud",
"compass",
"crown",
"droplet",
"graduation-cap",
"heart",
"file",
];
// @ts-ignore
export const VERSION = __WAVETERM_VERSION__;
// @ts-ignore
export const BUILD = __WAVETERM_BUILD__;
/**
* Levels for the screen status indicator
*/
export enum StatusIndicatorLevel {
None = 0,
Output = 1,
Success = 2,
Error = 3,
}
+1 -1
View File
@@ -1,4 +1,4 @@
@import "@/common/themes/themes.less"; @import "../../app/common/themes/themes.less";
.bookmarks-view { .bookmarks-view {
background-color: @background-session; background-color: @background-session;
+9 -20
View File
@@ -7,27 +7,20 @@ import * as mobx from "mobx";
import { boundMethod } from "autobind-decorator"; import { boundMethod } from "autobind-decorator";
import { If, For } from "tsx-control-statements/components"; import { If, For } from "tsx-control-statements/components";
import cn from "classnames"; import cn from "classnames";
import { GlobalModel } from "@/models"; import type { BookmarkType } from "../../types/types";
import { CmdStrCode, Markdown } from "@/common/elements"; import { GlobalModel } from "../../model/model";
import { CmdStrCode, Markdown } from "../common/elements";
import { ReactComponent as XmarkIcon } from "@/assets/icons/line/xmark.svg"; import { ReactComponent as XmarkIcon } from "../assets/icons/line/xmark.svg";
import { ReactComponent as CopyIcon } from "@/assets/icons/favourites/copy.svg"; import { ReactComponent as CopyIcon } from "../assets/icons/favourites/copy.svg";
import { ReactComponent as PenIcon } from "@/assets/icons/favourites/pen.svg"; import { ReactComponent as PenIcon } from "../assets/icons/favourites/pen.svg";
import { ReactComponent as TrashIcon } from "@/assets/icons/favourites/trash.svg"; import { ReactComponent as TrashIcon } from "../assets/icons/favourites/trash.svg";
import { ReactComponent as FavoritesIcon } from "@/assets/icons/favourites.svg"; import { ReactComponent as FavoritesIcon } from "../assets/icons/favourites.svg";
import "./bookmarks.less"; import "./bookmarks.less";
type BookmarkProps = {
bookmark: BookmarkType;
};
@mobxReact.observer @mobxReact.observer
class Bookmark extends React.Component<BookmarkProps, {}> { class Bookmark extends React.Component<{ bookmark: BookmarkType }, {}> {
constructor(props: BookmarkProps) {
super(props);
}
@boundMethod @boundMethod
handleDeleteClick(): void { handleDeleteClick(): void {
let { bookmark } = this.props; let { bookmark } = this.props;
@@ -186,10 +179,6 @@ class Bookmark extends React.Component<BookmarkProps, {}> {
@mobxReact.observer @mobxReact.observer
class BookmarksView extends React.Component<{}, {}> { class BookmarksView extends React.Component<{}, {}> {
constructor(props: {}) {
super(props);
}
@boundMethod @boundMethod
closeView(): void { closeView(): void {
GlobalModel.bookmarksModel.closeView(); GlobalModel.bookmarksModel.closeView();
+1 -1
View File
@@ -1,4 +1,4 @@
@import "@/common/themes/themes.less"; @import "../../app/common/themes/themes.less";
.clientsettings-view { .clientsettings-view {
background-color: @background-session; background-color: @background-session;
+28 -56
View File
@@ -6,18 +6,23 @@ import * as mobxReact from "mobx-react";
import * as mobx from "mobx"; import * as mobx from "mobx";
import { boundMethod } from "autobind-decorator"; import { boundMethod } from "autobind-decorator";
import cn from "classnames"; import cn from "classnames";
import { GlobalModel, GlobalCommandRunner, RemotesModel } from "@/models"; import { GlobalModel, GlobalCommandRunner, MinFontSize, MaxFontSize, RemotesModel } from "../../model/model";
import { Toggle, InlineSettingsTextEdit, SettingsError, Dropdown } from "@/common/elements"; import { Toggle, InlineSettingsTextEdit, SettingsError, Dropdown } from "../common/elements";
import { commandRtnHandler, isBlank } from "@/util/util"; import { CommandRtnType, ClientDataType } from "../../types/types";
import * as appconst from "@/app/appconst"; import { commandRtnHandler, isBlank } from "../../util/util";
import "./clientsettings.less"; import "./clientsettings.less";
type OV<V> = mobx.IObservableValue<V>;
// @ts-ignore
const VERSION = __WAVETERM_VERSION__;
// @ts-ignore
const BUILD = __WAVETERM_BUILD__;
@mobxReact.observer @mobxReact.observer
class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hoveredItemId: string }> { class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hoveredItemId: string }> {
fontSizeDropdownActive: OV<boolean> = mobx.observable.box(false, { fontSizeDropdownActive: OV<boolean> = mobx.observable.box(false, { name: "clientSettings-fontSizeDropdownActive" });
name: "clientSettings-fontSizeDropdownActive",
});
errorMessage: OV<string> = mobx.observable.box(null, { name: "ClientSettings-errorMessage" }); errorMessage: OV<string> = mobx.observable.box(null, { name: "ClientSettings-errorMessage" });
@boundMethod @boundMethod
@@ -29,12 +34,12 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
@boundMethod @boundMethod
handleChangeFontSize(fontSize: string): void { handleChangeFontSize(fontSize: string): void {
const newFontSize = Number(fontSize); let newFontSize = Number(fontSize);
this.fontSizeDropdownActive.set(false); this.fontSizeDropdownActive.set(false);
if (GlobalModel.termFontSize.get() == newFontSize) { if (GlobalModel.termFontSize.get() == newFontSize) {
return; return;
} }
const prtn = GlobalCommandRunner.setTermFontSize(newFontSize, false); let prtn = GlobalCommandRunner.setTermFontSize(newFontSize, false);
commandRtnHandler(prtn, this.errorMessage); commandRtnHandler(prtn, this.errorMessage);
} }
@@ -67,29 +72,29 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
commandRtnHandler(prtn, this.errorMessage); commandRtnHandler(prtn, this.errorMessage);
} }
getFontSizes(): DropdownItem[] { getFontSizes(): any {
const availableFontSizes: DropdownItem[] = []; let availableFontSizes: { label: string; value: number }[] = [];
for (let s = appconst.MinFontSize; s <= appconst.MaxFontSize; s++) { for (let s = MinFontSize; s <= MaxFontSize; s++) {
availableFontSizes.push({ label: s + "px", value: String(s) }); availableFontSizes.push({ label: s + "px", value: s });
} }
return availableFontSizes; return availableFontSizes;
} }
@boundMethod @boundMethod
inlineUpdateOpenAIModel(newModel: string): void { inlineUpdateOpenAIModel(newModel: string): void {
const prtn = GlobalCommandRunner.setClientOpenAISettings({ model: newModel }); let prtn = GlobalCommandRunner.setClientOpenAISettings({ model: newModel });
commandRtnHandler(prtn, this.errorMessage); commandRtnHandler(prtn, this.errorMessage);
} }
@boundMethod @boundMethod
inlineUpdateOpenAIToken(newToken: string): void { inlineUpdateOpenAIToken(newToken: string): void {
const prtn = GlobalCommandRunner.setClientOpenAISettings({ apitoken: newToken }); let prtn = GlobalCommandRunner.setClientOpenAISettings({ apitoken: newToken });
commandRtnHandler(prtn, this.errorMessage); commandRtnHandler(prtn, this.errorMessage);
} }
@boundMethod @boundMethod
inlineUpdateOpenAIMaxTokens(newMaxTokensStr: string): void { inlineUpdateOpenAIMaxTokens(newMaxTokensStr: string): void {
const prtn = GlobalCommandRunner.setClientOpenAISettings({ maxtokens: newMaxTokensStr }); let prtn = GlobalCommandRunner.setClientOpenAISettings({ maxtokens: newMaxTokensStr });
commandRtnHandler(prtn, this.errorMessage); commandRtnHandler(prtn, this.errorMessage);
} }
@@ -105,41 +110,19 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
GlobalModel.clientSettingsViewModel.closeView(); GlobalModel.clientSettingsViewModel.closeView();
} }
@boundMethod
handleChangeShortcut(newShortcut: string): void {
const prtn = GlobalCommandRunner.setGlobalShortcut(newShortcut);
commandRtnHandler(prtn, this.errorMessage);
}
getFKeys(): DropdownItem[] {
const opts: DropdownItem[] = [];
opts.push({ label: "Disabled", value: "" });
const platform = GlobalModel.getPlatform();
for (let i = 1; i <= 12; i++) {
const shortcut = (platform == "darwin" ? "Cmd" : "Alt") + "+F" + String(i);
opts.push({ label: shortcut, value: shortcut });
}
return opts;
}
getCurrentShortcut(): string {
const clientData = GlobalModel.clientData.get();
return clientData?.clientopts?.globalshortcut ?? "";
}
render() { render() {
const isHidden = GlobalModel.activeMainView.get() != "clientsettings"; let isHidden = GlobalModel.activeMainView.get() != "clientsettings";
if (isHidden) { if (isHidden) {
return null; return null;
} }
const cdata: ClientDataType = GlobalModel.clientData.get(); let cdata: ClientDataType = GlobalModel.clientData.get();
const openAIOpts = cdata.openaiopts ?? {}; let openAIOpts = cdata.openaiopts ?? {};
const apiTokenStr = isBlank(openAIOpts.apitoken) ? "(not set)" : "********"; let apiTokenStr = isBlank(openAIOpts.apitoken) ? "(not set)" : "********";
const maxTokensStr = String( let maxTokensStr = String(
openAIOpts.maxtokens == null || openAIOpts.maxtokens == 0 ? 1000 : openAIOpts.maxtokens openAIOpts.maxtokens == null || openAIOpts.maxtokens == 0 ? 1000 : openAIOpts.maxtokens
); );
const curFontSize = GlobalModel.termFontSize.get(); let curFontSize = GlobalModel.termFontSize.get();
return ( return (
<div className={cn("view clientsettings-view")}> <div className={cn("view clientsettings-view")}>
@@ -168,7 +151,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
<div className="settings-field"> <div className="settings-field">
<div className="settings-label">Client Version</div> <div className="settings-label">Client Version</div>
<div className="settings-input"> <div className="settings-input">
{appconst.VERSION} {appconst.BUILD} {VERSION} {BUILD}
</div> </div>
</div> </div>
<div className="settings-field"> <div className="settings-field">
@@ -229,17 +212,6 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
/> />
</div> </div>
</div> </div>
<div className="settings-field">
<div className="settings-label">Global Hotkey</div>
<div className="settings-input">
<Dropdown
className="hotkey-dropdown"
options={this.getFKeys()}
defaultValue={this.getCurrentShortcut()}
onChange={this.handleChangeShortcut}
/>
</div>
</div>
<SettingsError errorMessage={this.errorMessage} /> <SettingsError errorMessage={this.errorMessage} />
</div> </div>
</div> </div>
+1 -1
View File
@@ -1,4 +1,4 @@
@import "@/common/themes/themes.less"; @import "../../../app/common/themes/themes.less";
.wave-button { .wave-button {
background: none; background: none;
+1 -1
View File
@@ -1,4 +1,4 @@
@import "@/common/themes/themes.less"; @import "../../../app/common/themes/themes.less";
.checkbox { .checkbox {
display: flex; display: flex;
+1 -1
View File
@@ -1,4 +1,4 @@
@import "@/common/themes/themes.less"; @import "../../../app/common/themes/themes.less";
.cmdstr-code { .cmdstr-code {
position: relative; position: relative;
+2 -2
View File
@@ -6,8 +6,8 @@ import { boundMethod } from "autobind-decorator";
import cn from "classnames"; import cn from "classnames";
import { If } from "tsx-control-statements/components"; import { If } from "tsx-control-statements/components";
import { ReactComponent as CheckIcon } from "@/assets/icons/line/check.svg"; import { ReactComponent as CheckIcon } from "../../assets/icons/line/check.svg";
import { ReactComponent as CopyIcon } from "@/assets/icons/history/copy.svg"; import { ReactComponent as CopyIcon } from "../../assets/icons/history/copy.svg";
import "./cmdstrcode.less"; import "./cmdstrcode.less";
+1 -1
View File
@@ -1,4 +1,4 @@
@import "@/common/themes/themes.less"; @import "../../../app/common/themes/themes.less";
.wave-dropdown { .wave-dropdown {
position: relative; position: relative;
+1 -1
View File
@@ -17,7 +17,7 @@ interface DropdownDecorationProps {
interface DropdownProps { interface DropdownProps {
label?: string; label?: string;
options: DropdownItem[]; options: { value: string; label: string }[];
value?: string; value?: string;
className?: string; className?: string;
onChange: (value: string) => void; onChange: (value: string) => void;
@@ -1,4 +1,4 @@
@import "@/common/themes/themes.less"; @import "../../../app/common/themes/themes.less";
.inline-edit { .inline-edit {
.icon { .icon {
@@ -7,10 +7,12 @@ import * as mobx from "mobx";
import { boundMethod } from "autobind-decorator"; import { boundMethod } from "autobind-decorator";
import cn from "classnames"; import cn from "classnames";
import { If } from "tsx-control-statements/components"; import { If } from "tsx-control-statements/components";
import { checkKeyPressed, adaptFromReactOrNativeKeyEvent } from "@/util/keyutil"; import { checkKeyPressed, adaptFromReactOrNativeKeyEvent } from "../../../util/keyutil";
import "./inlinesettingstextedit.less"; import "./inlinesettingstextedit.less";
type OV<V> = mobx.IObservableValue<V>;
@mobxReact.observer @mobxReact.observer
class InlineSettingsTextEdit extends React.Component< class InlineSettingsTextEdit extends React.Component<
{ {
+1 -1
View File
@@ -1,4 +1,4 @@
@import "@/common/themes/themes.less"; @import "../../../app/common/themes/themes.less";
.wave-input-decoration { .wave-input-decoration {
display: flex; display: flex;
+1 -2
View File
@@ -1,11 +1,10 @@
@import "@/common/themes/themes.less"; @import "../../../app/common/themes/themes.less";
.markdown { .markdown {
color: @term-white; color: @term-white;
margin-bottom: 10px; margin-bottom: 10px;
font-family: @markdown-font; font-family: @markdown-font;
font-size: 14px; font-size: 14px;
overflow-wrap: break-word;
code { code {
background-color: @markdown-highlight; background-color: @markdown-highlight;
+1 -1
View File
@@ -6,7 +6,7 @@ import * as mobxReact from "mobx-react";
import ReactMarkdown from "react-markdown"; import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm"; import remarkGfm from "remark-gfm";
import cn from "classnames"; import cn from "classnames";
import { GlobalModel } from "@/models"; import { GlobalModel } from "../../../model/model";
import "./markdown.less"; import "./markdown.less";
+1 -1
View File
@@ -1,4 +1,4 @@
@import "@/common/themes/themes.less"; @import "../../../app/common/themes/themes.less";
.wave-modal-container { .wave-modal-container {
position: fixed; position: fixed;
+2
View File
@@ -10,6 +10,8 @@ import { IconButton } from "./iconbutton";
import "./modal.less"; import "./modal.less";
type OV<V> = mobx.IObservableValue<V>;
interface ModalHeaderProps { interface ModalHeaderProps {
onClose?: () => void; onClose?: () => void;
title: string; title: string;

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