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";...@@ -2,7 +2,7 @@ import { EnvironmentId } from "@t3tools/contracts";
2import type { RelayClientEnvironmentRecord } from "@t3tools/contracts/relay";2import type { RelayClientEnvironmentRecord } from "@t3tools/contracts/relay";
3import { describe, expect, it } from "vite-plus/test";3import { describe, expect, it } from "vite-plus/test";
4import type { ConnectedEnvironmentSummary } from "../../state/remote-runtime-types";4import type { ConnectedEnvironmentSummary } from "../../state/remote-runtime-types";
5import { splitEnvironmentSections } from "./environmentSections";5import { relayManagedEnvironmentIds, splitEnvironmentSections } from "./environmentSections";
66
7function connectedEnvironment(7function connectedEnvironment(
8 input: Omit<Partial<ConnectedEnvironmentSummary>, "environmentId"> & {8 input: Omit<Partial<ConnectedEnvironmentSummary>, "environmentId"> & {
...@@ -34,6 +34,17 @@ function cloudEnvironment(environmentId: string): RelayClientEnvironmentRecord {...@@ -34,6 +34,17 @@ function cloudEnvironment(environmentId: string): RelayClientEnvironmentRecord {
34 };34 };
35}35}
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
37describe("mobile environment settings sections", () => {48describe("mobile environment settings sections", () => {
38 it("keeps saved relay-managed connections under T3 Connect", () => {49 it("keeps saved relay-managed connections under T3 Connect", () => {
39 const local = connectedEnvironment({50 const local = connectedEnvironment({
...@@ -111,6 +122,24 @@ describe("mobile environment settings sections", () => {...@@ -111,6 +122,24 @@ describe("mobile environment settings sections", () => {
111 expect(sections.availableCloudEnvironments).toEqual([]);122 expect(sections.availableCloudEnvironments).toEqual([]);
112 });123 });
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
114 it("keeps failed relay environments in the local connection row", () => {143 it("keeps failed relay environments in the local connection row", () => {
115 const cloud = connectedEnvironment({144 const cloud = connectedEnvironment({
116 environmentId: "environment-cloud",145 environmentId: "environment-cloud",
apps/mobile/src/features/connection/environmentSections.ts+19-3
...@@ -1,3 +1,4 @@...@@ -1,3 +1,4 @@
1import type { EnvironmentId } from "@t3tools/contracts";
1import type { RelayClientEnvironmentRecord } from "@t3tools/contracts/relay";2import type { RelayClientEnvironmentRecord } from "@t3tools/contracts/relay";
2import type { ConnectedEnvironmentSummary } from "../../state/remote-runtime-types";3import type { ConnectedEnvironmentSummary } from "../../state/remote-runtime-types";
34
...@@ -12,10 +13,25 @@ export interface EnvironmentSections {...@@ -12,10 +13,25 @@ export interface EnvironmentSections {
12 readonly availableCloudEnvironments: ReadonlyArray<RelayClientEnvironmentRecord>;13 readonly availableCloudEnvironments: ReadonlyArray<RelayClientEnvironmentRecord>;
13}14}
1415
15export function splitEnvironmentSections(input: EnvironmentSectionsInput): EnvironmentSections {16/**
16 const savedEnvironmentIds = new Set(17 * Ids of the environments that already occupy a T3 Connect slot. A backend saved directly is
17 input.connectedEnvironments.map((environment) => environment.environmentId),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),
18 );30 );
31}
32
33export function splitEnvironmentSections(input: EnvironmentSectionsInput): EnvironmentSections {
34 const savedEnvironmentIds = relayManagedEnvironmentIds(input.connectedEnvironments);
1935
20 return {36 return {
21 localEnvironments: input.connectedEnvironments.filter(37 localEnvironments: input.connectedEnvironments.filter(
apps/mobile/src/features/connection/useConnectionController.ts+2-1
...@@ -20,6 +20,7 @@ import { useEnvironments } from "../../state/environments";...@@ -20,6 +20,7 @@ import { useEnvironments } from "../../state/environments";
20import { relayEnvironmentDiscovery } from "../../state/relay";20import { relayEnvironmentDiscovery } from "../../state/relay";
21import { useAtomCommand } from "../../state/use-atom-command";21import { useAtomCommand } from "../../state/use-atom-command";
22import { projectWorkspaceEnvironment, type WorkspaceEnvironment } from "../../state/workspaceModel";22import { projectWorkspaceEnvironment, type WorkspaceEnvironment } from "../../state/workspaceModel";
23import { relayManagedEnvironmentIds } from "./environmentSections";
2324
24export interface RelayEnvironmentView {25export interface RelayEnvironmentView {
25 readonly environment: RelayClientEnvironmentRecord;26 readonly environment: RelayClientEnvironmentRecord;
...@@ -49,7 +50,7 @@ export function useConnectionController() {...@@ -49,7 +50,7 @@ export function useConnectionController() {
49 [environments],50 [environments],
50 );51 );
51 const registeredIds = useMemo(52 const registeredIds = useMemo(
52 () => new Set(connectedEnvironments.map((environment) => environment.environmentId)),53 () => relayManagedEnvironmentIds(connectedEnvironments),
53 [connectedEnvironments],54 [connectedEnvironments],
54 );55 );
55 const relayEnvironments = useMemo<ReadonlyArray<RelayEnvironmentView>>(56 const relayEnvironments = useMemo<ReadonlyArray<RelayEnvironmentView>>(