diff --git a/.github/VOUCHED.td b/.github/VOUCHED.td index 4d6f88520816..353a1f41a261 100644 --- a/.github/VOUCHED.td +++ b/.github/VOUCHED.td @@ -53,6 +53,7 @@ github:mackinleysmith github:maria-rcks github:MatthewFeroz github:maxwellyoung +github:mweinbach github:mwolson github:myacoub91 github:naMqe-h diff --git a/.github/workflows/mobile-eas-production.yml b/.github/workflows/mobile-eas-production.yml index 8ae8ecc742e9..16be6ee5f296 100644 --- a/.github/workflows/mobile-eas-production.yml +++ b/.github/workflows/mobile-eas-production.yml @@ -234,6 +234,29 @@ jobs: MOBILE_BUILD_PROFILE: ${{ inputs.profile || 'production' }} run: eas build --platform ${{ inputs.platform }} --profile "$MOBILE_BUILD_PROFILE" --auto-submit --non-interactive --no-wait + # @expo/fingerprint swallows autolinking errors and returns no Expo module + # sources, so native changes stop moving the hash and OTAs reach binaries + # that lack them. Refuse to publish any OTA from such a fingerprint. + - name: Verify fingerprints hash Expo native modules + if: steps.expo-token.outputs.present == 'true' && (github.event_name == 'push' || inputs.mode == 'update') + working-directory: apps/mobile + env: + EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }} + PLATFORM: ${{ inputs.platform || 'all' }} + run: | + if [ "$PLATFORM" = "all" ]; then platforms="ios android"; else platforms="$PLATFORM"; fi + failed=0 + for platform in $platforms; do + # eas-cli prints an environment-loaded notice to stdout before the + # JSON even with --json, so discard everything before the document. + expo_modules="$(eas fingerprint:generate --platform "$platform" --environment production --json --non-interactive | sed -n '/^{/,$p' | jq --arg reason "expoAutolinking${platform^}" '[.sources[] | select((.reasons // []) | index($reason))] | length')" + if [ "${expo_modules:-0}" -eq 0 ]; then + failed=1 + echo ":x: $platform: the native fingerprint hashes no Expo native modules — OTAs and builds skipped" >> "$GITHUB_STEP_SUMMARY" + fi + done + exit "$failed" + - name: Publish OTA update (manual) if: steps.expo-token.outputs.present == 'true' && github.event_name == 'workflow_dispatch' && inputs.mode == 'update' working-directory: apps/mobile diff --git a/apps/mobile/deps/react-native-enriched-markdown-1.2.0-t3.13.tgz b/apps/mobile/deps/react-native-enriched-markdown-1.2.0-t3.13.tgz deleted file mode 100644 index 2ea48ea081a0..000000000000 Binary files a/apps/mobile/deps/react-native-enriched-markdown-1.2.0-t3.13.tgz and /dev/null differ diff --git a/apps/mobile/deps/react-native-enriched-markdown-1.2.0-t3.15.tgz b/apps/mobile/deps/react-native-enriched-markdown-1.2.0-t3.15.tgz new file mode 100644 index 000000000000..dbf87fde65e2 Binary files /dev/null and b/apps/mobile/deps/react-native-enriched-markdown-1.2.0-t3.15.tgz differ diff --git a/apps/mobile/modules/t3-native-controls/android/build.gradle b/apps/mobile/modules/t3-native-controls/android/build.gradle index e4e2e317cacf..01e035450f0e 100644 --- a/apps/mobile/modules/t3-native-controls/android/build.gradle +++ b/apps/mobile/modules/t3-native-controls/android/build.gradle @@ -27,4 +27,5 @@ dependencies { implementation project(':expo-modules-core') implementation 'androidx.compose.ui:ui-android:1.10.6' implementation 'androidx.compose.material3:material3-android:1.5.0-alpha17' + implementation 'androidx.window:window:1.5.1' } diff --git a/apps/mobile/modules/t3-native-controls/android/src/main/java/expo/modules/t3nativecontrols/T3FoldPostureModule.kt b/apps/mobile/modules/t3-native-controls/android/src/main/java/expo/modules/t3nativecontrols/T3FoldPostureModule.kt new file mode 100644 index 000000000000..c2169dabdc15 --- /dev/null +++ b/apps/mobile/modules/t3-native-controls/android/src/main/java/expo/modules/t3nativecontrols/T3FoldPostureModule.kt @@ -0,0 +1,129 @@ +package expo.modules.t3nativecontrols + +import android.content.Context +import android.hardware.Sensor +import android.hardware.SensorEvent +import android.hardware.SensorEventListener +import android.hardware.SensorManager +import android.os.Build +import androidx.window.layout.FoldingFeature +import androidx.window.layout.WindowInfoTracker +import expo.modules.kotlin.AppContext +import expo.modules.kotlin.modules.Module +import expo.modules.kotlin.modules.ModuleDefinition +import expo.modules.kotlin.viewevent.EventDispatcher +import expo.modules.kotlin.views.ExpoView +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel +import kotlinx.coroutines.launch + +class T3FoldPostureModule : Module() { + override fun definition() = ModuleDefinition { + Name("T3FoldPosture") + + View(T3FoldPostureView::class) { + Events("onHingeChange") + } + } +} + +/** + * Reports a vertical hinge, in this view's dp coordinates, while the device is bent like a book. + * The hinge sensor is only registered while a vertical fold is on screen. + */ +class T3FoldPostureView( + context: Context, + appContext: AppContext +) : ExpoView(context, appContext), SensorEventListener { + private val onHingeChange by EventDispatcher() + private val sensorManager = context.getSystemService(SensorManager::class.java) + private val hingeSensor = + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + sensorManager?.getDefaultSensor(Sensor.TYPE_HINGE_ANGLE) + } else { + null + } + private var scope: CoroutineScope? = null + private var fold: FoldingFeature? = null + private var listening = false + private var bent = false + private var reported: Map? = null + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + observeFold() + } + + // The activity can be missing when the view first attaches, so layout passes retry. + private fun observeFold() { + if (scope != null || !isAttachedToWindow) return + val activity = appContext.currentActivity ?: return + scope = MainScope().also { scope -> + scope.launch { + WindowInfoTracker.getOrCreate(activity).windowLayoutInfo(activity).collect { info -> + fold = info.displayFeatures.filterIsInstance().firstOrNull { + it.orientation == FoldingFeature.Orientation.VERTICAL + } + listen(fold != null) + report() + } + } + } + } + + override fun onDetachedFromWindow() { + scope?.cancel() + scope = null + listen(false) + super.onDetachedFromWindow() + } + + override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { + super.onLayout(changed, left, top, right, bottom) + observeFold() + if (changed) report() + } + + override fun onSensorChanged(event: SensorEvent) { + // Pixel foldables report the hinge in 5° steps and rest at 175° when nearly flat. Snapping at + // 170° and releasing at 175° keeps a resting hinge from flapping the layout. + val angle = event.values[0] + bent = if (bent) angle < 175f else angle <= 170f + report() + } + + override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) = Unit + + private fun listen(enabled: Boolean) { + if (enabled == listening || hingeSensor == null) return + listening = enabled + if (enabled) { + sensorManager.registerListener(this, hingeSensor, SensorManager.SENSOR_DELAY_UI) + } else { + sensorManager.unregisterListener(this) + bent = false + } + } + + private fun report() { + val feature = fold + // Without a hinge sensor, the platform's half-opened posture is the closest signal. + val aligned = feature != null && + if (hingeSensor != null) bent else feature.state == FoldingFeature.State.HALF_OPENED + val hinge = if (aligned && feature != null) { + val origin = IntArray(2).also { getLocationInWindow(it) } + val density = resources.displayMetrics.density + mapOf( + "x" to (feature.bounds.left - origin[0]) / density, + "windowX" to feature.bounds.left / density, + "width" to feature.bounds.width() / density + ) + } else { + emptyMap() + } + if (hinge == reported) return + reported = hinge + onHingeChange(hinge) + } +} diff --git a/apps/mobile/modules/t3-native-controls/expo-module.config.json b/apps/mobile/modules/t3-native-controls/expo-module.config.json index 08ac3e078534..22fcb74a36cf 100644 --- a/apps/mobile/modules/t3-native-controls/expo-module.config.json +++ b/apps/mobile/modules/t3-native-controls/expo-module.config.json @@ -11,7 +11,8 @@ "modules": [ "expo.modules.t3nativecontrols.T3NativeControlsModule", "expo.modules.t3nativecontrols.T3WorkspaceNavigationModule", - "expo.modules.t3nativecontrols.T3KeyboardCommandsModule" + "expo.modules.t3nativecontrols.T3KeyboardCommandsModule", + "expo.modules.t3nativecontrols.T3FoldPostureModule" ] } } diff --git a/apps/mobile/modules/t3-native-controls/ios/T3NativeControlsModule.swift b/apps/mobile/modules/t3-native-controls/ios/T3NativeControlsModule.swift index 3289fe90363b..57fa2a7c643c 100644 --- a/apps/mobile/modules/t3-native-controls/ios/T3NativeControlsModule.swift +++ b/apps/mobile/modules/t3-native-controls/ios/T3NativeControlsModule.swift @@ -20,6 +20,18 @@ public final class T3NativeControlsModule: Module { } return ["supportsWorkspaceColumns": false] } + View(T3SegmentedControlView.self) { + ViewName("SegmentedControl") + Events("onSelectionChange") + Prop("labels") { (view: T3SegmentedControlView, value: [String]) in view.labels = value } + Prop("selectedIndex") { (view: T3SegmentedControlView, value: Int) in view.selectedIndex = value } + Prop("trackColor") { (view: T3SegmentedControlView, value: UIColor) in view.trackColor = value } + Prop("selectedColor") { (view: T3SegmentedControlView, value: UIColor) in view.selectedColor = value } + Prop("textColor") { (view: T3SegmentedControlView, value: UIColor) in view.textColor = value } + Prop("mutedColor") { (view: T3SegmentedControlView, value: UIColor) in view.mutedColor = value } + Prop("appearance") { (view: T3SegmentedControlView, value: String) in view.appearance = value } + } + View(T3LayoutMetricsView.self) { ViewName("LayoutMetrics") Events("onMetricsChange") diff --git a/apps/mobile/modules/t3-native-controls/ios/T3SegmentedControlView.swift b/apps/mobile/modules/t3-native-controls/ios/T3SegmentedControlView.swift new file mode 100644 index 000000000000..9e60a85b7d2c --- /dev/null +++ b/apps/mobile/modules/t3-native-controls/ios/T3SegmentedControlView.swift @@ -0,0 +1,49 @@ +import ExpoModulesCore +import UIKit + +final class T3SegmentedControlView: ExpoView { + let onSelectionChange = EventDispatcher() + private let control = UISegmentedControl() + var labels: [String] = [] { + didSet { + guard labels != oldValue else { return } + control.removeAllSegments() + for (index, label) in labels.enumerated() { + control.insertSegment(withTitle: label, at: index, animated: false) + } + updateSelection() + } + } + var selectedIndex = -1 { didSet { updateSelection() } } + var trackColor: UIColor = .secondarySystemBackground { didSet { control.backgroundColor = trackColor } } + var selectedColor: UIColor = .secondarySystemFill { didSet { control.selectedSegmentTintColor = selectedColor } } + var textColor: UIColor = .label { didSet { updateColors() } } + var mutedColor: UIColor = .secondaryLabel { didSet { updateColors() } } + var appearance = "light" { + didSet { overrideUserInterfaceStyle = appearance == "dark" ? .dark : .light } + } + + required init(appContext: AppContext? = nil) { + super.init(appContext: appContext) + addSubview(control) + control.addTarget(self, action: #selector(selectionChanged), for: .valueChanged) + } + + override func layoutSubviews() { + super.layoutSubviews() + control.frame = bounds + } + + private func updateSelection() { + control.selectedSegmentIndex = labels.indices.contains(selectedIndex) ? selectedIndex : UISegmentedControl.noSegment + } + + private func updateColors() { + control.setTitleTextAttributes([.foregroundColor: mutedColor], for: .normal) + control.setTitleTextAttributes([.foregroundColor: textColor], for: .selected) + } + + @objc private func selectionChanged() { + onSelectionChange(["index": control.selectedSegmentIndex]) + } +} diff --git a/apps/mobile/package.json b/apps/mobile/package.json index 67c8a48d9a5b..3af444653b56 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -47,11 +47,11 @@ }, "dependencies": { "@clerk/expo": "catalog:", - "@clerk/expo-native-components": "0.1.1", + "@clerk/expo-native-components": "0.2.0", "@effect/atom-react": "catalog:", "@expo-google-fonts/dm-sans": "^0.4.2", "@expo/metro-runtime": "~58.0.14", - "@expo/ui": "58.0.18", + "@expo/ui": "58.0.20", "@legendapp/list": "catalog:", "@material/material-color-utilities": "0.3.0", "@noble/curves": "catalog:", @@ -82,46 +82,46 @@ "clsx": "^2.1.1", "diff": "8.0.3", "effect": "catalog:", - "expo": "58.0.11", + "expo": "58.0.14", "expo-asset": "~58.0.16", "expo-audio": "58.0.9", - "expo-auth-session": "~58.0.12", - "expo-blur": "58.0.3", - "expo-build-properties": "~58.0.10", + "expo-auth-session": "~58.0.13", + "expo-blur": "58.0.4", + "expo-build-properties": "~58.0.11", "expo-camera": "~58.0.10", "expo-clipboard": "~58.0.3", "expo-constants": "~58.0.12", - "expo-crypto": "~58.0.6", - "expo-dev-client": "~58.0.13", + "expo-crypto": "~58.0.7", + "expo-dev-client": "~58.0.14", "expo-device": "~58.0.5", "expo-document-picker": "~58.0.4", "expo-file-system": "~58.0.9", "expo-font": "~58.0.8", - "expo-glass-effect": "58.0.3", - "expo-haptics": "~58.0.6", + "expo-glass-effect": "58.0.4", + "expo-haptics": "~58.0.7", "expo-image": "~58.0.15", "expo-image-manipulator": "~58.0.14", "expo-image-picker": "~58.0.10", "expo-keep-awake": "~58.0.3", "expo-linking": "~58.0.13", "expo-network": "~58.0.3", - "expo-notifications": "~58.1.4", + "expo-notifications": "~58.1.5", "expo-paste-input": "^0.1.15", "expo-quick-actions": "^6.0.2", "expo-secure-store": "~58.0.2", "expo-sensors": "~58.0.4", - "expo-sharing": "58.0.18", - "expo-splash-screen": "~58.0.9", + "expo-sharing": "58.0.19", + "expo-splash-screen": "~58.0.10", "expo-sqlite": "~58.0.13", "expo-symbols": "~58.0.4", "expo-updates": "~58.0.17", "expo-video": "~58.0.11", "expo-web-browser": "~58.0.6", - "expo-widgets": "58.0.18", + "expo-widgets": "58.0.20", "react": "19.3.0", "react-dom": "19.3.0", "react-native": "0.88.0", - "react-native-enriched-markdown": "file:deps/react-native-enriched-markdown-1.2.0-t3.13.tgz", + "react-native-enriched-markdown": "file:deps/react-native-enriched-markdown-1.2.0-t3.15.tgz", "react-native-gesture-handler": "~3.3.0", "react-native-image-viewing": "^0.2.2", "react-native-incall-manager": "4.3.0", @@ -147,7 +147,7 @@ "@types/mdast": "^4.0.4", "@types/react": "~19.3.0", "@types/react-dom": "~19.2.3", - "babel-preset-expo": "~58.0.15", + "babel-preset-expo": "~58.0.17", "jsdom": "^30.0.1", "tailwindcss": "^4.0.0", "typescript": "catalog:" diff --git a/apps/mobile/src/components/ui/AndroidAnchoredMenu.tsx b/apps/mobile/src/components/ui/AndroidAnchoredMenu.tsx index dd5c4b4651a5..a5015d98ea4b 100644 --- a/apps/mobile/src/components/ui/AndroidAnchoredMenu.tsx +++ b/apps/mobile/src/components/ui/AndroidAnchoredMenu.tsx @@ -1,11 +1,13 @@ import type { MenuAction, MenuComponentProps } from "@react-native-menu/menu"; import type { ReactNode } from "react"; -import { useCallback, useEffect, useRef, useState } from "react"; +import { use, useCallback, useEffect, useRef, useState } from "react"; import type { StyleProp, ViewInstance, ViewStyle } from "react-native"; import { BackHandler, Pressable, ScrollView, View } from "react-native"; import { useKeyboardState } from "react-native-keyboard-controller"; import Animated, { FadeIn } from "react-native-reanimated"; +import { deriveMenuHorizontalPlacement } from "../../lib/menu-placement"; +import { WindowHingeContext } from "../../native/window-hinge-context"; import { OverlayPortal } from "./OverlayPortal"; import { useAndroidControlSizing } from "./useAndroidControlSizing"; import { MenuPopup } from "./MenuPopup"; @@ -46,10 +48,7 @@ export function AndroidAnchoredMenu(props: AndroidAnchoredMenuProps) { const [path, setPath] = useState([]); const [rootHeight, setRootHeight] = useState(null); const [overlay, setOverlay] = useState(null); - const menuWidth = - overlay === null - ? desiredMenuWidth - : Math.min(desiredMenuWidth, Math.max(0, overlay.width - 2 * SCREEN_MARGIN)); + const windowHinge = use(WindowHingeContext); const anchorRef = useRef(null); const overlayRef = useRef(null); @@ -105,16 +104,17 @@ export function AndroidAnchoredMenu(props: AndroidAnchoredMenuProps) { width: anchor.width, height: anchor.height, }; - const preferredLeft = + const { left, width: menuWidth } = local === null || overlay === null - ? 0 - : local.x + local.width / 2 <= overlay.width / 2 - ? local.x - : local.x + local.width - menuWidth; - const left = - overlay === null - ? 0 - : Math.min(Math.max(preferredLeft, SCREEN_MARGIN), overlay.width - menuWidth - SCREEN_MARGIN); + ? { left: 0, width: desiredMenuWidth } + : deriveMenuHorizontalPlacement({ + anchorX: local.x, + anchorWidth: local.width, + overlayWidth: overlay.width, + desiredWidth: desiredMenuWidth, + margin: SCREEN_MARGIN, + hinge: windowHinge && { x: windowHinge.x - overlay.x, width: windowHinge.width }, + }); // The keyboard stays up while the menu is open (in-window overlay, no // focus change), so the space it covers is not usable — without this the // composer-pill menus "open down" into the IME and can't be tapped. @@ -174,7 +174,9 @@ export function AndroidAnchoredMenu(props: AndroidAnchoredMenuProps) { {!placeable || local === null ? null : !anchor.keyboardWasVisible ? ( ): MailMenu["items"] export function AppBar(props: AppBarProps) { const usesNativeWorkspaceColumns = useNativeWorkspaceColumnsSupported(); + const deviceType = useDeviceType(); const headerId = useId(); const { layout, panes, togglePrimarySidebar } = useAdaptiveWorkspaceLayout(); const { themeVariables } = useAppearancePreferences(); @@ -123,9 +125,7 @@ export function AppBar(props: AppBarProps) { /> ) : null} {props.sidebar !== false && - (!usesNativeWorkspaceColumns || - (Platform.OS === "ios" && Platform.isPad) || - !panes.primarySidebarVisible) ? ( + (!usesNativeWorkspaceColumns || deviceType === "pad" || !panes.primarySidebarVisible) ? ( ) => void; + } +>("T3NativeControls", "SegmentedControl"); + +export function SegmentedControl( + props: SegmentedControlProps, +) { + const { colors, colorScheme } = useControlTheme(); + const trackColor = flattenThemeColor( + themeColorWithAlpha(colors["--color-primary"], colorScheme === "dark" ? 0.18 : 0.07), + colors["--color-screen"], + ); + const selectedColor = + colorScheme === "dark" ? colors["--color-primary"] : colors["--color-secondary"]; + const selectedTextColor = + colorScheme === "dark" + ? colors["--color-primary-foreground"] + : colors["--color-secondary-foreground"]; + return ( + + option.label)} + selectedIndex={props.options.findIndex((option) => option.value === props.selected)} + trackColor={trackColor} + selectedColor={selectedColor} + textColor={selectedTextColor} + mutedColor={themeColorWithContrast( + colors["--color-foreground-muted"], + trackColor, + colorScheme === "dark" ? 7 : 4.5, + )} + appearance={colorScheme} + onSelectionChange={({ nativeEvent }) => { + const option = props.options[nativeEvent.index]; + if (option) props.onSelect(option.value); + }} + style={{ height: props.size === "compact" ? 32 : 36 }} + /> + + ); +} diff --git a/apps/mobile/src/features/home/HomeHeader.tsx b/apps/mobile/src/features/home/HomeHeader.tsx index e381cd8ab059..5e25f3a17217 100644 --- a/apps/mobile/src/features/home/HomeHeader.tsx +++ b/apps/mobile/src/features/home/HomeHeader.tsx @@ -11,6 +11,7 @@ import { useHardwareKeyboardCommand } from "../keyboard/hardwareKeyboardCommands import { withNativeGlassHeaderItem } from "../layout/native-glass-header-items"; import { createNativeMailSearchToolbarItem } from "../layout/native-mail-search-toolbar"; import { useNativeMailSearchToolbar } from "../../native/use-native-mail-search-toolbar"; +import { useDeviceType } from "../../native/native-layout-metrics"; import { buildHomeListFilterMenu } from "./home-list-filter-menu"; import { createSidebarHeaderItems } from "../threads/sidebar-native-header-items"; import type { HomeHeaderProps } from "./HomeHeader.types"; @@ -22,12 +23,13 @@ export function HomeHeader(props: HomeHeaderProps) { const navigation = useNavigation>(); const { layout, panes, togglePrimarySidebar } = useAdaptiveWorkspaceLayout(); const usesNativeMailSearchToolbar = useNativeMailSearchToolbar(); + const deviceType = useDeviceType(); const primaryColumn = use(NativePrimaryColumnContext); const sidebarHeader = Platform.OS === "ios" && primaryColumn !== null && - (Platform.isPad || !usesNativeMailSearchToolbar); - const showsCompactCompose = Platform.OS === "ios" && Platform.isPad && !layout.usesSplitView; + (deviceType === "pad" || !usesNativeMailSearchToolbar); + const showsCompactCompose = deviceType === "pad" && !layout.usesSplitView; const searchBarRef = useRef(null); const focusAfterReveal = useRef(false); useEffect( diff --git a/apps/mobile/src/features/home/HomeRouteScreen.tsx b/apps/mobile/src/features/home/HomeRouteScreen.tsx index 3c16c84e9267..677abeaaa70b 100644 --- a/apps/mobile/src/features/home/HomeRouteScreen.tsx +++ b/apps/mobile/src/features/home/HomeRouteScreen.tsx @@ -17,7 +17,7 @@ import { usePendingNewTasks } from "../../state/use-pending-new-tasks"; import { useWorkspaceState } from "../../state/workspace"; import { useSavedRemoteConnections } from "../../state/use-remote-environment-registry"; import { useAdaptiveWorkspaceLayout } from "../layout/AdaptiveWorkspaceLayout"; -import { useNativeColumnLayoutMetrics } from "../../native/native-layout-metrics"; +import { useDeviceType, useNativeColumnLayoutMetrics } from "../../native/native-layout-metrics"; import { WorkspaceEmptyDetail } from "../layout/WorkspaceEmptyDetail"; import { AndroidScreenHeader } from "../../components/ui/AndroidScreenHeader"; import { checkForAppUpdateOnLaunch, startAppUpdateForegroundRecheck } from "../updates/app-updates"; @@ -39,6 +39,7 @@ export function HomeRouteScreen() { const { width: windowWidth } = useWindowDimensions(); const nativePrimaryColumn = use(NativePrimaryColumnContext); const columnMetrics = useNativeColumnLayoutMetrics(); + const deviceType = useDeviceType(); const headerWidth = nativePrimaryColumn ? (columnMetrics?.width ?? windowWidth) : windowWidth; const { layout, panes, primarySidebarSearchQuery, setPrimarySidebarSearchQuery } = useAdaptiveWorkspaceLayout(); @@ -237,7 +238,7 @@ export function HomeRouteScreen() { ...getConnectionAwareBrandHeaderOptions({ headerWidth, trailingItemCount: - (nativePrimaryColumn && Platform.OS === "ios" && Platform.isPad ? 2 : 1) + + (nativePrimaryColumn && deviceType === "pad" ? 2 : 1) + (openVoiceSession === null ? 0 : 1), onOpenEnvironments: () => navigation.navigate("SettingsSheet", { diff --git a/apps/mobile/src/features/layout/AdaptiveWorkspaceLayout.tsx b/apps/mobile/src/features/layout/AdaptiveWorkspaceLayout.tsx index d698c5e02916..338c795f0cc6 100644 --- a/apps/mobile/src/features/layout/AdaptiveWorkspaceLayout.tsx +++ b/apps/mobile/src/features/layout/AdaptiveWorkspaceLayout.tsx @@ -34,8 +34,11 @@ import { AsyncResult } from "effect/reactivity"; import { deriveFileInspectorPaneLayout, + alignListPaneToHinge, deriveLayout, + type VerticalHinge, deriveWorkspacePaneLayout, + isPrimarySidebarPinned, type FileInspectorPaneLayout, type Layout, type WorkspaceAuxiliaryPaneRole, @@ -76,6 +79,8 @@ import { } from "../../native/v5-workspace-context"; import { useNativeLayoutMetrics } from "../../native/native-layout-metrics"; +import { AndroidHingeObserver } from "../../native/AndroidHingeObserver"; +import { WindowHingeContext } from "../../native/window-hinge-context"; interface AdaptiveWorkspaceContextValue { readonly layout: Layout; @@ -241,7 +246,6 @@ function AdaptiveWorkspaceLayoutContent( const navigation = useNavigation(); const activeRoleOwner = useRef(null); const [primarySidebarPreferredVisible, setPrimarySidebarPreferredVisible] = useState(true); - const showPrimarySidebar = pathname === "/" || primarySidebarPreferredVisible; const [supplementaryPanePreferredVisible, setSupplementaryPanePreferredVisible] = useState(true); const [supplementaryPanePreferredWidth, setSupplementaryPanePreferredWidth] = useState< number | null @@ -257,12 +261,36 @@ function AdaptiveWorkspaceLayoutContent( () => deriveLayout({ width: viewportWidth, height, nativeMetrics }), [height, viewportWidth, nativeMetrics], ); - const layout = baseLayout; - const shouldRenderNavigationRail = Platform.OS === "android" && layout.usesSplitView; + const primarySidebarPinned = isPrimarySidebarPinned({ + pathname, + nativeWorkspace, + usesSplitView: baseLayout.usesSplitView, + }); + const showPrimarySidebar = primarySidebarPinned || primarySidebarPreferredVisible; + const shouldRenderNavigationRail = Platform.OS === "android" && baseLayout.usesSplitView; const navigationRailWidth = shouldRenderNavigationRail && showPrimarySidebar ? ANDROID_WORKSPACE_RAIL_WIDTH * Math.max(1, androidControlScale) : 0; + const [hinge, setHinge] = useState(null); + const [windowHinge, setWindowHinge] = useState(null); + const handleHingeChange = useCallback( + (next: VerticalHinge | null, nextWindow: VerticalHinge | null) => { + setHinge(next); + setWindowHinge(nextWindow); + }, + [], + ); + const layout = useMemo( + () => + alignListPaneToHinge({ + layout: baseLayout, + hinge, + viewportWidth, + leadingWidth: navigationRailWidth, + }), + [baseLayout, hinge, viewportWidth, navigationRailWidth], + ); const width = viewportWidth - navigationRailWidth; const shouldRenderPrimarySidebar = layout.usesSplitView; const fileInspector = useMemo( @@ -356,7 +384,7 @@ function AdaptiveWorkspaceLayoutContent( }; }, []); const togglePrimarySidebar = useCallback(() => { - if (pathname === "/") { + if (primarySidebarPinned) { return; } if (!panes.primarySidebarVisible && panes.primarySidebarSuppressedByAuxiliary) { @@ -365,7 +393,11 @@ function AdaptiveWorkspaceLayoutContent( return; } setPrimarySidebarPreferredVisible((current) => !current); - }, [panes.primarySidebarSuppressedByAuxiliary, panes.primarySidebarVisible, pathname]); + }, [ + panes.primarySidebarSuppressedByAuxiliary, + panes.primarySidebarVisible, + primarySidebarPinned, + ]); const revealPrimarySidebar = useCallback(() => { if (panes.primarySidebarSuppressedByAuxiliary) { setFileInspectorPreferredVisible(false); @@ -377,8 +409,8 @@ function AdaptiveWorkspaceLayoutContent( return true; }, [togglePrimarySidebar]); const sidebarCommands = useMemo( - () => (pathname === "/" ? [] : (["toggleSidebar"] as const)), - [pathname], + () => (primarySidebarPinned ? [] : (["toggleSidebar"] as const)), + [primarySidebarPinned], ); useHardwareKeyboardCommand(sidebarCommands, handleToggleSidebarCommand); const showAuxiliaryPane = useCallback((role: WorkspaceAuxiliaryPaneRole) => { @@ -481,38 +513,69 @@ function AdaptiveWorkspaceLayoutContent( target: contentTargetWidth, sidebarVisible: panes.primarySidebarVisible, width: contentTargetWidth, + listPaneTarget: layout.listPaneWidth, + listPaneFloor: layout.listPaneWidth, + listPaneCeiling: layout.listPaneWidth, revision: 0, }); if ( Platform.OS === "android" && (contentSizing.viewportWidth !== viewportWidth || contentSizing.target !== contentTargetWidth || - contentSizing.sidebarVisible !== panes.primarySidebarVisible) + contentSizing.sidebarVisible !== panes.primarySidebarVisible || + contentSizing.listPaneTarget !== layout.listPaneWidth) ) { + const sameViewport = contentSizing.viewportWidth === viewportWidth; const openingSidebar = - Platform.OS === "android" && - contentSizing.viewportWidth === viewportWidth && - !contentSizing.sidebarVisible && + sameViewport && !contentSizing.sidebarVisible && panes.primarySidebarVisible; + // A book-posture hinge resizes the visible list pane instead of revealing it. + const resizingSidebar = + sameViewport && + contentSizing.sidebarVisible && panes.primarySidebarVisible && + contentSizing.listPaneTarget !== layout.listPaneWidth; + const keepWide = + (openingSidebar || resizingSidebar) && contentSizing.width !== null && contentTargetWidth !== null; setContentSizing({ viewportWidth, target: contentTargetWidth, sidebarVisible: panes.primarySidebarVisible, - width: openingSidebar + // Clip the wide navigator while the sidebar opens or widens, then reflow once at the + // end. Narrowing it first exposes an empty strip before the sidebar arrives. + width: keepWide ? Math.max(contentSizing.width ?? 0, contentTargetWidth ?? 0) : contentTargetWidth, + listPaneTarget: layout.listPaneWidth, + // While a hinge resizes the list, its width follows the pane edge within this span. A + // retarget mid-animation widens the span, since the edge is still somewhere inside it. + listPaneFloor: resizingSidebar + ? Math.min(contentSizing.listPaneFloor ?? 0, layout.listPaneWidth ?? 0) + : layout.listPaneWidth, + listPaneCeiling: resizingSidebar + ? Math.max(contentSizing.listPaneCeiling ?? 0, layout.listPaneWidth ?? 0) + : layout.listPaneWidth, revision: contentSizing.revision + 1, }); } const settleContentWidth = useCallback((revision: number) => { setContentSizing((current) => - current.revision !== revision || current.width === current.target + current.revision !== revision || + (current.width === current.target && + current.listPaneFloor === current.listPaneTarget && + current.listPaneCeiling === current.listPaneTarget) ? current - : { ...current, width: current.target }, + : { + ...current, + width: current.target, + listPaneFloor: current.listPaneTarget, + listPaneCeiling: current.listPaneTarget, + }, ); }, []); + const listPaneFloor = contentSizing.listPaneFloor ?? 0; + const listPaneCeiling = contentSizing.listPaneCeiling ?? 0; const contentSettledWidth = Platform.OS === "android" ? contentSizing.width : contentTargetWidth; const contentRevision = contentSizing.revision; @@ -541,6 +604,15 @@ function AdaptiveWorkspaceLayoutContent( contentRevision, ]); const railAnimatedStyle = useAnimatedStyle(() => ({ width: renderedRailWidth.value })); + // Showing or hiding the sidebar clips a fixed-width list. A hinge resize instead tracks the + // animated edge, so the header actions slide with it rather than jumping or being covered. + const listPaneGap = layout.listPaneGap ?? 0; + const listPaneAnimatedStyle = useAnimatedStyle(() => ({ + width: Math.min( + listPaneCeiling, + Math.max(listPaneFloor, renderedSidebarWidth.value - listPaneGap), + ), + })); const sidebarAnimatedStyle = useAnimatedStyle(() => ({ // Fading a UIKit glass ancestor can leave remounted header effects missing. opacity: Platform.OS === "ios" ? 1 : Math.min(1, renderedSidebarWidth.value / 80), @@ -667,102 +739,105 @@ function AdaptiveWorkspaceLayoutContent( savedFilters={props.savedThreadListFilters} > - - {shouldRenderNavigationRail ? ( - 0 ? "auto" : "no-hide-descendants"} - pointerEvents={navigationRailWidth > 0 ? "auto" : "none"} - style={railAnimatedStyle} - > - - - ) : null} - {shouldRenderPrimarySidebar && layout.listPaneWidth !== null ? ( - - - ( - - )} - > - - - - - - - - - ) : null} + + + {shouldRenderNavigationRail ? ( + 0 ? "auto" : "no-hide-descendants"} + pointerEvents={navigationRailWidth > 0 ? "auto" : "none"} + style={railAnimatedStyle} + > + + + ) : null} + {shouldRenderPrimarySidebar && layout.listPaneWidth !== null ? ( + + + ( + + )} + > + + + + + + + + + ) : null} - - {props.children} - + + {props.children} + + + - - + ); diff --git a/apps/mobile/src/features/layout/createWorkspaceStackNavigator.ios.tsx b/apps/mobile/src/features/layout/createWorkspaceStackNavigator.ios.tsx index db3aa3a26446..d6819517deb6 100644 --- a/apps/mobile/src/features/layout/createWorkspaceStackNavigator.ios.tsx +++ b/apps/mobile/src/features/layout/createWorkspaceStackNavigator.ios.tsx @@ -20,7 +20,7 @@ import { type NativeStackTypeBag, } from "@react-navigation/native-stack"; import { use, useCallback, useEffect, useMemo, useRef, useState, type ComponentProps } from "react"; -import { Platform, View } from "react-native"; +import { View } from "react-native"; import { Split, type SplitHostCommands } from "react-native-screens"; import { EnvironmentId, ThreadId } from "@t3tools/contracts"; import { scopedThreadKey } from "../../lib/scopedEntities"; @@ -42,7 +42,6 @@ import { } from "../../native/NativeWorkspaceColumns"; import { V5StackHeader } from "../../native/V5StackHeader.ios"; import type { AppNativeStackNavigationOptions } from "../../native/StackHeader"; -import { dispatchHardwareKeyboardCommand } from "../keyboard/hardwareKeyboardCommands"; import { nativeWorkspacePopAction, projectWorkspaceStack, @@ -183,7 +182,9 @@ function WorkspaceColumns( preferredSplitBehavior="tile" topColumnForCollapsing={compactColumn} preferredDisplayMode={ - panes.primarySidebarVisible || !activeDetailKey ? "oneBesideSecondary" : "secondaryOnly" + panes.primarySidebarVisible || (!layout.usesSplitView && !activeDetailKey) + ? "oneBesideSecondary" + : "secondaryOnly" } displayModeButtonVisibility="never" presentsWithGesture @@ -220,24 +221,6 @@ function WorkspaceColumns( options={{ headerShown: true, title: "", - unstable_headerRightItems: () => - Platform.OS === "ios" && - !Platform.isPad && - layout.usesSplitView && - !panes.primarySidebarVisible - ? [ - { - type: "button", - axisBehavior: "verticalPreferred", - accessibilityLabel: "Search threads", - label: "Search threads", - icon: { type: "sfSymbol", name: "magnifyingglass" }, - onPress: () => { - dispatchHardwareKeyboardCommand("focusSearch"); - }, - }, - ] - : [], unstable_headerLeftItems: () => [ { type: "button", diff --git a/apps/mobile/src/features/threads/ThreadFeed.tsx b/apps/mobile/src/features/threads/ThreadFeed.tsx index 3a552779abf9..b02e9f461f4f 100644 --- a/apps/mobile/src/features/threads/ThreadFeed.tsx +++ b/apps/mobile/src/features/threads/ThreadFeed.tsx @@ -66,6 +66,8 @@ import { SymbolView, type AppSymbolName } from "../../components/ui/AppSymbol"; import { HeaderHeightContext } from "@react-navigation/elements"; import { useFocusEffect, useNavigation } from "@react-navigation/native"; import { useNativeWorkspaceColumnsSupported } from "../../native/NativeWorkspaceColumns"; +import { useDeviceType } from "../../native/native-layout-metrics"; +import { isDuoDevice } from "../../lib/device-type"; import { createContext, memo, @@ -998,7 +1000,7 @@ function renderFeedEntry( readonly reviewCommentColors: ReviewCommentColors; readonly reviewCommentBubbleWidth: number; readonly themeAppearance: "light" | "dark"; - readonly usesNativeWorkspaceColumns: boolean; + readonly duoColumns: boolean; readonly userBubbleMaxWidth: number; readonly markdownContentWidth: number; readonly contentWidth: number; @@ -1189,19 +1191,11 @@ function renderFeedEntry( className="min-w-0 gap-2 rounded-[20px] px-3.5 py-2.5" style={{ backgroundColor: userBubbleColor, - maxWidth: - props.usesNativeWorkspaceColumns && Platform.OS === "ios" && !Platform.isPad - ? "85%" - : props.userBubbleMaxWidth, + maxWidth: props.duoColumns ? "85%" : props.userBubbleMaxWidth, ...(hasReviewCommentContext ? { width: props.reviewCommentBubbleWidth } : hasWideBlock - ? { - width: - props.usesNativeWorkspaceColumns && Platform.OS === "ios" && !Platform.isPad - ? "85%" - : props.userBubbleMaxWidth, - } + ? { width: props.duoColumns ? "85%" : props.userBubbleMaxWidth } : null), }} > @@ -1667,7 +1661,8 @@ function ThreadFeedPlaceholder(props: { } export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) { - const usesNativeWorkspaceColumns = useNativeWorkspaceColumnsSupported(); + const deviceType = useDeviceType(); + const duoColumns = useNativeWorkspaceColumnsSupported() && isDuoDevice(deviceType); const openPullRequest = useOpenPullRequest(); const navigation = useNavigation(); const { themeAppearance } = useAppearancePreferences(); @@ -2478,7 +2473,7 @@ export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) { reviewCommentColors, reviewCommentBubbleWidth, themeAppearance, - usesNativeWorkspaceColumns, + duoColumns, userBubbleMaxWidth, markdownContentWidth, contentWidth, @@ -2517,7 +2512,7 @@ export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) { reviewCommentColors, reviewCommentBubbleWidth, themeAppearance, - usesNativeWorkspaceColumns, + duoColumns, userBubbleMaxWidth, markdownContentWidth, contentWidth, @@ -2572,10 +2567,7 @@ export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) { // Horizontal Duo reservations are already included in the row padding. contentInsetAdjustmentBehavior={ usesNativeAutomaticInsets - ? usesNativeWorkspaceColumns && - Platform.OS === "ios" && - !Platform.isPad && - props.layoutVariant === "split" + ? duoColumns && props.layoutVariant === "split" ? "scrollableAxes" : "automatic" : "never" diff --git a/apps/mobile/src/features/threads/ThreadNavigationSidebar.tsx b/apps/mobile/src/features/threads/ThreadNavigationSidebar.tsx index 7afe454ccb69..66be152db074 100644 --- a/apps/mobile/src/features/threads/ThreadNavigationSidebar.tsx +++ b/apps/mobile/src/features/threads/ThreadNavigationSidebar.tsx @@ -929,7 +929,8 @@ function ThreadNavigationSidebarPane( className={ Platform.OS === "android" ? "flex-1 bg-header" : "flex-1 border-r border-border bg-drawer" } - style={{ width: props.width }} + // Android fills its pane, which animates its width while a hinge resizes the split. + style={Platform.OS === "android" ? undefined : { width: props.width }} > void; }) { const usesNativeWorkspaceColumns = useNativeWorkspaceColumnsSupported(); - const usesDuoHeader = usesNativeWorkspaceColumns && Platform.OS === "ios" && !Platform.isPad; + const deviceType = useDeviceType(); + const usesDuoHeader = usesNativeWorkspaceColumns && isDuoDevice(deviceType); const navigation = useNavigation(); const { layout, panes, togglePrimarySidebar } = useAdaptiveWorkspaceLayout(); const threadCenterHeaderItems = useThreadGitCenterHeaderItems(props.gitControls); @@ -103,24 +104,6 @@ export function useThreadHeaderOptions(props: { () => [ ...threadCenterHeaderItems, { type: "spacing", spacing: 8 }, - ...(layout.usesSplitView && - Platform.OS === "ios" && - !Platform.isPad && - !panes.primarySidebarVisible - ? [ - withNativeGlassHeaderItem({ - type: "button" as const, - axisBehavior: "verticalPreferred", - identifier: "thread-right-search", - label: "Search threads", - accessibilityLabel: "Search threads", - icon: { name: "magnifyingglass", type: "sfSymbol" as const }, - onPress: () => { - dispatchHardwareKeyboardCommand("focusSearch"); - }, - }), - ] - : []), withNativeGlassHeaderItem({ type: "button" as const, axisBehavior: "verticalPreferred", @@ -131,7 +114,7 @@ export function useThreadHeaderOptions(props: { onPress: () => navigation.navigate("NewTaskSheet", { screen: "NewTask" }), }), ], - [navigation, threadCenterHeaderItems, layout.usesSplitView, panes.primarySidebarVisible], + [navigation, threadCenterHeaderItems], ); const options: AppNativeStackNavigationOptions = { diff --git a/apps/mobile/src/features/workspace/WorkspaceNativeTabs.ios.tsx b/apps/mobile/src/features/workspace/WorkspaceNativeTabs.ios.tsx index 40c19d6438ab..66571a1a3090 100644 --- a/apps/mobile/src/features/workspace/WorkspaceNativeTabs.ios.tsx +++ b/apps/mobile/src/features/workspace/WorkspaceNativeTabs.ios.tsx @@ -1,4 +1,4 @@ -import { useNativeLayoutMetrics } from "../../native/native-layout-metrics"; +import { useDeviceType, useNativeLayoutMetrics } from "../../native/native-layout-metrics"; import { useCallback, useMemo, useState, type ReactNode } from "react"; import { Keyboard, Platform, View, type NativeSyntheticEvent } from "react-native"; import { @@ -52,8 +52,11 @@ export function WorkspaceNativeTabs(props: { }) { const workspace = useWorkspaceTabs()!; const metrics = useNativeLayoutMetrics(); + const deviceType = useDeviceType(); const phoneBar = - Platform.OS === "ios" && !Platform.isPad && (metrics?.verticalBarEdge ?? "none") === "none"; + Platform.OS === "ios" && + deviceType !== "pad" && + (metrics?.verticalBarEdge ?? "none") === "none"; const [provenance, setProvenance] = useState(0); const systemTabBar = useSystemWorkspaceTabBar(); const selectedTab = workspace.state.selectedTab; diff --git a/apps/mobile/src/features/workspace/WorkspaceRootScreen.tsx b/apps/mobile/src/features/workspace/WorkspaceRootScreen.tsx index bcb777e46c95..3f6dc6415e20 100644 --- a/apps/mobile/src/features/workspace/WorkspaceRootScreen.tsx +++ b/apps/mobile/src/features/workspace/WorkspaceRootScreen.tsx @@ -9,6 +9,7 @@ import { AndroidScreenHeader } from "../../components/ui/AndroidScreenHeader"; import { NativeStackScreenOptions } from "../../native/StackHeader"; import { NativePrimaryColumnContext } from "../../native/v5-workspace-context"; import { + useDeviceType, useNativeColumnLayoutMetrics, useNativeLayoutMetrics, } from "../../native/native-layout-metrics"; @@ -57,13 +58,14 @@ function WorkspaceRootContent() { const primaryColumn = use(NativePrimaryColumnContext); const columnMetrics = useNativeColumnLayoutMetrics(); const nativeMetrics = useNativeLayoutMetrics(); + const deviceType = useDeviceType(); const systemTabBar = useSystemWorkspaceTabBar(); const sidebarTabs = useSidebarWorkspaceTabs(); const sidebarPicker = sidebarTabs === "picker"; const sidebarNavigation = primaryColumn !== null && (layout.usesSplitView || - (Platform.OS === "ios" && Platform.isPad) || + deviceType === "pad" || (nativeMetrics !== null && nativeMetrics.verticalBarEdge !== "none")); const width = columnMetrics?.width ?? windowWidth; const insets = useSafeAreaInsets(); diff --git a/apps/mobile/src/features/workspace/WorkspaceToolbar.ios.tsx b/apps/mobile/src/features/workspace/WorkspaceToolbar.ios.tsx index 33c3fab8ec9e..af815639fabc 100644 --- a/apps/mobile/src/features/workspace/WorkspaceToolbar.ios.tsx +++ b/apps/mobile/src/features/workspace/WorkspaceToolbar.ios.tsx @@ -2,7 +2,7 @@ import { Toolbar } from "../../components/ui/Toolbar"; import { useFocusEffect, useNavigation } from "@react-navigation/native"; import { use, useCallback, useEffect, useRef } from "react"; import { Platform } from "react-native"; -import { useNativeLayoutMetrics } from "../../native/native-layout-metrics"; +import { useDeviceType, useNativeLayoutMetrics } from "../../native/native-layout-metrics"; import type { SearchBarCommands } from "react-native-screens"; import { NATIVE_LIQUID_GLASS_SUPPORTED } from "../../native/native-glass"; @@ -25,12 +25,15 @@ export function WorkspaceToolbar(props: { const workspace = useWorkspaceTabs()!; const navigation = useNavigation(); const metrics = useNativeLayoutMetrics(); + const deviceType = useDeviceType(); const sidebarTabs = useSidebarWorkspaceTabs(); const selectTab = useSelectWorkspaceTab(); const selectedTint = useMobileNavigationTheme().colors.primary; const nativeToolbarCompose = Platform.OS === "ios" && - (Platform.isPad || sidebarTabs !== null || (metrics?.verticalBarEdge ?? "none") !== "none"); + (deviceType === "pad" || + sidebarTabs !== null || + (metrics?.verticalBarEdge ?? "none") !== "none"); const { isTabActive } = workspace; const tabActive = use(NativeWorkspaceTabActivityContext)?.active ?? true; const { panes, togglePrimarySidebar } = useAdaptiveWorkspaceLayout(); diff --git a/apps/mobile/src/features/workspace/useSystemWorkspaceTabBar.ts b/apps/mobile/src/features/workspace/useSystemWorkspaceTabBar.ts index d08f3095333b..56ea918ede0b 100644 --- a/apps/mobile/src/features/workspace/useSystemWorkspaceTabBar.ts +++ b/apps/mobile/src/features/workspace/useSystemWorkspaceTabBar.ts @@ -1,13 +1,14 @@ import { Platform } from "react-native"; import { useAdaptiveWorkspaceLayout } from "../layout/AdaptiveWorkspaceLayout"; -import { useNativeLayoutMetrics } from "../../native/native-layout-metrics"; +import { useDeviceType, useNativeLayoutMetrics } from "../../native/native-layout-metrics"; /** Where an iOS split window shows the workspace tabs instead of UIKit's tab bar. */ export function useSidebarWorkspaceTabs(): "picker" | "toolbar" | null { const { layout } = useAdaptiveWorkspaceLayout(); + const deviceType = useDeviceType(); const metrics = useNativeLayoutMetrics(); if (Platform.OS !== "ios" || !layout.usesSplitView) return null; - if (Platform.isPad) return "picker"; + if (deviceType === "pad") return "picker"; // The Duo's side rail carries UIKit's tabs. Unfolded in portrait it has no // rail, so the tabs sit in the thread list's own toolbar. return (metrics?.verticalBarEdge ?? "none") === "none" ? "toolbar" : null; diff --git a/apps/mobile/src/lib/device-type.test.ts b/apps/mobile/src/lib/device-type.test.ts new file mode 100644 index 000000000000..101c90c1f90d --- /dev/null +++ b/apps/mobile/src/lib/device-type.test.ts @@ -0,0 +1,62 @@ +import { describe, expect, it } from "vite-plus/test"; +import { deriveDeviceType, isDuoDevice } from "./device-type"; +import type { NativeLayoutMetrics } from "./reserved-regions"; + +// Poses reported by the iOS 27.1 iPhone Duo simulator. +const duoOuter: NativeLayoutMetrics = { + width: 466, + height: 678, + hasHinge: true, + horizontalSizeClass: "compact", + verticalBarEdge: "right", + safeArea: { top: 0, bottom: 34, left: 0, right: 84 }, + reservedRegions: [], +}; +const duoInnerPortrait: NativeLayoutMetrics = { + width: 669, + height: 951, + hasHinge: true, + horizontalSizeClass: "regular", + verticalBarEdge: "none", + safeArea: { top: 82, bottom: 34, left: 0, right: 0 }, + reservedRegions: [{ kind: "occlusion", x: 535, y: 0, width: 134, height: 82 }], +}; +const phone: NativeLayoutMetrics = { + width: 393, + height: 852, + horizontalSizeClass: "compact", + verticalBarEdge: "none", + safeArea: { top: 59, bottom: 34, left: 0, right: 0 }, + reservedRegions: [], +}; + +describe("deriveDeviceType", () => { + it("follows the Duo between its displays", () => { + expect(deriveDeviceType({ isPad: false, metrics: duoOuter })).toBe("duo-folded"); + expect(deriveDeviceType({ isPad: false, metrics: duoInnerPortrait })).toBe("duo-unfolded"); + expect( + deriveDeviceType({ + isPad: false, + metrics: { ...duoInnerPortrait, width: 951, height: 669, verticalBarEdge: "right" }, + }), + ).toBe("duo-unfolded"); + }); + + it("treats a narrow inner-display window like the folded screen", () => { + expect( + deriveDeviceType({ + isPad: false, + metrics: { ...duoInnerPortrait, width: 320, horizontalSizeClass: "compact" }, + }), + ).toBe("duo-folded"); + }); + + it("keeps ordinary phones and iPads out of the Duo branches", () => { + expect(deriveDeviceType({ isPad: false, metrics: phone })).toBe("phone"); + expect(deriveDeviceType({ isPad: false, metrics: null })).toBe("phone"); + expect(deriveDeviceType({ isPad: true, metrics: null })).toBe("pad"); + const slideOver = { ...phone, width: 320, height: 1024 }; + expect(deriveDeviceType({ isPad: true, metrics: slideOver })).toBe("pad"); + expect(isDuoDevice(deriveDeviceType({ isPad: true, metrics: slideOver }))).toBe(false); + }); +}); diff --git a/apps/mobile/src/lib/device-type.ts b/apps/mobile/src/lib/device-type.ts new file mode 100644 index 000000000000..f2d79399aeba --- /dev/null +++ b/apps/mobile/src/lib/device-type.ts @@ -0,0 +1,25 @@ +import type { NativeLayoutMetrics } from "./reserved-regions"; + +/** + * Hardware family for device-specific chrome. Column count still comes from + * `deriveLayout`: an iPad in Slide Over or a narrow window on the Duo's inner + * display keeps its device type but has no room for a sidebar. + * + * iOS only. Android has no layout metrics observer and always reads "phone". + */ +export type DeviceType = "phone" | "duo-folded" | "duo-unfolded" | "pad"; + +export function deriveDeviceType(input: { + readonly isPad: boolean; + readonly metrics: NativeLayoutMetrics | null; +}): DeviceType { + if (input.isPad) return "pad"; + // The hinge arrives with the first native layout pass, so a Duo reads as a + // phone until then. Compact width also covers a narrow inner-display window. + if (input.metrics?.hasHinge !== true) return "phone"; + return input.metrics.horizontalSizeClass === "regular" ? "duo-unfolded" : "duo-folded"; +} + +export function isDuoDevice(deviceType: DeviceType): boolean { + return deviceType === "duo-folded" || deviceType === "duo-unfolded"; +} diff --git a/apps/mobile/src/lib/layout.test.ts b/apps/mobile/src/lib/layout.test.ts index 7d288b1352a5..52415e799742 100644 --- a/apps/mobile/src/lib/layout.test.ts +++ b/apps/mobile/src/lib/layout.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it } from "vite-plus/test"; import { + alignListPaneToHinge, constrainAuxiliaryPaneWidth, deriveCenteredContentHorizontalPadding, deriveFileInspectorPaneLayout, @@ -8,6 +9,7 @@ import { deriveThreadFeedInitialContentInset, deriveThreadWorkLogSizing, deriveWorkspacePaneLayout, + isPrimarySidebarPinned, SPLIT_LAYOUT_MIN_HEIGHT, SPLIT_LAYOUT_MIN_WIDTH, } from "./layout"; @@ -160,6 +162,36 @@ describe("deriveLayout", () => { }); }); +describe("isPrimarySidebarPinned", () => { + it("lets native split columns collapse the sidebar on the workspace root", () => { + expect( + isPrimarySidebarPinned({ pathname: "/", nativeWorkspace: true, usesSplitView: true }), + ).toBe(false); + }); + + it("keeps compact native roots pinned so search cannot hide the sidebar for a later split", () => { + expect( + isPrimarySidebarPinned({ pathname: "/", nativeWorkspace: true, usesSplitView: false }), + ).toBe(true); + }); + + it("keeps the JS split layout pinned on the workspace root", () => { + expect( + isPrimarySidebarPinned({ pathname: "/", nativeWorkspace: false, usesSplitView: true }), + ).toBe(true); + }); + + it("never pins outside the workspace root", () => { + expect( + isPrimarySidebarPinned({ + pathname: "/threads/a/b", + nativeWorkspace: false, + usesSplitView: true, + }), + ).toBe(false); + }); +}); + describe("deriveWorkspacePaneLayout", () => { it("keeps the auxiliary pane out of a standard iPad detail column", () => { const layout = deriveLayout({ width: 1_194, height: 834 }); @@ -384,3 +416,35 @@ describe("deriveWorkspacePaneLayout", () => { }); }); }); + +describe("alignListPaneToHinge", () => { + const layout = deriveLayout({ width: 852, height: 880 }); + + it("ends the list pane at a book-posture hinge after the rail", () => { + expect( + alignListPaneToHinge({ + layout, + hinge: { x: 426, width: 0 }, + viewportWidth: 852, + leadingWidth: 96, + }), + ).toMatchObject({ listPaneWidth: 330, listPaneGap: 0 }); + }); + + it("keeps the default split when either side of the hinge would be too narrow", () => { + const narrowList = { + layout, + hinge: { x: 300, width: 0 }, + viewportWidth: 852, + leadingWidth: 96, + }; + const narrowDetail = { + layout, + hinge: { x: 600, width: 0 }, + viewportWidth: 852, + leadingWidth: 0, + }; + expect(alignListPaneToHinge(narrowList)).toBe(layout); + expect(alignListPaneToHinge(narrowDetail)).toBe(layout); + }); +}); diff --git a/apps/mobile/src/lib/layout.ts b/apps/mobile/src/lib/layout.ts index 49592afc6236..2fd4acc32e3f 100644 --- a/apps/mobile/src/lib/layout.ts +++ b/apps/mobile/src/lib/layout.ts @@ -131,6 +131,47 @@ export function deriveLayout(input: { }; } +export interface VerticalHinge { + readonly x: number; + readonly width: number; +} + +/** + * Moves the list/detail split onto a book-posture hinge so neither pane straddles the crease. + * `leadingWidth` is chrome left of the list pane, such as the Android navigation rail. + */ +export function alignListPaneToHinge(input: { + readonly layout: Layout; + readonly hinge: VerticalHinge | null; + readonly viewportWidth: number; + readonly leadingWidth: number; +}): Layout { + const { layout, hinge } = input; + if (!hinge || !layout.usesSplitView) return layout; + const listPaneWidth = hinge.x - input.leadingWidth; + if ( + listPaneWidth < SPLIT_SIDEBAR_MIN_WIDTH || + input.viewportWidth - hinge.x - hinge.width < 320 + ) { + return layout; + } + return { ...layout, listPaneWidth, listPaneGap: hinge.width }; +} + +/** + * Whether the workspace root must keep the primary sidebar open. Native split + * columns keep a sidebar toggle in the empty detail header, so only they may + * collapse it there. Compact layouts stay pinned so a reveal request (such as + * focusing search) cannot flip the saved preference for a later split view. + */ +export function isPrimarySidebarPinned(input: { + readonly pathname: string; + readonly nativeWorkspace: boolean; + readonly usesSplitView: boolean; +}): boolean { + return input.pathname === "/" && !(input.nativeWorkspace && input.usesSplitView); +} + export function deriveWorkspacePaneLayout(input: { readonly layout: Layout; readonly viewportWidth: number; diff --git a/apps/mobile/src/lib/menu-placement.test.ts b/apps/mobile/src/lib/menu-placement.test.ts new file mode 100644 index 000000000000..35721d910f5e --- /dev/null +++ b/apps/mobile/src/lib/menu-placement.test.ts @@ -0,0 +1,24 @@ +import { describe, expect, it } from "vite-plus/test"; + +import { deriveMenuHorizontalPlacement } from "./menu-placement"; + +const base = { anchorWidth: 48, overlayWidth: 852, desiredWidth: 224, margin: 12 }; + +describe("deriveMenuHorizontalPlacement", () => { + it("opens toward the roomier side of the whole screen without a hinge", () => { + expect(deriveMenuHorizontalPlacement({ ...base, anchorX: 300, hinge: null })).toEqual({ + left: 300, + width: 224, + }); + }); + + it("keeps a menu on its anchor's side of a creased hinge", () => { + // The filter button sits near the crease, so the menu right-aligns to it instead of crossing. + expect( + deriveMenuHorizontalPlacement({ ...base, anchorX: 340, hinge: { x: 426, width: 0 } }), + ).toEqual({ left: 164, width: 224 }); + expect( + deriveMenuHorizontalPlacement({ ...base, anchorX: 430, hinge: { x: 426, width: 0 } }), + ).toEqual({ left: 438, width: 224 }); + }); +}); diff --git a/apps/mobile/src/lib/menu-placement.ts b/apps/mobile/src/lib/menu-placement.ts new file mode 100644 index 000000000000..4de71bdea416 --- /dev/null +++ b/apps/mobile/src/lib/menu-placement.ts @@ -0,0 +1,28 @@ +import type { VerticalHinge } from "./layout"; + +/** + * Places a menu beside its anchor within the screen region that holds it. A creased hinge splits + * the overlay into two regions, so a menu never straddles the fold. + */ +export function deriveMenuHorizontalPlacement(input: { + readonly anchorX: number; + readonly anchorWidth: number; + readonly overlayWidth: number; + readonly desiredWidth: number; + readonly margin: number; + /** In the overlay's coordinates. */ + readonly hinge: VerticalHinge | null; +}) { + const center = input.anchorX + input.anchorWidth / 2; + let start = 0; + let end = input.overlayWidth; + if (input.hinge) { + if (center < input.hinge.x) end = input.hinge.x; + else start = input.hinge.x + input.hinge.width; + } + const width = Math.min(input.desiredWidth, Math.max(0, end - start - 2 * input.margin)); + const preferredLeft = + center <= (start + end) / 2 ? input.anchorX : input.anchorX + input.anchorWidth - width; + const left = Math.min(Math.max(preferredLeft, start + input.margin), end - width - input.margin); + return { left, width }; +} diff --git a/apps/mobile/src/native/AndroidHingeObserver.android.tsx b/apps/mobile/src/native/AndroidHingeObserver.android.tsx new file mode 100644 index 000000000000..39a1594b536d --- /dev/null +++ b/apps/mobile/src/native/AndroidHingeObserver.android.tsx @@ -0,0 +1,29 @@ +import { requireNativeView } from "expo"; +import type { NativeSyntheticEvent, ViewProps } from "react-native"; +import type { VerticalHinge } from "../lib/layout"; + +interface ObserverProps extends ViewProps { + readonly onHingeChange: ( + event: NativeSyntheticEvent>, + ) => void; +} + +const Observer = requireNativeView("T3FoldPosture"); + +/** Reports a vertical hinge in this view's coordinates while the device is bent like a book. */ +export function AndroidHingeObserver(props: { + /** Receives the hinge in this view's coordinates and in window coordinates. */ + readonly onChange: (hinge: VerticalHinge | null, windowHinge: VerticalHinge | null) => void; +}) { + return ( + + x === undefined || width === undefined || windowX === undefined + ? props.onChange(null, null) + : props.onChange({ x, width }, { x: windowX, width }) + } + style={{ position: "absolute", top: 0, bottom: 0, left: 0, right: 0 }} + /> + ); +} diff --git a/apps/mobile/src/native/AndroidHingeObserver.tsx b/apps/mobile/src/native/AndroidHingeObserver.tsx new file mode 100644 index 000000000000..164ce6211a51 --- /dev/null +++ b/apps/mobile/src/native/AndroidHingeObserver.tsx @@ -0,0 +1,7 @@ +import type { VerticalHinge } from "../lib/layout"; + +export function AndroidHingeObserver(_props: { + readonly onChange: (hinge: VerticalHinge | null, windowHinge: VerticalHinge | null) => void; +}) { + return null; +} diff --git a/apps/mobile/src/native/V5StackHeader.ios.tsx b/apps/mobile/src/native/V5StackHeader.ios.tsx index c9e923f86724..495492b9b55d 100644 --- a/apps/mobile/src/native/V5StackHeader.ios.tsx +++ b/apps/mobile/src/native/V5StackHeader.ios.tsx @@ -4,9 +4,9 @@ import type { NativeStackNavigationOptions, } from "@react-navigation/native-stack"; import { isValidElement, useEffect, useRef } from "react"; -import { Platform, StyleSheet } from "react-native"; +import { StyleSheet } from "react-native"; import { useMobileNavigationTheme } from "../lib/useMobileNavigationTheme"; -import { useNativeLayoutMetrics } from "../native/native-layout-metrics"; +import { useDeviceType, useNativeLayoutMetrics } from "../native/native-layout-metrics"; import { SearchBar, Stack, @@ -144,6 +144,7 @@ export function V5StackHeader(props: { const { options } = props; const theme = useMobileNavigationTheme(); const nativeMetrics = useNativeLayoutMetrics(); + const deviceType = useDeviceType(); const searchRef = useRef(null); const itemProps = { tintColor: options.headerTintColor, canGoBack: props.canGoBack }; const leading = convertItems(options.unstable_headerLeftItems?.(itemProps) ?? [], "leading"); @@ -158,7 +159,7 @@ export function V5StackHeader(props: { const mailSearch = toolbar.find( (item): item is HeaderBarButtonMailSearchToolbarItem => item.type === "mailSearchToolbar", ); - const bottomSearch = Boolean(mailSearch) && Platform.OS === "ios" && !Platform.isPad; + const bottomSearch = Boolean(mailSearch) && deviceType !== "pad"; const bottom = toolbar.flatMap((item, index) => { if (item.type === "mailSearchToolbar") return []; if (item.type === "searchBarPlacement") diff --git a/apps/mobile/src/native/native-layout-metrics.tsx b/apps/mobile/src/native/native-layout-metrics.tsx index bd2d5db18339..44d12142d522 100644 --- a/apps/mobile/src/native/native-layout-metrics.tsx +++ b/apps/mobile/src/native/native-layout-metrics.tsx @@ -1,17 +1,28 @@ import { createContext, use, useState, type ReactNode } from "react"; +import { Platform } from "react-native"; +import { deriveDeviceType, type DeviceType } from "../lib/device-type"; import type { NativeLayoutMetrics } from "../lib/reserved-regions"; import { NativeLayoutObserver } from "./NativeLayoutObserver"; +const IS_PAD = Platform.OS === "ios" && Platform.isPad; + const NativeLayoutContext = createContext(null); +// Separate from the metrics so device checks skip every resize and safe-area update. +const DeviceTypeContext = createContext( + deriveDeviceType({ isPad: IS_PAD, metrics: null }), +); // Column reservations come from UIKit's layout, outside the resizing navigator. export const NativeColumnLayoutMetricsContext = createContext(null); export function NativeLayoutMetricsProvider(props: { readonly children: ReactNode }) { const [metrics, setMetrics] = useState(null); + const deviceType = deriveDeviceType({ isPad: IS_PAD, metrics }); return ( - - {props.children} + + + {props.children} + ); } @@ -23,3 +34,7 @@ export function useNativeLayoutMetrics() { export function useNativeColumnLayoutMetrics() { return use(NativeColumnLayoutMetricsContext); } + +export function useDeviceType() { + return use(DeviceTypeContext); +} diff --git a/apps/mobile/src/native/window-hinge-context.ts b/apps/mobile/src/native/window-hinge-context.ts new file mode 100644 index 000000000000..f2e031b335d0 --- /dev/null +++ b/apps/mobile/src/native/window-hinge-context.ts @@ -0,0 +1,5 @@ +import { createContext } from "react"; +import type { VerticalHinge } from "../lib/layout"; + +/** A creased vertical hinge in window coordinates, for overlays placed in window space. */ +export const WindowHingeContext = createContext(null); diff --git a/apps/mobile/src/state/use-thread-composer-state.ts b/apps/mobile/src/state/use-thread-composer-state.ts index 438b419672bc..d0866906f43d 100644 --- a/apps/mobile/src/state/use-thread-composer-state.ts +++ b/apps/mobile/src/state/use-thread-composer-state.ts @@ -307,7 +307,6 @@ export function useThreadComposerState() { ? EMPTY_QUEUE_WORKFLOW_ATOM : environmentThreadDetails.queueWorkflowAtom(selectedThreadDetailRef), ); - const canSteerActiveTurn = queueWorkflow?.canPromoteToSteer === true; const queuedRunEdit = useQueuedRunEdit(selectedThreadKey); const composerDraftKey = selectedThreadKey === null @@ -394,6 +393,8 @@ export function useThreadComposerState() { selectedThreadRuntime, selectedThreadVisibleTurnItems, ]); + // A compacting turn cannot take steering input, so follow-ups queue meanwhile. + const canSteerActiveTurn = queueWorkflow?.canPromoteToSteer === true && !isCompacting; const runlessWorkStartedAt = useMemo( () => diff --git a/apps/server/src/orchestration-v2/CommandPolicy.test.ts b/apps/server/src/orchestration-v2/CommandPolicy.test.ts index 70f9a7e3fa5f..d3c9f38a4951 100644 --- a/apps/server/src/orchestration-v2/CommandPolicy.test.ts +++ b/apps/server/src/orchestration-v2/CommandPolicy.test.ts @@ -1,6 +1,7 @@ import { assert, it } from "@effect/vitest"; import { CommandId, + MessageId, type OrchestrationV2ProviderCapabilities, type OrchestrationV2ThreadProjection, ProviderInstanceId, @@ -19,6 +20,7 @@ import * as CommandPolicy from "./CommandPolicy.ts"; const commandId = CommandId.make("command-policy-test"); const threadId = ThreadId.make("command-policy-thread"); const activeRunId = RunId.make("command-policy-active-run"); +const userMessageId = MessageId.make("command-policy-user-message"); const baseCapabilities: OrchestrationV2ProviderCapabilities = CodexProviderCapabilitiesV2; @@ -37,7 +39,8 @@ function dispatchProjection( runs: sessionCapabilities === undefined ? [] - : [{ id: activeRunId, status: "running", providerThreadId }], + : [{ id: activeRunId, status: "running", providerThreadId, userMessageId }], + messages: [{ id: userMessageId, text: "first", attachments: [] }], providerThreads: sessionCapabilities === undefined ? [] : [{ id: providerThreadId, providerSessionId }], providerSessions: @@ -141,6 +144,39 @@ it("targets the latest active run for explicit steer and restart intent", () => ); }); +it.each(["/compact", " /LOGOUT "])("queues a steer sent while %s runs", (text) => { + const projection = dispatchProjection(baseCapabilities); + const maintenance = { + ...projection, + messages: [{ id: userMessageId, text, attachments: [] }], + } as unknown as OrchestrationV2ThreadProjection; + for (const deliveryIntent of ["auto", "steer"] as const) { + assert.deepEqual( + CommandPolicy.resolveMessageDispatchIntent( + maintenance, + { type: "start_immediately" }, + deliveryIntent, + ), + { type: "queue_after_active" }, + ); + } + assert.deepEqual( + CommandPolicy.resolveMessageDispatchIntent(maintenance, { + type: "steer_active", + targetRunId: activeRunId, + }), + { type: "queue_after_active" }, + ); + assert.deepEqual( + CommandPolicy.resolveMessageDispatchIntent( + maintenance, + { type: "start_immediately" }, + "restart", + ), + { type: "restart_active", targetRunId: activeRunId }, + ); +}); + const layer = it.layer(CommandPolicy.layer); layer("CommandPolicyV2", (it) => { diff --git a/apps/server/src/orchestration-v2/CommandPolicy.ts b/apps/server/src/orchestration-v2/CommandPolicy.ts index 1098c72c3072..751ce08f72ef 100644 --- a/apps/server/src/orchestration-v2/CommandPolicy.ts +++ b/apps/server/src/orchestration-v2/CommandPolicy.ts @@ -1,4 +1,5 @@ import { + type ChatAttachment, CommandId, ModelSelection, type OrchestrationV2Command, @@ -116,10 +117,37 @@ type MessageDispatchMode = Extract< { readonly type: "message.dispatch" } >["dispatchMode"]; +export function isNativeMaintenanceCommand(message: { + readonly text: string; + readonly attachments: ReadonlyArray; + readonly context?: import("@t3tools/contracts").OrchestrationMessageContext | undefined; +}): boolean { + return ( + message.attachments.length === 0 && + ["/compact", "/logout"].includes(message.text.trim().toLowerCase()) + ); +} + export function resolveMessageDispatchIntent( projection: OrchestrationV2ThreadProjection, requestedMode: MessageDispatchMode, deliveryIntent?: "auto" | "steer" | "restart", +): MessageDispatchMode { + const mode = resolveDeliveryIntent(projection, requestedMode, deliveryIntent); + if (mode.type !== "steer_active") return mode; + // Compaction and sign-out turns cannot take steering input. A message sent + // while one runs waits in the queue like any other follow-up. + const target = projection.runs.find((run) => run.id === mode.targetRunId); + const targetMessage = projection.messages.find((message) => message.id === target?.userMessageId); + return targetMessage !== undefined && isNativeMaintenanceCommand(targetMessage) + ? { type: "queue_after_active" } + : mode; +} + +function resolveDeliveryIntent( + projection: OrchestrationV2ThreadProjection, + requestedMode: MessageDispatchMode, + deliveryIntent?: "auto" | "steer" | "restart", ): MessageDispatchMode { if (deliveryIntent === undefined) return requestedMode; diff --git a/apps/server/src/orchestration-v2/Orchestrator.ts b/apps/server/src/orchestration-v2/Orchestrator.ts index 8369af77fdb6..491ddff3a720 100644 --- a/apps/server/src/orchestration-v2/Orchestrator.ts +++ b/apps/server/src/orchestration-v2/Orchestrator.ts @@ -84,7 +84,11 @@ import { SHARED_WORKSPACE_RESTORE_MESSAGE, } from "./CheckpointRestoreSafety.ts"; import { CheckpointServiceV2 } from "./CheckpointService.ts"; -import { CommandPolicyV2, resolveMessageDispatchIntent } from "./CommandPolicy.ts"; +import { + CommandPolicyV2, + isNativeMaintenanceCommand, + resolveMessageDispatchIntent, +} from "./CommandPolicy.ts"; import { CommandReceiptStoreV2 } from "./CommandReceiptStore.ts"; import { ContextHandoffServiceV2 } from "./ContextHandoffService.ts"; import { notificationTurnItem } from "@t3tools/provider-core/server/notification"; @@ -404,17 +408,6 @@ function wakeWorkStartedAt( return previous === undefined ? {} : { workStartedAt: orchestrationV2RunWorkStartedAt(previous) }; } -export function isNativeMaintenanceCommand(message: { - readonly text: string; - readonly attachments: ReadonlyArray; - readonly context?: import("@t3tools/contracts").OrchestrationMessageContext | undefined; -}): boolean { - return ( - message.attachments.length === 0 && - ["/compact", "/logout"].includes(message.text.trim().toLowerCase()) - ); -} - function isGoalCommand(message: { readonly text: string; readonly attachments: ReadonlyArray; diff --git a/apps/server/src/orchestration-v2/RestartContinuation.ts b/apps/server/src/orchestration-v2/RestartContinuation.ts index 152252233c17..59eee330c1d3 100644 --- a/apps/server/src/orchestration-v2/RestartContinuation.ts +++ b/apps/server/src/orchestration-v2/RestartContinuation.ts @@ -13,7 +13,7 @@ import * as Effect from "effect/Effect"; import type { ProjectionRuntimeRecoveryState } from "./ProjectionStore.ts"; import * as ServerSettings from "../serverSettings.ts"; -import { isNativeMaintenanceCommand } from "./Orchestrator.ts"; +import { isNativeMaintenanceCommand } from "./CommandPolicy.ts"; import * as ThreadManagementService from "./ThreadManagementService.ts"; import { cancelledRosterTaskWork, diff --git a/apps/server/src/orchestration-v2/ThreadLaunchService.test.ts b/apps/server/src/orchestration-v2/ThreadLaunchService.test.ts index f462c6f88a34..6df98b9809ef 100644 --- a/apps/server/src/orchestration-v2/ThreadLaunchService.test.ts +++ b/apps/server/src/orchestration-v2/ThreadLaunchService.test.ts @@ -755,19 +755,26 @@ it.effect("keeps native maintenance commands out of steering and restart message const targetRun = before.runs[0]; if (targetRun === undefined) return yield* Effect.die("Launch must create a run"); const commandId = CommandId.make(`${scenario.name}:message`); - const failure = yield* threads - .dispatch({ - type: "message.dispatch", - commandId, - threadId: launched.threadId, - messageId: MessageId.make(`${scenario.name}:message`), - createdBy: "user", - creationSource: "web", - text: scenario.next, - attachments: [], - dispatchMode: { type: scenario.mode, targetRunId: targetRun.id }, - }) - .pipe(Effect.flip); + const dispatch = threads.dispatch({ + type: "message.dispatch", + commandId, + threadId: launched.threadId, + messageId: MessageId.make(`${scenario.name}:message`), + createdBy: "user", + creationSource: "web", + text: scenario.next, + attachments: [], + dispatchMode: { type: scenario.mode, targetRunId: targetRun.id }, + }); + // A steer sent while a maintenance turn runs waits as a queued follow-up. + if (scenario.name.startsWith("steer-")) { + yield* dispatch; + const queued = (yield* threads.getThreadProjection(launched.threadId)).runs[1]; + assert.equal(queued?.status, "queued"); + assert.equal(queued?.userMessageId, MessageId.make(`${scenario.name}:message`)); + continue; + } + const failure = yield* dispatch.pipe(Effect.flip); assert.include( String(failure.cause).toLowerCase(), scenario.name.includes("logout") ? "sign" : "context compaction", diff --git a/apps/server/src/terminal/Manager.test.ts b/apps/server/src/terminal/Manager.test.ts index b803a7ee2094..65197ab61fa9 100644 --- a/apps/server/src/terminal/Manager.test.ts +++ b/apps/server/src/terminal/Manager.test.ts @@ -28,13 +28,15 @@ import * as PlatformError from "effect/PlatformError"; import * as Path from "effect/Path"; import * as Queue from "effect/Queue"; import * as Ref from "effect/Ref"; +import * as References from "effect/References"; import * as Schedule from "effect/Schedule"; import * as Schema from "effect/Schema"; import * as Scope from "effect/Scope"; import * as Stream from "effect/Stream"; +import * as SynchronizedRef from "effect/SynchronizedRef"; import * as TestClock from "effect/testing/TestClock"; import { ChildProcessSpawner } from "effect/process"; -import { expect } from "vite-plus/test"; +import { expect, vi } from "vite-plus/test"; import * as ServerSecretStore from "../auth/ServerSecretStore.ts"; import * as ServerConfig from "../config.ts"; @@ -44,6 +46,11 @@ import * as ServerSettings from "../serverSettings.ts"; import * as TerminalManager from "./Manager.ts"; import * as PtyAdapter from "@t3tools/shared/PtyAdapter"; +vi.mock("effect/SynchronizedRef", async (importOriginal) => { + const original = await importOriginal(); + return { ...original, make: vi.fn(original.make) }; +}); + const encodeUnknownJson = Schema.encodeUnknownSync(Schema.fromJsonString(Schema.Unknown)); class WaitForConditionError extends Data.TaggedError("WaitForConditionError")<{ @@ -61,6 +68,7 @@ class FakePtyProcess implements PtyAdapter.PtyProcess { private readonly exitListeners = new Set<(event: PtyAdapter.PtyExitEvent) => void>(); killed = false; exitOnSubscribe: PtyAdapter.PtyExitEvent | undefined; + onKill: ((signal?: string) => void) | undefined; constructor(pid: number) { this.pid = pid; @@ -83,6 +91,7 @@ class FakePtyProcess implements PtyAdapter.PtyProcess { kill(signal?: string): void { this.killed = true; this.killSignals.push(signal); + this.onKill?.(signal); } onData(callback: (data: string) => void): () => void { @@ -106,6 +115,10 @@ class FakePtyProcess implements PtyAdapter.PtyProcess { } } + get exitListenerCount(): number { + return this.exitListeners.size; + } + emitExit(event: PtyAdapter.PtyExitEvent): void { for (const listener of this.exitListeners) { listener(event); @@ -1792,6 +1805,94 @@ it.layer( }).pipe(Effect.provide(TestClock.layer())), ); + it.effect("skips SIGKILL when the process exits during the grace period", () => + Effect.gen(function* () { + const { manager, ptyAdapter } = yield* createManager(5, { processKillGraceMs: 10_000 }); + yield* manager.open(openInput()); + const process = ptyAdapter.processes[0]; + expect(process).toBeDefined(); + if (!process) return; + + const sigterm = yield* Deferred.make(); + process.onKill = (signal) => { + if (signal === "SIGTERM") Deferred.doneUnsafe(sigterm, Effect.void); + }; + + yield* manager.close({ threadId: "thread-1" }); + yield* Deferred.await(sigterm); + process.emitExit({ exitCode: 0, signal: 15 }); + yield* TestClock.adjust("10 seconds"); + + assert.deepEqual(process.killSignals, ["SIGTERM"]); + }).pipe(Effect.provide(TestClock.layer())), + ); + + it.effect("does not retain a kill fiber that finishes before registration", () => + Effect.gen(function* () { + let managerState: + | SynchronizedRef.SynchronizedRef<{ + killFibers: Map>; + }> + | undefined; + const originalMake = (value: A) => Effect.sync(() => SynchronizedRef.makeUnsafe(value)); + const makeSpy = vi.spyOn(SynchronizedRef, "make").mockImplementation((value) => + originalMake(value).pipe( + Effect.map((ref) => { + if (typeof value === "object" && value !== null && "killFibers" in value) { + managerState = ref as typeof managerState; + } + return ref; + }), + ), + ); + yield* Effect.addFinalizer(() => Effect.sync(() => makeSpy.mockRestore())); + for (const budget of [10, 15, 20, 25, 30, 40, 50, 75, 100, 150, 200, 500]) { + const { manager, ptyAdapter } = yield* createManager(); + yield* manager.open(openInput()); + const process = ptyAdapter.processes[0]!; + process.onKill = () => process.emitExit({ exitCode: 0, signal: 15 }); + // Vary the caller's operation budget to cover child completion before + // and after the parent resumes its registration step. + yield* manager + .close({ threadId: "thread-1" }) + .pipe(Effect.provideService(References.MaxOpsBeforeYield, budget)); + yield* Effect.yieldNow; + expect(managerState).toBeDefined(); + yield* Fiber.awaitAll(SynchronizedRef.getUnsafe(managerState!).killFibers.values()); + expect(SynchronizedRef.getUnsafe(managerState!).killFibers.size, `budget ${budget}`).toBe( + 0, + ); + expect(process.killSignals).toEqual(["SIGTERM"]); + } + }), + ); + + it.effect("releases the exit listener when kill escalation is interrupted", () => + Effect.gen(function* () { + const scope = yield* Scope.make("sequential"); + const { manager, ptyAdapter } = yield* createManager(5, { + processKillGraceMs: 10_000, + }).pipe(Effect.provideService(Scope.Scope, scope)); + yield* manager.open(openInput()); + const process = ptyAdapter.processes[0]; + expect(process).toBeDefined(); + if (!process) return; + + const sigterm = yield* Deferred.make(); + process.onKill = (signal) => { + if (signal === "SIGTERM") Deferred.doneUnsafe(sigterm, Effect.void); + }; + yield* manager.close({ threadId: "thread-1" }); + yield* Deferred.await(sigterm); + assert.isAbove(process.exitListenerCount, 0); + + yield* Scope.close(scope, Exit.void); + + assert.equal(process.exitListenerCount, 0); + assert.deepEqual(process.killSignals, ["SIGTERM"]); + }).pipe(Effect.provide(TestClock.layer())), + ); + it.effect("publishes closed events when terminals are explicitly closed", () => Effect.gen(function* () { const { manager, getEvents } = yield* createManager(); diff --git a/apps/server/src/terminal/Manager.ts b/apps/server/src/terminal/Manager.ts index a9145663d924..0be928ce98a7 100644 --- a/apps/server/src/terminal/Manager.ts +++ b/apps/server/src/terminal/Manager.ts @@ -41,6 +41,7 @@ import { mergePathEntries } from "@t3tools/shared/shell"; import { acpRegistryManagedBinaryDirectories } from "@t3tools/provider-acp-registry/server"; import { getTerminalLabel } from "@t3tools/shared/terminalLabels"; import * as DateTime from "effect/DateTime"; +import * as Deferred from "effect/Deferred"; import * as Context from "effect/Context"; import * as Effect from "effect/Effect"; import * as Base64Url from "effect/encoding/Base64Url"; @@ -1566,6 +1567,11 @@ export const makeWithOptions = Effect.fn("TerminalManager.makeWithOptions")(func fiber: Fiber.Fiber, ) { yield* modifyManagerState((state) => { + // The child may finish (and run its finalizer) before this registration. + // Check inside the synchronized update so completed fibers are not retained. + if (fiber.pollUnsafe() !== undefined) { + return [undefined, state] as const; + } const killFibers = new Map(state.killFibers); killFibers.set(process, fiber); return [undefined, { ...state, killFibers }] as const; @@ -1577,49 +1583,66 @@ export const makeWithOptions = Effect.fn("TerminalManager.makeWithOptions")(func threadId: string, terminalId: string, ) { - const terminated = yield* Effect.try({ - try: () => process.kill("SIGTERM"), - catch: (cause) => - new TerminalProcessSignalError({ - cause, - signal: "SIGTERM", - terminalPid: process.pid, - }), - }).pipe( - Effect.as(true), - Effect.catch((error) => - Effect.logWarning("failed to kill terminal process", { - threadId, - terminalId, - signal: "SIGTERM", - cause: error, - }).pipe(Effect.as(false)), - ), - ); - if (!terminated) { - return; - } - - yield* Effect.sleep(processKillGraceMs); + // Subscribe before SIGTERM so an immediate exit is not missed. Released with + // Effect.ensuring because a JS `finally` does not run when the fiber is interrupted. + const exited = Deferred.makeUnsafe(); + const unsubscribeExit = process.onExit(() => { + Deferred.doneUnsafe(exited, Effect.void); + }); + yield* Effect.gen(function* () { + const terminated = yield* Effect.try({ + try: () => process.kill("SIGTERM"), + catch: (cause) => + new TerminalProcessSignalError({ + cause, + signal: "SIGTERM", + terminalPid: process.pid, + }), + }).pipe( + Effect.as(true), + Effect.catch((error) => + Effect.logWarning("failed to kill terminal process", { + threadId, + terminalId, + signal: "SIGTERM", + cause: error, + }).pipe(Effect.as(false)), + ), + ); + if (!terminated) { + return; + } - yield* Effect.try({ - try: () => process.kill("SIGKILL"), - catch: (cause) => - new TerminalProcessSignalError({ - cause, - signal: "SIGKILL", - terminalPid: process.pid, - }), - }).pipe( - Effect.catch((error) => - Effect.logWarning("failed to force-kill terminal process", { - threadId, - terminalId, - signal: "SIGKILL", - cause: error, + const exitedBeforeGrace = yield* Deferred.await(exited).pipe( + Effect.as(true), + Effect.timeoutOrElse({ + duration: processKillGraceMs, + orElse: () => Effect.succeed(false), }), - ), - ); + ); + if (exitedBeforeGrace) { + return; + } + + yield* Effect.try({ + try: () => process.kill("SIGKILL"), + catch: (cause) => + new TerminalProcessSignalError({ + cause, + signal: "SIGKILL", + terminalPid: process.pid, + }), + }).pipe( + Effect.catch((error) => + Effect.logWarning("failed to force-kill terminal process", { + threadId, + terminalId, + signal: "SIGKILL", + cause: error, + }), + ), + ); + }).pipe(Effect.ensuring(Effect.sync(unsubscribeExit))); }); const startKillEscalation = Effect.fn("terminal.startKillEscalation")(function* ( diff --git a/apps/server/src/terminal/nodePtyConsoleList.test.ts b/apps/server/src/terminal/nodePtyConsoleList.test.ts new file mode 100644 index 000000000000..b412f3c8502a --- /dev/null +++ b/apps/server/src/terminal/nodePtyConsoleList.test.ts @@ -0,0 +1,70 @@ +import * as NodeEvents from "node:events"; +import * as NodeModule from "node:module"; + +import { afterEach, describe, expect, it } from "vite-plus/test"; + +// Exercises the patched console-list helper in patches/node-pty@1.2.0-beta.15.patch. +// The agent calls `require("child_process").fork` at call time, so replacing it on +// the shared CJS module stands in for the forked helper on every platform. +const requireCjs = NodeModule.createRequire(import.meta.url); +const childProcess: typeof import("node:child_process") = requireCjs("child_process"); +const { + WindowsPtyAgent, +}: { + WindowsPtyAgent: { + prototype: { _getConsoleProcessList(this: { _innerPid: number }): Promise }; + }; +} = requireCjs("node-pty/lib/windowsPtyAgent.js"); +const originalFork = childProcess.fork; + +const SHELL_PID = 4242; + +function getConsoleProcessList( + driveHelper: (helper: NodeEvents.EventEmitter) => void, +): Promise { + const helper = Object.assign(new NodeEvents.EventEmitter(), { kill: () => true }); + childProcess.fork = (() => { + queueMicrotask(() => driveHelper(helper)); + return helper; + }) as unknown as typeof childProcess.fork; + return WindowsPtyAgent.prototype._getConsoleProcessList.call({ _innerPid: SHELL_PID }); +} + +describe("node-pty console process list helper", () => { + afterEach(() => { + childProcess.fork = originalFork; + }); + + it("returns the helper's list when it replies and then closes", async () => { + const list = await getConsoleProcessList((helper) => { + helper.emit("message", { consoleProcessList: [SHELL_PID, 5001, 5002] }); + helper.emit("exit", 0, null); + helper.emit("close", 0, null); + }); + expect(list).toEqual([SHELL_PID, 5001, 5002]); + }); + + it("keeps waiting for the reply when exit arrives before the IPC message", async () => { + const list = await getConsoleProcessList((helper) => { + helper.emit("exit", 0, null); + helper.emit("message", { consoleProcessList: [SHELL_PID, 5001] }); + helper.emit("close", 0, null); + }); + expect(list).toEqual([SHELL_PID, 5001]); + }); + + it("falls back to the shell PID when the helper closes without replying", async () => { + const list = await getConsoleProcessList((helper) => { + helper.emit("exit", 1, null); + helper.emit("close", 1, null); + }); + expect(list).toEqual([SHELL_PID]); + }); + + it("falls back to the shell PID when the helper fails to spawn", async () => { + const list = await getConsoleProcessList((helper) => { + helper.emit("error", Object.assign(new Error("spawn ENOENT"), { code: "ENOENT" })); + }); + expect(list).toEqual([SHELL_PID]); + }); +}); diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index d5599f8c46a3..3e76a11c45ba 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -11192,6 +11192,7 @@ export default function ChatView(props: ChatViewProps) { isLocalDraftThread && activeProject === null } phase={phase} + isCompacting={isCompacting} canInterrupt={canInterruptRunningThread} isConnecting={isConnecting} isSendBusy={ diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx index 017705a864bc..41648e526e30 100644 --- a/apps/web/src/components/chat/ChatComposer.tsx +++ b/apps/web/src/components/chat/ChatComposer.tsx @@ -1354,6 +1354,7 @@ const ComposerFooterPrimaryActions = memo(function ComposerFooterPrimaryActions( isRunning: boolean; canInterrupt: boolean; followUpBehavior: "queue" | "steer"; + canSteer: boolean; alternateShortcutLabel: string | null; showPlanFollowUpPrompt: boolean; promptHasText: boolean; @@ -1397,6 +1398,7 @@ const ComposerFooterPrimaryActions = memo(function ComposerFooterPrimaryActions( isRunning={props.isRunning} canInterrupt={props.canInterrupt} followUpBehavior={props.followUpBehavior} + canSteer={props.canSteer} alternateShortcutLabel={props.alternateShortcutLabel} showPlanFollowUpPrompt={props.showPlanFollowUpPrompt} promptHasText={props.promptHasText} @@ -1516,6 +1518,7 @@ export interface ChatComposerProps { isRevertingCheckpoint?: boolean; sendDisabledReason: string | null; isPreparingWorktree: boolean; + isCompacting: boolean; bannerItems: readonly ComposerBannerStackItem[]; resumeCompactionTokens: number | null; keepFullHistory: boolean; @@ -1676,6 +1679,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) isRevertingCheckpoint = false, sendDisabledReason: externalSendDisabledReason, isPreparingWorktree, + isCompacting, environmentUnavailable, activePendingApproval: incomingPendingApproval, pendingApprovals, @@ -4023,6 +4027,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) running: phase === "running", alternateModifier: false, activeTurnDefault: settings.followUpBehavior, + canSteer: !isCompacting, }), submissionIntent, ); @@ -4045,6 +4050,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) running: phase === "running", alternateModifier: event.metaKey || event.ctrlKey, activeTurnDefault: settings.followUpBehavior, + canSteer: !isCompacting, }), ); }; @@ -4056,6 +4062,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) running: phase === "running", alternateModifier: false, activeTurnDefault: settings.followUpBehavior, + canSteer: !isCompacting, }), ); }; @@ -4216,6 +4223,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) running: phase === "running", alternateModifier: submissionIntent === "alternate", activeTurnDefault: settings.followUpBehavior, + canSteer: !isCompacting, }), submissionIntent, ); @@ -7282,6 +7290,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) isRunning={phase === "running"} canInterrupt={canInterrupt} followUpBehavior={settings.followUpBehavior} + canSteer={!isCompacting} alternateShortcutLabel={shortcutLabelForCommand( keybindings, "composer.sendAlternate", diff --git a/apps/web/src/components/chat/ComposerPrimaryActions.tsx b/apps/web/src/components/chat/ComposerPrimaryActions.tsx index 6317a090dce9..d74c5a694dc0 100644 --- a/apps/web/src/components/chat/ComposerPrimaryActions.tsx +++ b/apps/web/src/components/chat/ComposerPrimaryActions.tsx @@ -32,6 +32,7 @@ interface ComposerPrimaryActionsProps { isRunning: boolean; canInterrupt: boolean; followUpBehavior?: "queue" | "steer"; + canSteer?: boolean; alternateShortcutLabel?: string | null; showPlanFollowUpPrompt: boolean; promptHasText: boolean; @@ -86,6 +87,7 @@ export const ComposerPrimaryActions = memo(function ComposerPrimaryActions({ isRunning, canInterrupt, followUpBehavior = "steer", + canSteer = true, alternateShortcutLabel = null, showPlanFollowUpPrompt, promptHasText, @@ -117,6 +119,7 @@ export const ComposerPrimaryActions = memo(function ComposerPrimaryActions({ resolveComposerDispatchMode({ running: isRunning, activeTurnDefault: followUpBehavior, + canSteer, alternateModifier: shortcutModifiers.metaKey || shortcutModifiers.ctrlKey, }) === "queue"; const alternateAction = alternateComposerDispatchAction(followUpBehavior); @@ -297,7 +300,7 @@ export const ComposerPrimaryActions = memo(function ComposerPrimaryActions({ submitStatus ?? (compactsBeforeSend ? `Summarize ${compactTokens} tokens of history, then send` - : isRunning && !isEditingQueuedMessage + : isRunning && !isEditingQueuedMessage && canSteer ? `Click to ${followUpBehavior}, Ctrl/⌘-click${alternateShortcutLabel ? ` or ${alternateShortcutLabel}` : ""} to ${alternateAction}` : submitLabel); diff --git a/packages/client-runtime/src/state/composerDispatch.test.ts b/packages/client-runtime/src/state/composerDispatch.test.ts index c2d7cfb12693..e635066c86c7 100644 --- a/packages/client-runtime/src/state/composerDispatch.test.ts +++ b/packages/client-runtime/src/state/composerDispatch.test.ts @@ -64,6 +64,19 @@ describe("resolveComposerDispatchMode", () => { }, ); + it("queues with or without the modifier while steering is unavailable", () => { + for (const alternateModifier of [false, true]) { + expect( + resolveComposerDispatchMode({ + running: true, + alternateModifier, + activeTurnDefault: "steer", + canSteer: false, + }), + ).toBe("queue"); + } + }); + it("names the alternate action so the affordance can be labelled", () => { expect(alternateComposerDispatchAction("queue")).toBe("steer"); expect(alternateComposerDispatchAction("steer")).toBe("queue"); diff --git a/packages/client-runtime/src/state/composerDispatch.ts b/packages/client-runtime/src/state/composerDispatch.ts index b6f76499a331..145b1ba50814 100644 --- a/packages/client-runtime/src/state/composerDispatch.ts +++ b/packages/client-runtime/src/state/composerDispatch.ts @@ -5,8 +5,11 @@ export function resolveComposerDispatchMode(input: { readonly running: boolean; readonly alternateModifier: boolean; readonly activeTurnDefault?: ActiveTurnComposerAction; + /** False while the active turn cannot take steering input, such as during compaction. */ + readonly canSteer?: boolean; }): ComposerDispatchMode { if (!input.running) return "auto"; + if (input.canSteer === false) return "queue"; const defaultAction = input.activeTurnDefault ?? "steer"; if (input.alternateModifier) return defaultAction === "queue" ? "steer" : "queue"; return defaultAction; diff --git a/patches/@clerk__expo-native-components@0.1.1.patch b/patches/@clerk__expo-native-components@0.1.1.patch deleted file mode 100644 index e7669a820386..000000000000 --- a/patches/@clerk__expo-native-components@0.1.1.patch +++ /dev/null @@ -1,138 +0,0 @@ -diff --git a/android/build.gradle b/android/build.gradle -index 0946d68..1926024 100644 ---- a/android/build.gradle -+++ b/android/build.gradle -@@ -147,6 +147,12 @@ dependencies { - implementation "androidx.activity:activity-compose:$activityComposeVersion" - implementation "androidx.lifecycle:lifecycle-runtime-compose:$lifecycleVersion" - implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycleVersion" -+ // ClerkComposeNativeViewHost imports LocalSavedStateRegistryOwner and -+ // LocalLifecycleOwner from these artifacts. Earlier SDKs leaked them onto -+ // the compile classpath through clerk-android-ui's navigation3 runtime -+ // dependency; AGP 9 resolves the compile classpath on its own. -+ implementation "androidx.savedstate:savedstate-compose:1.4.0" -+ implementation "androidx.lifecycle:lifecycle-runtime-compose:2.10.0" - - testImplementation "junit:junit:4.13.2" - } -diff --git a/ios/ClerkAuthNativeView.swift b/ios/ClerkAuthNativeView.swift -index 5f8d2ba..b170304 100644 ---- a/ios/ClerkAuthNativeView.swift -+++ b/ios/ClerkAuthNativeView.swift -@@ -111,7 +111,12 @@ public class ClerkAuthNativeView: ClerkNativeViewHost { - - override func makeHostedController() -> UIViewController? { - let hostBackAction: (() -> Void)? = currentHostBackButton -- ? { [weak self] in self?.onHostBack([:]) } -+ ? { [weak self] in -+ guard let self else { return } -+ if !self.popEnclosingNavigationRoute() { -+ self.onHostBack([:]) -+ } -+ } - : nil - - return ClerkNativeBridge.shared.makeAuthViewController( -diff --git a/ios/ClerkNativeBridge.swift b/ios/ClerkNativeBridge.swift -index e9527c6..a59ee3b 100644 ---- a/ios/ClerkNativeBridge.swift -+++ b/ios/ClerkNativeBridge.swift -@@ -1557,6 +1557,8 @@ private struct ClerkReactEmbeddedUserProfileCustomPage: View { - } - - private struct ClerkReactUserProfileCustomPageContent: View { -+ @Environment(\.clerkTheme) private var theme -+ - let path: String - let rows: [ClerkUserProfileCustomRowConfig] - let state: ClerkUserProfileCustomPageState -@@ -1570,8 +1572,13 @@ private struct ClerkReactUserProfileCustomPageContent: View { - } - } - .frame(maxWidth: .infinity, maxHeight: .infinity) -+ // Match Clerk's own profile pages so the navigation bar and page share -+ // the theme's page background instead of a bare hosting container. -+ .background(theme.colors.muted) - .navigationTitle(userProfileCustomPageLabel(for: path, rows: rows)) - .navigationBarTitleDisplayMode(.inline) -+ .preGlassSolidNavBar() -+ .background(theme.colors.background) - } - } - -diff --git a/ios/ClerkNativeViewHost.swift b/ios/ClerkNativeViewHost.swift -index 4e6540a..6897350 100644 ---- a/ios/ClerkNativeViewHost.swift -+++ b/ios/ClerkNativeViewHost.swift -@@ -5,6 +5,7 @@ public class ClerkNativeViewHost: ExpoView { - private lazy var hostingCoordinator = ClerkNativeHostingCoordinator(containerView: self) - private var hasInitialized: Bool = false - private var configuredObserver: NSObjectProtocol? -+ private var isPoppingHostRoute = false - - public required init(appContext: AppContext? = nil) { - super.init(appContext: appContext) -@@ -23,6 +24,7 @@ public class ClerkNativeViewHost: ExpoView { - super.didMoveToWindow() - - guard window != nil else { -+ isPoppingHostRoute = false - if hasInitialized { - hostedViewDidDetachFromWindow() - } -@@ -58,6 +60,37 @@ public class ClerkNativeViewHost: ExpoView { - - func hostedViewDidDetachFromWindow() {} - -+ /// Pops the React Navigation route that contains this view without waiting for -+ /// the JavaScript event loop. React Native Screens reports the native dismissal -+ /// back to React Navigation so its state remains synchronized. -+ func popEnclosingNavigationRoute() -> Bool { -+ guard !isPoppingHostRoute else { return true } -+ -+ var responder: UIResponder? = self -+ -+ while let nextResponder = responder?.next { -+ if let viewController = nextResponder as? UIViewController, -+ let navigationController = viewController.navigationController, -+ navigationController.viewControllers.count > 1 { -+ isPoppingHostRoute = true -+ if navigationController.popViewController(animated: true) != nil { -+ if let coordinator = navigationController.transitionCoordinator { -+ coordinator.animate(alongsideTransition: nil) { [weak self] _ in -+ self?.isPoppingHostRoute = false -+ } -+ } else { -+ isPoppingHostRoute = false -+ } -+ return true -+ } -+ isPoppingHostRoute = false -+ } -+ responder = nextResponder -+ } -+ -+ return false -+ } -+ - private func addConfiguredObserver() { - guard configuredObserver == nil else { return } - -diff --git a/ios/ClerkUserProfileNativeView.swift b/ios/ClerkUserProfileNativeView.swift -index f2ca604..46f406d 100644 ---- a/ios/ClerkUserProfileNativeView.swift -+++ b/ios/ClerkUserProfileNativeView.swift -@@ -47,7 +47,12 @@ public class ClerkUserProfileNativeView: ClerkUserProfileCustomPageHost { - - override func makeHostedController() -> UIViewController? { - let hostBackAction: (() -> Void)? = currentHostBackButton -- ? { [weak self] in self?.onHostBack([:]) } -+ ? { [weak self] in -+ guard let self else { return } -+ if !self.popEnclosingNavigationRoute() { -+ self.onHostBack([:]) -+ } -+ } - : nil - - return ClerkNativeBridge.shared.makeUserProfileViewController( diff --git a/patches/@clerk__expo-native-components@0.2.0.patch b/patches/@clerk__expo-native-components@0.2.0.patch new file mode 100644 index 000000000000..d40b77ec86b7 --- /dev/null +++ b/patches/@clerk__expo-native-components@0.2.0.patch @@ -0,0 +1,132 @@ +diff --git a/ios/ClerkAuthNativeView.swift b/ios/ClerkAuthNativeView.swift +index 5f8d2ba..b170304 100644 +--- a/ios/ClerkAuthNativeView.swift ++++ b/ios/ClerkAuthNativeView.swift +@@ -111,7 +111,12 @@ public class ClerkAuthNativeView: ClerkNativeViewHost { + + override func makeHostedController() -> UIViewController? { + let hostBackAction: (() -> Void)? = currentHostBackButton +- ? { [weak self] in self?.onHostBack([:]) } ++ ? { [weak self] in ++ guard let self else { return } ++ if !self.popEnclosingNavigationRoute() { ++ self.onHostBack([:]) ++ } ++ } + : nil + + return ClerkNativeBridge.shared.makeAuthViewController( +diff --git a/ios/ClerkUserProfileNativeView.swift b/ios/ClerkUserProfileNativeView.swift +index f2ca604..46f406d 100644 +--- a/ios/ClerkUserProfileNativeView.swift ++++ b/ios/ClerkUserProfileNativeView.swift +@@ -47,7 +47,12 @@ public class ClerkUserProfileNativeView: ClerkUserProfileCustomPageHost { + + override func makeHostedController() -> UIViewController? { + let hostBackAction: (() -> Void)? = currentHostBackButton +- ? { [weak self] in self?.onHostBack([:]) } ++ ? { [weak self] in ++ guard let self else { return } ++ if !self.popEnclosingNavigationRoute() { ++ self.onHostBack([:]) ++ } ++ } + : nil + + return ClerkNativeBridge.shared.makeUserProfileViewController( +diff --git a/ios/ClerkNativeViewHost.swift b/ios/ClerkNativeViewHost.swift +--- a/ios/ClerkNativeViewHost.swift ++++ b/ios/ClerkNativeViewHost.swift +@@ -5,6 +5,7 @@ + private lazy var hostingCoordinator = ClerkNativeHostingCoordinator(containerView: self) + private var hasInitialized: Bool = false + private var configuredObserver: NSObjectProtocol? ++ private var isPoppingHostRoute = false + + public required init(appContext: AppContext? = nil) { + super.init(appContext: appContext) +@@ -23,6 +24,7 @@ + super.didMoveToWindow() + + guard window != nil else { ++ isPoppingHostRoute = false + if hasInitialized { + hostedViewDidDetachFromWindow() + } +@@ -58,6 +60,39 @@ + + func hostedViewDidDetachFromWindow() {} + ++ func popEnclosingNavigationRoute() -> Bool { ++ guard !isPoppingHostRoute else { return true } ++ ++ // Follow controller containment, not the responder chain: past a presented controller the ++ // responder chain continues to its presenter, so a host inside a modal would pop the screen ++ // behind the modal instead of letting `onHostBack` dismiss it. ++ var route = enclosingViewController(of: self) ++ ++ while let candidate = route { ++ if let navigationController = candidate.parent as? UINavigationController, ++ navigationController.viewControllers.count > 1 { ++ guard navigationController.topViewController === candidate else { return false } ++ ++ isPoppingHostRoute = true ++ guard navigationController.popViewController(animated: true) != nil else { ++ isPoppingHostRoute = false ++ return false ++ } ++ if let coordinator = navigationController.transitionCoordinator { ++ coordinator.animate(alongsideTransition: nil) { [weak self] _ in ++ self?.isPoppingHostRoute = false ++ } ++ } else { ++ isPoppingHostRoute = false ++ } ++ return true ++ } ++ route = candidate.parent ++ } ++ ++ return false ++ } ++ + private func addConfiguredObserver() { + guard configuredObserver == nil else { return } + +@@ -162,7 +197,7 @@ + controller.view.frame = containerView.bounds + controller.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] + +- if let parentVC = findViewController(from: containerView) { ++ if let parentVC = enclosingViewController(of: containerView) { + parentVC.addChild(controller) + containerView.addSubview(controller.view) + controller.didMove(toParent: parentVC) +@@ -190,15 +225,15 @@ + guard let containerView else { return } + hostingController?.view.frame = containerView.bounds + } +- +- private func findViewController(from view: UIView) -> UIViewController? { +- var responder: UIResponder? = view +- while let nextResponder = responder?.next { +- if let vc = nextResponder as? UIViewController { +- return vc +- } +- responder = nextResponder +- } +- return nil +- } +-} ++} ++ ++private func enclosingViewController(of view: UIView) -> UIViewController? { ++ var responder: UIResponder? = view ++ while let nextResponder = responder?.next { ++ if let viewController = nextResponder as? UIViewController { ++ return viewController ++ } ++ responder = nextResponder ++ } ++ return nil ++} diff --git a/patches/@expo__fingerprint@0.21.5.patch b/patches/@expo__fingerprint@0.21.5.patch new file mode 100644 index 000000000000..8045438709c6 --- /dev/null +++ b/patches/@expo__fingerprint@0.21.5.patch @@ -0,0 +1,16 @@ +diff --git a/build/sourcer/Expo.js b/build/sourcer/Expo.js +index 785ec516921af68ea5922462a0177112e15c6bb1..8ce5ce7937b83b3677416bf18f4c60d759ba4fcf 100644 +--- a/build/sourcer/Expo.js ++++ b/build/sourcer/Expo.js +@@ -368,6 +368,11 @@ async function getExpoAutolinkingAndroidSourcesAsync(projectRoot, options, expoA + } + if (module1.plugins) { + for (const plugin of module1.plugins){ ++ // Gradle plugins resolved from Maven (e.g. expo-widgets' glance fork) have no ++ // sourceDir; hashing them would throw and drop every Expo module source. ++ if (typeof plugin.sourceDir !== 'string') { ++ continue; ++ } + const filePath = (0, _Path.toPosixPath)(_path().default.relative(realProjectRoot, plugin.sourceDir)); + plugin.sourceDir = filePath; // use relative path for the dir + debug(`Adding expo-modules-autolinking android dir - ${_chalk().default.dim(filePath)}`); diff --git a/patches/@expo__ui@58.0.18.patch b/patches/@expo__ui@58.0.20.patch similarity index 100% rename from patches/@expo__ui@58.0.18.patch rename to patches/@expo__ui@58.0.20.patch diff --git a/patches/expo-blur@58.0.3.patch b/patches/expo-blur@58.0.3.patch deleted file mode 100644 index f88c657204ff..000000000000 --- a/patches/expo-blur@58.0.3.patch +++ /dev/null @@ -1,57 +0,0 @@ -diff --git a/build/BlurView.types.d.ts b/build/BlurView.types.d.ts -index cc93ffe2cd398a73ac50ebbe5427cbe4187fd83b..7246e9ffbe67af7da4fed20e1e08d0768be812a3 100644 ---- a/build/BlurView.types.d.ts -+++ b/build/BlurView.types.d.ts -@@ -1,5 +1,5 @@ - import type { RefObject } from 'react'; --import type { ViewProps, View } from 'react-native'; -+import type { ViewProps, ViewInstance } from 'react-native'; - /** - * Blur method to use on Android. - * -@@ -24,7 +24,7 @@ export type BlurViewProps = { - * - * @platform android - */ -- blurTarget?: RefObject; -+ blurTarget?: RefObject; - /** - * A tint mode which will be applied to the view. - * -@@ -68,6 +68,6 @@ export type BlurViewProps = { - blurMethod?: BlurMethod; - } & ViewProps; - export type BlurTargetViewProps = { -- ref?: RefObject; -+ ref?: RefObject; - } & ViewProps; - export type BlurTint = 'light' | 'dark' | 'default' | 'extraLight' | 'regular' | 'prominent' | 'systemUltraThinMaterial' | 'systemThinMaterial' | 'systemMaterial' | 'systemThickMaterial' | 'systemChromeMaterial' | 'systemUltraThinMaterialLight' | 'systemThinMaterialLight' | 'systemMaterialLight' | 'systemThickMaterialLight' | 'systemChromeMaterialLight' | 'systemUltraThinMaterialDark' | 'systemThinMaterialDark' | 'systemMaterialDark' | 'systemThickMaterialDark' | 'systemChromeMaterialDark'; -diff --git a/src/BlurView.types.ts b/src/BlurView.types.ts -index b63ad6b3a9e30bd0f13cff322be79077d0cb5326..bdc3295af94bc17e8a6457b6c9567ff2d57799a7 100644 ---- a/src/BlurView.types.ts -+++ b/src/BlurView.types.ts -@@ -1,5 +1,5 @@ - import type { RefObject } from 'react'; --import type { ViewProps, View } from 'react-native'; -+import type { ViewProps, ViewInstance } from 'react-native'; - - /** - * Blur method to use on Android. -@@ -27,7 +27,7 @@ export type BlurViewProps = { - * - * @platform android - */ -- blurTarget?: RefObject; -+ blurTarget?: RefObject; - /** - * A tint mode which will be applied to the view. - * -@@ -74,7 +74,7 @@ export type BlurViewProps = { - } & ViewProps; - - export type BlurTargetViewProps = { -- ref?: RefObject; -+ ref?: RefObject; - } & ViewProps; - - export type BlurTint = diff --git a/patches/expo-glass-effect@58.0.3.patch b/patches/expo-glass-effect@58.0.3.patch deleted file mode 100644 index 23d09d012608..000000000000 --- a/patches/expo-glass-effect@58.0.3.patch +++ /dev/null @@ -1,72 +0,0 @@ -diff --git a/build/GlassContainer.types.d.ts b/build/GlassContainer.types.d.ts -index 502f9b037900d62aa5875dc37f0fcb517dec7a44..cc521dcb7e411cba7dfe99f191bbc42ac979849f 100644 ---- a/build/GlassContainer.types.d.ts -+++ b/build/GlassContainer.types.d.ts -@@ -1,5 +1,5 @@ - import type { Ref } from 'react'; --import type { View, ViewProps } from 'react-native'; -+import type { ViewInstance, ViewProps } from 'react-native'; - export type GlassContainerProps = { - /** - * The distance at which glass elements start affecting each other. -@@ -7,5 +7,5 @@ export type GlassContainerProps = { - * @default undefined - */ - spacing?: number; -- ref?: Ref; -+ ref?: Ref; - } & ViewProps; -diff --git a/build/GlassView.types.d.ts b/build/GlassView.types.d.ts -index a09487b1b3ef2e4d89b19e2bad81f99fc532d94d..eeadfff1dcd891bf581ef6be0493e2a6eda0849a 100644 ---- a/build/GlassView.types.d.ts -+++ b/build/GlassView.types.d.ts -@@ -1,5 +1,5 @@ - import type { Ref } from 'react'; --import type { ColorValue, View, ViewProps } from 'react-native'; -+import type { ColorValue, ViewInstance, ViewProps } from 'react-native'; - export type GlassStyle = 'clear' | 'regular' | 'none'; - export type GlassEffectStyleConfig = { - /** -@@ -40,5 +40,5 @@ export type GlassViewProps = { - * @default 'auto' - */ - colorScheme?: GlassColorScheme; -- ref?: Ref; -+ ref?: Ref; - } & ViewProps; -diff --git a/src/GlassContainer.types.ts b/src/GlassContainer.types.ts -index f57a30713a4a2c1769e4f213a43d29fa17d8c411..fa934d45d488dcbc8cb6396e88f0a2996834367b 100644 ---- a/src/GlassContainer.types.ts -+++ b/src/GlassContainer.types.ts -@@ -1,5 +1,5 @@ - import type { Ref } from 'react'; --import type { View, ViewProps } from 'react-native'; -+import type { ViewInstance, ViewProps } from 'react-native'; - - export type GlassContainerProps = { - /** -@@ -8,5 +8,5 @@ export type GlassContainerProps = { - * @default undefined - */ - spacing?: number; -- ref?: Ref; -+ ref?: Ref; - } & ViewProps; -diff --git a/src/GlassView.types.ts b/src/GlassView.types.ts -index 7fc30003a9337a12ffb12ffb44a050aae99e9b40..413db6b698055dd00d6ec2cf7b71e4370c85054c 100644 ---- a/src/GlassView.types.ts -+++ b/src/GlassView.types.ts -@@ -1,5 +1,5 @@ - import type { Ref } from 'react'; --import type { ColorValue, View, ViewProps } from 'react-native'; -+import type { ColorValue, ViewInstance, ViewProps } from 'react-native'; - - export type GlassStyle = 'clear' | 'regular' | 'none'; - -@@ -44,5 +44,5 @@ export type GlassViewProps = { - * @default 'auto' - */ - colorScheme?: GlassColorScheme; -- ref?: Ref; -+ ref?: Ref; - } & ViewProps; diff --git a/patches/expo-sharing@58.0.18.patch b/patches/expo-sharing@58.0.19.patch similarity index 98% rename from patches/expo-sharing@58.0.18.patch rename to patches/expo-sharing@58.0.19.patch index 6f3948f704f4..d4aa7c4bf4bb 100644 --- a/patches/expo-sharing@58.0.18.patch +++ b/patches/expo-sharing@58.0.19.patch @@ -1,8 +1,8 @@ diff --git a/android/src/main/java/expo/modules/sharing/SharingRecords.kt b/android/src/main/java/expo/modules/sharing/SharingRecords.kt -index 0b87b53..65f1c57 100644 +index 1113a0a..e89529a 100644 --- a/android/src/main/java/expo/modules/sharing/SharingRecords.kt +++ b/android/src/main/java/expo/modules/sharing/SharingRecords.kt -@@ -52,7 +52,8 @@ enum class ContentType(val value: String) : Enumerable { +@@ -51,7 +51,8 @@ enum class ContentType(val value: String) : Enumerable { internal data class SharePayload( @Field var value: String = "", @Field var shareType: ShareType = ShareType.Text, diff --git a/patches/expo-widgets@58.0.18.patch b/patches/expo-widgets@58.0.20.patch similarity index 91% rename from patches/expo-widgets@58.0.18.patch rename to patches/expo-widgets@58.0.20.patch index f5ac33c003be..8b9db8b9d23a 100644 --- a/patches/expo-widgets@58.0.18.patch +++ b/patches/expo-widgets@58.0.20.patch @@ -150,20 +150,6 @@ index 4d135c4..dae4744 100644 if #available(iOS 18.0, *) { LiveActivityBanner(context: context, nodes: nodes) } else if let node = nodes["banner"] as? [String: Any] { -diff --git a/scripts/build-layout-registry.mjs b/scripts/build-layout-registry.mjs -index d52a60e..fa9bd77 100644 ---- a/scripts/build-layout-registry.mjs -+++ b/scripts/build-layout-registry.mjs -@@ -154,6 +154,8 @@ function createLayoutRegistry(expectedWidgets, capturedLayouts) { - return registry; - } - --if (process.argv[1] && path.resolve(process.argv[1]) === __filename) { -+// Compare real paths: pnpm exposes the package through a symlink, so the -+// invoked path and import.meta.url differ while naming the same file. -+if (process.argv[1] && fs.realpathSync(path.resolve(process.argv[1])) === fs.realpathSync(__filename)) { - await main(); - } diff --git a/src/Widgets.types.ts b/src/Widgets.types.ts index 690d069..ffab6f3 100644 --- a/src/Widgets.types.ts diff --git a/patches/node-pty@1.2.0-beta.15.patch b/patches/node-pty@1.2.0-beta.15.patch index 2232766cdb65..125447607990 100644 --- a/patches/node-pty@1.2.0-beta.15.patch +++ b/patches/node-pty@1.2.0-beta.15.patch @@ -17,7 +17,7 @@ diff --git a/lib/windowsConoutConnection.js b/lib/windowsConoutConnection.js diff --git a/lib/windowsPtyAgent.js b/lib/windowsPtyAgent.js --- a/lib/windowsPtyAgent.js +++ b/lib/windowsPtyAgent.js -@@ -218,8 +218,14 @@ +@@ -218,13 +218,31 @@ return Promise.resolve([]); } return new Promise(function (resolve) { @@ -25,11 +25,31 @@ diff --git a/lib/windowsPtyAgent.js b/lib/windowsPtyAgent.js + // Node's watch mode sends its own messages over the helper's IPC channel. + var agentEnv = Object.assign({}, process.env); + delete agentEnv.WATCH_REPORT_DEPENDENCIES; -+ var agent = (0, child_process_1.fork)(path.join(__dirname, 'conpty_console_list_agent'), [_this._innerPid.toString()], { env: agentEnv, execArgv: [] }); ++ var settled = false; ++ var finish = function (list) { ++ if (settled) return; ++ settled = true; ++ clearTimeout(timeout); ++ resolve(list); ++ }; ++ var agent = (0, child_process_1.fork)(path.join(__dirname, 'conpty_console_list_agent'), [_this._innerPid.toString()], { env: agentEnv, execArgv: [], windowsHide: true }); agent.on('message', function (message) { -+ if (!Array.isArray(message.consoleProcessList)) { +- clearTimeout(timeout); +- resolve(message.consoleProcessList); ++ if (!message || !Array.isArray(message.consoleProcessList)) { + return; + } - clearTimeout(timeout); - resolve(message.consoleProcessList); ++ finish(message.consoleProcessList); ++ }); ++ agent.on('error', function () { ++ finish([_this._innerPid]); ++ }); ++ agent.on('close', function () { ++ finish([_this._innerPid]); }); + var timeout = setTimeout(function () { + // Something went wrong, just send back the shell PID + agent.kill(); +- resolve([_this._innerPid]); ++ finish([_this._innerPid]); + }, 5000); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a856fe07f6e4..88bbab718ea4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -87,7 +87,7 @@ catalogs: overrides: '@exodus/bytes>@noble/hashes': 1.8.0 - '@react-navigation/core': 7.21.13 + '@react-navigation/core': 7.24.0 dbus-next>usocket: '-' '@anthropic-ai/claude-agent-sdk>@anthropic-ai/claude-agent-sdk-darwin-arm64': '-' '@anthropic-ai/claude-agent-sdk>@anthropic-ai/claude-agent-sdk-darwin-x64': '-' @@ -101,17 +101,17 @@ overrides: '@alchemy.run/sigil>react-reconciler': '-' '@alchemy.run/sigil>scheduler': '-' alchemy>@prisma/dev: '-' - '@clerk/backend': 3.24.0 - '@clerk/clerk-js': 6.39.0 + '@clerk/backend': 3.25.0 + '@clerk/clerk-js': 6.39.1 '@clerk/clerk-js>@base-org/account': '-' '@clerk/clerk-js>@coinbase/wallet-sdk': '-' '@clerk/clerk-js>@solana/wallet-adapter-base': '-' '@clerk/clerk-js>@solana/wallet-adapter-react': '-' '@clerk/clerk-js>@solana/wallet-standard': '-' '@clerk/clerk-js>@wallet-standard/core': '-' - '@clerk/electron': 0.1.0 + '@clerk/electron': 0.1.1 '@clerk/electron-passkeys': 0.0.3 - '@clerk/expo': 4.12.0 + '@clerk/expo': 4.13.0 '@clerk/react': 6.17.8 '@clerk/shared': 4.40.0 '@effect/atom-react': 4.0.5 @@ -149,10 +149,11 @@ overrides: packageExtensionsChecksum: sha256-EowbsmlBFaoO0Ypufw901RnvdyjKG5dcdk2FRbc7Dr0= patchedDependencies: - '@clerk/expo-native-components@0.1.1': 5f3738f8e5d50bfa467ce8afbaf7c2aa7c7c9adb95a2307424eb908f6af0d299 + '@clerk/expo-native-components@0.2.0': 7a808b92da8460750b85818552e13be3fb73d111691c7db76965970351e124e4 '@effect/vitest@4.0.5': 2731c9c3761c595f25ddc625a7d61ca376b389d5b3049ecb837c8940f21cfa02 + '@expo/fingerprint@0.21.5': 8fba80d6bbce46c72de427fe8c7907462d262a0bfe50c6b2b7ee9c4e0c61e5e1 '@expo/metro-config@58.0.14': 90fa980e8b6480631fb2fbb04559834e3c612db40c550cd828f11be297d8d760 - '@expo/ui@58.0.18': 5a26480373850c1a7943919aa21f904151b335a0cb01042109e0746def37923e + '@expo/ui@58.0.20': 5a26480373850c1a7943919aa21f904151b335a0cb01042109e0746def37923e '@ff-labs/fff-node@0.11.0': cc71fcec015f4d39bc96ae2e2bf6b0ca678124c722c66a7841efce9d34b5983c '@legendapp/list@3.3.5': 680cc6a5c5b4a4032e467e7b3fde22f89a84c0ee2e6eac6fda737d6277cc0806 '@pierre/diffs@1.5.2': 298e94372dbd51846a4e26ece2ecc3e22eb1f94b0450b1f1a9c6fec127809be7 @@ -162,11 +163,9 @@ patchedDependencies: alchemy@2.0.0-beta.80: bea1b6c0c0b23157fd5f439a1d7feff430f28ac1621ba135d8a13eeec60ccacd dbus-next@0.10.2: cfff57561b0ee59b5addb3b2e6c6f20906e967507a530ab67e8db8108e520ba4 expo-audio@58.0.9: 2c2f8c73a23d48804c8b537b8cd73c25eb331aa47d82eaa481c6766cb81e5add - expo-blur@58.0.3: d0311b0c0b05bd94393bd9a84653cb42503d5f3c8a19eb2627c34ace08bedf18 - expo-glass-effect@58.0.3: f750041c45ab838a3530451dc7b50d6640a79141037a1b0499c5e3412a860c57 - expo-sharing@58.0.18: d0ca151b2a4eec8bb28df547c8663e4b803acd981ace492c6b401bcb279f524a - expo-widgets@58.0.18: 40806e85c756563935c7368b93d679bd3bb7742bff21d9c7611d9161e1aee602 - node-pty@1.2.0-beta.15: f2fe901c61cde17986240002d05c172d5d0272d83ffaab8d0ebeb922763be414 + expo-sharing@58.0.19: ad248759641ddd71b8331c09dbb3b18c8a551785f2df507533805babd3c0c124 + expo-widgets@58.0.20: 8623cb034b720c5ef2da8012c765805a7298909bd92eaf8381f64dbde41b77dd + node-pty@1.2.0-beta.15: f1e680afec85f650699ea756f91f469844ec4c976f4f168492a45c6b3f67d651 react-native-gesture-handler@3.3.0: abe20e1d1c23549297cbbc818e14fe479b41455930d9663135d6b40fe359b626 react-native-keyboard-controller@1.22.7: f28d08f1233e3cce8b9324b4357d2b10f1ee040b8051bc87235b0fb95069b9bb react-native-webview@14.0.1: 81caa279ec3dc1f81209062133b66e8f824e13f106cca57f1fa732a72c2ab378 @@ -203,8 +202,8 @@ importers: apps/desktop: dependencies: '@clerk/electron': - specifier: 0.1.0 - version: 0.1.0(@clerk/electron-passkeys@0.0.3)(electron-store@8.2.0)(electron@44.4.5)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + specifier: 0.1.1 + version: 0.1.1(@clerk/electron-passkeys@0.0.3)(electron-store@8.2.0)(electron@44.4.5)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@clerk/electron-passkeys': specifier: 0.0.3 version: 0.0.3 @@ -310,11 +309,11 @@ importers: apps/mobile: dependencies: '@clerk/expo': - specifier: 4.12.0 - version: 4.12.0(fc0c782bb008f08bb0dbe9eee6e857d7) + specifier: 4.13.0 + version: 4.13.0(7b5e2b0afc01ce7ef5801e333b018457) '@clerk/expo-native-components': - specifier: 0.1.1 - version: 0.1.1(patch_hash=5f3738f8e5d50bfa467ce8afbaf7c2aa7c7c9adb95a2307424eb908f6af0d299)(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) + specifier: 0.2.0 + version: 0.2.0(patch_hash=7a808b92da8460750b85818552e13be3fb73d111691c7db76965970351e124e4)(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) '@effect/atom-react': specifier: 4.0.5 version: 4.0.5(effect@4.0.5)(react@19.3.0)(scheduler@0.28.0) @@ -323,10 +322,10 @@ importers: version: 0.4.2 '@expo/metro-runtime': specifier: ~58.0.14 - version: 58.0.14(@expo/log-box@58.0.12)(expo@58.0.11)(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + version: 58.0.14(@expo/log-box@58.0.12)(expo@58.0.14)(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) '@expo/ui': - specifier: 58.0.18 - version: 58.0.18(patch_hash=5a26480373850c1a7943919aa21f904151b335a0cb01042109e0746def37923e)(@babel/core@7.29.7)(expo@58.0.11)(react-dom@19.3.0(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + specifier: 58.0.20 + version: 58.0.20(patch_hash=5a26480373850c1a7943919aa21f904151b335a0cb01042109e0746def37923e)(@babel/core@7.29.7)(expo@58.0.14)(react-dom@19.3.0(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) '@legendapp/list': specifier: 'catalog:' version: 3.3.5(patch_hash=680cc6a5c5b4a4032e467e7b3fde22f89a84c0ee2e6eac6fda737d6277cc0806)(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) @@ -418,113 +417,113 @@ importers: specifier: 4.0.5 version: 4.0.5 expo: - specifier: 58.0.11 - version: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + specifier: 58.0.14 + version: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) expo-asset: specifier: ~58.0.16 - version: 58.0.16(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) + version: 58.0.16(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) expo-audio: specifier: 58.0.9 - version: 58.0.9(patch_hash=2c2f8c73a23d48804c8b537b8cd73c25eb331aa47d82eaa481c6766cb81e5add)(expo-asset@58.0.16(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2))(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + version: 58.0.9(patch_hash=2c2f8c73a23d48804c8b537b8cd73c25eb331aa47d82eaa481c6766cb81e5add)(expo-asset@58.0.16(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2))(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) expo-auth-session: - specifier: ~58.0.12 - version: 58.0.12(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) + specifier: ~58.0.13 + version: 58.0.13(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) expo-blur: - specifier: 58.0.3 - version: 58.0.3(patch_hash=d0311b0c0b05bd94393bd9a84653cb42503d5f3c8a19eb2627c34ace08bedf18)(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + specifier: 58.0.4 + version: 58.0.4(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) expo-build-properties: - specifier: ~58.0.10 - version: 58.0.10(expo@58.0.11) + specifier: ~58.0.11 + version: 58.0.11(expo@58.0.14) expo-camera: specifier: ~58.0.10 - version: 58.0.10(@types/emscripten@1.41.5)(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + version: 58.0.10(@types/emscripten@1.41.5)(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) expo-clipboard: specifier: ~58.0.3 - version: 58.0.3(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + version: 58.0.3(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) expo-constants: specifier: 58.0.12 - version: 58.0.12(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2) + version: 58.0.12(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2) expo-crypto: - specifier: ~58.0.6 - version: 58.0.6(expo@58.0.11) + specifier: ~58.0.7 + version: 58.0.7(expo@58.0.14) expo-dev-client: - specifier: ~58.0.13 - version: 58.0.13(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) + specifier: ~58.0.14 + version: 58.0.14(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) expo-device: specifier: ~58.0.5 - version: 58.0.5(expo@58.0.11) + version: 58.0.5(expo@58.0.14) expo-document-picker: specifier: ~58.0.4 - version: 58.0.4(expo@58.0.11) + version: 58.0.4(expo@58.0.14) expo-file-system: specifier: ~58.0.9 - version: 58.0.9(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) + version: 58.0.9(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) expo-font: specifier: ~58.0.8 - version: 58.0.8(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + version: 58.0.8(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) expo-glass-effect: - specifier: 58.0.3 - version: 58.0.3(patch_hash=f750041c45ab838a3530451dc7b50d6640a79141037a1b0499c5e3412a860c57)(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + specifier: 58.0.4 + version: 58.0.4(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) expo-haptics: - specifier: ~58.0.6 - version: 58.0.6(expo@58.0.11) + specifier: ~58.0.7 + version: 58.0.7(expo@58.0.14) expo-image: specifier: ~58.0.15 - version: 58.0.15(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + version: 58.0.15(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) expo-image-manipulator: specifier: ~58.0.14 - version: 58.0.14(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + version: 58.0.14(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) expo-image-picker: specifier: ~58.0.10 - version: 58.0.10(expo@58.0.11) + version: 58.0.10(expo@58.0.14) expo-keep-awake: specifier: ~58.0.3 - version: 58.0.3(expo@58.0.11)(react@19.3.0) + version: 58.0.3(expo@58.0.14)(react@19.3.0) expo-linking: specifier: ~58.0.13 - version: 58.0.13(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) + version: 58.0.13(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) expo-network: specifier: ~58.0.3 - version: 58.0.3(expo@58.0.11)(react@19.3.0) + version: 58.0.3(expo@58.0.14)(react@19.3.0) expo-notifications: - specifier: ~58.1.4 - version: 58.1.4(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) + specifier: ~58.1.5 + version: 58.1.5(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) expo-paste-input: specifier: ^0.1.15 - version: 0.1.15(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + version: 0.1.15(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) expo-quick-actions: specifier: ^6.0.2 - version: 6.0.2(expo@58.0.11)(typescript@7.0.2) + version: 6.0.2(expo@58.0.14)(typescript@7.0.2) expo-secure-store: specifier: ~58.0.2 - version: 58.0.2(expo@58.0.11) + version: 58.0.2(expo@58.0.14) expo-sensors: specifier: ~58.0.4 - version: 58.0.4(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) + version: 58.0.4(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) expo-sharing: - specifier: 58.0.18 - version: 58.0.18(patch_hash=d0ca151b2a4eec8bb28df547c8663e4b803acd981ace492c6b401bcb279f524a)(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) + specifier: 58.0.19 + version: 58.0.19(patch_hash=ad248759641ddd71b8331c09dbb3b18c8a551785f2df507533805babd3c0c124)(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) expo-splash-screen: - specifier: ~58.0.9 - version: 58.0.9(expo@58.0.11)(typescript@7.0.2) + specifier: ~58.0.10 + version: 58.0.10(expo@58.0.14)(typescript@7.0.2) expo-sqlite: specifier: ~58.0.13 - version: 58.0.13(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + version: 58.0.13(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) expo-symbols: specifier: ~58.0.4 - version: 58.0.4(expo-font@58.0.8(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + version: 58.0.4(expo-font@58.0.8(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) expo-updates: specifier: ~58.0.17 - version: 58.0.17(expo-dev-client@58.0.13(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)))(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + version: 58.0.17(expo-dev-client@58.0.14(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)))(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) expo-video: specifier: ~58.0.11 - version: 58.0.11(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + version: 58.0.11(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) expo-web-browser: specifier: ~58.0.6 - version: 58.0.6(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) + version: 58.0.6(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) expo-widgets: - specifier: 58.0.18 - version: 58.0.18(patch_hash=40806e85c756563935c7368b93d679bd3bb7742bff21d9c7611d9161e1aee602)(@babel/core@7.29.7)(expo@58.0.11)(react-dom@19.3.0(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + specifier: 58.0.20 + version: 58.0.20(patch_hash=8623cb034b720c5ef2da8012c765805a7298909bd92eaf8381f64dbde41b77dd)(@babel/core@7.29.7)(expo@58.0.14)(react-dom@19.3.0(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) react: specifier: 19.3.0 version: 19.3.0 @@ -535,8 +534,8 @@ importers: specifier: 0.88.0 version: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) react-native-enriched-markdown: - specifier: file:deps/react-native-enriched-markdown-1.2.0-t3.13.tgz - version: file:apps/mobile/deps/react-native-enriched-markdown-1.2.0-t3.13.tgz(katex@0.16.47)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + specifier: file:deps/react-native-enriched-markdown-1.2.0-t3.15.tgz + version: file:apps/mobile/deps/react-native-enriched-markdown-1.2.0-t3.15.tgz(katex@0.16.47)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) react-native-gesture-handler: specifier: ~3.3.0 version: 3.3.0(patch_hash=abe20e1d1c23549297cbbc818e14fe479b41455930d9663135d6b40fe359b626)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) @@ -590,7 +589,7 @@ importers: version: 11.0.5 uniwind: specifier: 1.12.1 - version: 1.12.1(@expo/metro-config@58.0.14(patch_hash=90fa980e8b6480631fb2fbb04559834e3c612db40c550cd828f11be297d8d760)(bufferutil@4.1.0)(expo@58.0.11)(typescript@7.0.2)(utf-8-validate@6.0.6))(metro-cache@0.87.1)(metro-transform-worker@0.87.1(bufferutil@4.1.0)(utf-8-validate@6.0.6))(metro@0.87.1(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(tailwindcss@4.3.3) + version: 1.12.1(@expo/metro-config@58.0.14(patch_hash=90fa980e8b6480631fb2fbb04559834e3c612db40c550cd828f11be297d8d760)(bufferutil@4.1.0)(expo@58.0.14)(typescript@7.0.2)(utf-8-validate@6.0.6))(metro-cache@0.87.1)(metro-transform-worker@0.87.1(bufferutil@4.1.0)(utf-8-validate@6.0.6))(metro@0.87.1(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(tailwindcss@4.3.3) devDependencies: '@effect/vitest': specifier: 4.0.5 @@ -608,8 +607,8 @@ importers: specifier: ~19.2.3 version: 19.2.3(@types/react@19.3.0) babel-preset-expo: - specifier: ~58.0.15 - version: 58.0.15(@babel/core@7.29.7)(@babel/runtime@7.29.7)(expo-widgets@58.0.18)(expo@58.0.11)(react-refresh@0.14.2) + specifier: ~58.0.17 + version: 58.0.17(@babel/core@7.29.7)(@babel/runtime@7.29.7)(expo-widgets@58.0.20)(expo@58.0.14)(react-refresh@0.14.2) jsdom: specifier: ^30.0.1 version: 30.1.0(@noble/hashes@1.8.0) @@ -699,7 +698,7 @@ importers: version: 6.2.2 node-pty: specifier: ^1.2.0-beta.15 - version: 1.2.0-beta.15(patch_hash=f2fe901c61cde17986240002d05c172d5d0272d83ffaab8d0ebeb922763be414) + version: 1.2.0-beta.15(patch_hash=f1e680afec85f650699ea756f91f469844ec4c976f4f168492a45c6b3f67d651) playwright-core: specifier: 1.60.0 version: 1.60.0 @@ -802,11 +801,11 @@ importers: specifier: ^1.4.1 version: 1.5.0(@date-fns/tz@1.5.0)(@types/react@19.3.0)(date-fns@4.4.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) '@clerk/clerk-js': - specifier: 6.39.0 - version: 6.39.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + specifier: 6.39.1 + version: 6.39.1(react-dom@19.2.6(react@19.2.6))(react@19.2.6) '@clerk/electron': - specifier: 0.1.0 - version: 0.1.0(@clerk/electron-passkeys@0.0.3)(electron-store@8.2.0)(electron@44.4.5)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + specifier: 0.1.1 + version: 0.1.1(@clerk/electron-passkeys@0.0.3)(electron-store@8.2.0)(electron@44.4.5)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) '@clerk/react': specifier: 6.17.8 version: 6.17.8(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -1043,8 +1042,8 @@ importers: infra/relay: dependencies: '@clerk/backend': - specifier: 3.24.0 - version: 3.24.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + specifier: 3.25.0 + version: 3.25.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@effect/sql-pg': specifier: 4.0.5 version: 4.0.5(effect@4.0.5) @@ -1068,10 +1067,10 @@ importers: version: link:../../packages/shared alchemy: specifier: 2.0.0-beta.80 - version: 2.0.0-beta.80(patch_hash=bea1b6c0c0b23157fd5f439a1d7feff430f28ac1621ba135d8a13eeec60ccacd)(0ba0331b8debaa0ad7a4056eaf11dc21) + version: 2.0.0-beta.80(patch_hash=bea1b6c0c0b23157fd5f439a1d7feff430f28ac1621ba135d8a13eeec60ccacd)(575369c756745bf3feea15f355990f30) drizzle-orm: specifier: 1.0.0-rc.5-ab785fc - version: 1.0.0-rc.5-ab785fc(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0(effect@4.0.5))(@effect/sql-pg@4.0.5(effect@4.0.5))(@effect/sql-sqlite-bun@4.0.0-rc.112(effect@4.0.5))(@effect/sql-sqlite-do@4.0.5(effect@4.0.5))(@electric-sql/pglite@0.3.15)(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(bun-types@1.3.14)(effect@4.0.5)(expo-sqlite@58.0.13(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(pg@8.23.0)(valibot@1.2.0(typescript@7.0.2))(zod@4.4.3) + version: 1.0.0-rc.5-ab785fc(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0(effect@4.0.5))(@effect/sql-pg@4.0.5(effect@4.0.5))(@effect/sql-sqlite-bun@4.0.0-rc.112(effect@4.0.5))(@effect/sql-sqlite-do@4.0.5(effect@4.0.5))(@electric-sql/pglite@0.3.15)(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(bun-types@1.3.14)(effect@4.0.5)(expo-sqlite@58.0.13(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(pg@8.23.0)(valibot@1.2.0(typescript@7.0.2))(zod@4.4.3) effect: specifier: 4.0.5 version: 4.0.5 @@ -2716,12 +2715,12 @@ packages: resolution: {integrity: sha512-dlT1m5e/0yUL0kRNcQn7yGLVThkgbB0Ga/1AmfDDC/8ik6AIiSf2QLQO2zPYvefsHP0aFgxO93cVLCCfDp7kzQ==} engines: {node: '>= 20.12.0'} - '@clerk/backend@3.24.0': - resolution: {integrity: sha512-ak5U2IabnBvYzhTrPl7de0ywiLmrBqfA4aonjhC5Kmt9IUEwXIPf294zgfXfFeDy3JGTSTvgWAy7p+15OagirA==} + '@clerk/backend@3.25.0': + resolution: {integrity: sha512-hmJS0a61FO08PDaV2MtZ/hj6pE+cQBRmpxR8oUFGQTXewOQLLOAbcgob0rmFAnMNuHgXfsYf3NVxcQCUOWE+QA==} engines: {node: '>=20.9.0'} - '@clerk/clerk-js@6.39.0': - resolution: {integrity: sha512-1vGRCP+220kawQn827xgrcdUubSrCVmSlQT64WBHQoM60FaXkAzNaK7aPNEIMTRfg5Ync4SNBwCBr9YbwIUZLg==} + '@clerk/clerk-js@6.39.1': + resolution: {integrity: sha512-QtxMDDgtnZ6V/N3rOcjyEGqXHsugWOSFYzv176htNF57wN5lcRieUxwEYbXfpOdq2z4FYmS2bUDB1s+5AU0QsA==} engines: {node: '>=20.9.0'} '@clerk/electron-passkeys-darwin-arm64@0.0.3': @@ -2748,8 +2747,8 @@ packages: resolution: {integrity: sha512-OHhIe88qDL+FxyBalXdXNHAS5eEramr6Rerp+6iNkfkjqT8rx4hHNmfpmjg5/T1/am8QfknbOBZkqoXZlCrjPg==} engines: {node: '>=20.9.0'} - '@clerk/electron@0.1.0': - resolution: {integrity: sha512-O91JqP7VFgCl3U13Ht9Mi4R8ddJQS8efoQcVglF2DpNDDmlYU5ZiOI+6Q1XC5hSYoUTzOSsxYg9C7UiHmV3mXg==} + '@clerk/electron@0.1.1': + resolution: {integrity: sha512-ZnZTVBCjWQ7+YYrzjkG5G9bDpA2wEHdBggyijY4Q6Cny7l9aHdimz/iEaRNvz6ELeVmR2BBL4ictfFfzCqLjnA==} engines: {node: '>=20.9.0'} peerDependencies: '@clerk/electron-passkeys': 0.0.3 @@ -2765,23 +2764,23 @@ packages: react-dom: optional: true - '@clerk/expo-native-components@0.1.1': - resolution: {integrity: sha512-KgN1+7yP+BfacxHQBtmRypj04x/tCG5a6TZlsBW0oKIUdg98xJvJxP1+gLWevGdRLVY2NyBs7/Rd4+E9v4sa4w==} + '@clerk/expo-native-components@0.2.0': + resolution: {integrity: sha512-9EffqP+phLspxAm4AzwqPP8DAG6u410W3Sixfx1zwXYCna0UiG8yUPXUHOtrquGiq0qrmn2e+Ov8leo6nKX3SA==} engines: {node: '>=20.9.0'} peerDependencies: - expo: '>=54 <58' + expo: '>=54 <59' react: ^18.0.0 || ^19.0.0 react-native: '>=0.75' - '@clerk/expo@4.12.0': - resolution: {integrity: sha512-jLnyEtWc/D+7PbCTuddO1WEn8Anv4I/h1OujpeqLOPDCWiRHOOpP9UoDVIxKUAh+hTkO2bq6U4OpGtt4KDk9Lw==} + '@clerk/expo@4.13.0': + resolution: {integrity: sha512-Hxss//4FE4lWCEtiLRchhnQOkWwy3KJUjPDj8khqqZ+K78ujqwPPaNDoQDM3c2O2gEd1Snp7KaHO4CQKkwehMA==} engines: {node: '>=20.9.0'} peerDependencies: '@clerk/expo-biometrics': '>=0.1.0' '@clerk/expo-google-signin': '>=0.1.0' '@clerk/expo-native-components': '>=0.1.0' '@clerk/expo-passkeys': '>=0.0.6' - expo: '>=54 <58' + expo: '>=54 <59' expo-apple-authentication: '>=7.0.0' expo-auth-session: '>=5' expo-constants: 58.0.12 @@ -3690,8 +3689,8 @@ packages: '@expo-google-fonts/material-symbols@0.4.38': resolution: {integrity: sha512-IJkBtN1o8u9BW5fvSii1MyHPQ7Q0HxbWcVBvOrOzgMLpVtZw7R2w94wBTVR7kZwv3w1JNTESMmLA5Sqn1+Z36A==} - '@expo/cli@58.1.9': - resolution: {integrity: sha512-XSTtCXU0xvPSJOMdYG8m0srpXcUmsfs1iSmGo6vs/epnp8iLd8Id2fT7iExHNMJkctJopvK8tKY8E7Eja03ipQ==} + '@expo/cli@58.1.11': + resolution: {integrity: sha512-wkFTSLXXYqLkRT5oy4DnLuTOtbFIu3qTiXHSHkFSqUBTHiE92y3bOIwM3UN7Y1ys18qVJge8lXjezaEfsHmijQ==} hasBin: true peerDependencies: expo: '*' @@ -3867,8 +3866,8 @@ packages: react-server-dom-webpack: optional: true - '@expo/schema-utils@58.0.1': - resolution: {integrity: sha512-r5ox9st0g1IYC37tKD0WYiKH6RXout9FqjSwVv0nIhRYYTXhChJfzcMnJ90zkBznKO1lZVCqdO302YVYsm3qQA==} + '@expo/schema-utils@58.0.2': + resolution: {integrity: sha512-w28y8SG+5ZTdDdmH2ZnCQk9wHVwGzI9NqX5V4urJUFEnxbm7I129fJRkb8RIAJmMA1WKU5h3ONmranV473uaXQ==} '@expo/sdk-runtime-versions@1.0.1': resolution: {integrity: sha512-kvisefkhxu8Fm/4M8G6DEqUaigrXfrSOm2lFw7hsk/nq0zchcp6B4wSk8rlheHY8FRi5iHxKtoVMGY/3M6h04A==} @@ -3880,8 +3879,8 @@ packages: '@expo/sudo-prompt@9.3.2': resolution: {integrity: sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw==} - '@expo/ui@58.0.18': - resolution: {integrity: sha512-hRpRJZfBoqfxfhGrwnYFhHKVWS28Ax89ygBlOSIpIUvXGqdIsrpk7JJ4xm0UCYOEO9N/pfCOReyEDQFMYaos3A==} + '@expo/ui@58.0.20': + resolution: {integrity: sha512-aJwvnp0rgKFX1+/EjaSBpNBpWd/4PIos3mZG5/mTHJcKOM6HJ1gG561PRqRBIdCkR1qziDDxjWru6QvH1qe0EA==} peerDependencies: '@babel/core': '*' expo: '*' @@ -5606,8 +5605,8 @@ packages: '@types/react': optional: true - '@react-navigation/core@7.21.13': - resolution: {integrity: sha512-d1syMXra7RlJjGsjsIxEA14F6U+awFtQJeOfDc+V7x3y1mPqYQVTYnqnt3PR+fBBouUKaKsgKZsSR3MP5919Xg==} + '@react-navigation/core@7.24.0': + resolution: {integrity: sha512-PPMHGSgLB65eqWOBHeD/nGyzGJV3rcZ5sZbsCXlaC37HnLmwTEjB4CaOQn8CBVVv/Sc0Kl/W5dpPLls9Stk2WA==} peerDependencies: react: '>= 18.2.0' @@ -5638,8 +5637,8 @@ packages: react: '>= 18.2.0' react-native: '*' - '@react-navigation/routers@7.6.4': - resolution: {integrity: sha512-GI7eJm8/KsZUQaYcXvEExikKurRZRgEsSzyZ7faENfi65yqJBCXjDMwyN1pF6pNW1MoLH1ErDwDivFxY6BzD3w==} + '@react-navigation/routers@7.6.5': + resolution: {integrity: sha512-hpvpVFt6wu3U014F/0Qy45VZCErlUvIV8kN1L6HovN5P9OpbXAzFTaRQmG7VW6czg2tSkUL5S3dZA0HIu5QirQ==} '@redis/bloom@6.2.1': resolution: {integrity: sha512-huQgNLaCIZfQ9SeLn4q9124uOUd8HbZDYHwwUzNcRgHqCHiHKl2dDxMqJCeWh8cMqZAoWuHR8XnWbDMIf+o7ag==} @@ -7543,12 +7542,12 @@ packages: babel-plugin-transform-flow-enums@0.0.2: resolution: {integrity: sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==} - babel-preset-expo@58.0.15: - resolution: {integrity: sha512-9eDK3wKo+BpSFiUc8kqpIoxCZM7BB0l7tVMBILyuXkaenQyPclUmaIV+pjpDVQ8h5KoEAFeJKZkufp0Zhnc0+w==} + babel-preset-expo@58.0.17: + resolution: {integrity: sha512-Rrqc/Z5Idc4bG2/PrEh725t3kvuAc7jUKCJ+wZVU9KXk2bKSdqAniXxQa8aph9aHdv4h5sGKLpMXMaMNz/4+Og==} peerDependencies: '@babel/runtime': ^7.20.0 expo: '*' - expo-widgets: ^58.0.18 + expo-widgets: ^58.0.20 react-refresh: '>=0.14.0 <1.0.0' peerDependenciesMeta: '@babel/runtime': @@ -8244,10 +8243,6 @@ packages: decode-named-character-reference@1.3.0: resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} - decode-uri-component@0.2.2: - resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} - engines: {node: '>=0.10'} - decompress-response@6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} @@ -8723,8 +8718,8 @@ packages: resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} engines: {node: '>=12.0.0'} - expo-application@58.1.1: - resolution: {integrity: sha512-5DWFlvEa2BFFBlQqT+w8C2XdR/vFVvCa++w/2lKtyfFhXrFA9S1yHrcffCjAc6bdvV3M7mL1cTXJgdUz+157/g==} + expo-application@58.1.2: + resolution: {integrity: sha512-WYFdNHGaxe/j69oYREhK0cKsKYszuIuz399WXYCP+M1grfO+FCWB/RbuMgaXJsLWlzqhNjA/zLgfJ+33FwrQvw==} peerDependencies: expo: '*' @@ -8743,21 +8738,21 @@ packages: react: '*' react-native: '*' - expo-auth-session@58.0.12: - resolution: {integrity: sha512-a+bN2bzGfUsUUlPjYFQFTgE48fiUMK9iN+kKe/brseJ83YZOvr2tM1JoMXLQr5eUb9sCiNwnxYcZhMXtNpYJjg==} + expo-auth-session@58.0.13: + resolution: {integrity: sha512-x1WOQClARC36nikmzbuxSVmA/HCOISF7FUAPCHsdhlNXvKQ/geh/fXYo5wTd4U5yBxDpho7ijxdGGvNb3WKtFw==} peerDependencies: react: '*' react-native: '*' - expo-blur@58.0.3: - resolution: {integrity: sha512-aqP279YTuioGLGq6wFPFKdSY4KRQYEri8MdbiCI99T8kPP1oPwTQP6iCKHQrxAebBNxoRTeN/4UXwpBB5uGkdw==} + expo-blur@58.0.4: + resolution: {integrity: sha512-GtRPQ+w2SGNiDUTtwLaVHuFnP+aGjYVjbD7kPEPhXWLmyT+Nan1J5/KbbGLJ14LXJezIqShS42JXXcRDfXuU+w==} peerDependencies: expo: '*' react: '*' react-native: '*' - expo-build-properties@58.0.10: - resolution: {integrity: sha512-Em8Vjru76RbNiJczohxoTx/b16Ag6PCvqIZWIJeYjIJG6lSxOPtc+54Qw5f+KGIU0WrZCLm+usSN7wbE8tmNNQ==} + expo-build-properties@58.0.11: + resolution: {integrity: sha512-8vjp+RSD7VW/VeEpG9l1YON4ZqOqQXPmtMYFqmh41I7cBGwELRYybHFrh2P3uBgzWlRBuQrRLO5UAtAYfT7HLg==} peerDependencies: expo: '*' @@ -8785,18 +8780,18 @@ packages: expo: '*' react-native: '*' - expo-crypto@58.0.6: - resolution: {integrity: sha512-sN3xnfp809g6xpyIjfJ+7ITPggmhkVW6WPCHfXRhGmniZdgjQeb57CpyY0mUup8ZJGfSqkWXxMhuOMZMctQMDA==} + expo-crypto@58.0.7: + resolution: {integrity: sha512-g+4i4UpqQ5jNy1VPRvVVvr9aIdh8WwvxbpwL2ntiSESDRsXyVSeb8JM6tHVdC3b9J2nGxjtrhrsaWOo0jbSxlA==} peerDependencies: expo: '*' - expo-dev-client@58.0.13: - resolution: {integrity: sha512-2Ot6Sec/OYPTIfcAwesDUPea30gyFr49OdB/8yB3zpUMCtYf7dQyuHnPo7qGyhSxnActwJVW1KKAUJ134Ehrwg==} + expo-dev-client@58.0.14: + resolution: {integrity: sha512-gyzONNNS/SLZdxFdDshgzc0Uxxt2i+MjYwOQX3LNvr3pXFtYHYM9kza8MpdYOqhqGvWnA4BebeBWq3T1hjt9nQ==} peerDependencies: expo: '*' - expo-dev-launcher@58.0.13: - resolution: {integrity: sha512-n/Ta15l3Ti2nVhchQ3L8OzuAgtyD+R/UGinqiZUVlT2rDslUS0Qwb05bRY5QeLNF0NzLFaO0522/bhCLDLAJww==} + expo-dev-launcher@58.0.14: + resolution: {integrity: sha512-RFgP59Tesnr3wBPj4B82Qwx2k0355VkVmHuovzwfmuti22pWhJvNhdr2aR7BokQ5U6z2Vm4HAz6NjRE+xBIFPA==} peerDependencies: expo: '*' react-native: '*' @@ -8838,15 +8833,15 @@ packages: react: '*' react-native: '*' - expo-glass-effect@58.0.3: - resolution: {integrity: sha512-NoFT5j2uZecNsiDAd47z37PWYTxNJnJMrVYiAU+SggiV9K91Sc0IuIcMsuOM4sUuPBQdSTs8/I9KXk5M0Z2O/w==} + expo-glass-effect@58.0.4: + resolution: {integrity: sha512-PrxU1FINOpqpnjtZMXHAC/APLq3T3fDforMqQ+JRqRtIrlQ8wntrX8IztLxJBKD9s8cJJ8V9MAoI89aYRK8j9Q==} peerDependencies: expo: '*' react: '*' react-native: '*' - expo-haptics@58.0.6: - resolution: {integrity: sha512-a5B/qbjCCqvBFh25r8qnFKDt0JmBRniTtNTKwhRlZVpEmR/ZxCSQC5EsPw2Cob+G/27rcWgK7Lo8ICMq/megwA==} + expo-haptics@58.0.7: + resolution: {integrity: sha512-mAY3rbng6EuYysq9wnJKhKwYYlDjqnPYcS5OXe3zj4TlAaOFMl/EfiSOuAMawc2nsXCAnwJ5U0E11nq5zQO0mg==} peerDependencies: expo: '*' @@ -8903,18 +8898,18 @@ packages: resolution: {integrity: sha512-uzLFoTnAKabUdITvzRqWTvFkZsOdRPEXj7AEMAuBEhA2kGhqaBDa2EOWqPXVay0QJVoZuIQaEEgPGAXN1dPuYg==} hasBin: true - expo-modules-core@58.0.19: - resolution: {integrity: sha512-4AZnsKLSpEv2PhF4W5n73KkZJo0TjiSXBpDREX4HXZVhE0AC/KeYieCqyYyMsKMfWFuCTpI0m3HPmhvL2tnQHw==} + expo-modules-core@58.0.22: + resolution: {integrity: sha512-T3YJYziFkF4JlGDpX4zCl91oIxz1Skq5sp1LFVO+GL/BARSIXk013QWGdRZrvt+wMxoVaql5dpOdPdP5q2+0jQ==} peerDependencies: react: '*' react-native: '*' - react-native-worklets: ^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0 + react-native-worklets: '>=0.13.0' peerDependenciesMeta: react-native-worklets: optional: true - expo-modules-jsi@58.0.14: - resolution: {integrity: sha512-ZgpVRmt7Z/5y6n8Yj53MthoAElinvkZ5voFaVsmfuTebCver9b71DiLyTCkXEh69Qjp+j53nayha5VD7zn6vBw==} + expo-modules-jsi@58.0.15: + resolution: {integrity: sha512-PsjYgL4KWtvBqWH242r0wbP99VjgHkHCpkPCekO7nzb+ulkDNyrNnhysxa0TcNpfRTNLetmCUaLs9t4CcoquZQ==} peerDependencies: react-native: '*' @@ -8927,8 +8922,8 @@ packages: expo: '*' react: '*' - expo-notifications@58.1.4: - resolution: {integrity: sha512-ZIEodG1qEDCmlX8bMaKN4V426vrt776qmQFRNg/ddR3qwFCgN/PTZFcHlhtSD5bKTD8sOSKw0kCPLswUvTd9SQ==} + expo-notifications@58.1.5: + resolution: {integrity: sha512-5bf3l+nP/yIadq6v1f3pyOmEk0WRsEaSEcfJdpCXzOyaMwg5YtqR48sMPU0Wg7KESwOtLVtetSH6y3XkGzSiVw==} peerDependencies: expo: '*' react: '*' @@ -8961,15 +8956,15 @@ packages: resolution: {integrity: sha512-FHYecxfGOuAhacHcanR6qCN8Cln9S+FFulcYetLu3ddDg55ohuCsMZ9U4Egzwdm+A2o6N+MdSoJKquBC5F9NIg==} engines: {node: ^22.13.0 || ^24.3.0 || ^26.0.0 || >=27.0.0} - expo-sharing@58.0.18: - resolution: {integrity: sha512-GqL1dJ5v+zgqdgDG6KApBV+hvOsTmLKK0ZaoZo1mWo9Krxxanl6W7dV92PQ2xQLcLMjH2hpOsDNehr1Onmk9VQ==} + expo-sharing@58.0.19: + resolution: {integrity: sha512-FzTUT7uquCBbWVwjYm1fogpO3UNBoj+XRCNrCv7GzRNy9f0KPzLZTnaqJw28nEvaesYg/Q9nAiwSwkH1Df/Bdg==} peerDependencies: expo: '*' react: '*' react-native: '*' - expo-splash-screen@58.0.9: - resolution: {integrity: sha512-xQzyZnqznW0SgRdpddkJVJUTijHrTUDxIlZUiEhR5ki6G8/b0CDOvonNzPAIa2CbzzvXCMrjVIV+bQ1Gg033Kw==} + expo-splash-screen@58.0.10: + resolution: {integrity: sha512-rjzCLKo7SHSOkaFnVnh+bYWK/pO/vC05qvJe++AjaQidTSGLxD2buj7zWFLlbEEpkqP+wZYQHRyx2mvHyZrUQw==} peerDependencies: expo: '*' @@ -9021,15 +9016,15 @@ packages: expo: '*' react-native: '*' - expo-widgets@58.0.18: - resolution: {integrity: sha512-OqaM1KsOatj88rJgWMWSyrhsNSNgHcFb65ElPTiNazvjEn20j4Y1OGvnRB1fsehd4dWXsiJwemYeMQD8MuAVBg==} + expo-widgets@58.0.20: + resolution: {integrity: sha512-RV/EKVlRe0dEGyFPx4Z5AawlYg+mYGGRqjnei4Qv/yd1tPRqYK8bMvYbOcBYh5salc/Xsj29EP8clmY7sxjK4Q==} peerDependencies: expo: '*' react: '*' react-native: '*' - expo@58.0.11: - resolution: {integrity: sha512-GLb3RXy6vSHa27BBi7tbIQThYfbVhGWaN4o3WBZSxlGetKm1tyf+vPAHfzn7DFWqsccS7sr0YuvpxpgHG9Y/Jw==} + expo@58.0.14: + resolution: {integrity: sha512-M05O++KRgG4NA6kQ9AP60kbN8xqHJ6S8uTXdtkeiwcGVIYzdu2kaUXJyraVturvePO/Mf4PWa0C9+JggrHITwA==} engines: {node: ^22.13.0 || ^24.3.0 || ^26.0.0 || >=27.0.0} hasBin: true peerDependencies: @@ -9146,10 +9141,6 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} - filter-obj@1.1.0: - resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} - engines: {node: '>=0.10.0'} - finalhandler@1.1.2: resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} engines: {node: '>= 0.8'} @@ -10976,10 +10967,6 @@ packages: resolution: {integrity: sha512-h6fhOIaRrID2CbEY2fqs+7t+UXZo+MLAnU5gRIq85uFtdiUPCdsApMlHhXogKVM4HM2DVbIjGNTTYH2OcmP1vA==} engines: {node: '>=0.6'} - query-string@7.1.3: - resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==} - engines: {node: '>=6'} - quick-lru@5.1.1: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} @@ -11048,9 +11035,9 @@ packages: '@types/react': '>=18' react: '>=18' - react-native-enriched-markdown@file:apps/mobile/deps/react-native-enriched-markdown-1.2.0-t3.13.tgz: - resolution: {integrity: sha512-m7BcMN2RCG3/7RftAXPbjwQhgzba9nGC+Fj16INzHyxCj1VQ4kCtS121WaqX7gXN28rLP/2n6AYUP3cwfr6svA==, tarball: file:apps/mobile/deps/react-native-enriched-markdown-1.2.0-t3.13.tgz} - version: 1.2.0-t3.13 + react-native-enriched-markdown@file:apps/mobile/deps/react-native-enriched-markdown-1.2.0-t3.15.tgz: + resolution: {integrity: sha512-p9o8zNoVoNwqdlG8a9Fvhj0RFUjmpE6VecwOVsO6a8Alj2HPfCDzeLBq0SFn2KdUYX32MC2fH1gJJs/HyfP5Mg==, tarball: file:apps/mobile/deps/react-native-enriched-markdown-1.2.0-t3.15.tgz} + version: 1.2.0-t3.15 peerDependencies: katex: '>=0.16.0' react: '*' @@ -11575,10 +11562,6 @@ packages: sparse-bitfield@3.0.3: resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==} - split-on-first@1.1.0: - resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==} - engines: {node: '>=6'} - split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} @@ -11646,10 +11629,6 @@ packages: strict-event-emitter@0.5.1: resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} - strict-uri-encode@2.0.0: - resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} - engines: {node: '>=4'} - strictdom@1.0.1: resolution: {integrity: sha512-cEmp9QeXXRmjj/rVp9oyiqcvyocWab/HaoN4+bwFeZ7QzykJD6L3yD4v12K1x0tHpqRqVpJevN3gW7kyM39Bqg==} @@ -13651,7 +13630,7 @@ snapshots: fast-wrap-ansi: 0.2.2 sisteransi: 1.0.5 - '@clerk/backend@3.24.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + '@clerk/backend@3.25.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: '@clerk/shared': 4.40.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0) standardwebhooks: 1.0.0 @@ -13660,7 +13639,7 @@ snapshots: - react - react-dom - '@clerk/clerk-js@6.39.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': + '@clerk/clerk-js@6.39.1(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@clerk/shared': 4.40.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6) '@stripe/stripe-js': 5.6.0 @@ -13677,7 +13656,7 @@ snapshots: - react - react-dom - '@clerk/clerk-js@6.39.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + '@clerk/clerk-js@6.39.1(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: '@clerk/shared': 4.40.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@stripe/stripe-js': 5.6.0 @@ -13713,9 +13692,9 @@ snapshots: '@clerk/electron-passkeys-win32-arm64-msvc': 0.0.3 '@clerk/electron-passkeys-win32-x64-msvc': 0.0.3 - '@clerk/electron@0.1.0(@clerk/electron-passkeys@0.0.3)(electron-store@8.2.0)(electron@44.4.5)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': + '@clerk/electron@0.1.1(@clerk/electron-passkeys@0.0.3)(electron-store@8.2.0)(electron@44.4.5)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: - '@clerk/clerk-js': 6.39.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@clerk/clerk-js': 6.39.1(react-dom@19.2.6(react@19.2.6))(react@19.2.6) '@clerk/react': 6.17.8(react-dom@19.2.6(react@19.2.6))(react@19.2.6) '@clerk/shared': 4.40.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6) electron: 44.4.5 @@ -13726,9 +13705,9 @@ snapshots: electron-store: 8.2.0 react-dom: 19.2.6(react@19.2.6) - '@clerk/electron@0.1.0(@clerk/electron-passkeys@0.0.3)(electron-store@8.2.0)(electron@44.4.5)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + '@clerk/electron@0.1.1(@clerk/electron-passkeys@0.0.3)(electron-store@8.2.0)(electron@44.4.5)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: - '@clerk/clerk-js': 6.39.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@clerk/clerk-js': 6.39.1(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@clerk/react': 6.17.8(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@clerk/shared': 4.40.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0) electron: 44.4.5 @@ -13739,10 +13718,10 @@ snapshots: electron-store: 8.2.0 react-dom: 19.3.0(react@19.3.0) - '@clerk/expo-native-components@0.1.1(patch_hash=5f3738f8e5d50bfa467ce8afbaf7c2aa7c7c9adb95a2307424eb908f6af0d299)(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2)': + '@clerk/expo-native-components@0.2.0(patch_hash=7a808b92da8460750b85818552e13be3fb73d111691c7db76965970351e124e4)(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2)': dependencies: '@expo/config-plugins': 58.0.9(typescript@7.0.2) - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) tslib: 2.8.1 @@ -13750,25 +13729,25 @@ snapshots: - supports-color - typescript - '@clerk/expo@4.12.0(fc0c782bb008f08bb0dbe9eee6e857d7)': + '@clerk/expo@4.13.0(7b5e2b0afc01ce7ef5801e333b018457)': dependencies: - '@clerk/clerk-js': 6.39.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@clerk/clerk-js': 6.39.1(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@clerk/react': 6.17.8(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@clerk/shared': 4.40.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@expo/config-plugins': 58.0.9(typescript@7.0.2) base-64: 1.0.0 - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) react-native-url-polyfill: 4.0.0(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) tslib: 2.8.1 optionalDependencies: - '@clerk/expo-native-components': 0.1.1(patch_hash=5f3738f8e5d50bfa467ce8afbaf7c2aa7c7c9adb95a2307424eb908f6af0d299)(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) - expo-auth-session: 58.0.12(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) - expo-constants: 58.0.12(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2) - expo-crypto: 58.0.6(expo@58.0.11) - expo-secure-store: 58.0.2(expo@58.0.11) - expo-web-browser: 58.0.6(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) + '@clerk/expo-native-components': 0.2.0(patch_hash=7a808b92da8460750b85818552e13be3fb73d111691c7db76965970351e124e4)(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) + expo-auth-session: 58.0.13(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) + expo-constants: 58.0.12(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2) + expo-crypto: 58.0.7(expo@58.0.14) + expo-secure-store: 58.0.2(expo@58.0.14) + expo-web-browser: 58.0.6(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) react-dom: 19.3.0(react@19.3.0) transitivePeerDependencies: - supports-color @@ -14556,7 +14535,7 @@ snapshots: '@expo-google-fonts/material-symbols@0.4.38': {} - '@expo/cli@58.1.9(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(bufferutil@4.1.0)(expo-constants@58.0.12(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2))(expo-font@58.0.8(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(expo@58.0.11)(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2)(utf-8-validate@6.0.6)': + '@expo/cli@58.1.11(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(bufferutil@4.1.0)(expo-constants@58.0.12(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2))(expo-font@58.0.8(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(expo@58.0.14)(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2)(utf-8-validate@6.0.6)': dependencies: 2g: 1.0.1(typescript@7.0.2) '@expo/code-signing-certificates': 0.0.7 @@ -14567,10 +14546,10 @@ snapshots: '@expo/image-utils': 0.12.5(typescript@7.0.2) '@expo/inline-modules': 0.2.6(typescript@7.0.2) '@expo/json-file': 11.2.1 - '@expo/log-box': 58.0.12(@expo/dom-webview@58.0.2)(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + '@expo/log-box': 58.0.12(@expo/dom-webview@58.0.2)(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) '@expo/log-box-utils': 58.0.2 '@expo/metro': 58.0.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) - '@expo/metro-config': 58.0.14(patch_hash=90fa980e8b6480631fb2fbb04559834e3c612db40c550cd828f11be297d8d760)(bufferutil@4.1.0)(expo@58.0.11)(typescript@7.0.2)(utf-8-validate@6.0.6) + '@expo/metro-config': 58.0.14(patch_hash=90fa980e8b6480631fb2fbb04559834e3c612db40c550cd828f11be297d8d760)(bufferutil@4.1.0)(expo@58.0.14)(typescript@7.0.2)(utf-8-validate@6.0.6) '@expo/metro-file-map': 58.0.5(typescript@7.0.2) '@expo/osascript': 2.8.1 '@expo/package-manager': 1.14.2 @@ -14578,8 +14557,8 @@ snapshots: '@expo/plist': 0.10.1 '@expo/prebuild-config': 58.0.14(typescript@7.0.2) '@expo/require-utils': 58.0.4(typescript@7.0.2) - '@expo/router-server': 58.0.14(@expo/metro-runtime@58.0.14)(expo-constants@58.0.12(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2))(expo-font@58.0.8(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(expo-server@58.0.5)(expo@58.0.11)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) - '@expo/schema-utils': 58.0.1 + '@expo/router-server': 58.0.14(@expo/metro-runtime@58.0.14)(expo-constants@58.0.12(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2))(expo-font@58.0.8(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(expo-server@58.0.5)(expo@58.0.14)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@expo/schema-utils': 58.0.2 '@expo/spawn-async': 1.8.0 '@expo/ws-tunnel': 2.0.1(ws@8.22.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@expo/xcpretty': 4.4.7 @@ -14596,7 +14575,7 @@ snapshots: compression: 1.8.2 connect: 3.7.0 dnssd-advertise: 1.1.6 - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) expo-server: 58.0.5 fetch-nodeshim: 0.4.10 getenv: 2.0.0 @@ -14686,17 +14665,17 @@ snapshots: transitivePeerDependencies: - supports-color - '@expo/devtools@58.0.2(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)': + '@expo/devtools@58.0.2(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)': dependencies: chalk: 4.1.2 optionalDependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) - '@expo/dom-webview@58.0.2(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)': + '@expo/dom-webview@58.0.2(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)': dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) @@ -14708,7 +14687,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@expo/fingerprint@0.21.5': + '@expo/fingerprint@0.21.5(patch_hash=8fba80d6bbce46c72de427fe8c7907462d262a0bfe50c6b2b7ee9c4e0c61e5e1)': dependencies: '@expo/env': 2.5.2 '@expo/spawn-async': 1.8.0 @@ -14772,18 +14751,18 @@ snapshots: '@expo/log-box-utils@58.0.2': {} - '@expo/log-box@58.0.12(@expo/dom-webview@58.0.2)(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)': + '@expo/log-box@58.0.12(@expo/dom-webview@58.0.2)(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)': dependencies: - '@expo/dom-webview': 58.0.2(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + '@expo/dom-webview': 58.0.2(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) '@expo/log-box-utils': 58.0.2 anser: 1.4.10 react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) stacktrace-parser: 0.1.11 optionalDependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) - '@expo/metro-config@58.0.14(patch_hash=90fa980e8b6480631fb2fbb04559834e3c612db40c550cd828f11be297d8d760)(bufferutil@4.1.0)(expo@58.0.11)(typescript@7.0.2)(utf-8-validate@6.0.6)': + '@expo/metro-config@58.0.14(patch_hash=90fa980e8b6480631fb2fbb04559834e3c612db40c550cd828f11be297d8d760)(bufferutil@4.1.0)(expo@58.0.14)(typescript@7.0.2)(utf-8-validate@6.0.6)': dependencies: 2g: 1.0.1(typescript@7.0.2) '@babel/code-frame': 7.29.7 @@ -14814,7 +14793,7 @@ snapshots: postcss: 8.5.28 resolve-from: 5.0.0 optionalDependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) transitivePeerDependencies: - bufferutil - supports-color @@ -14833,11 +14812,11 @@ snapshots: - supports-color - typescript - '@expo/metro-runtime@58.0.14(@expo/log-box@58.0.12)(expo@58.0.11)(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)': + '@expo/metro-runtime@58.0.14(@expo/log-box@58.0.12)(expo@58.0.14)(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)': dependencies: - '@expo/log-box': 58.0.12(@expo/dom-webview@58.0.2)(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + '@expo/log-box': 58.0.12(@expo/dom-webview@58.0.2)(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) anser: 1.4.10 - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) pretty-format: 29.7.0 react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) @@ -14930,21 +14909,21 @@ snapshots: transitivePeerDependencies: - supports-color - '@expo/router-server@58.0.14(@expo/metro-runtime@58.0.14)(expo-constants@58.0.12(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2))(expo-font@58.0.8(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(expo-server@58.0.5)(expo@58.0.11)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + '@expo/router-server@58.0.14(@expo/metro-runtime@58.0.14)(expo-constants@58.0.12(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2))(expo-font@58.0.8(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(expo-server@58.0.5)(expo@58.0.14)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: debug: 4.4.3 - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) - expo-constants: 58.0.12(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2) - expo-font: 58.0.8(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) + expo-constants: 58.0.12(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2) + expo-font: 58.0.8(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) expo-server: 58.0.5 react: 19.3.0 optionalDependencies: - '@expo/metro-runtime': 58.0.14(@expo/log-box@58.0.12)(expo@58.0.11)(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + '@expo/metro-runtime': 58.0.14(@expo/log-box@58.0.12)(expo@58.0.14)(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) react-dom: 19.3.0(react@19.3.0) transitivePeerDependencies: - supports-color - '@expo/schema-utils@58.0.1': {} + '@expo/schema-utils@58.0.2': {} '@expo/sdk-runtime-versions@1.0.1': {} @@ -14954,9 +14933,9 @@ snapshots: '@expo/sudo-prompt@9.3.2': {} - '@expo/ui@58.0.18(patch_hash=5a26480373850c1a7943919aa21f904151b335a0cb01042109e0746def37923e)(@babel/core@7.29.7)(expo@58.0.11)(react-dom@19.3.0(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)': + '@expo/ui@58.0.20(patch_hash=5a26480373850c1a7943919aa21f904151b335a0cb01042109e0746def37923e)(@babel/core@7.29.7)(expo@58.0.14)(react-dom@19.3.0(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)': dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) sf-symbols-typescript: 2.2.0 @@ -16340,13 +16319,11 @@ snapshots: optionalDependencies: '@types/react': 19.3.0 - '@react-navigation/core@7.21.13(react@19.3.0)': + '@react-navigation/core@7.24.0(react@19.3.0)': dependencies: - '@react-navigation/routers': 7.6.4 + '@react-navigation/routers': 7.6.5 escape-string-regexp: 4.0.0 fast-deep-equal: 3.1.3 - nanoid: 3.3.19 - query-string: 7.1.3 react: 19.3.0 react-is: 19.2.7 use-latest-callback: 0.2.6(react@19.3.0) @@ -16380,7 +16357,7 @@ snapshots: '@react-navigation/native@7.5.1(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)': dependencies: - '@react-navigation/core': 7.21.13(react@19.3.0) + '@react-navigation/core': 7.24.0(react@19.3.0) escape-string-regexp: 4.0.0 fast-deep-equal: 3.1.3 nanoid: 3.3.19 @@ -16389,7 +16366,7 @@ snapshots: standard-navigation: 0.0.8(react@19.3.0) use-latest-callback: 0.2.6(react@19.3.0) - '@react-navigation/routers@7.6.4': + '@react-navigation/routers@7.6.5': dependencies: nanoid: 3.3.19 @@ -17859,7 +17836,7 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - alchemy@2.0.0-beta.80(patch_hash=bea1b6c0c0b23157fd5f439a1d7feff430f28ac1621ba135d8a13eeec60ccacd)(0ba0331b8debaa0ad7a4056eaf11dc21): + alchemy@2.0.0-beta.80(patch_hash=bea1b6c0c0b23157fd5f439a1d7feff430f28ac1621ba135d8a13eeec60ccacd)(575369c756745bf3feea15f355990f30): dependencies: '@alchemy.run/cloudflare-runtime': 2.0.0-beta.80(@distilled.cloud/cloudflare@1.0.0-rc.13(effect@4.0.5))(@effect/platform-node@4.0.5(bufferutil@4.1.0)(effect@4.0.5)(redis@6.2.1)(utf-8-validate@6.0.6))(@types/node@24.12.4)(@voidzero-dev/vite-plus-core@1.0.0(@types/node@24.12.4)(esbuild@0.28.2)(jiti@2.7.0)(terser@5.48.0)(typescript@7.0.2)(unrun@0.2.39)(yaml@2.9.0))(effect@4.0.5)(rolldown@1.2.5)(typescript@7.0.2) '@alchemy.run/floci': 2.0.0-beta.80(effect@4.0.5) @@ -17902,7 +17879,7 @@ snapshots: '@effect/sql-pg': 4.0.5(effect@4.0.5) '@effect/vitest': 4.0.5(patch_hash=2731c9c3761c595f25ddc625a7d61ca376b389d5b3049ecb837c8940f21cfa02)(@types/node@24.12.4)(@vitest/ui@5.0.1)(bufferutil@4.1.0)(effect@4.0.5)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.1.0(@noble/hashes@1.8.0))(msw@2.12.11(@types/node@24.12.4)(typescript@7.0.2))(terser@5.48.0)(typescript@7.0.2)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) drizzle-kit: 1.0.0-rc.5-ab785fc - drizzle-orm: 1.0.0-rc.5-ab785fc(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0(effect@4.0.5))(@effect/sql-pg@4.0.5(effect@4.0.5))(@effect/sql-sqlite-bun@4.0.0-rc.112(effect@4.0.5))(@effect/sql-sqlite-do@4.0.5(effect@4.0.5))(@electric-sql/pglite@0.3.15)(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(bun-types@1.3.14)(effect@4.0.5)(expo-sqlite@58.0.13(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(pg@8.23.0)(valibot@1.2.0(typescript@7.0.2))(zod@4.4.3) + drizzle-orm: 1.0.0-rc.5-ab785fc(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0(effect@4.0.5))(@effect/sql-pg@4.0.5(effect@4.0.5))(@effect/sql-sqlite-bun@4.0.0-rc.112(effect@4.0.5))(@effect/sql-sqlite-do@4.0.5(effect@4.0.5))(@electric-sql/pglite@0.3.15)(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(bun-types@1.3.14)(effect@4.0.5)(expo-sqlite@58.0.13(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(pg@8.23.0)(valibot@1.2.0(typescript@7.0.2))(zod@4.4.3) mongodb: 6.21.0(@aws-sdk/credential-providers@3.1062.0)(socks@2.8.9) pg: 8.23.0 vite: '@voidzero-dev/vite-plus-core@1.0.0(@types/node@24.12.4)(esbuild@0.28.2)(jiti@2.7.0)(terser@5.48.0)(typescript@7.0.2)(unrun@0.2.39)(yaml@2.9.0)' @@ -18189,7 +18166,7 @@ snapshots: transitivePeerDependencies: - '@babel/core' - babel-preset-expo@58.0.15(@babel/core@7.29.7)(@babel/runtime@7.29.7)(expo-widgets@58.0.18)(expo@58.0.11)(react-refresh@0.14.2): + babel-preset-expo@58.0.17(@babel/core@7.29.7)(@babel/runtime@7.29.7)(expo-widgets@58.0.20)(expo@58.0.14)(react-refresh@0.14.2): dependencies: '@babel/generator': 7.29.7 '@babel/helper-module-imports': 7.29.7 @@ -18236,8 +18213,8 @@ snapshots: react-refresh: 0.14.2 optionalDependencies: '@babel/runtime': 7.29.7 - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) - expo-widgets: 58.0.18(patch_hash=40806e85c756563935c7368b93d679bd3bb7742bff21d9c7611d9161e1aee602)(@babel/core@7.29.7)(expo@58.0.11)(react-dom@19.3.0(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) + expo-widgets: 58.0.20(patch_hash=8623cb034b720c5ef2da8012c765805a7298909bd92eaf8381f64dbde41b77dd)(@babel/core@7.29.7)(expo@58.0.14)(react-dom@19.3.0(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) transitivePeerDependencies: - '@babel/core' - supports-color @@ -18937,8 +18914,6 @@ snapshots: dependencies: character-entities: 2.0.2 - decode-uri-component@0.2.2: {} - decompress-response@6.0.0: dependencies: mimic-response: 3.1.0 @@ -19062,7 +19037,7 @@ snapshots: get-tsconfig: 4.14.3 jiti: 2.7.0 - drizzle-orm@1.0.0-rc.5-ab785fc(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0(effect@4.0.5))(@effect/sql-pg@4.0.5(effect@4.0.5))(@effect/sql-sqlite-bun@4.0.0-rc.112(effect@4.0.5))(@effect/sql-sqlite-do@4.0.5(effect@4.0.5))(@electric-sql/pglite@0.3.15)(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(bun-types@1.3.14)(effect@4.0.5)(expo-sqlite@58.0.13(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(pg@8.23.0)(valibot@1.2.0(typescript@7.0.2))(zod@4.4.3): + drizzle-orm@1.0.0-rc.5-ab785fc(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0(effect@4.0.5))(@effect/sql-pg@4.0.5(effect@4.0.5))(@effect/sql-sqlite-bun@4.0.0-rc.112(effect@4.0.5))(@effect/sql-sqlite-do@4.0.5(effect@4.0.5))(@electric-sql/pglite@0.3.15)(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(bun-types@1.3.14)(effect@4.0.5)(expo-sqlite@58.0.13(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(pg@8.23.0)(valibot@1.2.0(typescript@7.0.2))(zod@4.4.3): optionalDependencies: '@cloudflare/workers-types': 4.20260604.1 '@effect/sql-d1': 4.0.0(effect@4.0.5) @@ -19073,7 +19048,7 @@ snapshots: '@libsql/client': 0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) bun-types: 1.3.14 effect: 4.0.5 - expo-sqlite: 58.0.13(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + expo-sqlite: 58.0.13(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) pg: 8.23.0 valibot: 1.2.0(typescript@7.0.2) zod: 4.4.3 @@ -19351,35 +19326,35 @@ snapshots: expect-type@1.4.0: {} - expo-application@58.1.1(expo@58.0.11): + expo-application@58.1.2(expo@58.0.14): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) - expo-asset@58.0.16(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2): + expo-asset@58.0.16(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2): dependencies: '@expo/image-utils': 0.12.5(typescript@7.0.2) - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) - expo-constants: 58.0.12(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) + expo-constants: 58.0.12(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) transitivePeerDependencies: - supports-color - typescript - expo-audio@58.0.9(patch_hash=2c2f8c73a23d48804c8b537b8cd73c25eb331aa47d82eaa481c6766cb81e5add)(expo-asset@58.0.16(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2))(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): + expo-audio@58.0.9(patch_hash=2c2f8c73a23d48804c8b537b8cd73c25eb331aa47d82eaa481c6766cb81e5add)(expo-asset@58.0.16(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2))(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) - expo-asset: 58.0.16(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) + expo-asset: 58.0.16(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) - expo-auth-session@58.0.12(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2): + expo-auth-session@58.0.13(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2): dependencies: - expo-application: 58.1.1(expo@58.0.11) - expo-constants: 58.0.12(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2) - expo-crypto: 58.0.6(expo@58.0.11) - expo-linking: 58.0.13(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) - expo-web-browser: 58.0.6(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) + expo-application: 58.1.2(expo@58.0.14) + expo-constants: 58.0.12(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2) + expo-crypto: 58.0.7(expo@58.0.14) + expo-linking: 58.0.13(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) + expo-web-browser: 58.0.6(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) invariant: 2.2.4 react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) @@ -19388,143 +19363,143 @@ snapshots: - supports-color - typescript - expo-blur@58.0.3(patch_hash=d0311b0c0b05bd94393bd9a84653cb42503d5f3c8a19eb2627c34ace08bedf18)(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): + expo-blur@58.0.4(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) - expo-build-properties@58.0.10(expo@58.0.11): + expo-build-properties@58.0.11(expo@58.0.14): dependencies: - '@expo/schema-utils': 58.0.1 - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + '@expo/schema-utils': 58.0.2 + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) resolve-from: 5.0.0 semver: 7.8.5 - expo-camera@58.0.10(@types/emscripten@1.41.5)(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): + expo-camera@58.0.10(@types/emscripten@1.41.5)(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): dependencies: barcode-detector: 3.2.0(@types/emscripten@1.41.5) - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) transitivePeerDependencies: - '@types/emscripten' - expo-clipboard@58.0.3(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): + expo-clipboard@58.0.3(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) - expo-constants@58.0.12(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2): + expo-constants@58.0.12(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2): dependencies: '@expo/env': 2.5.2 '@expo/require-utils': 58.0.4(typescript@7.0.2) - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) transitivePeerDependencies: - supports-color - typescript - expo-crypto@58.0.6(expo@58.0.11): + expo-crypto@58.0.7(expo@58.0.14): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) - expo-dev-client@58.0.13(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)): + expo-dev-client@58.0.14(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) - expo-dev-launcher: 58.0.13(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) - expo-dev-menu: 58.0.11(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) - expo-dev-menu-interface: 58.0.1(expo@58.0.11) - expo-manifests: 58.0.1(expo@58.0.11) - expo-updates-interface: 58.0.1(expo@58.0.11) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) + expo-dev-launcher: 58.0.14(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) + expo-dev-menu: 58.0.11(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) + expo-dev-menu-interface: 58.0.1(expo@58.0.14) + expo-manifests: 58.0.1(expo@58.0.14) + expo-updates-interface: 58.0.1(expo@58.0.14) transitivePeerDependencies: - react-native - expo-dev-launcher@58.0.13(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)): + expo-dev-launcher@58.0.14(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)): dependencies: - '@expo/schema-utils': 58.0.1 - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) - expo-dev-menu: 58.0.11(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) - expo-manifests: 58.0.1(expo@58.0.11) + '@expo/schema-utils': 58.0.2 + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) + expo-dev-menu: 58.0.11(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) + expo-manifests: 58.0.1(expo@58.0.14) react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) - expo-dev-menu-interface@58.0.1(expo@58.0.11): + expo-dev-menu-interface@58.0.1(expo@58.0.14): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) - expo-dev-menu@58.0.11(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)): + expo-dev-menu@58.0.11(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) - expo-dev-menu-interface: 58.0.1(expo@58.0.11) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) + expo-dev-menu-interface: 58.0.1(expo@58.0.14) react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) - expo-device@58.0.5(expo@58.0.11): + expo-device@58.0.5(expo@58.0.14): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) ua-parser-js: 0.7.41 - expo-document-picker@58.0.4(expo@58.0.11): + expo-document-picker@58.0.4(expo@58.0.14): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) expo-eas-client@58.0.2: {} - expo-file-system@58.0.9(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)): + expo-file-system@58.0.9(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) - expo-font@58.0.8(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): + expo-font@58.0.8(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) - expo-glass-effect@58.0.3(patch_hash=f750041c45ab838a3530451dc7b50d6640a79141037a1b0499c5e3412a860c57)(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): + expo-glass-effect@58.0.4(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) - expo-haptics@58.0.6(expo@58.0.11): + expo-haptics@58.0.7(expo@58.0.14): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) - expo-image-loader@58.0.3(expo@58.0.11): + expo-image-loader@58.0.3(expo@58.0.14): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) - expo-image-manipulator@58.0.14(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): + expo-image-manipulator@58.0.14(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) - expo-image-loader: 58.0.3(expo@58.0.11) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) + expo-image-loader: 58.0.3(expo@58.0.14) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) - expo-image-picker@58.0.10(expo@58.0.11): + expo-image-picker@58.0.10(expo@58.0.14): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) - expo-image-loader: 58.0.3(expo@58.0.11) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) + expo-image-loader: 58.0.3(expo@58.0.14) - expo-image@58.0.15(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): + expo-image@58.0.15(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) sf-symbols-typescript: 2.2.0 expo-json-utils@58.0.1: {} - expo-keep-awake@58.0.3(expo@58.0.11)(react@19.3.0): + expo-keep-awake@58.0.3(expo@58.0.14)(react@19.3.0): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react: 19.3.0 - expo-linking@58.0.13(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2): + expo-linking@58.0.13(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) - expo-constants: 58.0.12(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) + expo-constants: 58.0.12(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2) invariant: 2.2.4 react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) @@ -19532,9 +19507,9 @@ snapshots: - supports-color - typescript - expo-manifests@58.0.1(expo@58.0.11): + expo-manifests@58.0.1(expo@58.0.14): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) expo-json-utils: 58.0.1 expo-modules-autolinking@58.0.13(typescript@7.0.2): @@ -19548,9 +19523,9 @@ snapshots: - supports-color - typescript - expo-modules-core@58.0.19(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): + expo-modules-core@58.0.22(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): dependencies: - expo-modules-jsi: 58.0.14(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) + expo-modules-jsi: 58.0.15(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) expo-modules-macros: 0.20.0 invariant: 2.2.4 react: 19.3.0 @@ -19558,7 +19533,7 @@ snapshots: optionalDependencies: react-native-worklets: 0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) - expo-modules-jsi@58.0.14(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)): + expo-modules-jsi@58.0.15(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)): dependencies: react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) @@ -19567,98 +19542,98 @@ snapshots: '@expo/modules-macros-win32-arm64': 0.20.0 '@expo/modules-macros-win32-x64': 0.20.0 - expo-network@58.0.3(expo@58.0.11)(react@19.3.0): + expo-network@58.0.3(expo@58.0.14)(react@19.3.0): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react: 19.3.0 - expo-notifications@58.1.4(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2): + expo-notifications@58.1.5(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2): dependencies: '@expo/image-utils': 0.12.5(typescript@7.0.2) abort-controller: 3.0.0 badgin: 1.2.3 - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) - expo-application: 58.1.1(expo@58.0.11) - expo-constants: 58.0.12(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) + expo-application: 58.1.2(expo@58.0.14) + expo-constants: 58.0.12(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) transitivePeerDependencies: - supports-color - typescript - expo-paste-input@0.1.15(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): + expo-paste-input@0.1.15(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) - expo-quick-actions@6.0.2(expo@58.0.11)(typescript@7.0.2): + expo-quick-actions@6.0.2(expo@58.0.14)(typescript@7.0.2): dependencies: '@expo/image-utils': 0.8.14(typescript@7.0.2) - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) schema-utils: 4.3.3 sf-symbols-typescript: 2.2.0 transitivePeerDependencies: - supports-color - typescript - expo-secure-store@58.0.2(expo@58.0.11): + expo-secure-store@58.0.2(expo@58.0.14): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) - expo-sensors@58.0.4(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)): + expo-sensors@58.0.4(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) invariant: 2.2.4 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) expo-server@58.0.5: {} - expo-sharing@58.0.18(patch_hash=d0ca151b2a4eec8bb28df547c8663e4b803acd981ace492c6b401bcb279f524a)(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2): + expo-sharing@58.0.19(patch_hash=ad248759641ddd71b8331c09dbb3b18c8a551785f2df507533805babd3c0c124)(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2): dependencies: '@expo/config-plugins': 58.0.9(typescript@7.0.2) '@expo/config-types': 58.0.3 '@expo/plist': 0.10.1 - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) transitivePeerDependencies: - supports-color - typescript - expo-splash-screen@58.0.9(expo@58.0.11)(typescript@7.0.2): + expo-splash-screen@58.0.10(expo@58.0.14)(typescript@7.0.2): dependencies: '@expo/config-plugins': 58.0.9(typescript@7.0.2) '@expo/image-utils': 0.12.5(typescript@7.0.2) - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) xml2js: 0.6.0 transitivePeerDependencies: - supports-color - typescript - expo-sqlite@58.0.13(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): + expo-sqlite@58.0.13(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): dependencies: await-lock: 2.2.2 - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) expo-structured-headers@58.0.1: {} - expo-symbols@58.0.4(expo-font@58.0.8(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): + expo-symbols@58.0.4(expo-font@58.0.8(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): dependencies: '@expo-google-fonts/material-symbols': 0.4.38 - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) - expo-font: 58.0.8(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) + expo-font: 58.0.8(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) sf-symbols-typescript: 2.2.0 - expo-updates-interface@58.0.1(expo@58.0.11): + expo-updates-interface@58.0.1(expo@58.0.14): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) - expo-updates@58.0.17(expo-dev-client@58.0.13(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)))(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): + expo-updates@58.0.17(expo-dev-client@58.0.14(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)))(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): dependencies: '@expo/code-signing-certificates': 0.0.7 '@expo/env': 2.5.2 @@ -19668,11 +19643,11 @@ snapshots: arg: 4.1.3 chalk: 4.1.2 debug: 4.4.3 - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) expo-eas-client: 58.0.2 - expo-manifests: 58.0.1(expo@58.0.11) + expo-manifests: 58.0.1(expo@58.0.14) expo-structured-headers: 58.0.1 - expo-updates-interface: 58.0.1(expo@58.0.11) + expo-updates-interface: 58.0.1(expo@58.0.14) getenv: 2.0.0 glob: 13.0.6 ignore: 5.3.2 @@ -19681,26 +19656,26 @@ snapshots: react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) resolve-from: 5.0.0 optionalDependencies: - expo-dev-client: 58.0.13(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) + expo-dev-client: 58.0.14(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) transitivePeerDependencies: - supports-color - expo-video@58.0.11(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): + expo-video@58.0.11(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) - expo-web-browser@58.0.6(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)): + expo-web-browser@58.0.6(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)): dependencies: - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) - expo-widgets@58.0.18(patch_hash=40806e85c756563935c7368b93d679bd3bb7742bff21d9c7611d9161e1aee602)(@babel/core@7.29.7)(expo@58.0.11)(react-dom@19.3.0(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): + expo-widgets@58.0.20(patch_hash=8623cb034b720c5ef2da8012c765805a7298909bd92eaf8381f64dbde41b77dd)(@babel/core@7.29.7)(expo@58.0.14)(react-dom@19.3.0(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): dependencies: '@expo/plist': 0.10.1 - '@expo/ui': 58.0.18(patch_hash=5a26480373850c1a7943919aa21f904151b335a0cb01042109e0746def37923e)(@babel/core@7.29.7)(expo@58.0.11)(react-dom@19.3.0(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) - expo: 58.0.11(0279ba067f3e563cec3a046cc8b71592) + '@expo/ui': 58.0.20(patch_hash=5a26480373850c1a7943919aa21f904151b335a0cb01042109e0746def37923e)(@babel/core@7.29.7)(expo@58.0.14)(react-dom@19.3.0(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + expo: 58.0.14(1106b1d11fc0fad6d0556b6a93329d99) react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) transitivePeerDependencies: @@ -19708,36 +19683,36 @@ snapshots: - react-dom - react-native-worklets - expo@58.0.11(0279ba067f3e563cec3a046cc8b71592): + expo@58.0.14(1106b1d11fc0fad6d0556b6a93329d99): dependencies: '@babel/runtime': 7.29.7 - '@expo/cli': 58.1.9(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(bufferutil@4.1.0)(expo-constants@58.0.12(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2))(expo-font@58.0.8(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(expo@58.0.11)(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2)(utf-8-validate@6.0.6) + '@expo/cli': 58.1.11(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(bufferutil@4.1.0)(expo-constants@58.0.12(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2))(expo-font@58.0.8(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(expo@58.0.14)(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2)(utf-8-validate@6.0.6) '@expo/config': 58.0.6(typescript@7.0.2) '@expo/config-plugins': 58.0.9(typescript@7.0.2) - '@expo/devtools': 58.0.2(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) - '@expo/fingerprint': 0.21.5 + '@expo/devtools': 58.0.2(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + '@expo/fingerprint': 0.21.5(patch_hash=8fba80d6bbce46c72de427fe8c7907462d262a0bfe50c6b2b7ee9c4e0c61e5e1) '@expo/local-build-cache-provider': 58.0.6(typescript@7.0.2) - '@expo/log-box': 58.0.12(@expo/dom-webview@58.0.2)(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + '@expo/log-box': 58.0.12(@expo/dom-webview@58.0.2)(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) '@expo/log-box-utils': 58.0.2 '@expo/metro': 58.0.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) - '@expo/metro-config': 58.0.14(patch_hash=90fa980e8b6480631fb2fbb04559834e3c612db40c550cd828f11be297d8d760)(bufferutil@4.1.0)(expo@58.0.11)(typescript@7.0.2)(utf-8-validate@6.0.6) + '@expo/metro-config': 58.0.14(patch_hash=90fa980e8b6480631fb2fbb04559834e3c612db40c550cd828f11be297d8d760)(bufferutil@4.1.0)(expo@58.0.14)(typescript@7.0.2)(utf-8-validate@6.0.6) '@ungap/structured-clone': 1.3.1 - babel-preset-expo: 58.0.15(@babel/core@7.29.7)(@babel/runtime@7.29.7)(expo-widgets@58.0.18)(expo@58.0.11)(react-refresh@0.14.2) - expo-asset: 58.0.16(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) - expo-constants: 58.0.12(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2) - expo-file-system: 58.0.9(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) - expo-font: 58.0.8(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) - expo-keep-awake: 58.0.3(expo@58.0.11)(react@19.3.0) + babel-preset-expo: 58.0.17(@babel/core@7.29.7)(@babel/runtime@7.29.7)(expo-widgets@58.0.20)(expo@58.0.14)(react-refresh@0.14.2) + expo-asset: 58.0.16(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(typescript@7.0.2) + expo-constants: 58.0.12(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(typescript@7.0.2) + expo-file-system: 58.0.9(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6)) + expo-font: 58.0.8(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + expo-keep-awake: 58.0.3(expo@58.0.14)(react@19.3.0) expo-modules-autolinking: 58.0.13(typescript@7.0.2) - expo-modules-core: 58.0.19(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + expo-modules-core: 58.0.22(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) pretty-format: 29.7.0 react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) react-refresh: 0.14.2 whatwg-url-minimum: 0.2.0 optionalDependencies: - '@expo/dom-webview': 58.0.2(expo@58.0.11)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) - '@expo/metro-runtime': 58.0.14(@expo/log-box@58.0.12)(expo@58.0.11)(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + '@expo/dom-webview': 58.0.2(expo@58.0.14)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) + '@expo/metro-runtime': 58.0.14(@expo/log-box@58.0.12)(expo@58.0.14)(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) react-dom: 19.3.0(react@19.3.0) react-native-webview: 14.0.1(patch_hash=81caa279ec3dc1f81209062133b66e8f824e13f106cca57f1fa732a72c2ab378)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0) transitivePeerDependencies: @@ -19880,8 +19855,6 @@ snapshots: dependencies: to-regex-range: 5.0.1 - filter-obj@1.1.0: {} - finalhandler@1.1.2: dependencies: debug: 2.6.9 @@ -21516,7 +21489,7 @@ snapshots: node-mock-http@1.0.5: {} - node-pty@1.2.0-beta.15(patch_hash=f2fe901c61cde17986240002d05c172d5d0272d83ffaab8d0ebeb922763be414): + node-pty@1.2.0-beta.15(patch_hash=f1e680afec85f650699ea756f91f469844ec4c976f4f168492a45c6b3f67d651): dependencies: node-addon-api: 7.1.1 @@ -22253,13 +22226,6 @@ snapshots: es-define-property: 1.0.1 side-channel: 1.1.1 - query-string@7.1.3: - dependencies: - decode-uri-component: 0.2.2 - filter-obj: 1.1.0 - split-on-first: 1.1.0 - strict-uri-encode: 2.0.0 - quick-lru@5.1.1: {} radix3@1.1.2: {} @@ -22334,7 +22300,7 @@ snapshots: transitivePeerDependencies: - supports-color - react-native-enriched-markdown@file:apps/mobile/deps/react-native-enriched-markdown-1.2.0-t3.13.tgz(katex@0.16.47)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): + react-native-enriched-markdown@file:apps/mobile/deps/react-native-enriched-markdown-1.2.0-t3.15.tgz(katex@0.16.47)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0): dependencies: react: 19.3.0 react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) @@ -23104,8 +23070,6 @@ snapshots: memory-pager: 1.5.0 optional: true - split-on-first@1.1.0: {} - split2@4.2.0: optional: true @@ -23161,8 +23125,6 @@ snapshots: strict-event-emitter@0.5.1: optional: true - strict-uri-encode@2.0.0: {} - strictdom@1.0.1: {} string-width@4.2.3: @@ -23539,7 +23501,7 @@ snapshots: universalify@2.0.1: {} - uniwind@1.12.1(@expo/metro-config@58.0.14(patch_hash=90fa980e8b6480631fb2fbb04559834e3c612db40c550cd828f11be297d8d760)(bufferutil@4.1.0)(expo@58.0.11)(typescript@7.0.2)(utf-8-validate@6.0.6))(metro-cache@0.87.1)(metro-transform-worker@0.87.1(bufferutil@4.1.0)(utf-8-validate@6.0.6))(metro@0.87.1(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(tailwindcss@4.3.3): + uniwind@1.12.1(@expo/metro-config@58.0.14(patch_hash=90fa980e8b6480631fb2fbb04559834e3c612db40c550cd828f11be297d8d760)(bufferutil@4.1.0)(expo@58.0.14)(typescript@7.0.2)(utf-8-validate@6.0.6))(metro-cache@0.87.1)(metro-transform-worker@0.87.1(bufferutil@4.1.0)(utf-8-validate@6.0.6))(metro@0.87.1(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)(tailwindcss@4.3.3): dependencies: '@tailwindcss/node': 4.3.3 '@tailwindcss/oxide': 4.3.3 @@ -23551,7 +23513,7 @@ snapshots: react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6) tailwindcss: 4.3.3 optionalDependencies: - '@expo/metro-config': 58.0.14(patch_hash=90fa980e8b6480631fb2fbb04559834e3c612db40c550cd828f11be297d8d760)(bufferutil@4.1.0)(expo@58.0.11)(typescript@7.0.2)(utf-8-validate@6.0.6) + '@expo/metro-config': 58.0.14(patch_hash=90fa980e8b6480631fb2fbb04559834e3c612db40c550cd828f11be297d8d760)(bufferutil@4.1.0)(expo@58.0.14)(typescript@7.0.2)(utf-8-validate@6.0.6) metro-transform-worker: 0.87.1(bufferutil@4.1.0)(utf-8-validate@6.0.6) unpipe@1.0.0: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index ede421587dc7..caa31f9be55b 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -20,18 +20,18 @@ allowBuilds: node-pty: true # Ships N-API prebuilds; its install script only rebuilds from source. objc-js: false - "react-native-enriched-markdown@file:apps/mobile/deps/react-native-enriched-markdown-1.2.0-t3.13.tgz": true + "react-native-enriched-markdown@file:apps/mobile/deps/react-native-enriched-markdown-1.2.0-t3.15.tgz": true sharp: true tsc-rs: true utf-8-validate: false workerd: false catalog: - "@clerk/backend": 3.24.0 - "@clerk/clerk-js": 6.39.0 - "@clerk/electron": 0.1.0 + "@clerk/backend": 3.25.0 + "@clerk/clerk-js": 6.39.1 + "@clerk/electron": 0.1.1 "@clerk/electron-passkeys": 0.0.3 - "@clerk/expo": 4.12.0 + "@clerk/expo": 4.13.0 "@clerk/react": 6.17.8 "@clerk/shared": 4.40.0 "@effect/atom-react": 4.0.5 @@ -85,14 +85,14 @@ catalog: minimumReleaseAgeExclude: - tsc-rs - "@tsc-rs/*" - - expo-glass-effect@58.0.3 - - expo-blur@58.0.3 + - expo-glass-effect@58.0.4 + - expo-blur@58.0.4 - expo-audio@58.0.9 - - "@clerk/backend@3.24.0" - - "@clerk/clerk-js@6.39.0" - - "@clerk/electron@0.1.0" - - "@clerk/expo-native-components@0.1.1" - - "@clerk/expo@4.12.0" + - "@clerk/backend@3.25.0" + - "@clerk/clerk-js@6.39.1" + - "@clerk/electron@0.1.1" + - "@clerk/expo-native-components@0.2.0" + - "@clerk/expo@4.13.0" - "@clerk/react@6.17.8" - "@clerk/shared@4.40.0" - "@distilled.cloud/aws@1.0.0-rc.13" @@ -112,15 +112,15 @@ minimumReleaseAgeExclude: - alchemy@2.0.0-beta.80 - effect@4.0.5 - "@legendapp/list@3.3.5" - - "@expo/cli@58.1.1 || 58.1.9" + - "@expo/cli@58.1.1 || 58.1.9 || 58.1.11" - "@expo/env@2.5.1" - "@expo/fingerprint@0.21.2" - "@expo/metro-config@58.0.14" - expo-constants@58.0.12 - expo-font@58.0.8 - expo-updates@58.0.17 - - expo@58.0.11 - - expo-widgets@58.0.18 + - expo@58.0.14 + - expo-widgets@58.0.20 - "@expo/config-plugins@58.0.9" - "@expo/log-box@58.0.8" - "@expo/metro-file-map@58.0.3" @@ -128,22 +128,22 @@ minimumReleaseAgeExclude: - "@expo/metro@58.0.0-rc.0" - "@expo/prebuild-config@58.0.7 || 58.0.14" - "@expo/router-server@58.0.6 || 58.0.14" - - "@expo/ui@58.0.18" - - babel-preset-expo@58.0.15 + - "@expo/ui@58.0.20" + - babel-preset-expo@58.0.17 - expo-asset@58.0.16 - - expo-build-properties@58.0.10 - - expo-dev-client@58.0.13 - - expo-dev-launcher@58.0.10 + - expo-build-properties@58.0.11 + - expo-dev-client@58.0.14 + - expo-dev-launcher@58.0.10 || 58.0.14 - expo-dev-menu@58.0.10 - expo-image-manipulator@58.0.14 - expo-image-picker@58.0.10 - expo-image@58.0.15 - expo-linking@58.0.13 - expo-modules-autolinking@58.0.7 - - expo-modules-core@58.0.11 || 58.0.19 - - expo-modules-jsi@58.0.7 || 58.0.14 - - expo-notifications@58.1.4 - - expo-sharing@58.0.18 + - expo-modules-core@58.0.11 || 58.0.19 || 58.0.22 + - expo-modules-jsi@58.0.7 || 58.0.14 || 58.0.15 + - expo-notifications@58.1.5 + - expo-sharing@58.0.19 - expo-sqlite@58.0.13 - expo-symbols@58.0.4 - electron@44.4.5 @@ -160,18 +160,18 @@ minimumReleaseAgeExclude: - cn@0.3.2 - uniwind@1.12.1 - "@expo/dom-webview@58.0.2" - - "expo-auth-session@58.0.12" + - "expo-auth-session@58.0.13" - "expo-camera@58.0.10" - "expo-clipboard@58.0.3" - - "expo-crypto@58.0.6" + - "expo-crypto@58.0.7" - "expo-device@58.0.5" - "expo-document-picker@58.0.4" - "expo-file-system@58.0.9" - - "expo-haptics@58.0.6" + - "expo-haptics@58.0.7" - "expo-keep-awake@58.0.3" - "expo-network@58.0.3" - "expo-secure-store@58.0.2" - - "expo-splash-screen@58.0.9" + - "expo-splash-screen@58.0.10" - "expo-video@58.0.11" - "expo-web-browser@58.0.6" - "react@19.3.0" @@ -182,7 +182,7 @@ minimumReleaseAgeExclude: - "react-native-reanimated@4.7.1" - "react-native-screens@4.28.0" - "@expo/config-types@58.0.3" - - expo-application@58.0.3 + - expo-application@58.0.3 || 58.1.2 - expo-eas-client@58.0.2 - expo-image-loader@58.0.3 - "@distilled.cloud/acme@1.0.0-rc.13" @@ -210,12 +210,15 @@ minimumReleaseAgeExclude: - "@react-native/normalize-colors@0.88.0" - "@react-native/virtualized-lists@0.88.0" - react-native-svg@15.16.0 + - "@expo/schema-utils@58.0.2" overrides: # Keep jsdom's optional peer consistent so Vite+ has one test-runner instance. "@exodus/bytes>@noble/hashes": "1.8.0" # Earlier React Navigation declarations create a circular type alias in TypeScript 7. - "@react-navigation/core": 7.21.13 + # Move this with @react-navigation/native: an older core than it requires crashes + # every native stack at launch. + "@react-navigation/core": 7.24.0 # The dbus-next patch drops usocket from the package, but pnpm resolves from the # registry manifest, so the edge has to be cut here as well. "dbus-next>usocket": "-" @@ -308,14 +311,12 @@ packageExtensions: patchedDependencies: alchemy@2.0.0-beta.80: patches/alchemy@2.0.0-beta.80.patch - expo-glass-effect@58.0.3: patches/expo-glass-effect@58.0.3.patch - expo-blur@58.0.3: patches/expo-blur@58.0.3.patch expo-audio@58.0.9: patches/expo-audio@58.0.9.patch - "@clerk/expo-native-components@0.1.1": patches/@clerk__expo-native-components@0.1.1.patch + "@clerk/expo-native-components@0.2.0": patches/@clerk__expo-native-components@0.2.0.patch "@effect/vitest@4.0.5": patches/@effect__vitest@4.0.5.patch "@expo/metro-config@58.0.14": patches/@expo__metro-config@58.0.14.patch - expo-sharing@58.0.18: patches/expo-sharing@58.0.18.patch - expo-widgets@58.0.18: patches/expo-widgets@58.0.18.patch + expo-sharing@58.0.19: patches/expo-sharing@58.0.19.patch + expo-widgets@58.0.20: patches/expo-widgets@58.0.20.patch "@ff-labs/fff-node@0.11.0": patches/@ff-labs__fff-node@0.11.0.patch "@legendapp/list@3.3.5": patches/@legendapp__list@3.3.5.patch # Exports the dependency-light subpaths mobile and the web diff parser import, and keeps @@ -330,7 +331,10 @@ patchedDependencies: react-native-keyboard-controller@1.22.7: patches/react-native-keyboard-controller@1.22.7.patch # Android: a nested WebView hands a vertical drag to its scrolling parent at the page's edge. react-native-webview@14.0.1: patches/react-native-webview@14.0.1.patch - "@expo/ui@58.0.18": patches/@expo__ui@58.0.18.patch + "@expo/ui@58.0.20": patches/@expo__ui@58.0.20.patch + # Android: Maven-resolved gradle plugins (expo-widgets) have no sourceDir; without this + # skip, the fingerprint silently drops every Expo native module and OTAs reach stale binaries. + "@expo/fingerprint@0.21.5": patches/@expo__fingerprint@0.21.5.patch peerDependencyRules: allowAny: