Skip to content

Commit 95a97ca

Browse files
Copilotsawka
andauthored
Add Onboarding Flows to Preview Server (#2960)
`FilesPage` was previously previewed through a special path because `EditBashrcCommand` (Monaco via `CodeEditor`) threw in preview mode. With preview/global handling now fixed, preview can run the real Files onboarding flow end-to-end without command overrides. - **Files preview now uses the real FilesPage path** - `OnboardingPreview` renders `FilesPage` directly. - Removed preview-only command injection/override behavior for Files onboarding. - **Reverted FilesPage customization** - Dropped optional command renderer plumbing added for preview. - Restored FilesPage to its original internal command rotation: `EditBashrcCommand -> ViewShortcutsCommand -> ViewLogoCommand`. - **Result** - No Files-specific preview fork remains. - Preview and production use the same FilesPage command lifecycle. ```tsx const commands = [ (onComplete: () => void) => <EditBashrcCommand onComplete={onComplete} />, (onComplete: () => void) => <ViewShortcutsCommand isMac={isMac} onComplete={onComplete} />, (onComplete: () => void) => <ViewLogoCommand onComplete={onComplete} />, ]; ``` <screenshot> ![Onboarding FilesPage preview using default commands](https://github.com/user-attachments/assets/c5baf015-6204-41da-b72b-408ef137f32b) </screenshot> <!-- START COPILOT CODING AGENT TIPS --> --- ✨ Let Copilot coding agent [set things up for you](https://github.com/wavetermdev/waveterm/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: sawka <2722291+sawka@users.noreply.github.com> Co-authored-by: sawka <mike@commandline.dev>
1 parent cff8477 commit 95a97ca

File tree

8 files changed

+94
-15
lines changed

8 files changed

+94
-15
lines changed

frontend/app/monaco/monaco-react.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export function MonacoCodeEditor({ text, readonly, language, onChange, onMount,
5656
return () => {
5757
sub.dispose();
5858
if (onUnmountRef.current) onUnmountRef.current();
59+
editor.setModel(null);
5960
editor.dispose();
6061
model.dispose();
6162
console.log("[monaco] dispose model");
@@ -146,6 +147,7 @@ export function MonacoDiffViewer({ original, modified, language, path, options }
146147
diff.setModel({ original: originalModel, modified: modifiedModel });
147148

148149
return () => {
150+
diff.setModel(null);
149151
diff.dispose();
150152
originalModel.dispose();
151153
modifiedModel.dispose();

frontend/app/onboarding/onboarding-features.tsx

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { FakeLayout } from "./onboarding-layout";
1919

2020
type FeaturePageName = "waveai" | "durable" | "magnify" | "files";
2121

22-
const WaveAIPage = ({ onNext, onSkip }: { onNext: () => void; onSkip: () => void }) => {
22+
export const WaveAIPage = ({ onNext, onSkip }: { onNext: () => void; onSkip: () => void }) => {
2323
const isMac = isMacOS();
2424
const shortcutKey = isMac ? "⌘-Shift-A" : "Alt-Shift-A";
2525
const [fireClicked, setFireClicked] = useState(false);
@@ -106,7 +106,7 @@ const WaveAIPage = ({ onNext, onSkip }: { onNext: () => void; onSkip: () => void
106106
);
107107
};
108108

109-
const MagnifyBlocksPage = ({
109+
export const MagnifyBlocksPage = ({
110110
onNext,
111111
onSkip,
112112
onPrev,
@@ -149,13 +149,13 @@ const MagnifyBlocksPage = ({
149149
better view.
150150
</p>
151151
<p>Use the magnify feature to work with complex outputs and large files more efficiently.</p>
152-
<p>
152+
<div>
153153
You can also magnify a block by clicking on the{" "}
154154
<span className="inline-block align-middle [&_svg_path]:!fill-foreground">
155155
<MagnifyIcon enabled={false} />
156156
</span>{" "}
157157
icon in the block header.
158-
</p>
158+
</div>
159159
<p>
160160
A quick {shortcutKey}-M to magnify and another {shortcutKey}-M to unmagnify
161161
</p>
@@ -172,11 +172,10 @@ const MagnifyBlocksPage = ({
172172
);
173173
};
174174

175-
const FilesPage = ({ onFinish, onPrev }: { onFinish: () => void; onPrev?: () => void }) => {
175+
export const FilesPage = ({ onFinish, onPrev }: { onFinish: () => void; onPrev?: () => void }) => {
176176
const [fireClicked, setFireClicked] = useState(false);
177177
const isMac = isMacOS();
178178
const [commandIndex, setCommandIndex] = useState(0);
179-
const [key, setKey] = useState(0);
180179

181180
const handleFireClick = () => {
182181
setFireClicked(!fireClicked);
@@ -200,7 +199,6 @@ const FilesPage = ({ onFinish, onPrev }: { onFinish: () => void; onPrev?: () =>
200199
const handleCommandComplete = () => {
201200
setTimeout(() => {
202201
setCommandIndex((prev) => (prev + 1) % commands.length);
203-
setKey((prev) => prev + 1);
204202
}, 2500);
205203
};
206204

frontend/app/onboarding/onboarding-upgrade-patch.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ interface VersionConfig {
2929
nextText?: string;
3030
}
3131

32-
const versions: VersionConfig[] = [
32+
export const UpgradeOnboardingVersions: VersionConfig[] = [
3333
{
3434
version: "v0.12.1",
3535
content: () => <UpgradeOnboardingModal_v0_12_1_Content />,
@@ -69,11 +69,11 @@ const versions: VersionConfig[] = [
6969
const UpgradeOnboardingPatch = () => {
7070
const modalRef = useRef<HTMLDivElement | null>(null);
7171
const [isCompact, setIsCompact] = useState<boolean>(window.innerHeight < 800);
72-
const [currentIndex, setCurrentIndex] = useState<number>(versions.length - 1);
72+
const [currentIndex, setCurrentIndex] = useState<number>(UpgradeOnboardingVersions.length - 1);
7373

74-
const currentVersion = versions[currentIndex];
74+
const currentVersion = UpgradeOnboardingVersions[currentIndex];
7575
const hasPrev = currentIndex > 0;
76-
const hasNext = currentIndex < versions.length - 1;
76+
const hasNext = currentIndex < UpgradeOnboardingVersions.length - 1;
7777

7878
const updateModalHeight = () => {
7979
const windowHeight = window.innerHeight;

frontend/app/store/global.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ import {
2525
isBlank,
2626
isLocalConnName,
2727
isWslConnName,
28+
NullAtom,
2829
} from "@/util/util";
30+
import { isPreviewWindow } from "./windowtype";
2931
import { atom, Atom, PrimitiveAtom, useAtomValue } from "jotai";
3032
import {
3133
atoms,
@@ -168,6 +170,7 @@ function useOrefMetaKeyAtom<T extends keyof MetaType>(oref: string, key: T): Met
168170
}
169171

170172
function getConnConfigKeyAtom<T extends keyof ConnKeywords>(connName: string, key: T): Atom<ConnKeywords[T]> {
173+
if (isPreviewWindow()) return NullAtom as Atom<ConnKeywords[T]>;
171174
let connCache = getSingleConnAtomCache(connName);
172175
const keyAtomName = "#conn-" + key;
173176
let keyAtom = connCache.get(keyAtomName);
@@ -185,6 +188,7 @@ function getConnConfigKeyAtom<T extends keyof ConnKeywords>(connName: string, ke
185188
const settingsAtomCache = new Map<string, Atom<any>>();
186189

187190
function getOverrideConfigAtom<T extends keyof SettingsType>(blockId: string, key: T): Atom<SettingsType[T]> {
191+
if (isPreviewWindow()) return NullAtom as Atom<SettingsType[T]>;
188192
const blockCache = getSingleBlockAtomCache(blockId);
189193
const overrideAtomName = "#settingsoverride-" + key;
190194
let overrideAtom = blockCache.get(overrideAtomName);
@@ -223,6 +227,7 @@ function useOverrideConfigAtom<T extends keyof SettingsType>(blockId: string | n
223227
}
224228

225229
function getSettingsKeyAtom<T extends keyof SettingsType>(key: T): Atom<SettingsType[T]> {
230+
if (isPreviewWindow()) return NullAtom as Atom<SettingsType[T]>;
226231
let settingsKeyAtom = settingsAtomCache.get(key) as Atom<SettingsType[T]>;
227232
if (settingsKeyAtom == null) {
228233
settingsKeyAtom = atom((get) => {
@@ -242,6 +247,7 @@ function useSettingsKeyAtom<T extends keyof SettingsType>(key: T): SettingsType[
242247
}
243248

244249
function getSettingsPrefixAtom(prefix: string): Atom<SettingsType> {
250+
if (isPreviewWindow()) return NullAtom as Atom<SettingsType>;
245251
let settingsPrefixAtom = settingsAtomCache.get(prefix + ":");
246252
if (settingsPrefixAtom == null) {
247253
// create a stable, closured reference to use as the deepCompareReturnPrev key
@@ -745,6 +751,7 @@ function setActiveTab(tabId: string) {
745751
}
746752

747753
function recordTEvent(event: string, props?: TEventProps) {
754+
if (isPreviewWindow()) return;
748755
if (props == null) {
749756
props = {};
750757
}

frontend/preview/preview.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ function PreviewApp() {
9393
return (
9494
<>
9595
<PreviewHeader previewName={previewName} />
96-
<div className="min-h-screen bg-background text-foreground font-sans flex flex-col items-center justify-center">
96+
<div className="h-screen overflow-y-auto bg-background text-foreground font-sans flex flex-col items-center pt-12 pb-8">
9797
<Suspense fallback={null}>
9898
<PreviewComponent />
9999
</Suspense>
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright 2026, Command Line Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import Logo from "@/app/asset/logo.svg";
5+
import { DurableSessionPage } from "@/app/onboarding/onboarding-durable";
6+
import { FilesPage, MagnifyBlocksPage, WaveAIPage } from "@/app/onboarding/onboarding-features";
7+
import { UpgradeOnboardingVersions } from "@/app/onboarding/onboarding-upgrade-patch";
8+
9+
function OnboardingFeaturesV() {
10+
const noop = () => {};
11+
return (
12+
<div className="flex flex-col w-full gap-8">
13+
<div className="w-[800px] rounded-[10px] p-[30px] relative overflow-hidden bg-panel">
14+
<WaveAIPage onNext={noop} onSkip={noop} />
15+
</div>
16+
<div className="w-[800px] rounded-[10px] p-[30px] relative overflow-hidden bg-panel">
17+
<DurableSessionPage onNext={noop} onSkip={noop} onPrev={noop} />
18+
</div>
19+
<div className="w-[800px] rounded-[10px] p-[30px] relative overflow-hidden bg-panel">
20+
<MagnifyBlocksPage onNext={noop} onSkip={noop} onPrev={noop} />
21+
</div>
22+
<div className="w-[800px] rounded-[10px] p-[30px] relative overflow-hidden bg-panel">
23+
<FilesPage onFinish={noop} onPrev={noop} />
24+
</div>
25+
</div>
26+
);
27+
}
28+
29+
function UpgradeOnboardingPatchV() {
30+
return (
31+
<div className="flex flex-col gap-6 w-full max-w-[900px]">
32+
{UpgradeOnboardingVersions.map((version) => (
33+
<div
34+
key={version.version}
35+
className="w-[650px] rounded-[10px] p-[30px] relative overflow-hidden bg-panel"
36+
>
37+
<div className="absolute inset-0 bg-gradient-to-br from-accent/[0.25] via-transparent to-accent/[0.05] pointer-events-none rounded-[10px]" />
38+
<div className="flex flex-col w-full h-full relative z-10">
39+
<header className="flex flex-col gap-2 border-b-0 p-0 mt-1 mb-6 w-full unselectable flex-shrink-0">
40+
<div className="flex justify-center">
41+
<Logo />
42+
</div>
43+
<div className="text-center text-[25px] font-normal text-foreground">
44+
Wave {version.version} Update
45+
</div>
46+
</header>
47+
<div className="flex-1">{version.content()}</div>
48+
</div>
49+
</div>
50+
))}
51+
</div>
52+
);
53+
}
54+
55+
export function OnboardingPreview() {
56+
return (
57+
<div className="w-full max-w-[1300px] py-10 px-4 flex flex-col gap-8">
58+
<div className="text-sm font-mono text-muted">Onboarding features</div>
59+
<OnboardingFeaturesV />
60+
<div className="text-sm font-mono text-muted mt-6">Onboarding patch updates</div>
61+
<UpgradeOnboardingPatchV />
62+
</div>
63+
);
64+
}

frontend/util/endpoints.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
1-
// Copyright 2025, Command Line Inc.
1+
// Copyright 2026, Command Line Inc.
22
// SPDX-License-Identifier: Apache-2.0
33

4+
import { isPreviewWindow } from "@/app/store/windowtype";
45
import { getEnv } from "./getenv";
56
import { lazy } from "./util";
67

78
export const WebServerEndpointVarName = "WAVE_SERVER_WEB_ENDPOINT";
89
export const WSServerEndpointVarName = "WAVE_SERVER_WS_ENDPOINT";
910

10-
export const getWebServerEndpoint = lazy(() => `http://${getEnv(WebServerEndpointVarName)}`);
11+
export const getWebServerEndpoint = lazy(() => {
12+
if (isPreviewWindow()) return null;
13+
return `http://${getEnv(WebServerEndpointVarName)}`;
14+
});
1115

12-
export const getWSServerEndpoint = lazy(() => `ws://${getEnv(WSServerEndpointVarName)}`);
16+
export const getWSServerEndpoint = lazy(() => {
17+
if (isPreviewWindow()) return null;
18+
return `ws://${getEnv(WSServerEndpointVarName)}`;
19+
});

frontend/util/util.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ export {
534534
makeExternLink,
535535
makeIconClass,
536536
mergeMeta,
537+
NullAtom,
537538
parseDataUrl,
538539
sleep,
539540
sortByDisplayOrder,

0 commit comments

Comments
 (0)