diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/pending/$pendingId/page.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/pending/$pendingId/page.tsx index 933c264fc8b..d144b347215 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/pending/$pendingId/page.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/pending/$pendingId/page.tsx @@ -5,7 +5,7 @@ import { useQuery } from "@tanstack/react-query"; import { createFileRoute, useNavigate } from "@tanstack/react-router"; import { useCallback, useEffect, useRef, useState } from "react"; import { GoGitBranch } from "react-icons/go"; -import { HiExclamationTriangle } from "react-icons/hi2"; +import { HiCheck, HiExclamationTriangle } from "react-icons/hi2"; import { useHostTargetUrl } from "renderer/hooks/host-service/useHostTargetUrl"; import { authClient } from "renderer/lib/auth-client"; import { electronTrpc } from "renderer/lib/electron-trpc"; @@ -15,7 +15,6 @@ import { clearAttachments, loadAttachments, } from "renderer/lib/pending-attachment-store"; -import { V2WorkspaceLoadingView } from "renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView"; import { useAdoptWorktree } from "renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/hooks/useAdoptWorktree"; import { useCheckoutDashboardWorkspace } from "renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/hooks/useCheckoutDashboardWorkspace"; import { useCreateDashboardWorkspace } from "renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/hooks/useCreateDashboardWorkspace"; @@ -23,7 +22,6 @@ import { useDashboardSidebarState } from "renderer/routes/_authenticated/hooks/u import { useCollections } from "renderer/routes/_authenticated/providers/CollectionsProvider"; import type { PendingWorkspaceRow } from "renderer/routes/_authenticated/providers/CollectionsProvider/dashboardSidebarLocal/schema"; import { useLocalHostService } from "renderer/routes/_authenticated/providers/LocalHostServiceProvider"; -import type { WorkspaceInitStep } from "shared/types/workspace-init"; import type { ResolvedPrContent } from "./buildForkAgentLaunch"; import { buildAdoptPayload, @@ -279,8 +277,7 @@ function PendingWorkspacePage() { }, [pending, fireIntent]); // Poll host-service for step-by-step progress (fork + checkout only; - // adopt is fast and doesn't instrument progress). Drives the keypad-loader - // off real backend state so keys press as steps advance. + // adopt is fast and doesn't instrument progress). const intentHasProgress = pending?.intent === "fork" || pending?.intent === "checkout"; const hostUrl = useHostTargetUrl(pending?.hostTarget ?? null); @@ -298,7 +295,7 @@ function PendingWorkspacePage() { enabled: pending?.status === "creating" && !!hostUrl && intentHasProgress, }); - const loaderStep = mapHostProgressToInitStep(progress?.steps); + const steps = progress?.steps ?? []; const STALE_THRESHOLD_MS = 2 * 60 * 1000; const [now, setNow] = useState(Date.now()); @@ -374,62 +371,12 @@ function PendingWorkspacePage() { ); } - const creatingTitle = + const creatingLabel = pending.intent === "adopt" - ? "Adopting worktree" + ? "Adopting worktree..." : pending.intent === "checkout" - ? "Checking out branch" - : "Setting up workspace"; - - // Render the keypad through the "succeeded" hold (and during the brief - // pre-sync window before that) so the last key animates to pressed — - // the host clears progress without ever flagging "registering: done", - // so the success transition is the only signal we have for that frame. - const showKeypad = - pending.status === "creating" || - (pending.status === "succeeded" && !(syncTimedOut && !workspaceSynced)); - - if (showKeypad) { - const isFinalizing = pending.status === "succeeded"; - return ( - - {!isFinalizing && ( - - )} - {isFinalizing && pending.warnings.length > 0 && ( - - )} - - ); - } + ? "Checking out branch..." + : "Creating workspace..."; return (
@@ -442,30 +389,59 @@ function PendingWorkspacePage() {
- {pending.status === "succeeded" && syncTimedOut && !workspaceSynced && ( -
-
- - - Workspace was created but hasn't synced to this device yet. - Check your connection. + {pending.status === "creating" && ( +
+
+

+ {isStale + ? "This is taking longer than expected..." + : creatingLabel} +

+ + {elapsedLabel}
-
- - + {intentHasProgress && steps.length > 0 ? ( +
+ {steps.map((step) => ( +
+ {step.status === "done" ? ( + + ) : step.status === "active" ? ( +
+
+
+ ) : ( +
+
+
+ )} + + {step.label} + +
+ ))} +
+ ) : ( + // Adopt has no host-side progress steps — show a generic spinner. +
+
+
+
+
+ )} +
+ + +
+
+ ) : ( +
+
+ + Workspace ready — opening... +
+ {pending.warnings.length > 0 && ( +
    + {pending.warnings.map((w) => ( +
  • + + {w} +
  • + ))} +
+ )} +
+ ))} + {pending.status === "failed" && (
@@ -518,24 +551,3 @@ function PendingWorkspacePage() {
); } - -type HostProgressStep = { - id: string; - label: string; - status: "pending" | "active" | "done"; -}; - -// Maps the host-service's 3-step progress (ensuring_repo → creating_worktree -// → registering) onto the v1 keypad's step vocabulary. Skipped keys (fetching, -// copying_config) press through quickly when the keypad jumps past them. -function mapHostProgressToInitStep( - steps: HostProgressStep[] | null | undefined, -): WorkspaceInitStep | undefined { - if (!steps || steps.length === 0) return undefined; - const byId = new Map(steps.map((s) => [s.id, s.status])); - if (byId.get("registering") === "done") return "ready"; - if (byId.get("registering") === "active") return "finalizing"; - if (byId.get("creating_worktree") === "active") return "creating_worktree"; - if (byId.get("ensuring_repo") === "active") return "syncing"; - return "pending"; -} diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/KeypadLoader/KeypadLoader.css b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/KeypadLoader/KeypadLoader.css deleted file mode 100644 index 07730377568..00000000000 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/KeypadLoader/KeypadLoader.css +++ /dev/null @@ -1,146 +0,0 @@ -.keypad-loader { - --travel: 26; - position: relative; - aspect-ratio: 400 / 310; - display: flex; - place-items: center; - width: clamp(260px, 34vw, 420px); - transform-style: preserve-3d; - user-select: none; -} - -.keypad-loader__base { - position: absolute; - bottom: 0; - width: 100%; - pointer-events: none; -} - -.keypad-loader__base img { - width: 100%; - display: block; -} - -.keypad-loader__key { - position: absolute; - width: 21%; - height: 24%; - transform-style: preserve-3d; - clip-path: polygon( - 0 0, - 54% 0, - 89% 24%, - 100% 70%, - 54% 100%, - 46% 100%, - 0 69%, - 12% 23%, - 47% 0% - ); - mask: url("../assets/key-single.png") 50% 50% / 100% 100%; - -webkit-mask: url("../assets/key-single.png") 50% 50% / 100% 100%; -} - -.keypad-loader__key--one { - left: 13.5%; - bottom: 57.2%; -} -.keypad-loader__key--two { - left: 25.8%; - bottom: 48.5%; -} -.keypad-loader__key--three { - left: 38%; - bottom: 39.2%; -} -.keypad-loader__key--four { - left: 50.4%; - bottom: 30.2%; -} -.keypad-loader__key--five { - left: 62.7%; - bottom: 21%; -} - -.keypad-loader__mask { - width: 100%; - height: 100%; - display: inline-block; -} - -.keypad-loader__content { - width: 100%; - height: 100%; - display: inline-block; - position: relative; - container-type: inline-size; - transition: - translate 0.7s cubic-bezier(0.22, 1, 0.36, 1), - filter 0.7s ease-out; -} - -.keypad-loader__content img { - position: absolute; - top: 0; - left: 50%; - width: 96%; - translate: -50% 1%; - pointer-events: none; - filter: hue-rotate(118deg) saturate(1.15) brightness(0.92); - transition: filter 0.7s ease-out; -} - -.keypad-loader__key[data-pressed="true"] .keypad-loader__content { - translate: 0 calc(var(--travel) * 1%); -} - -.keypad-loader__key[data-pressed="true"] .keypad-loader__content img { - filter: hue-rotate(118deg) saturate(1.35) brightness(1.05); -} - -.keypad-loader__key[data-active="true"] .keypad-loader__content { - animation: keypad-loader-bob 2.2s ease-in-out infinite; -} - -@keyframes keypad-loader-bob { - 0%, - 100% { - translate: 0 0; - } - 50% { - translate: 0 calc(var(--travel) * 0.28%); - } -} - -.keypad-loader__text { - position: absolute; - top: 5%; - left: 0; - width: 52%; - height: 62%; - z-index: 21; - font-size: 18cqi; - color: #fff; - translate: 45% -16%; - transform: rotateX(36deg) rotateY(45deg) rotateX(-90deg); - display: grid; - place-items: center; - filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.45)); -} - -.keypad-loader__text svg { - width: 62%; - height: 62%; -} - -.keypad-loader__key[data-pressed="true"] .keypad-loader__text { - opacity: 0.85; -} - -@media (prefers-reduced-motion: reduce) { - .keypad-loader__content, - .keypad-loader__key[data-active="true"] .keypad-loader__content { - transition: none; - animation: none; - } -} diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/KeypadLoader/KeypadLoader.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/KeypadLoader/KeypadLoader.tsx deleted file mode 100644 index ef5f10be5f9..00000000000 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/KeypadLoader/KeypadLoader.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import { cn } from "@superset/ui/utils"; -import type { ComponentType } from "react"; -import { - LuDatabase, - LuDownload, - LuFileCog, - LuGitBranch, - LuRefreshCw, -} from "react-icons/lu"; -import { - getStepIndex, - type WorkspaceInitStep, -} from "shared/types/workspace-init"; -import keySingleUrl from "../assets/key-single.png"; -import keypadBaseUrl from "../assets/keypad-base.png"; -import "./KeypadLoader.css"; - -type KeyId = "one" | "two" | "three" | "four" | "five"; - -interface KeyDef { - id: KeyId; - pressedAfter: WorkspaceInitStep; - activeSteps: readonly WorkspaceInitStep[]; - Icon: ComponentType<{ className?: string }>; - label: string; -} - -const KEYS: readonly KeyDef[] = [ - { - id: "one", - pressedAfter: "verifying", - activeSteps: ["pending", "syncing", "verifying"], - Icon: LuRefreshCw, - label: "Syncing", - }, - { - id: "two", - pressedAfter: "fetching", - activeSteps: ["fetching"], - Icon: LuDownload, - label: "Fetching", - }, - { - id: "three", - pressedAfter: "creating_worktree", - activeSteps: ["creating_worktree"], - Icon: LuGitBranch, - label: "Creating worktree", - }, - { - id: "four", - pressedAfter: "copying_config", - activeSteps: ["copying_config"], - Icon: LuFileCog, - label: "Copying config", - }, - { - id: "five", - pressedAfter: "finalizing", - activeSteps: ["finalizing"], - Icon: LuDatabase, - label: "Finalizing", - }, -]; - -interface KeypadLoaderProps { - currentStep: WorkspaceInitStep; - className?: string; -} - -export function KeypadLoader({ currentStep, className }: KeypadLoaderProps) { - const currentIdx = getStepIndex(currentStep); - - return ( -
k.activeSteps.includes(currentStep))?.label ?? - "Preparing" - }`} - > -
- -
- {KEYS.map(({ id, pressedAfter, activeSteps, Icon }) => { - const thresholdIdx = getStepIndex(pressedAfter); - const isPressed = currentIdx > thresholdIdx; - const isActive = activeSteps.includes(currentStep); - return ( -
- - - - - - - - -
- ); - })} -
- ); -} diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/KeypadLoader/index.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/KeypadLoader/index.ts deleted file mode 100644 index d2bb8f2de8f..00000000000 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/KeypadLoader/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { KeypadLoader } from "./KeypadLoader"; diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/StepProgress/StepProgress.css b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/StepProgress/StepProgress.css deleted file mode 100644 index 828f1e522b9..00000000000 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/StepProgress/StepProgress.css +++ /dev/null @@ -1,123 +0,0 @@ -.step-progress { - position: relative; - width: 100%; - max-width: 20rem; - height: 1.75rem; - overflow: hidden; - margin: 0 auto; - mask-image: linear-gradient( - to bottom, - transparent, - black 35%, - black 65%, - transparent - ); - -webkit-mask-image: linear-gradient( - to bottom, - transparent, - black 35%, - black 65%, - transparent - ); -} - -.step-progress__list { - position: relative; - width: 100%; - height: 100%; -} - -.step-progress__item { - position: absolute; - inset: 0; - display: flex; - align-items: center; - justify-content: center; - gap: 0.5rem; - transition: - opacity 0.55s cubic-bezier(0.22, 1, 0.36, 1), - transform 0.55s cubic-bezier(0.22, 1, 0.36, 1), - color 0.3s ease-out; - will-change: transform, opacity; -} - -.step-progress__icon { - display: grid; - place-items: center; - font-size: 0.875rem; - flex-shrink: 0; -} - -.step-progress__check-stroke { - stroke: var(--background, #fff); -} - -.step-progress__title { - font-size: 0.8125rem; - font-weight: 500; - line-height: 1; - display: inline-flex; - align-items: baseline; -} - -.step-progress__ellipsis { - display: inline-flex; - width: 0.9em; - margin-left: 0.05em; - letter-spacing: 0.05em; -} - -.step-progress__ellipsis-dot { - visibility: hidden; - animation: step-progress-dot-1 1.6s steps(1, end) infinite; -} - -.step-progress__ellipsis-dot:nth-child(2) { - animation-name: step-progress-dot-2; -} - -.step-progress__ellipsis-dot:nth-child(3) { - animation-name: step-progress-dot-3; -} - -@keyframes step-progress-dot-1 { - 0% { - visibility: hidden; - } - 25%, - 100% { - visibility: visible; - } -} - -@keyframes step-progress-dot-2 { - 0%, - 25% { - visibility: hidden; - } - 50%, - 100% { - visibility: visible; - } -} - -@keyframes step-progress-dot-3 { - 0%, - 50% { - visibility: hidden; - } - 75%, - 100% { - visibility: visible; - } -} - -@media (prefers-reduced-motion: reduce) { - .step-progress__item { - transition: none; - } - .step-progress__ellipsis-dot { - animation: none; - visibility: visible; - } -} diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/StepProgress/StepProgress.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/StepProgress/StepProgress.tsx deleted file mode 100644 index 6c6d8b0454e..00000000000 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/StepProgress/StepProgress.tsx +++ /dev/null @@ -1,184 +0,0 @@ -import { cn } from "@superset/ui/utils"; -import { useEffect, useState } from "react"; -import { - getStepIndex, - INIT_STEP_MESSAGES, - INIT_STEP_ORDER, - type WorkspaceInitStep, -} from "shared/types/workspace-init"; -import "./StepProgress.css"; - -const DONE_HOLD_MS = 750; - -const DISPLAY_STEPS: readonly WorkspaceInitStep[] = INIT_STEP_ORDER.filter( - (s) => s !== "ready", -); - -type StepState = "waiting" | "progress" | "done"; - -interface StepProgressProps { - currentStep: WorkspaceInitStep; -} - -export function StepProgress({ currentStep }: StepProgressProps) { - const targetIdx = getStepIndex(currentStep); - const [renderIdx, setRenderIdx] = useState(targetIdx); - const [holdDoneIdx, setHoldDoneIdx] = useState(null); - - useEffect(() => { - if (targetIdx === renderIdx) { - setHoldDoneIdx(null); - return; - } - if (targetIdx < renderIdx) { - setRenderIdx(targetIdx); - setHoldDoneIdx(null); - return; - } - setHoldDoneIdx(renderIdx); - const t = window.setTimeout(() => { - setHoldDoneIdx(null); - setRenderIdx((prev) => Math.min(prev + 1, targetIdx)); - }, DONE_HOLD_MS); - return () => window.clearTimeout(t); - }, [targetIdx, renderIdx]); - - return ( -
-
- {DISPLAY_STEPS.map((step) => { - const idx = getStepIndex(step); - const distance = idx - renderIdx; - const isHeldDone = holdDoneIdx === idx; - const state: StepState = isHeldDone - ? "done" - : distance < 0 - ? "done" - : distance === 0 - ? "progress" - : "waiting"; - const fade = Math.abs(distance); - - return ( -
- - - - - {stripEllipsis(INIT_STEP_MESSAGES[step])} - {state === "progress" ? : null} - -
- ); - })} -
-
- ); -} - -function stripEllipsis(s: string) { - return s.replace(/[.…]+$/, ""); -} - -function StepIcon({ state }: { state: StepState }) { - if (state === "done") { - return ; - } - if (state === "progress") { - return ; - } - return ; -} - -function CheckCircle() { - return ( - - ); -} - -function EmptyCircle() { - const angles = Array.from({ length: 16 }, (_, i) => (360 / 16) * i); - return ( - - ); -} - -function HalfCircle() { - return ( - - ); -} - -function Ellipsis() { - return ( - - ); -} diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/StepProgress/index.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/StepProgress/index.ts deleted file mode 100644 index 18126b94971..00000000000 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/StepProgress/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { StepProgress } from "./StepProgress"; diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/assets/key-single.png b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/assets/key-single.png deleted file mode 100644 index 251661fa55d..00000000000 Binary files a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/assets/key-single.png and /dev/null differ diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/assets/keypad-base.png b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/assets/keypad-base.png deleted file mode 100644 index b3dc1ddf578..00000000000 Binary files a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/assets/keypad-base.png and /dev/null differ diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/page.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/page.tsx deleted file mode 100644 index 518ce5aa0be..00000000000 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/page.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { eq } from "@tanstack/db"; -import { useLiveQuery } from "@tanstack/react-db"; -import { createFileRoute, useNavigate } from "@tanstack/react-router"; -import { useEffect } from "react"; -import { useCollections } from "renderer/routes/_authenticated/providers/CollectionsProvider"; -import { V2WorkspaceLoadingView } from "./components/V2WorkspaceLoadingView"; - -export const Route = createFileRoute( - "/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/", -)({ - component: V2WorkspaceLoadingPage, -}); - -function V2WorkspaceLoadingPage() { - const { workspaceId } = Route.useParams(); - const navigate = useNavigate(); - const collections = useCollections(); - - const { data: workspaces, isReady } = useLiveQuery( - (q) => - q - .from({ v2Workspaces: collections.v2Workspaces }) - .where(({ v2Workspaces }) => eq(v2Workspaces.id, workspaceId)), - [collections, workspaceId], - ); - const workspace = workspaces?.[0] ?? null; - - useEffect(() => { - if (!isReady) return; - void navigate({ - to: "/v2-workspace/$workspaceId", - params: { workspaceId }, - replace: true, - }); - }, [isReady, navigate, workspaceId]); - - return ; -} diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/V2WorkspaceLoadingView.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/V2WorkspaceLoadingView/V2WorkspaceLoadingView.tsx similarity index 53% rename from apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/V2WorkspaceLoadingView.tsx rename to apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/V2WorkspaceLoadingView/V2WorkspaceLoadingView.tsx index 806015907ae..8950652536f 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/V2WorkspaceLoadingView.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/V2WorkspaceLoadingView/V2WorkspaceLoadingView.tsx @@ -1,23 +1,13 @@ -import type { ReactNode } from "react"; import { useEffect, useState } from "react"; +import { KeypadLoader } from "renderer/screens/main/components/WorkspaceView/WorkspaceInitializingView/KeypadLoader"; +import { StepProgress } from "renderer/screens/main/components/WorkspaceView/WorkspaceInitializingView/StepProgress"; import { INIT_STEP_ORDER, type WorkspaceInitStep, } from "shared/types/workspace-init"; -import { KeypadLoader } from "./KeypadLoader"; -import { StepProgress } from "./StepProgress"; interface V2WorkspaceLoadingViewProps { workspaceName?: string; - title?: string; - description?: string; - children?: ReactNode; - /** - * Drives the keypad directly. When omitted, the loader cycles through - * steps on a short timer so the keys still animate even with no real - * backend progress data (e.g. adopt intent, cold-load route). - */ - currentStep?: WorkspaceInitStep; } const VISIBLE_STEPS: readonly WorkspaceInitStep[] = INIT_STEP_ORDER.filter( @@ -28,40 +18,33 @@ const STEP_INTERVAL_MS = 400; export function V2WorkspaceLoadingView({ workspaceName, - title = "Loading workspace", - description = "Hang tight while we get things ready", - children, - currentStep: currentStepProp, }: V2WorkspaceLoadingViewProps) { const [stepIdx, setStepIdx] = useState(0); useEffect(() => { - if (currentStepProp !== undefined) return; const id = window.setInterval(() => { setStepIdx((prev) => Math.min(prev + 1, VISIBLE_STEPS.length - 1)); }, STEP_INTERVAL_MS); return () => window.clearInterval(id); - }, [currentStepProp]); + }, []); - const currentStep = currentStepProp ?? VISIBLE_STEPS[stepIdx] ?? "pending"; + const currentStep = VISIBLE_STEPS[stepIdx] ?? "pending"; return (
- +
-

{title}

+

+ Loading workspace +

{workspaceName ? (

{workspaceName}

) : null}
- -

{description}

- - {children}
); diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/index.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/V2WorkspaceLoadingView/index.ts similarity index 100% rename from apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace-loading/$workspaceId/components/V2WorkspaceLoadingView/index.ts rename to apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/V2WorkspaceLoadingView/index.ts diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/layout.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/layout.tsx index f087fe18bd5..9ad28032a31 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/layout.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/layout.tsx @@ -1,12 +1,7 @@ import { buildHostRoutingKey } from "@superset/shared/host-routing"; import { eq } from "@tanstack/db"; import { useLiveQuery } from "@tanstack/react-db"; -import { - createFileRoute, - Outlet, - useMatchRoute, - useNavigate, -} from "@tanstack/react-router"; +import { createFileRoute, Outlet, useMatchRoute } from "@tanstack/react-router"; import { useEffect, useRef } from "react"; import { env } from "renderer/env.renderer"; import { @@ -16,6 +11,7 @@ import { import { useDashboardSidebarState } from "renderer/routes/_authenticated/hooks/useDashboardSidebarState"; import { useCollections } from "renderer/routes/_authenticated/providers/CollectionsProvider"; import { useLocalHostService } from "renderer/routes/_authenticated/providers/LocalHostServiceProvider"; +import { V2WorkspaceLoadingView } from "./components/V2WorkspaceLoadingView"; import { WorkspaceNotFoundState } from "./components/WorkspaceNotFoundState"; import { WorkspaceTrpcProvider } from "./providers/WorkspaceTrpcProvider"; @@ -27,7 +23,6 @@ export const Route = createFileRoute("/_authenticated/_dashboard/v2-workspace")( function V2WorkspaceLayout() { const matchRoute = useMatchRoute(); - const navigate = useNavigate(); const workspaceMatch = matchRoute({ to: "/v2-workspace/$workspaceId", }); @@ -47,6 +42,7 @@ function V2WorkspaceLayout() { .where(({ v2Workspaces }) => eq(v2Workspaces.id, workspaceId ?? "")) .select(({ v2Workspaces, hosts }) => ({ id: v2Workspaces.id, + name: v2Workspaces.name, organizationId: v2Workspaces.organizationId, hostId: v2Workspaces.hostId, hostMachineId: hosts?.machineId ?? null, @@ -73,20 +69,14 @@ function V2WorkspaceLayout() { ensureWorkspaceInSidebar(workspace.id, workspace.projectId); }, [ensureWorkspaceInSidebar, workspace]); - useEffect(() => { - if (workspaceId && !isReady) { - void navigate({ - to: "/v2-workspace-loading/$workspaceId", - params: { workspaceId }, - replace: true, - }); - } - }, [workspaceId, isReady, navigate]); - - if (!workspaceId || !isReady) { + if (!workspaceId) { return null; } + if (!isReady) { + return ; + } + if (!workspace || !hostUrl) { return ; }