Compare commits

..

1 Commits

Author SHA1 Message Date
Red Adaya f4d7697749 button stories 2024-09-20 09:55:28 +08:00
28 changed files with 552 additions and 413 deletions
-1
View File
@@ -58,7 +58,6 @@ jobs:
shell: bash
- name: "Push version bump: ${{ steps.bump-version.outputs.WAVETERM_VERSION }}"
if: github.ref_protected
run: |
# Create a new commit for the package version bump in package.json
export VERSION=${{ steps.bump-version.outputs.WAVETERM_VERSION }}
+1
View File
@@ -1,6 +1,7 @@
body {
height: 100vh;
padding: 0;
overflow: auto;
}
#storybook-root {
+3
View File
@@ -3,6 +3,9 @@ import type { Preview } from "@storybook/react";
import React from "react";
import { DndProvider } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
import "../frontend/app/theme.less";
import "../frontend/app/app.less";
import "../frontend/app/reset.less";
import "./global.css";
const preview: Preview = {
+18
View File
@@ -0,0 +1,18 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Start Storybook",
"type": "shell",
"command": "yarn storybook",
"presentation": {
"reveal": "silent",
"panel": "shared"
},
"runOptions": {
"instanceLimit": 1,
"runOn": "folderOpen"
}
}
]
}
+16 -15
View File
@@ -17,7 +17,8 @@ vars:
tasks:
electron:dev:
desc: Run the Electron application via the Vite dev server (enables hot reloading).
cmd: yarn dev
cmds:
- yarn dev
deps:
- yarn
- build:backend
@@ -27,15 +28,12 @@ tasks:
electron:start:
desc: Run the Electron application directly.
cmd: yarn start
cmds:
- yarn start
deps:
- yarn
- build:backend
storybook:
desc: Start the Storybook server.
cmd: yarn storybook
package:
desc: Package the application for the current platform.
cmds:
@@ -100,12 +98,12 @@ tasks:
requires:
vars:
- ARCHS
cmd:
cmd: CGO_ENABLED=1 GOARCH={{.GOARCH}} go build -tags "osusergo,netcgo,sqlite_omit_load_extension" -ldflags "{{.GO_LDFLAGS}} -X main.BuildTime=$({{.DATE}} +'%Y%m%d%H%M') -X main.WaveVersion={{.VERSION}}" -o dist/bin/wavesrv.{{if eq .GOARCH "amd64"}}x64{{else}}{{.GOARCH}}{{end}}{{exeExt}} cmd/server/main-server.go
for:
var: ARCHS
split: ","
as: GOARCH
cmds:
- cmd: CGO_ENABLED=1 GOARCH={{.GOARCH}} go build -tags "osusergo,netcgo,sqlite_omit_load_extension" -ldflags "{{.GO_LDFLAGS}} -X main.BuildTime=$({{.DATE}} +'%Y%m%d%H%M') -X main.WaveVersion={{.VERSION}}" -o dist/bin/wavesrv.{{if eq .GOARCH "amd64"}}x64{{else}}{{.GOARCH}}{{end}}{{exeExt}} cmd/server/main-server.go
for:
var: ARCHS
split: ","
as: GOARCH
sources:
- "cmd/server/*.go"
- "pkg/**/*.go"
@@ -175,7 +173,8 @@ tasks:
- "pkg/**/*.go"
generates:
- dist/bin/wsh-{{.VERSION}}-{{.GOOS}}.{{.NORMALIZEDARCH}}{{.EXT}}
cmd: (CGO_ENABLED=0 GOOS={{.GOOS}} GOARCH={{.GOARCH}} go build -ldflags="-s -w -X main.BuildTime=$({{.DATE}} +'%Y%m%d%H%M') -X main.WaveVersion={{.VERSION}}" -o dist/bin/wsh-{{.VERSION}}-{{.GOOS}}.{{.NORMALIZEDARCH}}{{.EXT}} cmd/wsh/main-wsh.go)
cmds:
- (CGO_ENABLED=0 GOOS={{.GOOS}} GOARCH={{.GOARCH}} go build -ldflags="-s -w -X main.BuildTime=$({{.DATE}} +'%Y%m%d%H%M') -X main.WaveVersion={{.VERSION}}" -o dist/bin/wsh-{{.VERSION}}-{{.GOOS}}.{{.NORMALIZEDARCH}}{{.EXT}} cmd/wsh/main-wsh.go)
deps:
- go:mod:tidy
internal: true
@@ -252,7 +251,8 @@ tasks:
- yarn.lock
- package.json
- .yarnrc.yml
cmd: yarn
cmds:
- yarn
go:mod:tidy:
desc: Runs `go mod tidy`
@@ -261,4 +261,5 @@ tasks:
- go.sum
sources:
- go.mod
cmd: go mod tidy
cmds:
- go mod tidy
+2 -3
View File
@@ -10,7 +10,7 @@ const path = require("path");
const config = {
appId: pkg.build.appId,
productName: pkg.productName,
executableName: pkg.productName,
executableName: pkg.name,
artifactName: "${productName}-${platform}-${arch}-${version}.${ext}",
generateUpdatesFilesForAllChannels: true,
npmRebuild: false,
@@ -55,7 +55,6 @@ const config = {
linux: {
artifactName: "${name}-${platform}-${arch}-${version}.${ext}",
category: "TerminalEmulator",
executableName: pkg.name,
icon: "build/icons.icns",
target: ["zip", "deb", "rpm", "AppImage", "pacman"],
synopsis: pkg.description,
@@ -87,7 +86,7 @@ const config = {
if (context.electronPlatformName === "darwin" && context.arch === Arch.universal) {
const packageBinDir = path.resolve(
context.appOutDir,
`${pkg.productName}.app/Contents/Resources/app.asar.unpacked/dist/bin`
`${pkg.name}.app/Contents/Resources/app.asar.unpacked/dist/bin`
);
// Reapply file permissions to the wavesrv binaries in the final app package
+121
View File
@@ -0,0 +1,121 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
import type { Meta, StoryObj } from "@storybook/react";
import { fn } from "@storybook/test";
import { Button } from "./button";
const meta = {
title: "Elements/Button",
component: Button,
args: {
children: "Click Me",
disabled: false,
className: "",
onClick: fn(),
},
argTypes: {
onClick: {
action: "clicked",
description: "Click event handler",
},
children: {
description: "Content inside the button",
},
disabled: {
description: "Disables the button if true",
},
className: {
description: "Additional class names to style the button",
},
},
} satisfies Meta<typeof Button>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {};
export const Disabled: Story = {
args: {
disabled: true,
children: "Disabled Button",
},
};
export const GreySolid: Story = {
args: {
className: "solid grey",
children: "Grey Solid Button",
},
};
export const RedSolid: Story = {
args: {
className: "solid red",
children: "Red Solid Button",
},
};
export const YellowSolid: Story = {
args: {
className: "solid yellow",
children: "Yellow Solid Button",
},
};
export const GreenOutlined: Story = {
args: {
className: "outlined green",
children: "Green Outline Button",
},
};
export const GreyOutlined: Story = {
args: {
className: "outlined grey",
children: "Grey Outline Button",
},
};
export const RedOutlined: Story = {
args: {
className: "outlined red",
children: "Red Outline Button",
},
};
export const YellowOutlined: Story = {
args: {
className: "outlined yellow",
children: "Yellow Outline Button",
},
};
export const GreenGhostText: Story = {
args: {
className: "ghost green",
children: "Yellow Ghost Text Button",
},
};
export const GreyGhostText: Story = {
args: {
className: "ghost grey",
children: "Grey Ghost Text Button",
},
};
export const RedGhost: Story = {
args: {
className: "ghost red",
children: "Red Ghost Text Button",
},
};
export const YellowGhostText: Story = {
args: {
className: "ghost yellow",
children: "Yellow Ghost Text Button",
},
};
+26 -28
View File
@@ -9,41 +9,39 @@ import "./button.less";
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
className?: string;
children?: ReactNode;
target?: string;
source?: string;
}
const Button = memo(
forwardRef<HTMLButtonElement, ButtonProps>(
({ children, disabled, source, className = "", ...props }: ButtonProps, ref) => {
const btnRef = useRef<HTMLButtonElement>(null);
useImperativeHandle(ref, () => btnRef.current as HTMLButtonElement);
forwardRef<HTMLButtonElement, ButtonProps>(({ children, disabled, className = "", ...props }: ButtonProps, ref) => {
const btnRef = useRef<HTMLButtonElement>(null);
useImperativeHandle(ref, () => btnRef.current as HTMLButtonElement);
const childrenArray = Children.toArray(children);
const childrenArray = Children.toArray(children);
// Check if the className contains any of the categories: solid, outlined, or ghost
const containsButtonCategory = /(solid|outline|ghost)/.test(className);
// If no category is present, default to 'solid'
const categoryClassName = containsButtonCategory ? className : `solid ${className}`;
// Check if the className contains any of the categories: solid, outlined, or ghost
const containsButtonCategory = /(solid|outline|ghost)/.test(className);
// If no category is present, default to 'solid'
const categoryClassName = containsButtonCategory ? className : `solid ${className}`;
// Check if the className contains any of the color options: green, grey, red, or yellow
const containsColor = /(green|grey|red|yellow)/.test(categoryClassName);
// If no color is present, default to 'green'
const finalClassName = containsColor ? categoryClassName : `green ${categoryClassName}`;
// Check if the className contains any of the color options: green, grey, red, or yellow
const containsColor = /(green|grey|red|yellow)/.test(categoryClassName);
// If no color is present, default to 'green'
const finalClassName = containsColor ? categoryClassName : `green ${categoryClassName}`;
return (
<button
ref={btnRef}
tabIndex={disabled ? -1 : 0}
className={clsx("button", finalClassName)}
disabled={disabled}
{...props}
>
{childrenArray}
</button>
);
}
)
return (
<button
ref={btnRef}
tabIndex={disabled ? -1 : 0}
className={clsx("button", finalClassName)}
disabled={disabled}
{...props}
>
{childrenArray}
</button>
);
})
);
Button.displayName = "Button";
export { Button };
-11
View File
@@ -144,17 +144,6 @@ const QuickTips = () => {
</div>
</div>
</div>
<div className="tip-section-header">Need More Help?</div>
<div className="tip">
<div>
<div>
<a target="_blank" href="https://discord.gg/XfvZ334gwU" rel="noopener">
Join Our Discord
</a>
</div>
</div>
</div>
</div>
</div>
);
+1 -1
View File
@@ -11,7 +11,7 @@ import React, { createRef, useCallback, useEffect, useRef, useState } from "reac
import { debounce } from "throttle-debounce";
import { Tab } from "./tab";
import "./tabbar.less";
import { UpdateStatusBanner } from "./updatebanner";
import { UpdateStatusBanner } from "./updatestatus";
const TAB_DEFAULT_WIDTH = 130;
const TAB_MIN_WIDTH = 100;
-71
View File
@@ -1,71 +0,0 @@
import { Button } from "@/element/button";
import { atoms, getApi } from "@/store/global";
import { useAtomValue } from "jotai";
import { memo, useEffect, useState } from "react";
import "./updatebanner.less";
const UpdateStatusBannerComponent = ({ buttonRef }: { buttonRef: React.RefObject<HTMLButtonElement> }) => {
const appUpdateStatus = useAtomValue(atoms.updaterStatusAtom);
const [updateStatusMessage, setUpdateStatusMessage] = useState<string>();
const [dismissBannerTimeout, setDismissBannerTimeout] = useState<NodeJS.Timeout>();
useEffect(() => {
let message: string;
let dismissBanner = false;
switch (appUpdateStatus) {
case "ready":
message = "Update Available";
break;
case "downloading":
message = "Downloading Update";
break;
case "installing":
message = "Installing Update";
break;
case "error":
message = "Updater Error: Try Checking Again";
dismissBanner = true;
break;
default:
break;
}
setUpdateStatusMessage(message);
// Clear any existing timeout
if (dismissBannerTimeout) {
clearTimeout(dismissBannerTimeout);
}
// If we want to dismiss the banner, set the new timeout, otherwise clear the state
if (dismissBanner) {
setDismissBannerTimeout(
setTimeout(() => {
setUpdateStatusMessage(null);
setDismissBannerTimeout(null);
}, 10000)
);
} else {
setDismissBannerTimeout(null);
}
}, [appUpdateStatus]);
function onClick() {
getApi().installAppUpdate();
}
if (updateStatusMessage) {
return (
<Button
ref={buttonRef}
className="update-available-button"
title={appUpdateStatus === "ready" ? "Click to Install Update" : updateStatusMessage}
onClick={onClick}
disabled={appUpdateStatus !== "ready"}
>
{updateStatusMessage}
</Button>
);
}
};
export const UpdateStatusBanner = memo(UpdateStatusBannerComponent) as typeof UpdateStatusBannerComponent;
+49
View File
@@ -0,0 +1,49 @@
import { Button } from "@/element/button";
import { atoms, getApi } from "@/store/global";
import { useAtomValue } from "jotai";
import { memo } from "react";
import "./updatestatus.less";
const UpdateStatusBannerComponent = ({ buttonRef }: { buttonRef: React.RefObject<HTMLButtonElement> }) => {
const appUpdateStatus = useAtomValue(atoms.updaterStatusAtom);
function onClick() {
getApi().installAppUpdate();
}
let buttonText: string;
switch (appUpdateStatus) {
case "ready":
buttonText = "Update Available";
break;
case "checking":
buttonText = "Checking for Updates";
break;
case "downloading":
buttonText = "Downloading Update";
break;
case "installing":
buttonText = "Installing Update";
break;
case "error":
buttonText = "Updater Error: Try Checking Again";
break;
default:
break;
}
if (buttonText) {
return (
<Button
ref={buttonRef}
className="update-available-button"
title={appUpdateStatus === "ready" ? "Click to Install Update" : buttonText}
onClick={onClick}
disabled={appUpdateStatus !== "ready"}
>
{buttonText}
</Button>
);
}
};
export const UpdateStatusBanner = memo(UpdateStatusBannerComponent) as typeof UpdateStatusBannerComponent;
+3 -8
View File
@@ -149,11 +149,8 @@ class CpuPlotViewModel {
if (initialData == null) {
return;
}
const newData = this.getDefaultData();
const initialDataItems: DataItem[] = initialData.map(convertWaveEventToDataItem);
// splice the initial data into the default data (replacing the newest points)
newData.splice(newData.length - initialDataItems.length, initialDataItems.length, ...initialDataItems);
globalStore.set(this.addDataAtom, newData);
globalStore.set(this.addDataAtom, initialDataItems);
} catch (e) {
console.log("Error loading initial data for cpuplot", e);
} finally {
@@ -161,7 +158,7 @@ class CpuPlotViewModel {
}
}
getDefaultData(): DataItem[] {
getDefaultData(): Array<DataItem> {
// set it back one to avoid backwards line being possible
const numPoints = globalStore.get(this.numPoints);
const currentTime = Date.now() - 1000;
@@ -200,8 +197,6 @@ function CpuPlotView({ model, blockId }: CpuPlotViewProps) {
lastConnName.current = connName;
model.loadInitialData();
}
}, [connStatus.status, connName]);
React.useEffect(() => {
const unsubFn = waveEventSubscribe({
eventType: "sysinfo",
scope: connName,
@@ -214,11 +209,11 @@ function CpuPlotView({ model, blockId }: CpuPlotViewProps) {
addPlotData([dataItem]);
},
});
console.log("subscribe to sysinfo", connName);
return () => {
unsubFn();
};
}, [connName]);
React.useEffect(() => {}, [connName]);
if (connStatus?.status != "connected") {
return null;
}
+53 -24
View File
@@ -97,6 +97,54 @@ function isStreamingType(mimeType: string): boolean {
mimeType.startsWith("image/")
);
}
const previewTipText = `
### Preview
Preview is the generic type of block used for viewing files. This can take many different forms based on the type of file being viewed.
You can use \`wsh view [path]\` from any Wave terminal window to open a preview block with the contents of the specified path (e.g. \`wsh view .\` or \`wsh view ~/myimage.jpg\`).
#### Directory
When looking at a directory, preview will show a file viewer much like MacOS' *Finder* application or Windows' *File Explorer* application. This variant is slightly more geared toward software development with the focus on seeing what is shown by the \`ls -alh\` command.
##### View a New File
The simplest way to view a new file is to double click its row in the file viewer. Alternatively, while the block is focused, you can use the &uarr; and &darr; arrow keys to select a row and press enter to preview the associated file.
##### View the Parent Directory
In the directory view, this is as simple as opening the \`..\` file as if it were a regular file. This can be done with the method above. You can also use the keyboard shortcut \`Cmd + ArrowUp\`.
##### Navigate Back and Forward
When looking at a file, you can navigate back by clicking the back button in the block header or the keyboard shortcut \`Cmd + ArrowLeft\`. You can always navigate back and forward using \`Cmd + ArrowLeft\` and \`Cmd + ArrowRight\`.
##### Filter the List of Files
While the block is focused, you can filter by filename by typing a substring of the filename you're working for. To clear the filter, you can click the &#x2715; on the filter dropdown or press esc.
##### Sort by a File Column
To sort a file by a specific column, click on the header for that column. If you click the header again, it will reverse the sort order.
##### Hide and Show Hidden Files
At the right of the block header, there is an &#128065;&#65039; button. Clicking this button hides and shows hidden files.
##### Refresh the Directory
At the right of the block header, there is a refresh button. Clicking this button refreshes the directory contents.
##### Navigate to Common Directories
At the left of the block header, there is a file icon. Clicking and holding on this icon opens a menu where you can select a common folder to navigate to. The available options are *Home*, *Desktop*, *Downloads*, and *Root*.
##### Open a New Terminal in the Current Directory
If you right click the header of the block (alternatively, click the gear icon), one of the menu items listed is **Open Terminal in New Block**. This will create a new terminal block at your current directory.
##### Open a New Terminal in a Child Directory
If you want to open a terminal for a child directory instead, you can right click on that file's row to get the **Open Terminal in New Block** option. Clicking this will open a terminal at that directory. Note that this option is only available for children that are directories.
##### Open a New Preview for a Child
To open a new Preview Block for a Child, you can right click on that file's row and select the **Open Preview in New Block** option.
#### Markdown
Opening a markdown file will bring up a view of the rendered markdown. These files cannot be edited in the preview at this time.
#### Images/Media
Opening a picture will bring up the image of that picture. Opening a video will bring up a player that lets you watch the video.
`;
export class PreviewModel implements ViewModel {
viewType: string;
blockId: string;
@@ -125,8 +173,7 @@ export class PreviewModel implements ViewModel {
fullFile: jotai.Atom<Promise<FullFile>>;
fileMimeType: jotai.Atom<Promise<string>>;
fileMimeTypeLoadable: jotai.Atom<Loadable<string>>;
fileContentSaved: jotai.PrimitiveAtom<string | null>;
fileContent: jotai.WritableAtom<Promise<string>, [string], void>;
fileContent: jotai.Atom<Promise<string>>;
newFileContent: jotai.PrimitiveAtom<string | null>;
openFileModal: jotai.PrimitiveAtom<boolean>;
@@ -144,8 +191,6 @@ export class PreviewModel implements ViewModel {
codeEditKeyDownHandler: (waveEvent: WaveKeyboardEvent) => boolean;
setPreviewFileName(fileName: string) {
globalStore.set(this.fileContentSaved, null);
globalStore.set(this.newFileContent, null);
services.ObjectService.UpdateObjectMeta(`block:${this.blockId}`, { file: fileName });
}
@@ -385,25 +430,10 @@ export class PreviewModel implements ViewModel {
return file;
});
this.fileContentSaved = jotai.atom(null) as jotai.PrimitiveAtom<string | null>;
const fileContentAtom = jotai.atom(
async (get) => {
const _ = get(this.metaFilePath);
const newContent = get(this.newFileContent);
if (newContent != null) {
return newContent;
}
const savedContent = get(this.fileContentSaved);
if (savedContent != null) {
return savedContent;
}
const fullFile = await get(fullFileAtom);
return util.base64ToString(fullFile?.data64);
},
(get, set, update: string) => {
set(this.fileContentSaved, update);
}
);
const fileContentAtom = jotai.atom<Promise<string>>(async (get) => {
const fullFile = await get(fullFileAtom);
return util.base64ToString(fullFile?.data64);
});
this.fullFile = fullFileAtom;
this.fileContent = fileContentAtom;
@@ -560,7 +590,6 @@ export class PreviewModel implements ViewModel {
const conn = globalStore.get(this.connection) ?? "";
try {
services.FileService.SaveFile(conn, filePath, util.stringToBase64(newFileContent));
globalStore.set(this.fileContent, newFileContent);
globalStore.set(this.newFileContent, null);
console.log("saved file", filePath);
} catch (error) {
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
.quicktips-view {
padding: 10px 5px;
padding: 10px 2px;
overflow: auto;
width: 100%;
}
+22 -52
View File
@@ -1,10 +1,8 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
import { getApi, openLink, useSettingsKeyAtom } from "@/app/store/global";
import { getApi, openLink } from "@/app/store/global";
import { getSimpleControlShiftAtom } from "@/app/store/keymodel";
import { RpcApi } from "@/app/store/wshclientapi";
import { WindowRpcClient } from "@/app/store/wshrpcutil";
import { NodeModel } from "@/layout/index";
import { WOS, globalStore } from "@/store/global";
import * as services from "@/store/services";
@@ -32,7 +30,6 @@ export class WebViewModel implements ViewModel {
webviewRef: React.RefObject<WebviewTag>;
urlInputRef: React.RefObject<HTMLInputElement>;
nodeModel: NodeModel;
endIconButtons?: jotai.Atom<IconButtonDecl[]>;
constructor(blockId: string, nodeModel: NodeModel) {
this.nodeModel = nodeModel;
@@ -51,8 +48,7 @@ export class WebViewModel implements ViewModel {
this.webviewRef = React.createRef<WebviewTag>();
this.viewText = jotai.atom((get) => {
const defaultUrlAtom = useSettingsKeyAtom("web:defaulturl");
let url = get(this.blockAtom)?.meta?.url || get(defaultUrlAtom);
let url = get(this.blockAtom)?.meta?.url || "";
const currUrl = get(this.url);
if (currUrl !== undefined) {
url = currUrl;
@@ -95,22 +91,6 @@ export class WebViewModel implements ViewModel {
},
] as HeaderElem[];
});
this.endIconButtons = jotai.atom((get) => {
return [
{
elemtype: "iconbutton",
icon: "arrow-up-right-from-square",
title: "Open in External Browser",
click: () => {
const url = this.getUrl();
if (url != null && url != "") {
return getApi().openExternal(this.getUrl());
}
},
},
];
});
}
/**
@@ -219,11 +199,7 @@ export class WebViewModel implements ViewModel {
globalStore.set(this.url, url);
}
ensureUrlScheme(url: string, searchTemplate: string) {
if (url == null) {
url = "";
}
ensureUrlScheme(url: string) {
if (/^(http|https):/.test(url)) {
// If the URL starts with http: or https:, return it as is
return url;
@@ -247,10 +223,23 @@ export class WebViewModel implements ViewModel {
}
// Otherwise, treat it as a search query
if (searchTemplate == null) {
return `https://www.google.com/search?q=${encodeURIComponent(url)}`;
return `https://www.google.com/search?q=${encodeURIComponent(url)}`;
}
normalizeUrl(url: string) {
if (!url) {
return url;
}
try {
const parsedUrl = new URL(url);
if (parsedUrl.hostname.startsWith("www.")) {
parsedUrl.hostname = parsedUrl.hostname.slice(4);
}
return parsedUrl.href;
} catch (e) {
return url.replace(/\/+$/, "") + "/";
}
return searchTemplate.replace("{query}", encodeURIComponent(url));
}
/**
@@ -258,9 +247,7 @@ export class WebViewModel implements ViewModel {
* @param newUrl The new URL to load in the webview.
*/
loadUrl(newUrl: string, reason: string) {
const defaultSearchAtom = useSettingsKeyAtom("web:defaultsearch");
const searchTemplate = globalStore.get(defaultSearchAtom);
const nextUrl = this.ensureUrlScheme(newUrl, searchTemplate);
const nextUrl = this.ensureUrlScheme(newUrl);
console.log("webview loadUrl", reason, nextUrl, "cur=", this.webviewRef?.current.getURL());
if (newUrl != nextUrl) {
globalStore.set(this.url, nextUrl);
@@ -330,20 +317,8 @@ export class WebViewModel implements ViewModel {
return false;
}
getSettingsMenuItems(): ContextMenuItem[] {
getSettingsMenuItems() {
return [
{
label: "Set Homepage",
click: async () => {
const url = this.getUrl();
if (url != null && url != "") {
RpcApi.SetConfigCommand(WindowRpcClient, { "web:defaulturl": url });
}
},
},
{
type: "separator",
},
{
label: this.webviewRef.current?.isDevToolsOpened() ? "Close DevTools" : "Open DevTools",
click: async () => {
@@ -372,12 +347,7 @@ interface WebViewProps {
const WebView = memo(({ model }: WebViewProps) => {
const blockData = jotai.useAtomValue(model.blockAtom);
const defaultUrlAtom = useSettingsKeyAtom("web:defaulturl");
const defaultUrl = jotai.useAtomValue(defaultUrlAtom);
const defaultSearchAtom = useSettingsKeyAtom("web:defaultsearch");
const defaultSearch = jotai.useAtomValue(defaultSearchAtom);
let metaUrl = blockData?.meta?.url || defaultUrl;
metaUrl = model.ensureUrlScheme(metaUrl, defaultSearch);
const metaUrl = blockData?.meta?.url;
const metaUrlRef = React.useRef(metaUrl);
// The initial value of the block metadata URL when the component first renders. Used to set the starting src value for the webview.
-2
View File
@@ -421,8 +421,6 @@ declare global {
"editor:stickyscrollenabled"?: boolean;
"web:*"?: boolean;
"web:openlinksinternally"?: boolean;
"web:defaulturl"?: string;
"web:defaultsearch"?: string;
"blockheader:*"?: boolean;
"blockheader:showblockids"?: boolean;
"autoupdate:*"?: boolean;
+9 -9
View File
@@ -7,7 +7,7 @@
"productName": "Wave",
"description": "Open-Source AI-Native Terminal Built for Seamless Workflows",
"license": "Apache-2.0",
"version": "0.8.0",
"version": "0.8.0-beta.7",
"homepage": "https://waveterm.dev",
"build": {
"appId": "dev.commandline.waveterm"
@@ -30,13 +30,13 @@
"@chromatic-com/storybook": "^2.0.2",
"@eslint/js": "^9.10.0",
"@rollup/plugin-node-resolve": "^15.2.3",
"@storybook/addon-essentials": "^8.3.0",
"@storybook/addon-interactions": "^8.3.0",
"@storybook/addon-links": "^8.3.0",
"@storybook/blocks": "^8.3.0",
"@storybook/react": "^8.3.0",
"@storybook/react-vite": "^8.3.0",
"@storybook/test": "^8.3.0",
"@storybook/addon-essentials": "^8.3.2",
"@storybook/addon-interactions": "^8.3.2",
"@storybook/addon-links": "^8.3.2",
"@storybook/blocks": "^8.3.2",
"@storybook/react": "^8.3.2",
"@storybook/react-vite": "^8.3.2",
"@storybook/test": "^8.3.2",
"@types/css-tree": "^2",
"@types/debug": "^4",
"@types/electron": "^1.6.10",
@@ -65,7 +65,7 @@
"prettier-plugin-organize-imports": "^4.0.0",
"rollup-plugin-flow": "^1.1.1",
"semver": "^7.6.3",
"storybook": "^8.3.0",
"storybook": "^8.3.2",
"ts-node": "^10.9.2",
"tslib": "^2.6.3",
"tsx": "^4.19.1",
+2 -2
View File
@@ -166,7 +166,7 @@ func StartRemoteShellProc(termSize waveobj.TermSize, cmdStr string, cmdOpts Comm
} else if remote.IsPowershell(shellPath) {
// powershell is weird about quoted path executables and requires an ampersand first
shellPath = "& " + shellPath
shellOpts = append(shellOpts, "-ExecutionPolicy", "Bypass", "-NoExit", "-File", homeDir+fmt.Sprintf("/.waveterm/%s/wavepwsh.ps1", shellutil.PwshIntegrationDir))
shellOpts = append(shellOpts, "-NoExit", "-File", homeDir+fmt.Sprintf("/.waveterm/%s/wavepwsh.ps1", shellutil.PwshIntegrationDir))
} else {
if cmdOpts.Login {
shellOpts = append(shellOpts, "-l")
@@ -276,7 +276,7 @@ func StartShellProc(termSize waveobj.TermSize, cmdStr string, cmdOpts CommandOpt
// cant set -l or -i with --rcfile
shellOpts = append(shellOpts, "--rcfile", shellutil.GetBashRcFileOverride())
} else if remote.IsPowershell(shellPath) {
shellOpts = append(shellOpts, "-ExecutionPolicy", "Bypass", "-NoExit", "-File", shellutil.GetWavePowershellEnv())
shellOpts = append(shellOpts, "-NoExit", "-File", shellutil.GetWavePowershellEnv())
} else {
if cmdOpts.Login {
shellOpts = append(shellOpts, "-l")

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