From af713273713e15553edd5bc6e5ec2041f5fbe712 Mon Sep 17 00:00:00 2001 From: flamboh Date: Thu, 22 Oct 2026 01:18:04 +0000 Subject: [PATCH] fix(web): provider updates no longer pop toasts on launch --- .../ProviderUpdateEnvironmentRows.tsx | 356 ---------------- ...erUpdateLaunchNotification.environments.ts | 75 ---- ...iderUpdateLaunchNotification.logic.test.ts | 207 --------- .../ProviderUpdateLaunchNotification.logic.ts | 401 +----------------- .../ProviderUpdateLaunchNotification.tsx | 168 -------- .../ProviderUpdatePrimaryNotification.tsx | 340 --------------- apps/web/src/components/ui/toast.tsx | 2 +- apps/web/src/components/ui/toastHelpers.ts | 8 - apps/web/src/providerUpdateDismissal.ts | 36 -- apps/web/src/routes/__root.tsx | 2 - 10 files changed, 6 insertions(+), 1589 deletions(-) delete mode 100644 apps/web/src/components/ProviderUpdateEnvironmentRows.tsx delete mode 100644 apps/web/src/components/ProviderUpdateLaunchNotification.environments.ts delete mode 100644 apps/web/src/components/ProviderUpdateLaunchNotification.tsx delete mode 100644 apps/web/src/components/ProviderUpdatePrimaryNotification.tsx delete mode 100644 apps/web/src/providerUpdateDismissal.ts diff --git a/apps/web/src/components/ProviderUpdateEnvironmentRows.tsx b/apps/web/src/components/ProviderUpdateEnvironmentRows.tsx deleted file mode 100644 index eecea9a146531..0000000000000 --- a/apps/web/src/components/ProviderUpdateEnvironmentRows.tsx +++ /dev/null @@ -1,356 +0,0 @@ -import { CheckIcon } from "lucide-react"; -import { type ReactNode, useRef, useState } from "react"; -import { - AuthProvidersManageScope, - type EnvironmentId, - type ServerProvider, -} from "@t3tools/contracts"; -import { - isAtomCommandInterrupted, - settlePromise, - squashAtomCommandFailure, - type AtomCommandResult, -} from "@t3tools/client-runtime/state/runtime"; - -import { cn } from "~/lib/utils"; -import { serverEnvironment } from "~/state/server"; -import { readEnvironmentScope, useEnvironmentScope } from "~/state/session"; -import { useAtomCommand } from "~/state/use-atom-command"; -import { useLocalEnvironmentUpdateGroups } from "./ProviderUpdateLaunchNotification.environments"; -import { - collectProviderUpdateOutcomeSnapshots, - firstRejectedProviderUpdateMessage, - getProviderUpdateProgressToastView, - getProviderUpdateSidebarPillView, - isTerminalProviderUpdatePhase, - resolveEnvironmentUpdateRowStatus, - type LocalEnvironmentUpdateGroup, - type LocalProviderUpdateOutcome, - type ProviderUpdateRowStatus, - type ProviderUpdateRowStatusKind, - type ProviderUpdateToastView, -} from "./ProviderUpdateLaunchNotification.logic"; -import { Button } from "./ui/button"; -import { Spinner } from "./ui/spinner"; - -type ProviderUpdateCommandResult = AtomCommandResult< - { readonly providers: ReadonlyArray }, - unknown ->; - -function toProviderUpdateOutcome(input: { - readonly environmentId: EnvironmentId; - readonly isPrimary: boolean; - readonly target: { - readonly driver: ServerProvider["driver"]; - readonly instanceId: ServerProvider["instanceId"]; - }; - readonly result: ProviderUpdateCommandResult; -}): PromiseSettledResult { - if (input.result._tag === "Failure") { - if (isAtomCommandInterrupted(input.result)) { - return { - status: "fulfilled", - value: { - environmentId: input.environmentId, - isPrimary: input.isPrimary, - driver: input.target.driver, - instanceId: input.target.instanceId, - provider: null, - }, - }; - } - const error = squashAtomCommandFailure(input.result); - return { - status: "rejected", - reason: error instanceof Error ? error : new Error("Provider update failed."), - }; - } - - const provider = - input.result.value.providers.find( - (candidate) => candidate.instanceId === input.target.instanceId, - ) ?? null; - return { - status: "fulfilled", - value: { - environmentId: input.environmentId, - isPrimary: input.isPrimary, - driver: input.target.driver, - instanceId: input.target.instanceId, - provider, - }, - }; -} - -// Keep it well beyond the server's own update timeout (5 min) so a legitimately -// slow update (npm installs routinely run tens of seconds) is never cut off and -// left showing a dead, unresponsive Update button. -const PENDING_EXPIRY_MS = 6 * 60_000; - -function rowToneClass(kind: ProviderUpdateRowStatusKind): string { - switch (kind) { - case "failed": - return "text-destructive"; - case "unchanged": - return "text-warning"; - case "success": - return "text-success"; - default: - return "text-muted-foreground"; - } -} - -function EnvironmentUpdateRow({ - group, - status, - onUpdate, -}: { - readonly group: LocalEnvironmentUpdateGroup; - readonly status: ProviderUpdateRowStatus; - readonly onUpdate: () => void; -}) { - const canManageProviders = useEnvironmentScope(group.environmentId, AuthProvidersManageScope); - let trailing: ReactNode; - switch (status.kind) { - case "loading": - trailing = ; - break; - case "success": - trailing =