| author | |
| committer | |
| log | 0f21fcbb6dbabb6d2185a73edf6b865fd64c6019 |
| tree | 1bfaf895e6e5880304c03dc68c74d7a9da74d852 |
| parent | bcc20249cc0a888430f2006d61c11de176d531cd |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>6 files changed, 374 insertions(+), 12 deletions(-)
apps/mobile/global.css+25| ... | ... | @@ -233,6 +233,31 @@ |
| 233 | 233 | } |
| 234 | 234 | } |
| 235 | 235 | |
| 236 | /* ─── Clerk native profile ──────────────────────────────────────────── */ | |
| 237 | /* Fixed palette for custom pages inside Clerk's native user profile. Mirrors | |
| 238 | clerk-theme.json, which themes the SDK's own screens, so ours match them. | |
| 239 | Kept out of the runtime palette above on purpose: custom themes must not | |
| 240 | restyle Clerk's chrome. Keep in sync with clerk-theme.json. */ | |
| 241 | @layer theme { | |
| 242 | :root { | |
| 243 | @variant light { | |
| 244 | --color-clerk-page: #f2f2f7; | |
| 245 | --color-clerk-foreground: #262626; | |
| 246 | --color-clerk-foreground-muted: #737373; | |
| 247 | --color-clerk-border: rgba(229, 229, 234, 0.06); | |
| 248 | --color-clerk-danger: #dc2626; | |
| 249 | } | |
| 250 | ||
| 251 | @variant dark { | |
| 252 | --color-clerk-page: #0e0e0e; | |
| 253 | --color-clerk-foreground: #f5f5f5; | |
| 254 | --color-clerk-foreground-muted: #a3a3a3; | |
| 255 | --color-clerk-border: rgba(42, 42, 42, 0.06); | |
| 256 | --color-clerk-danger: #fca5a5; | |
| 257 | } | |
| 258 | } | |
| 259 | } | |
| 260 | ||
| 236 | 261 | /* ─── Typography ────────────────────────────────────────────────────── */ |
| 237 | 262 | @theme { |
| 238 | 263 | /* Keep these native family names aligned with app.config.ts. */ |
apps/mobile/src/features/cloud/T3ConnectProfilePage.tsx created+273| ... | ... | @@ -0,0 +1,273 @@ |
| 1 | import { findErrorTraceId } from "@t3tools/client-runtime/errors"; | |
| 2 | import { | |
| 3 | isAtomCommandInterrupted, | |
| 4 | squashAtomCommandFailure, | |
| 5 | } from "@t3tools/client-runtime/state/runtime"; | |
| 6 | import type { MenuAction } from "@react-native-menu/menu"; | |
| 7 | import type { EnvironmentId } from "@t3tools/contracts"; | |
| 8 | import type { RelayClientEnvironmentRecord } from "@t3tools/contracts/relay"; | |
| 9 | import { type ReactNode, useRef, useState } from "react"; | |
| 10 | import { | |
| 11 | ActivityIndicator, | |
| 12 | Alert, | |
| 13 | Pressable, | |
| 14 | RefreshControl, | |
| 15 | ScrollView, | |
| 16 | Text, | |
| 17 | View, | |
| 18 | } from "react-native"; | |
| 19 | ||
| 20 | import { SymbolView } from "../../components/AppSymbol"; | |
| 21 | import { showConfirmDialog } from "../../components/ConfirmDialogHost"; | |
| 22 | import { ControlPillMenu } from "../../components/ControlPill"; | |
| 23 | import { copyTextWithHaptic } from "../../lib/copyTextWithHaptic"; | |
| 24 | import { useAtomCommand } from "../../state/use-atom-command"; | |
| 25 | import { | |
| 26 | deregisterManagedRelayEnvironmentCommand, | |
| 27 | useManagedRelayEnvironments, | |
| 28 | } from "./managedRelayState"; | |
| 29 | ||
| 30 | const linkedAtFormatter = new Intl.DateTimeFormat(undefined, { dateStyle: "medium" }); | |
| 31 | ||
| 32 | function linkedAtLabel(value: string): string { | |
| 33 | const linkedAt = new Date(value); | |
| 34 | return Number.isNaN(linkedAt.getTime()) | |
| 35 | ? "Link date unavailable" | |
| 36 | : `Linked ${linkedAtFormatter.format(linkedAt)}`; | |
| 37 | } | |
| 38 | ||
| 39 | function endpointLabel(environment: RelayClientEnvironmentRecord): string { | |
| 40 | return environment.endpoint.providerKind === "cloudflare_tunnel" | |
| 41 | ? "Managed tunnel" | |
| 42 | : "Activity publishing only"; | |
| 43 | } | |
| 44 | ||
| 45 | function confirmDeregister(environment: RelayClientEnvironmentRecord, onConfirm: () => void) { | |
| 46 | const title = "Deregister server?"; | |
| 47 | const message = `“${environment.label}” will be removed from this account. T3 Connect access will be revoked, any managed tunnel will be removed, and a host space will become available. Local connections on your devices are not changed.`; | |
| 48 | if (process.env.EXPO_OS === "ios") { | |
| 49 | Alert.alert(title, message, [ | |
| 50 | { text: "Cancel", style: "cancel" }, | |
| 51 | { text: "Deregister", style: "destructive", onPress: onConfirm }, | |
| 52 | ]); | |
| 53 | return; | |
| 54 | } | |
| 55 | showConfirmDialog({ title, message, confirmText: "Deregister", destructive: true, onConfirm }); | |
| 56 | } | |
| 57 | ||
| 58 | /** | |
| 59 | * The "T3 Connect" custom page inside Clerk's native user profile: every | |
| 60 | * environment registered to the signed-in account, with account-level | |
| 61 | * deregistration. Mirrors the web UserButton page; connections on this device | |
| 62 | * are managed in Settings instead. | |
| 63 | */ | |
| 64 | export function T3ConnectProfilePage() { | |
| 65 | const environmentsState = useManagedRelayEnvironments(); | |
| 66 | const deregisterEnvironment = useAtomCommand(deregisterManagedRelayEnvironmentCommand, { | |
| 67 | reportFailure: false, | |
| 68 | }); | |
| 69 | const [deregisteringEnvironmentId, setDeregisteringEnvironmentId] = | |
| 70 | useState<EnvironmentId | null>(null); | |
| 71 | const mutationPendingRef = useRef(false); | |
| 72 | // Deregistered rows stay in the cached list until the refresh lands, so hide | |
| 73 | // them by the linkedAt they had. A re-link produces a new linkedAt and shows again. | |
| 74 | const [removedEnvironments, setRemovedEnvironments] = useState<{ | |
| 75 | readonly accountId: string | null; | |
| 76 | readonly linkedAtById: ReadonlyMap<EnvironmentId, string>; | |
| 77 | }>({ accountId: null, linkedAtById: new Map() }); | |
| 78 | ||
| 79 | const handleDeregister = async (environment: RelayClientEnvironmentRecord) => { | |
| 80 | const accountId = environmentsState.accountId; | |
| 81 | if (!accountId || mutationPendingRef.current) return; | |
| 82 | ||
| 83 | mutationPendingRef.current = true; | |
| 84 | setDeregisteringEnvironmentId(environment.environmentId); | |
| 85 | const result = await deregisterEnvironment({ | |
| 86 | accountId, | |
| 87 | environmentId: environment.environmentId, | |
| 88 | }); | |
| 89 | mutationPendingRef.current = false; | |
| 90 | setDeregisteringEnvironmentId(null); | |
| 91 | ||
| 92 | if (result._tag === "Success") { | |
| 93 | setRemovedEnvironments((current) => { | |
| 94 | const linkedAtById = new Map(current.accountId === accountId ? current.linkedAtById : []); | |
| 95 | linkedAtById.set(environment.environmentId, environment.linkedAt); | |
| 96 | return { accountId, linkedAtById }; | |
| 97 | }); | |
| 98 | environmentsState.refresh(); | |
| 99 | return; | |
| 100 | } | |
| 101 | if (isAtomCommandInterrupted(result)) return; | |
| 102 | ||
| 103 | const cause = squashAtomCommandFailure(result); | |
| 104 | const message = cause instanceof Error ? cause.message : "Could not deregister the server."; | |
| 105 | const traceId = findErrorTraceId(cause); | |
| 106 | console.error("[t3-connect] Could not deregister environment", { | |
| 107 | environmentId: environment.environmentId, | |
| 108 | message, | |
| 109 | traceId, | |
| 110 | cause, | |
| 111 | }); | |
| 112 | Alert.alert( | |
| 113 | "Could not deregister server", | |
| 114 | traceId ? `${message}\n\nTrace ID: ${traceId}` : message, | |
| 115 | traceId | |
| 116 | ? [ | |
| 117 | { | |
| 118 | text: "Copy trace ID", | |
| 119 | onPress: () => copyTextWithHaptic(traceId, { target: "connection-trace-id" }), | |
| 120 | }, | |
| 121 | { text: "OK", style: "cancel" }, | |
| 122 | ] | |
| 123 | : undefined, | |
| 124 | ); | |
| 125 | }; | |
| 126 | ||
| 127 | const removedEnvironmentLinkedAt = | |
| 128 | removedEnvironments.accountId === environmentsState.accountId | |
| 129 | ? removedEnvironments.linkedAtById | |
| 130 | : new Map<EnvironmentId, string>(); | |
| 131 | const environments = (environmentsState.data ?? []).filter( | |
| 132 | (environment) => | |
| 133 | removedEnvironmentLinkedAt.get(environment.environmentId) !== environment.linkedAt, | |
| 134 | ); | |
| 135 | const isInitialLoad = | |
| 136 | !environmentsState.accountId || (environmentsState.data === null && !environmentsState.error); | |
| 137 | const errorTraceId = environmentsState.errorTraceId; | |
| 138 | ||
| 139 | return ( | |
| 140 | <ScrollView | |
| 141 | className="flex-1 bg-clerk-page" | |
| 142 | contentContainerClassName="pb-8" | |
| 143 | contentInsetAdjustmentBehavior="automatic" | |
| 144 | refreshControl={ | |
| 145 | <RefreshControl | |
| 146 | refreshing={environmentsState.isPending && environmentsState.data !== null} | |
| 147 | onRefresh={environmentsState.refresh} | |
| 148 | /> | |
| 149 | } | |
| 150 | > | |
| 151 | <ClerkSectionHeader>Registered servers</ClerkSectionHeader> | |
| 152 | ||
| 153 | {environmentsState.error ? ( | |
| 154 | <> | |
| 155 | <ClerkRow | |
| 156 | title="Could not load T3 Connect environments" | |
| 157 | subtitle={environmentsState.error} | |
| 158 | /> | |
| 159 | {errorTraceId ? ( | |
| 160 | <ClerkButtonRow | |
| 161 | label="Copy trace ID" | |
| 162 | onPress={() => { | |
| 163 | copyTextWithHaptic(errorTraceId, { target: "connection-trace-id" }); | |
| 164 | }} | |
| 165 | /> | |
| 166 | ) : null} | |
| 167 | </> | |
| 168 | ) : isInitialLoad ? ( | |
| 169 | <View className="flex-row items-center gap-3 px-6 py-4"> | |
| 170 | <ActivityIndicator colorClassName={"accent-clerk-foreground-muted"} size="small" /> | |
| 171 | <Text className="text-base text-clerk-foreground-muted">Loading environments</Text> | |
| 172 | </View> | |
| 173 | ) : environments.length > 0 ? ( | |
| 174 | environments.map((environment) => ( | |
| 175 | <ClerkRow | |
| 176 | key={environment.environmentId} | |
| 177 | title={environment.label} | |
| 178 | subtitle={`${linkedAtLabel(environment.linkedAt)} · ${endpointLabel(environment)}`} | |
| 179 | accessory={ | |
| 180 | deregisteringEnvironmentId === environment.environmentId ? ( | |
| 181 | <ActivityIndicator colorClassName={"accent-clerk-foreground-muted"} size="small" /> | |
| 182 | ) : ( | |
| 183 | <ControlPillMenu | |
| 184 | actions={ENVIRONMENT_MENU_ACTIONS} | |
| 185 | isAnchoredToRight | |
| 186 | onPressAction={() => | |
| 187 | confirmDeregister(environment, () => void handleDeregister(environment)) | |
| 188 | } | |
| 189 | > | |
| 190 | <Pressable | |
| 191 | accessibilityLabel={`Actions for ${environment.label}`} | |
| 192 | accessibilityRole="button" | |
| 193 | disabled={deregisteringEnvironmentId !== null} | |
| 194 | className="size-[30px] items-center justify-center active:opacity-60 disabled:opacity-50" | |
| 195 | > | |
| 196 | <View className="rotate-90"> | |
| 197 | <SymbolView | |
| 198 | name="ellipsis" | |
| 199 | size={18} | |
| 200 | tintColorClassName={"accent-clerk-foreground-muted"} | |
| 201 | type="monochrome" | |
| 202 | /> | |
| 203 | </View> | |
| 204 | </Pressable> | |
| 205 | </ControlPillMenu> | |
| 206 | ) | |
| 207 | } | |
| 208 | /> | |
| 209 | )) | |
| 210 | ) : ( | |
| 211 | <ClerkRow | |
| 212 | title="No servers registered" | |
| 213 | subtitle="Link a server from its local Settings to reach it through T3 Connect." | |
| 214 | /> | |
| 215 | )} | |
| 216 | ||
| 217 | <Text className="px-6 pt-6 text-xs leading-normal text-clerk-foreground-muted"> | |
| 218 | Connections on this device are managed in Settings. | |
| 219 | </Text> | |
| 220 | </ScrollView> | |
| 221 | ); | |
| 222 | } | |
| 223 | ||
| 224 | const ENVIRONMENT_MENU_ACTIONS = [ | |
| 225 | { id: "deregister", title: "Deregister", image: "trash", attributes: { destructive: true } }, | |
| 226 | ] satisfies MenuAction[]; | |
| 227 | ||
| 228 | // Layout primitives that mirror clerk-ios ClerkKitUI's profile rows so a custom | |
| 229 | // page reads as one of Clerk's own screens. System font on purpose: Clerk's | |
| 230 | // native views do not use the app's DM Sans. | |
| 231 | ||
| 232 | function ClerkSectionHeader(props: { readonly children: string }) { | |
| 233 | return ( | |
| 234 | <Text className="min-h-4 border-b border-clerk-border px-6 pt-8 pb-4 text-xs font-medium tracking-[0.3px] text-clerk-foreground-muted uppercase"> | |
| 235 | {props.children} | |
| 236 | </Text> | |
| 237 | ); | |
| 238 | } | |
| 239 | ||
| 240 | function ClerkRow(props: { | |
| 241 | readonly title: string; | |
| 242 | readonly subtitle: string; | |
| 243 | readonly accessory?: ReactNode; | |
| 244 | }) { | |
| 245 | return ( | |
| 246 | <View | |
| 247 | collapsable={false} | |
| 248 | className="flex-row items-center gap-3 border-b border-clerk-border px-6 py-4" | |
| 249 | > | |
| 250 | <View className="min-w-0 flex-1 gap-0.5"> | |
| 251 | <Text className="min-h-[22px] text-base text-clerk-foreground" numberOfLines={1}> | |
| 252 | {props.title} | |
| 253 | </Text> | |
| 254 | <Text className="min-h-5 text-sm text-clerk-foreground-muted" numberOfLines={2}> | |
| 255 | {props.subtitle} | |
| 256 | </Text> | |
| 257 | </View> | |
| 258 | {props.accessory} | |
| 259 | </View> | |
| 260 | ); | |
| 261 | } | |
| 262 | ||
| 263 | function ClerkButtonRow(props: { readonly label: string; readonly onPress: () => void }) { | |
| 264 | return ( | |
| 265 | <Pressable | |
| 266 | accessibilityRole="button" | |
| 267 | onPress={props.onPress} | |
| 268 | className="border-b border-clerk-border px-6 py-4 active:opacity-60" | |
| 269 | > | |
| 270 | <Text className="text-base font-semibold text-clerk-foreground">{props.label}</Text> | |
| 271 | </Pressable> | |
| 272 | ); | |
| 273 | } |
apps/mobile/src/features/cloud/managedRelayState.ts+22| ... | ... | @@ -1,9 +1,15 @@ |
| 1 | 1 | import { useAtomValue } from "@effect/atom-react"; |
| 2 | 2 | import { |
| 3 | 3 | createManagedRelayQueryManager, |
| 4 | deregisterManagedRelayEnvironment, | |
| 4 | 5 | managedRelaySessionAtom, |
| 5 | 6 | readManagedRelaySnapshotState, |
| 6 | 7 | } from "@t3tools/client-runtime/relay"; |
| 8 | import { | |
| 9 | createAtomCommandScheduler, | |
| 10 | createRuntimeCommand, | |
| 11 | } from "@t3tools/client-runtime/state/runtime"; | |
| 12 | import type { EnvironmentId } from "@t3tools/contracts"; | |
| 7 | 13 | import type { RelayClientEnvironmentRecord } from "@t3tools/contracts/relay"; |
| 8 | 14 | import { AsyncResult, Atom } from "effect/unstable/reactivity"; |
| 9 | 15 | import { useCallback, useEffect } from "react"; |
| ... | ... | @@ -19,6 +25,22 @@ export const managedRelayQueryManager = createManagedRelayQueryManager(managedRe |
| 19 | 25 | cloudDebugLog(`query:${event.operation}:${event.stage}:${event.phase}`, { ...event }), |
| 20 | 26 | }); |
| 21 | 27 | |
| 28 | const managedRelayMutationScheduler = createAtomCommandScheduler(); | |
| 29 | ||
| 30 | export const deregisterManagedRelayEnvironmentCommand = createRuntimeCommand( | |
| 31 | managedRelayAtomRuntime, | |
| 32 | { | |
| 33 | label: "mobile:managed-relay:deregister-environment", | |
| 34 | scheduler: managedRelayMutationScheduler, | |
| 35 | concurrency: { | |
| 36 | mode: "serial", | |
| 37 | key: (input: { readonly accountId: string; readonly environmentId: EnvironmentId }) => | |
| 38 | input.accountId, | |
| 39 | }, | |
| 40 | execute: (input, registry) => deregisterManagedRelayEnvironment(registry, input), | |
| 41 | }, | |
| 42 | ); | |
| 43 | ||
| 22 | 44 | const EMPTY_ENVIRONMENTS_ATOM = Atom.make( |
| 23 | 45 | AsyncResult.success<ReadonlyArray<RelayClientEnvironmentRecord>>([]), |
| 24 | 46 | ).pipe(Atom.keepAlive, Atom.withLabel("managed-relay:mobile:environments:null")); |
apps/mobile/src/features/settings/SettingsAuthRouteScreen.tsx+17-2| ... | ... | @@ -1,10 +1,21 @@ |
| 1 | 1 | import { useAuth } from "@clerk/expo"; |
| 2 | import { AuthView, UserProfileView } from "@clerk/expo/native"; | |
| 2 | import { AuthView, type UserProfileCustomPage, UserProfileView } from "@clerk/expo/native"; | |
| 3 | 3 | import { StackActions, useNavigation } from "@react-navigation/native"; |
| 4 | 4 | import { useCallback, useEffect, useLayoutEffect, useRef } from "react"; |
| 5 | 5 | import { View } from "react-native"; |
| 6 | 6 | |
| 7 | 7 | import { hasCloudPublicConfig } from "../cloud/publicConfig"; |
| 8 | import { T3ConnectProfilePage } from "../cloud/T3ConnectProfilePage"; | |
| 9 | ||
| 10 | // Custom rows in Clerk's native profile. Mirrors the web UserButton pages. | |
| 11 | const USER_PROFILE_CUSTOM_PAGES = [ | |
| 12 | { | |
| 13 | path: "t3-connect", | |
| 14 | label: "T3 Connect", | |
| 15 | icon: "globe", | |
| 16 | content: <T3ConnectProfilePage />, | |
| 17 | }, | |
| 18 | ] satisfies UserProfileCustomPage[]; | |
| 8 | 19 | |
| 9 | 20 | export function SettingsAuthRouteScreen() { |
| 10 | 21 | const navigation = useNavigation(); |
| ... | ... | @@ -40,7 +51,11 @@ function ConfiguredSettingsAuthRouteScreen() { |
| 40 | 51 | <View collapsable={false} className="flex-1 overflow-hidden bg-sheet"> |
| 41 | 52 | {isLoaded ? ( |
| 42 | 53 | hasBeenSignedIn.current ? ( |
| 43 | <UserProfileView isDismissible={false} onHostBack={handleHostBack} /> | |
| 54 | <UserProfileView | |
| 55 | customPages={USER_PROFILE_CUSTOM_PAGES} | |
| 56 | isDismissible={false} | |
| 57 | onHostBack={handleHostBack} | |
| 58 | /> | |
| 44 | 59 | ) : ( |
| 45 | 60 | <AuthView isDismissible={false} onHostBack={handleHostBack} /> |
| 46 | 61 | ) |
patches/@clerk__expo@4.6.6.patch+32-5| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | diff --git a/ios/ClerkAuthNativeView.swift b/ios/ClerkAuthNativeView.swift |
| 2 | index e76a8be1b1c8faa64ec6dfa83764764094133aff..17b36ad1319765e2b6db0551d32e07d7140e482f 100644 | |
| 2 | index 5f8d2ba66d5b232890af75c22b173c86d2ef546b..b170304cbf2fbaae8032db8dd6f89b6a59c6e3fe 100644 | |
| 3 | 3 | --- a/ios/ClerkAuthNativeView.swift |
| 4 | 4 | +++ b/ios/ClerkAuthNativeView.swift |
| 5 | @@ -108,7 +108,12 @@ public class ClerkAuthNativeView: ClerkNativeViewHost { | |
| 5 | @@ -111,7 +111,12 @@ public class ClerkAuthNativeView: ClerkNativeViewHost { | |
| 6 | 6 | |
| 7 | 7 | override func makeHostedController() -> UIViewController? { |
| 8 | 8 | let hostBackAction: (() -> Void)? = currentHostBackButton |
| ... | ... | @@ -16,8 +16,35 @@ index e76a8be1b1c8faa64ec6dfa83764764094133aff..17b36ad1319765e2b6db0551d32e07d7 |
| 16 | 16 | : nil |
| 17 | 17 | |
| 18 | 18 | return ClerkNativeBridge.shared.makeAuthViewController( |
| 19 | diff --git a/ios/ClerkNativeBridge.swift b/ios/ClerkNativeBridge.swift | |
| 20 | index c90ad2ef1162cc2ac025c8b0b4aa135e8913dc21..ce8cb68764b1a3d3537672fc83e4e3077fceb97a 100644 | |
| 21 | --- a/ios/ClerkNativeBridge.swift | |
| 22 | +++ b/ios/ClerkNativeBridge.swift | |
| 23 | @@ -1470,6 +1470,8 @@ private struct ClerkReactEmbeddedUserProfileCustomPage: View { | |
| 24 | } | |
| 25 | ||
| 26 | private struct ClerkReactUserProfileCustomPageContent: View { | |
| 27 | + @Environment(\.clerkTheme) private var theme | |
| 28 | + | |
| 29 | let path: String | |
| 30 | let rows: [ClerkUserProfileCustomRowConfig] | |
| 31 | let state: ClerkUserProfileCustomPageState | |
| 32 | @@ -1483,8 +1485,13 @@ private struct ClerkReactUserProfileCustomPageContent: View { | |
| 33 | } | |
| 34 | } | |
| 35 | .frame(maxWidth: .infinity, maxHeight: .infinity) | |
| 36 | + // Match Clerk's own profile pages so the navigation bar and page share | |
| 37 | + // the theme's page background instead of a bare hosting container. | |
| 38 | + .background(theme.colors.muted) | |
| 39 | .navigationTitle(userProfileCustomPageLabel(for: path, rows: rows)) | |
| 40 | .navigationBarTitleDisplayMode(.inline) | |
| 41 | + .preGlassSolidNavBar() | |
| 42 | + .background(theme.colors.background) | |
| 43 | } | |
| 44 | } | |
| 45 | ||
| 19 | 46 | diff --git a/ios/ClerkNativeViewHost.swift b/ios/ClerkNativeViewHost.swift |
| 20 | index 0d91f0e749f121595c17bc803663df6ac90e4163..8f8a89df97a54168b8b45d0e9c197ca3953b7028 100644 | |
| 47 | index 4e6540aceeaaab56ddf327bb3f16e120438f066f..cc16c94ca7a6eb91a97e76d5de02dc586f02a766 100644 | |
| 21 | 48 | --- a/ios/ClerkNativeViewHost.swift |
| 22 | 49 | +++ b/ios/ClerkNativeViewHost.swift |
| 23 | 50 | @@ -5,6 +5,7 @@ public class ClerkNativeViewHost: ExpoView { |
| ... | ... | @@ -60,10 +87,10 @@ index 0d91f0e749f121595c17bc803663df6ac90e4163..8f8a89df97a54168b8b45d0e9c197ca3 |
| 60 | 87 | guard configuredObserver == nil else { return } |
| 61 | 88 | |
| 62 | 89 | diff --git a/ios/ClerkUserProfileNativeView.swift b/ios/ClerkUserProfileNativeView.swift |
| 63 | index 12d6248b1dc4b4779b252c9954c2f89145907310..d838283b7adcf49fec2a63bff53251b9bee31bf8 100644 | |
| 90 | index f2ca604d41f50d05de8ac334879126cdc0414f84..46f406d5361b9a560a7c4ce855e344cbddd1d0b6 100644 | |
| 64 | 91 | --- a/ios/ClerkUserProfileNativeView.swift |
| 65 | 92 | +++ b/ios/ClerkUserProfileNativeView.swift |
| 66 | @@ -44,7 +44,12 @@ public class ClerkUserProfileNativeView: ClerkNativeViewHost { | |
| 93 | @@ -47,7 +47,12 @@ public class ClerkUserProfileNativeView: ClerkUserProfileCustomPageHost { | |
| 67 | 94 | |
| 68 | 95 | override func makeHostedController() -> UIViewController? { |
| 69 | 96 | let hostBackAction: (() -> Void)? = currentHostBackButton |
pnpm-lock.yaml+5-5| ... | ... | @@ -85,7 +85,7 @@ overrides: |
| 85 | 85 | packageExtensionsChecksum: sha256-k/dT9NFDl5hihRPaoFKeY11hzyutMFs5psfZLFiKJic= |
| 86 | 86 | |
| 87 | 87 | patchedDependencies: |
| 88 | '@clerk/expo@4.6.6': 72e426f44fc1cde16fc2cbba3d1e96cdca7c6d957faa73d0fe6b43948608a6c1 | |
| 88 | '@clerk/expo@4.6.6': a82bb41039ee88a290a87d4ab58be7be4c49fa338603b17ea646e1ec140a1cfb | |
| 89 | 89 | '@effect/vitest@4.0.0-rc.112': a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b |
| 90 | 90 | '@expo/metro-config@57.0.12': 96f1a75347e6ea02dc4b7034ace815d8ee39e18b8166ebfb573d9e58328f0dc2 |
| 91 | 91 | '@ff-labs/fff-node@0.9.4': c4e3cc2420ceb9dc650f9d189e9c24baf7e83f342998bacda5f459a4ce7927a8 |
| ... | ... | @@ -231,7 +231,7 @@ importers: |
| 231 | 231 | dependencies: |
| 232 | 232 | '@clerk/expo': |
| 233 | 233 | specifier: 4.6.6 |
| 234 | version: 4.6.6(patch_hash=72e426f44fc1cde16fc2cbba3d1e96cdca7c6d957faa73d0fe6b43948608a6c1)(dbc31631339ce74330e188d5d7a88158) | |
| 234 | version: 4.6.6(patch_hash=a82bb41039ee88a290a87d4ab58be7be4c49fa338603b17ea646e1ec140a1cfb)(dbc31631339ce74330e188d5d7a88158) | |
| 235 | 235 | '@effect/atom-react': |
| 236 | 236 | specifier: 4.0.0-rc.112 |
| 237 | 237 | version: 4.0.0-rc.112(effect@4.0.0-rc.112(patch_hash=8bef799f35729cf3465eb428196f617b434a7c9f658d56acb2874d74b21b98b2))(react@19.2.3)(scheduler@0.27.0) |
| ... | ... | @@ -774,7 +774,7 @@ importers: |
| 774 | 774 | version: link:../../packages/shared |
| 775 | 775 | alchemy: |
| 776 | 776 | specifier: 2.0.0-beta.76 |
| 777 | version: 2.0.0-beta.76(b3825b36417e56a486ccb5f22a7f3d7e) | |
| 777 | version: 2.0.0-beta.76(197b68e0d20fdf20cf352009eca17c9f) | |
| 778 | 778 | drizzle-orm: |
| 779 | 779 | specifier: 1.0.0-rc.5-ab785fc |
| 780 | 780 | version: 1.0.0-rc.5-ab785fc(8ab70e2706da13c78d64d8a92fef1884) |
| ... | ... | @@ -12437,7 +12437,7 @@ snapshots: |
| 12437 | 12437 | electron-store: 8.2.0 |
| 12438 | 12438 | react-dom: 19.2.6(react@19.2.6) |
| 12439 | 12439 | |
| 12440 | '@clerk/expo@4.6.6(patch_hash=72e426f44fc1cde16fc2cbba3d1e96cdca7c6d957faa73d0fe6b43948608a6c1)(dbc31631339ce74330e188d5d7a88158)': | |
| 12440 | '@clerk/expo@4.6.6(patch_hash=a82bb41039ee88a290a87d4ab58be7be4c49fa338603b17ea646e1ec140a1cfb)(dbc31631339ce74330e188d5d7a88158)': | |
| 12441 | 12441 | dependencies: |
| 12442 | 12442 | '@clerk/clerk-js': 6.31.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) |
| 12443 | 12443 | '@clerk/react': 6.15.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3) |
| ... | ... | @@ -16445,7 +16445,7 @@ snapshots: |
| 16445 | 16445 | json-schema-traverse: 1.0.0 |
| 16446 | 16446 | require-from-string: 2.0.2 |
| 16447 | 16447 | |
| 16448 | alchemy@2.0.0-beta.76(b3825b36417e56a486ccb5f22a7f3d7e): | |
| 16448 | alchemy@2.0.0-beta.76(197b68e0d20fdf20cf352009eca17c9f): | |
| 16449 | 16449 | dependencies: |
| 16450 | 16450 | '@alchemy.run/cloudflare-runtime': 2.0.0-beta.76(@distilled.cloud/cloudflare@1.0.0-rc.8(effect@4.0.0-rc.112(patch_hash=8bef799f35729cf3465eb428196f617b434a7c9f658d56acb2874d74b21b98b2)))(@effect/platform-bun@4.0.0-rc.112(bufferutil@4.1.0)(effect@4.0.0-rc.112(patch_hash=8bef799f35729cf3465eb428196f617b434a7c9f658d56acb2874d74b21b98b2))(utf-8-validate@6.0.6))(@effect/platform-node@4.0.0-rc.112(bufferutil@4.1.0)(effect@4.0.0-rc.112(patch_hash=8bef799f35729cf3465eb428196f617b434a7c9f658d56acb2874d74b21b98b2))(redis@6.2.1)(utf-8-validate@6.0.6))(@types/node@24.12.4)(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@7.0.2)(unrun@0.2.39)(yaml@2.9.0))(effect@4.0.0-rc.112(patch_hash=8bef799f35729cf3465eb428196f617b434a7c9f658d56acb2874d74b21b98b2))(rolldown@1.2.5)(typescript@7.0.2) |
| 16451 | 16451 | '@alchemy.run/floci': 2.0.0-beta.76(effect@4.0.0-rc.112(patch_hash=8bef799f35729cf3465eb428196f617b434a7c9f658d56acb2874d74b21b98b2)) |