Skip to content
Source
Sign inSign up

thread-route-hydration.ts

75 lines2.7 KB

1import type { EnvironmentConnectionPhase } from "@t3tools/client-runtime/connection";
2import type { EnvironmentShellStatus } from "@t3tools/client-runtime/state/shell";
3import type { EnvironmentThreadStatus } from "@t3tools/client-runtime/state/threads";
4import * as Option from "effect/Option";
5​
6export function threadRouteIsHydrating(input: {
7 readonly isLoadingConnections: boolean;
8 readonly environmentRegistered: boolean;
9 readonly localCacheRead: boolean;
10 readonly connectionState: EnvironmentConnectionPhase;
11 readonly shellStatus: EnvironmentShellStatus;
12 readonly shellHasError: boolean;
13 readonly detailStatus: EnvironmentThreadStatus;
14 readonly detailHasError: boolean;
15}): boolean {
16 if (input.detailStatus === "deleted" || input.shellHasError || input.detailHasError) {
17 return false;
18 }
19 if (input.isLoadingConnections) {
20 return true;
21 }
22 if (!input.environmentRegistered) {
23 return false;
24 }
25 if (!input.localCacheRead) {
26 return true;
27 }
28 // Only a first attempt is worth waiting out; a reconnecting environment has already failed.
29 if (
30 input.connectionState === "available" ||
31 input.connectionState === "offline" ||
32 input.connectionState === "reconnecting" ||
33 input.connectionState === "error"
34 ) {
35 return false;
36 }
37 return (
38 input.connectionState === "connecting" ||
39 input.shellStatus === "synchronizing" ||
40 (input.connectionState === "connected" && input.shellStatus === "empty") ||
41 input.detailStatus === "synchronizing" ||
42 (input.connectionState === "connected" && input.detailStatus === "empty")
43 );
45​
46/**
47 * Replacing the route with a draft can't be undone, so a thread that may still arrive keeps its
48 * route: a reconnecting environment often delivers it moments later, and Reconnect starts a
49 * fresh connecting attempt.
50 */
51export function threadRouteOpensDraft(input: {
52 readonly connectionState: EnvironmentConnectionPhase;
53 readonly detailStatus: EnvironmentThreadStatus;
54}): boolean {
55 if (input.detailStatus === "deleted") {
56 return true;
57 }
58 return input.connectionState !== "reconnecting" && input.connectionState !== "connecting";
60​
61/**
62 * A thread keeps its sync error until the new connection resubscribes, so the first renders after
63 * a reconnect still show the old connection's error. Only an error the live connection reported
64 * counts.
65 */
66export function threadDetailErrorIsCurrent<E>(input: {
67 readonly connectionState: EnvironmentConnectionPhase;
68 readonly error: Option.Option<E>;
69 readonly errorBeforeConnected: Option.Option<E>;
70}): boolean {
71 return (
72 Option.isSome(input.error) &&
73 !(input.connectionState === "connected" && input.error === input.errorBeforeConnected)
74 );