authorgravatar for 154429365+Rishet11@users.noreply.github.comRishet11 <154429365+Rishet11@users.noreply.github.com> 2026-08-22 07:42:14+05:30
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-08-21 22:12:14-04:00
log035058a23e651ea5f407c9ab73cf5329cc40c102
tree62b54752c2635f22c4aba2ae6e30891df26ec4fb
parent421088c27367da227d922ce999c1637416a6d0f4
signature Signed by PGP key B5690EEEBB952194

fix(mobile): stop a directly-saved backend from hiding its T3 Connect environment (#7086)


3 files changed, 51 insertions(+), 5 deletions(-)

apps/mobile/src/features/connection/environmentSections.test.ts+30-1
......@@ -2,7 +2,7 @@ import { EnvironmentId } from "@t3tools/contracts";
22import type { RelayClientEnvironmentRecord } from "@t3tools/contracts/relay";
33import { describe, expect, it } from "vite-plus/test";
44import type { ConnectedEnvironmentSummary } from "../../state/remote-runtime-types";
5import { splitEnvironmentSections } from "./environmentSections";
5import { relayManagedEnvironmentIds, splitEnvironmentSections } from "./environmentSections";
66
77function connectedEnvironment(
88 input: Omit<Partial<ConnectedEnvironmentSummary>, "environmentId"> & {
......@@ -34,6 +34,17 @@ function cloudEnvironment(environmentId: string): RelayClientEnvironmentRecord {
3434 };
3535}
3636
37describe("relayManagedEnvironmentIds", () => {
38 it("leaves out a backend that was saved directly", () => {
39 const ids = relayManagedEnvironmentIds([
40 connectedEnvironment({ environmentId: "environment-local", isRelayManaged: false }),
41 connectedEnvironment({ environmentId: "environment-cloud", isRelayManaged: true }),
42 ]);
43
44 expect([...ids]).toEqual([EnvironmentId.make("environment-cloud")]);
45 });
46});
47
3748describe("mobile environment settings sections", () => {
3849 it("keeps saved relay-managed connections under T3 Connect", () => {
3950 const local = connectedEnvironment({
......@@ -111,6 +122,24 @@ describe("mobile environment settings sections", () => {
111122 expect(sections.availableCloudEnvironments).toEqual([]);
112123 });
113124
125 it("still offers a cloud environment saved directly as a local backend", () => {
126 const local = connectedEnvironment({
127 environmentId: "environment-cloud",
128 isRelayManaged: false,
129 });
130
131 const sections = splitEnvironmentSections({
132 connectedEnvironments: [local],
133 cloudEnvironments: [cloudEnvironment("environment-cloud")],
134 });
135
136 expect(sections.localEnvironments).toEqual([local]);
137 expect(sections.connectedCloudEnvironments).toEqual([]);
138 expect(
139 sections.availableCloudEnvironments.map((environment) => environment.environmentId),
140 ).toEqual([EnvironmentId.make("environment-cloud")]);
141 });
142
114143 it("keeps failed relay environments in the local connection row", () => {
115144 const cloud = connectedEnvironment({
116145 environmentId: "environment-cloud",
apps/mobile/src/features/connection/environmentSections.ts+19-3
......@@ -1,3 +1,4 @@
1import type { EnvironmentId } from "@t3tools/contracts";
12import type { RelayClientEnvironmentRecord } from "@t3tools/contracts/relay";
23import type { ConnectedEnvironmentSummary } from "../../state/remote-runtime-types";
34
......@@ -12,10 +13,25 @@ export interface EnvironmentSections {
1213 readonly availableCloudEnvironments: ReadonlyArray<RelayClientEnvironmentRecord>;
1314}
1415
15export function splitEnvironmentSections(input: EnvironmentSectionsInput): EnvironmentSections {
16 const savedEnvironmentIds = new Set(
17 input.connectedEnvironments.map((environment) => environment.environmentId),
16/**
17 * Ids of the environments that already occupy a T3 Connect slot. A backend saved directly is
18 * not one of them, so it must not suppress the cloud environment that happens to share its id.
19 */
20export function relayManagedEnvironmentIds(
21 environments: ReadonlyArray<{
22 readonly environmentId: EnvironmentId;
23 readonly isRelayManaged: boolean;
24 }>,
25): ReadonlySet<EnvironmentId> {
26 return new Set(
27 environments
28 .filter((environment) => environment.isRelayManaged)
29 .map((environment) => environment.environmentId),
1830 );
31}
32
33export function splitEnvironmentSections(input: EnvironmentSectionsInput): EnvironmentSections {
34 const savedEnvironmentIds = relayManagedEnvironmentIds(input.connectedEnvironments);
1935
2036 return {
2137 localEnvironments: input.connectedEnvironments.filter(
apps/mobile/src/features/connection/useConnectionController.ts+2-1
......@@ -20,6 +20,7 @@ import { useEnvironments } from "../../state/environments";
2020import { relayEnvironmentDiscovery } from "../../state/relay";
2121import { useAtomCommand } from "../../state/use-atom-command";
2222import { projectWorkspaceEnvironment, type WorkspaceEnvironment } from "../../state/workspaceModel";
23import { relayManagedEnvironmentIds } from "./environmentSections";
2324
2425export interface RelayEnvironmentView {
2526 readonly environment: RelayClientEnvironmentRecord;
......@@ -49,7 +50,7 @@ export function useConnectionController() {
4950 [environments],
5051 );
5152 const registeredIds = useMemo(
52 () => new Set(connectedEnvironments.map((environment) => environment.environmentId)),
53 () => relayManagedEnvironmentIds(connectedEnvironments),
5354 [connectedEnvironments],
5455 );
5556 const relayEnvironments = useMemo<ReadonlyArray<RelayEnvironmentView>>(