feat(FN-3399): route desktop remote mode into shell onboarding flow
Removes the standalone `DesktopShellBootstrap` component from the desktop package, routing desktop remote mode into the shell onboarding flow instead. Updates the corresponding test file to reflect the component removal and adjusts the README. Fusion-Task-Id: FN-3399
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
.desktop-mode-chooser {
|
||||
max-width: 640px;
|
||||
margin: 0 auto;
|
||||
padding: var(--space-2xl);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-lg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-lg);
|
||||
background: var(--card);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.desktop-mode-chooser__title {
|
||||
margin: 0;
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.2;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.desktop-mode-chooser__subtitle {
|
||||
margin: 0;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.desktop-mode-chooser__actions {
|
||||
display: flex;
|
||||
gap: var(--space-md);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import React, { useState } from "react";
|
||||
import "./DesktopModeChooser.css";
|
||||
|
||||
export type DesktopModeChoice = "local" | "remote";
|
||||
|
||||
interface DesktopModeChooserProps {
|
||||
onSelectMode: (mode: DesktopModeChoice) => Promise<void>;
|
||||
}
|
||||
|
||||
export function DesktopModeChooser({ onSelectMode }: DesktopModeChooserProps) {
|
||||
const [pendingMode, setPendingMode] = useState<DesktopModeChoice | null>(null);
|
||||
|
||||
const handleSelect = async (mode: DesktopModeChoice) => {
|
||||
setPendingMode(mode);
|
||||
try {
|
||||
await onSelectMode(mode);
|
||||
} finally {
|
||||
setPendingMode(null);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="desktop-mode-chooser" data-testid="desktop-mode-chooser">
|
||||
<h1 className="desktop-mode-chooser__title">How do you want to run Fusion?</h1>
|
||||
<p className="desktop-mode-chooser__subtitle">
|
||||
Run Fusion locally in this app, or continue with remote server setup.
|
||||
</p>
|
||||
<div className="desktop-mode-chooser__actions">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary"
|
||||
onClick={() => void handleSelect("local")}
|
||||
disabled={pendingMode !== null}
|
||||
>
|
||||
Continue with Local Fusion
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn"
|
||||
onClick={() => void handleSelect("remote")}
|
||||
disabled={pendingMode !== null}
|
||||
>
|
||||
Continue to Remote Connection
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import { DesktopWrapper } from "./DesktopWrapper";
|
||||
import { DesktopModeChooser, type DesktopModeChoice } from "./DesktopModeChooser";
|
||||
|
||||
interface DesktopModeState {
|
||||
isFirstRun: boolean;
|
||||
desktopMode: DesktopModeChoice | null;
|
||||
}
|
||||
|
||||
interface FusionShellWithModeApi {
|
||||
getDesktopModeState: () => Promise<DesktopModeState>;
|
||||
setDesktopMode: (mode: DesktopModeChoice) => Promise<unknown>;
|
||||
}
|
||||
|
||||
function getFusionShell(): FusionShellWithModeApi | null {
|
||||
if (typeof window === "undefined") {
|
||||
return null;
|
||||
}
|
||||
|
||||
const api = (window as Window & { fusionShell?: Partial<FusionShellWithModeApi> }).fusionShell;
|
||||
if (!api?.getDesktopModeState || !api?.setDesktopMode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return api as FusionShellWithModeApi;
|
||||
}
|
||||
|
||||
export function DesktopShellBootstrap({ DashboardApp }: { DashboardApp: React.ComponentType }) {
|
||||
const fusionShell = useMemo(() => getFusionShell(), []);
|
||||
const [modeState, setModeState] = useState<DesktopModeState | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!fusionShell) {
|
||||
setModeState({ isFirstRun: false, desktopMode: "local" });
|
||||
return;
|
||||
}
|
||||
|
||||
let cancelled = false;
|
||||
void fusionShell.getDesktopModeState().then((state) => {
|
||||
if (!cancelled) {
|
||||
setModeState(state);
|
||||
}
|
||||
}).catch(() => {
|
||||
if (!cancelled) {
|
||||
setModeState({ isFirstRun: false, desktopMode: "local" });
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [fusionShell]);
|
||||
|
||||
const handleModeSelect = async (mode: DesktopModeChoice) => {
|
||||
if (fusionShell) {
|
||||
await fusionShell.setDesktopMode(mode);
|
||||
}
|
||||
setModeState({ isFirstRun: false, desktopMode: mode });
|
||||
};
|
||||
|
||||
if (!modeState) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (modeState.isFirstRun) {
|
||||
return (
|
||||
<DesktopWrapper>
|
||||
<DesktopModeChooser onSelectMode={handleModeSelect} />
|
||||
</DesktopWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<DesktopWrapper>
|
||||
<DashboardApp />
|
||||
</DesktopWrapper>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user