import { findErrorTraceId } from "@t3tools/client-runtime/errors";
import {
type EnvironmentConnectionPresentation,
RelayConnectionRegistration,
RelayConnectionTarget,
} from "@t3tools/client-runtime/connection";
import {
isAtomCommandInterrupted,
squashAtomCommandFailure,
} from "@t3tools/client-runtime/state/runtime";
import type { EnvironmentId } from "@t3tools/contracts";
import type { RelayClientEnvironmentRecord } from "@t3tools/contracts/relay";
import * as Option from "effect/Option";
import { type ReactNode, useCallback, useEffect, useState } from "react";
import { environmentCatalog } from "~/connection/catalog";
import { cn } from "~/lib/utils";
import { relayEnvironmentDiscovery } from "~/state/relay";
import { useRelayEnvironmentDiscovery } from "~/state/environments";
import { useAtomCommand } from "~/state/use-atom-command";
import { ConnectionStatusDot } from "../ConnectionStatusDot";
import { ITEM_ROW_CLASSNAME, ITEM_ROW_INNER_CLASSNAME } from "../settings/itemRows";
import { Button } from "../ui/button";
import { Skeleton } from "../ui/skeleton";
import { toastManager } from "../ui/toast";
import { presentSavedCloudEnvironmentConnection } from "./cloudEnvironmentConnectionPresentation";
export interface SavedCloudEnvironmentConnection {
readonly environmentId: EnvironmentId;
readonly connection: EnvironmentConnectionPresentation;
}
export function RemoteEnvironmentRowsSkeleton() {
return (
);
}
/**
* The user's T3 Connect environments from relay discovery, each with a
* Connect button. The primary environment is always excluded; already-saved
* environments are hidden unless `showSavedEnvironments` renders them with
* their live connection state (used by onboarding, where the full device mesh
* should be visible).
*/
export function CloudEnvironmentConnectRows({
primaryEnvironmentId,
savedEnvironments,
showSavedEnvironments = false,
empty = null,
}: {
readonly primaryEnvironmentId: EnvironmentId | null;
readonly savedEnvironments: ReadonlyArray;
readonly showSavedEnvironments?: boolean;
readonly empty?: ReactNode;
}) {
const environmentsState = useRelayEnvironmentDiscovery();
const registerEnvironment = useAtomCommand(environmentCatalog.register, {
reportFailure: false,
});
const refreshRelayEnvironments = useAtomCommand(relayEnvironmentDiscovery.refresh, {
reportFailure: false,
});
const connectRelayEnvironment = useCallback(
(environment: RelayClientEnvironmentRecord) =>
registerEnvironment(
new RelayConnectionRegistration({
target: new RelayConnectionTarget({
environmentId: environment.environmentId,
label: environment.label,
}),
}),
),
[registerEnvironment],
);
const [connectingEnvironmentId, setConnectingEnvironmentId] = useState(
null,
);
const savedById = new Map(
savedEnvironments.map((environment) => [environment.environmentId, environment]),
);
useEffect(() => {
void refreshRelayEnvironments();
}, [refreshRelayEnvironments]);
const connectEnvironment = async (environment: RelayClientEnvironmentRecord) => {
setConnectingEnvironmentId(environment.environmentId);
const result = await connectRelayEnvironment(environment);
setConnectingEnvironmentId(null);
if (result._tag === "Success") {
toastManager.add({
type: "success",
title: "Environment added",
description: `Connecting to ${environment.label} through T3 Connect.`,
});
return;
}
if (isAtomCommandInterrupted(result)) {
return;
}
const cause = squashAtomCommandFailure(result);
const message =
cause instanceof Error ? cause.message : "Could not connect the T3 Connect environment.";
const traceId = findErrorTraceId(cause);
console.error("[t3-connect] Could not connect environment", { message, traceId, cause });
toastManager.add({
type: "error",
title: "Could not connect environment",
description: message,
data: traceId
? {
secondaryActionProps: {
children: "Copy trace ID",
onClick: () => void navigator.clipboard?.writeText(traceId),
},
}
: undefined,
});
};
const visibleEnvironments = [...environmentsState.environments.values()].filter(
({ environment }) =>
environment.environmentId !== primaryEnvironmentId &&
(showSavedEnvironments || !savedById.has(environment.environmentId)),
);
const standalone = showSavedEnvironments || savedEnvironments.length === 0;
if (
standalone &&
visibleEnvironments.length === 0 &&
environmentsState.refreshing &&
environmentsState.environments.size === 0
) {
return ;
}
if (standalone && visibleEnvironments.length === 0) {
// A failed or offline discovery is not "no environments" — misreporting it
// as empty would read as the user's devices having disappeared.
const discoveryProblem = environmentsState.offline
? "You appear to be offline."
: (Option.getOrNull(environmentsState.error)?.message ?? null);
if (discoveryProblem !== null && !environmentsState.refreshing) {
return (
Could not load T3 Connect environments
{discoveryProblem}
);
}
return empty;
}
return visibleEnvironments.map(({ environment, availability, error }) => {
const savedEnvironment = savedById.get(environment.environmentId);
const savedConnection = savedEnvironment
? presentSavedCloudEnvironmentConnection(savedEnvironment.connection)
: null;
const dotClassName = savedConnection
? savedConnection.tone === "connected"
? "bg-success"
: savedConnection.tone === "connecting"
? "bg-warning"
: savedConnection.tone === "error"
? "bg-destructive"
: "bg-muted-foreground/35"
: availability === "online"
? "bg-success"
: availability === "error"
? "bg-destructive"
: availability === "checking"
? "bg-warning"
: "bg-muted-foreground/35";
const statusText = savedConnection
? savedConnection.statusText
: availability === "online"
? "Available · Relay online"
: availability === "offline"
? "Available · Relay offline"
: availability === "checking"
? "Available · Checking relay status…"
: (Option.getOrNull(error)?.message ?? "Available · Relay status unavailable");
return (
{savedConnection ? (
) : (
)}
);
});
}