@q9labsai/chalk-react-native 5.0.1 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/android/build.gradle +4 -1
  3. package/dist/android/call-service.d.ts +0 -1
  4. package/dist/android/connection-service.d.ts +0 -1
  5. package/dist/avatar/FaceAvatar.d.ts +0 -1
  6. package/dist/avatar/tile-avatar-size.d.ts +0 -1
  7. package/dist/callkit/callkit.d.ts +0 -1
  8. package/dist/callkit/resolve-space-callkit-options.d.ts +0 -1
  9. package/dist/{chunk-OIBT2FNM.js → chunk-MBZRE4US.js} +2 -3
  10. package/dist/client.d.ts +0 -1
  11. package/dist/client.js +8 -5
  12. package/dist/clipboard-store.d.ts +0 -1
  13. package/dist/clipboard.d.ts +0 -1
  14. package/dist/components/EmbeddedWhiteboard.d.ts +0 -1
  15. package/dist/components/RtcVideoView.d.ts +0 -1
  16. package/dist/components/android-connection-service-controller.d.ts +0 -1
  17. package/dist/components/native-media-visibility.d.ts +0 -1
  18. package/dist/components/native-space-callkit-controller.d.ts +0 -1
  19. package/dist/components/native-space-view/screen-share-availability.d.ts +0 -1
  20. package/dist/components/rtc-video-view-availability.d.ts +0 -1
  21. package/dist/components/space-lifecycle.d.ts +0 -1
  22. package/dist/components/useAndroidCallService.d.ts +0 -1
  23. package/dist/components/useAndroidConnectionService.d.ts +0 -1
  24. package/dist/context/space-client-context.d.ts +0 -1
  25. package/dist/dev.d.ts +0 -1
  26. package/dist/diagnostics.d.ts +0 -1
  27. package/dist/dock/Dock.d.ts +0 -1
  28. package/dist/dock/LeaveMenu.d.ts +0 -1
  29. package/dist/dock/MoreSheet.d.ts +0 -1
  30. package/dist/dock/ReactionBurst.d.ts +0 -1
  31. package/dist/dock/RoutePicker.d.ts +0 -1
  32. package/dist/dock/audio-route.d.ts +0 -1
  33. package/dist/frame/CallFrame.d.ts +0 -1
  34. package/dist/frame/Chalk.d.ts +0 -1
  35. package/dist/frame/back-handler.d.ts +0 -1
  36. package/dist/frame/dev-scenario.d.ts +0 -1
  37. package/dist/frame/device-layout.d.ts +0 -1
  38. package/dist/frame/measurement.d.ts +0 -1
  39. package/dist/frame/portal.d.ts +0 -1
  40. package/dist/frame/preferences.d.ts +0 -1
  41. package/dist/frame/regions.d.ts +0 -1
  42. package/dist/haptics/haptics.d.ts +0 -1
  43. package/dist/header/CallDetailsSheet.d.ts +0 -1
  44. package/dist/header/Header.d.ts +0 -1
  45. package/dist/header/QrCode.d.ts +0 -1
  46. package/dist/hooks/external-store.d.ts +0 -1
  47. package/dist/hooks/space-hooks.d.ts +0 -1
  48. package/dist/icons/Icon.d.ts +0 -1
  49. package/dist/icons/icon-element.d.ts +0 -1
  50. package/dist/icons/icon-paths.d.ts +0 -1
  51. package/dist/index.d.ts +0 -1
  52. package/dist/index.js +45 -17
  53. package/dist/invites.d.ts +0 -1
  54. package/dist/limbo/Limbo.d.ts +0 -1
  55. package/dist/limbo/Veil.d.ts +0 -1
  56. package/dist/media/native-capture-error.d.ts +0 -1
  57. package/dist/media/native-webrtc.d.ts +0 -1
  58. package/dist/motion/MovingFrame.d.ts +0 -1
  59. package/dist/motion/motion.d.ts +0 -1
  60. package/dist/motion/presence.d.ts +0 -1
  61. package/dist/motion/press.d.ts +0 -1
  62. package/dist/platform/platform.d.ts +0 -1
  63. package/dist/primitives/BottomSheet.d.ts +0 -1
  64. package/dist/primitives/ChalkText.d.ts +0 -1
  65. package/dist/primitives/CopyButton.d.ts +0 -1
  66. package/dist/primitives/IconButton.d.ts +0 -1
  67. package/dist/primitives/Menu.d.ts +0 -1
  68. package/dist/primitives/NameTag.d.ts +0 -1
  69. package/dist/primitives/PillButton.d.ts +0 -1
  70. package/dist/primitives/SegmentedControl.d.ts +0 -1
  71. package/dist/primitives/SheetGroup.d.ts +0 -1
  72. package/dist/primitives/Switch.d.ts +0 -1
  73. package/dist/primitives/TileShell.d.ts +0 -1
  74. package/dist/primitives/announce.d.ts +0 -1
  75. package/dist/primitives/menu-placement.d.ts +0 -1
  76. package/dist/primitives/toast/Toast.d.ts +0 -1
  77. package/dist/primitives/toast/ToastStack.d.ts +0 -1
  78. package/dist/primitives/toast/toast-store.d.ts +0 -1
  79. package/dist/runtime.d.ts +0 -1
  80. package/dist/sheets/people-chat/ChatNotices.d.ts +0 -1
  81. package/dist/sheets/people-chat/ChatTab.d.ts +0 -1
  82. package/dist/sheets/people-chat/Composer.d.ts +0 -1
  83. package/dist/sheets/people-chat/PeopleChatSheet.d.ts +0 -1
  84. package/dist/sheets/people-chat/PeopleTab.d.ts +0 -1
  85. package/dist/sheets/people-chat/PhotoViewer.d.ts +0 -1
  86. package/dist/sheets/people-chat/TextField.d.ts +0 -1
  87. package/dist/sheets/people-chat/attachments.d.ts +0 -1
  88. package/dist/sheets/people-chat/chat-model.d.ts +0 -1
  89. package/dist/sheets/people-chat/people-model.d.ts +0 -1
  90. package/dist/sounds/sounds.d.ts +0 -1
  91. package/dist/space-client/create-native-space-client.d.ts +0 -1
  92. package/dist/space-client/random-uuid.d.ts +0 -1
  93. package/dist/stage/ContentTile.d.ts +0 -1
  94. package/dist/stage/ParticipantTile.d.ts +0 -1
  95. package/dist/stage/Stage.d.ts +0 -1
  96. package/dist/stage/TileSheet.d.ts +0 -1
  97. package/dist/stage/camera.d.ts +0 -1
  98. package/dist/stage/layout.d.ts +0 -1
  99. package/dist/stage/space-selector.d.ts +0 -1
  100. package/dist/stage/stage-view.d.ts +0 -1
  101. package/dist/status/CallOverlays.d.ts +1 -2
  102. package/dist/status/ChalkArrival.d.ts +0 -1
  103. package/dist/status/StatusPage.d.ts +0 -1
  104. package/dist/status/call-screen.d.ts +0 -1
  105. package/dist/theme/theme.d.ts +0 -1
  106. package/dist/theme/tokens.d.ts +0 -1
  107. package/dist/toasts/CallEventToasts.d.ts +1 -2
  108. package/dist/toasts/media-failure-copy.d.ts +2 -0
  109. package/dist/toasts/notices.d.ts +0 -1
  110. package/dist/ui/ChalkUI.d.ts +0 -1
  111. package/dist/ui.d.ts +0 -1
  112. package/dist/ui.js +1 -1
  113. package/dist/utils/build-chalk-invite-link.d.ts +0 -1
  114. package/dist/utils/ios-simulator.d.ts +0 -1
  115. package/dist/whiteboard/embedded-whiteboard-assets.d.ts +0 -1
  116. package/dist/whiteboard/embedded-whiteboard-viewport.d.ts +0 -1
  117. package/embedded/chalk-whiteboard/asset-manifest.json +2 -2
  118. package/embedded/chalk-whiteboard/renderer.js +579 -579
  119. package/package.json +8 -4
  120. package/src/components/rtc-video-view-availability.ts +1 -1
  121. package/src/dock/Dock.tsx +4 -2
  122. package/src/dock/MoreSheet.tsx +3 -2
  123. package/src/frame/CallFrame.tsx +4 -4
  124. package/src/frame/device-layout.tsx +2 -3
  125. package/src/space-client/create-native-space-client.ts +8 -5
  126. package/src/stage/TileSheet.tsx +5 -1
  127. package/src/status/CallOverlays.tsx +18 -3
  128. package/src/toasts/CallEventToasts.tsx +16 -7
  129. package/src/toasts/media-failure-copy.ts +10 -0
  130. package/android/src/test/kotlin/ai/q9labs/chalk/compatibility/UnsafeSignatures.kt +0 -29
  131. package/dist/android/call-service.d.ts.map +0 -1
  132. package/dist/android/connection-service.d.ts.map +0 -1
  133. package/dist/avatar/FaceAvatar.d.ts.map +0 -1
  134. package/dist/avatar/tile-avatar-size.d.ts.map +0 -1
  135. package/dist/callkit/callkit.d.ts.map +0 -1
  136. package/dist/callkit/resolve-space-callkit-options.d.ts.map +0 -1
  137. package/dist/client.d.ts.map +0 -1
  138. package/dist/clipboard-store.d.ts.map +0 -1
  139. package/dist/clipboard.d.ts.map +0 -1
  140. package/dist/components/EmbeddedWhiteboard.d.ts.map +0 -1
  141. package/dist/components/RtcVideoView.d.ts.map +0 -1
  142. package/dist/components/android-connection-service-controller.d.ts.map +0 -1
  143. package/dist/components/native-media-visibility.d.ts.map +0 -1
  144. package/dist/components/native-space-callkit-controller.d.ts.map +0 -1
  145. package/dist/components/native-space-view/screen-share-availability.d.ts.map +0 -1
  146. package/dist/components/rtc-video-view-availability.d.ts.map +0 -1
  147. package/dist/components/space-lifecycle.d.ts.map +0 -1
  148. package/dist/components/useAndroidCallService.d.ts.map +0 -1
  149. package/dist/components/useAndroidConnectionService.d.ts.map +0 -1
  150. package/dist/context/space-client-context.d.ts.map +0 -1
  151. package/dist/dev.d.ts.map +0 -1
  152. package/dist/diagnostics.d.ts.map +0 -1
  153. package/dist/dock/Dock.d.ts.map +0 -1
  154. package/dist/dock/LeaveMenu.d.ts.map +0 -1
  155. package/dist/dock/MoreSheet.d.ts.map +0 -1
  156. package/dist/dock/ReactionBurst.d.ts.map +0 -1
  157. package/dist/dock/RoutePicker.d.ts.map +0 -1
  158. package/dist/dock/audio-route.d.ts.map +0 -1
  159. package/dist/frame/CallFrame.d.ts.map +0 -1
  160. package/dist/frame/Chalk.d.ts.map +0 -1
  161. package/dist/frame/back-handler.d.ts.map +0 -1
  162. package/dist/frame/dev-scenario.d.ts.map +0 -1
  163. package/dist/frame/device-layout.d.ts.map +0 -1
  164. package/dist/frame/measurement.d.ts.map +0 -1
  165. package/dist/frame/portal.d.ts.map +0 -1
  166. package/dist/frame/preferences.d.ts.map +0 -1
  167. package/dist/frame/regions.d.ts.map +0 -1
  168. package/dist/haptics/haptics.d.ts.map +0 -1
  169. package/dist/header/CallDetailsSheet.d.ts.map +0 -1
  170. package/dist/header/Header.d.ts.map +0 -1
  171. package/dist/header/QrCode.d.ts.map +0 -1
  172. package/dist/hooks/external-store.d.ts.map +0 -1
  173. package/dist/hooks/space-hooks.d.ts.map +0 -1
  174. package/dist/icons/Icon.d.ts.map +0 -1
  175. package/dist/icons/icon-element.d.ts.map +0 -1
  176. package/dist/icons/icon-paths.d.ts.map +0 -1
  177. package/dist/index.d.ts.map +0 -1
  178. package/dist/invites.d.ts.map +0 -1
  179. package/dist/limbo/Limbo.d.ts.map +0 -1
  180. package/dist/limbo/Veil.d.ts.map +0 -1
  181. package/dist/media/native-capture-error.d.ts.map +0 -1
  182. package/dist/media/native-webrtc.d.ts.map +0 -1
  183. package/dist/motion/MovingFrame.d.ts.map +0 -1
  184. package/dist/motion/motion.d.ts.map +0 -1
  185. package/dist/motion/presence.d.ts.map +0 -1
  186. package/dist/motion/press.d.ts.map +0 -1
  187. package/dist/platform/platform.d.ts.map +0 -1
  188. package/dist/primitives/BottomSheet.d.ts.map +0 -1
  189. package/dist/primitives/ChalkText.d.ts.map +0 -1
  190. package/dist/primitives/CopyButton.d.ts.map +0 -1
  191. package/dist/primitives/IconButton.d.ts.map +0 -1
  192. package/dist/primitives/Menu.d.ts.map +0 -1
  193. package/dist/primitives/NameTag.d.ts.map +0 -1
  194. package/dist/primitives/PillButton.d.ts.map +0 -1
  195. package/dist/primitives/SegmentedControl.d.ts.map +0 -1
  196. package/dist/primitives/SheetGroup.d.ts.map +0 -1
  197. package/dist/primitives/Switch.d.ts.map +0 -1
  198. package/dist/primitives/TileShell.d.ts.map +0 -1
  199. package/dist/primitives/announce.d.ts.map +0 -1
  200. package/dist/primitives/menu-placement.d.ts.map +0 -1
  201. package/dist/primitives/toast/Toast.d.ts.map +0 -1
  202. package/dist/primitives/toast/ToastStack.d.ts.map +0 -1
  203. package/dist/primitives/toast/toast-store.d.ts.map +0 -1
  204. package/dist/runtime.d.ts.map +0 -1
  205. package/dist/sheets/people-chat/ChatNotices.d.ts.map +0 -1
  206. package/dist/sheets/people-chat/ChatTab.d.ts.map +0 -1
  207. package/dist/sheets/people-chat/Composer.d.ts.map +0 -1
  208. package/dist/sheets/people-chat/PeopleChatSheet.d.ts.map +0 -1
  209. package/dist/sheets/people-chat/PeopleTab.d.ts.map +0 -1
  210. package/dist/sheets/people-chat/PhotoViewer.d.ts.map +0 -1
  211. package/dist/sheets/people-chat/TextField.d.ts.map +0 -1
  212. package/dist/sheets/people-chat/attachments.d.ts.map +0 -1
  213. package/dist/sheets/people-chat/chat-model.d.ts.map +0 -1
  214. package/dist/sheets/people-chat/people-model.d.ts.map +0 -1
  215. package/dist/sounds/sounds.d.ts.map +0 -1
  216. package/dist/space-client/create-native-space-client.d.ts.map +0 -1
  217. package/dist/space-client/random-uuid.d.ts.map +0 -1
  218. package/dist/stage/ContentTile.d.ts.map +0 -1
  219. package/dist/stage/ParticipantTile.d.ts.map +0 -1
  220. package/dist/stage/Stage.d.ts.map +0 -1
  221. package/dist/stage/TileSheet.d.ts.map +0 -1
  222. package/dist/stage/camera.d.ts.map +0 -1
  223. package/dist/stage/layout.d.ts.map +0 -1
  224. package/dist/stage/space-selector.d.ts.map +0 -1
  225. package/dist/stage/stage-view.d.ts.map +0 -1
  226. package/dist/status/CallOverlays.d.ts.map +0 -1
  227. package/dist/status/ChalkArrival.d.ts.map +0 -1
  228. package/dist/status/StatusPage.d.ts.map +0 -1
  229. package/dist/status/call-screen.d.ts.map +0 -1
  230. package/dist/theme/theme.d.ts.map +0 -1
  231. package/dist/theme/tokens.d.ts.map +0 -1
  232. package/dist/toasts/CallEventToasts.d.ts.map +0 -1
  233. package/dist/toasts/notices.d.ts.map +0 -1
  234. package/dist/ui/ChalkUI.d.ts.map +0 -1
  235. package/dist/ui.d.ts.map +0 -1
  236. package/dist/utils/build-chalk-invite-link.d.ts.map +0 -1
  237. package/dist/utils/ios-simulator.d.ts.map +0 -1
  238. package/dist/whiteboard/embedded-whiteboard-assets.d.ts.map +0 -1
  239. package/dist/whiteboard/embedded-whiteboard-viewport.d.ts.map +0 -1
  240. package/src/callkit/callkit.test.ts +0 -97
  241. package/src/components/native-space-view/screen-share-availability.test.ts +0 -16
  242. package/src/frame/regions.test.ts +0 -38
  243. package/src/media/native-capture-error.test.ts +0 -19
  244. package/src/primitives/menu-placement.test.ts +0 -50
  245. package/src/sheets/people-chat/people-chat-model.test.ts +0 -98
  246. package/src/space-client/whiteboard-watchdog.test.ts +0 -23
  247. package/src/stage/layout.test.ts +0 -77
  248. package/src/status/call-screen.test.ts +0 -42
  249. package/src/toasts/notices.test.ts +0 -92
  250. package/src/whiteboard/embedded-whiteboard-viewport.test.ts +0 -13
package/CHANGELOG.md ADDED
@@ -0,0 +1,25 @@
1
+ # Changelog
2
+
3
+ ## 5.1.0
4
+
5
+ - Bound each Sync and whiteboard WebSocket opening attempt to the existing 30-second startup allowance, or to `syncStartupTimeoutMs` when set. `syncStartupTimeoutMs` accepts 1 to 60,000 ms, and each attempt gets at least 10 seconds. The whiteboard retries a timed-out attempt through the existing reconnect backoff, and so does Sync once the call is live, such as after a drop or a return to the foreground. A first join does not retry a Sync socket that never opens: the join fails when its startup wait of `syncStartupTimeoutMs` ends, and a setting below 10 seconds ends the join before the attempt's own 10-second minimum. The client's 10-second default does not apply to React Native.
6
+ - Size the call from the enclosing safe-area frame instead of the global window size. Orientation and call-region arrangement now follow the space `Chalk` is given, so a call rendered inside a smaller container, split view or modal lays out for that container rather than the whole screen. Full-screen calls look the same.
7
+ - Render registered native WebRTC host components so remote screen shares and camera video no longer disappear when React Native exports the video view as a string.
8
+ - Disable reaction sending and media enable controls until Sync is live, and keep recovery notices non-blocking.
9
+ - Show plain connection-not-ready and confirmation-timeout media feedback without exposing raw internal exception messages.
10
+ - Run the Android module API compatibility check only in the Chalk repository, so an app's `./gradlew check` no longer needs Chalk's test fixtures or the API 30 platform.
11
+
12
+ ## 5.0.1
13
+
14
+ - Fix the Android 11 crash when joining a call by isolating API 31 audio listeners from React Native module signatures.
15
+
16
+ ## 5.0.0
17
+
18
+ - Rebuild `Chalk` with a call header, Spotlight and Grid layouts, a dock, People and Chat sheets, and status pages.
19
+ - Add `ChalkArrival`, light and dark color schemes, call sounds and haptics, and permission recovery callbacks.
20
+ - BREAKING: replace the old layout and theme exports with `ChalkProps`, `ColorScheme`, and `Palette`. Remove the `/appearance` and platform-specific entry points.
21
+ - BREAKING: call `onLeave` when the user chooses Home on the post-call page, not immediately after leaving.
22
+ - BREAKING: add Expo audio, haptics, clipboard, document picker, file system, and `expo-crypto` peers. Add Reanimated, Worklets, Gesture Handler, and Safe Area Context peers.
23
+ - Use the v5 client, whiteboard, and facehash packages.
24
+
25
+ See the [project changelog](../../../CHANGELOG.md) for the full export removals and migration details.
@@ -75,4 +75,7 @@ tasks.register("checkModuleApiCompatibility", JavaExec) {
75
75
  }
76
76
  }
77
77
 
78
- tasks.named("check").configure { dependsOn "checkModuleApiCompatibility" }
78
+ // The published package leaves out src/test and its fixtures, so only the Chalk repo runs this check.
79
+ if (file("src/test").isDirectory()) {
80
+ tasks.named("check").configure { dependsOn "checkModuleApiCompatibility" }
81
+ }
@@ -1,4 +1,3 @@
1
1
  /** Starts the Android foreground service for the call. Resolves false when there's nothing to keep running (no microphone or camera permission) or Android refused the start. */
2
2
  export declare function startAndroidCallService(): Promise<boolean>;
3
3
  export declare function stopAndroidCallService(): Promise<void>;
4
- //# sourceMappingURL=call-service.d.ts.map
@@ -23,4 +23,3 @@ export declare function setAndroidConnectionServiceActive(callId: string): Promi
23
23
  export declare function endAndroidConnectionServiceCall(callId: string, options?: AndroidConnectionServiceEndCallOptions): Promise<boolean>;
24
24
  export declare function addAndroidConnectionServiceListener(listener: (event: AndroidConnectionServiceEvent) => void): () => void;
25
25
  export {};
26
- //# sourceMappingURL=connection-service.d.ts.map
@@ -16,4 +16,3 @@ export type FaceAvatarProps = {
16
16
  * stops with reduced motion. Decorative: the parent names the person.
17
17
  */
18
18
  export declare const FaceAvatar: import("react").MemoExoticComponent<({ name, size, style, level, lookAround, testID }: FaceAvatarProps) => React.JSX.Element>;
19
- //# sourceMappingURL=FaceAvatar.d.ts.map
@@ -1,3 +1,2 @@
1
1
  /** A camera-off tile's avatar is 42 % of the tile's shorter side, between 32 and 150 pt. */
2
2
  export declare function tileAvatarSize(width: number, height: number): number;
3
- //# sourceMappingURL=tile-avatar-size.d.ts.map
@@ -58,4 +58,3 @@ export declare const callKit: {
58
58
  } | null>;
59
59
  updateCall(options: CallKitCallOptions): Promise<void>;
60
60
  };
61
- //# sourceMappingURL=callkit.d.ts.map
@@ -14,4 +14,3 @@ export declare function resolveSpaceCallKitOptions({ callKit, hasVideo, spaceId,
14
14
  spaceId: string;
15
15
  spaceName?: string;
16
16
  }): ResolvedSpaceCallKitOptions | null;
17
- //# sourceMappingURL=resolve-space-callkit-options.d.ts.map
@@ -4,8 +4,7 @@ import {
4
4
 
5
5
  // src/frame/device-layout.tsx
6
6
  import { createContext, useContext, useMemo } from "react";
7
- import { useWindowDimensions } from "react-native";
8
- import { useSafeAreaInsets } from "react-native-safe-area-context";
7
+ import { useSafeAreaFrame, useSafeAreaInsets } from "react-native-safe-area-context";
9
8
 
10
9
  // src/frame/regions.ts
11
10
  function arrangementFor(width, height) {
@@ -46,7 +45,7 @@ function frameRegions(arrangement, width, height, insets, cardOpen = false) {
46
45
  import { jsx } from "react/jsx-runtime";
47
46
  var DeviceLayoutContext = createContext(null);
48
47
  function DeviceLayoutProvider({ children }) {
49
- const { width, height } = useWindowDimensions();
48
+ const { width, height } = useSafeAreaFrame();
50
49
  const insets = useSafeAreaInsets();
51
50
  const value = useMemo(() => {
52
51
  const arrangement = arrangementFor(width, height);
package/dist/client.d.ts CHANGED
@@ -1,4 +1,3 @@
1
1
  /** Native client construction for applications that own the call lifecycle. */
2
2
  export { createNativeSpaceClient } from "./space-client/create-native-space-client";
3
3
  export type { NativeSpaceClientOptions } from "./space-client/create-native-space-client";
4
- //# sourceMappingURL=client.d.ts.map
package/dist/client.js CHANGED
@@ -39,6 +39,7 @@ function ensureRandomUUID() {
39
39
  function createNativeSpaceClient(options) {
40
40
  ensureRandomUUID();
41
41
  const { storage } = options;
42
+ const syncStartupTimeoutMs = options.syncStartupTimeoutMs ?? 3e4;
42
43
  const apiBaseURL = options.baseUrl ?? "https://api.chalkmeet.com";
43
44
  const syncURL = options.syncUrl ?? defaultSyncURL(apiBaseURL);
44
45
  const fetch = globalThis.fetch;
@@ -61,9 +62,9 @@ function createNativeSpaceClient(options) {
61
62
  getDisplayMedia: async () => await mediaDevices.getDisplayMedia()
62
63
  },
63
64
  createMediaClient: (input) => createMediaClient(apiBaseURL, input, fetch),
64
- createSyncClient: (input) => createSyncClient(syncURL, input, lifecycle, webSocket, storage),
65
+ createSyncClient: (input) => createSyncClient(syncURL, input, lifecycle, webSocket, storage, syncStartupTimeoutMs),
65
66
  createChatFileTransport: (input) => createChatFileTransport(apiBaseURL, input, fetch),
66
- createWhiteboardClient: options.whiteboardURL === null ? void 0 : (input) => createWhiteboardClient(apiBaseURL, options.whiteboardURL ?? whiteboardURL(syncURL), input, fetch, lifecycle, webSocket),
67
+ createWhiteboardClient: options.whiteboardURL === null ? void 0 : (input) => createWhiteboardClient(apiBaseURL, options.whiteboardURL ?? whiteboardURL(syncURL), input, fetch, lifecycle, webSocket, syncStartupTimeoutMs),
67
68
  subscribeForeground: (listener) => {
68
69
  const subscription = AppState.addEventListener("change", (state) => {
69
70
  if (state === "active") listener();
@@ -79,7 +80,7 @@ function createNativeSpaceClient(options) {
79
80
  whiteboardUrl: options.whiteboardURL,
80
81
  dependencies,
81
82
  fetch,
82
- syncStartupTimeoutMs: options.syncStartupTimeoutMs ?? 3e4,
83
+ syncStartupTimeoutMs,
83
84
  initialMicrophoneEnabled: options.microphone,
84
85
  initialCameraEnabled: options.camera
85
86
  }
@@ -135,7 +136,7 @@ function createSFUConnectionMediaClient(client) {
135
136
  subscribe: client.subscribe.bind(client)
136
137
  };
137
138
  }
138
- function createSyncClient(syncURL, input, lifecycle, webSocket, storage) {
139
+ function createSyncClient(syncURL, input, lifecycle, webSocket, storage, dialTimeoutMs) {
139
140
  const subject = input.access.subject;
140
141
  const scope = `${subject.tenantId}:${subject.episodeId}:${subject.participantId}`;
141
142
  return createV1SyncClient({
@@ -144,13 +145,14 @@ function createSyncClient(syncURL, input, lifecycle, webSocket, storage) {
144
145
  mediaPlane: input.media,
145
146
  lifecycle,
146
147
  webSocket,
148
+ dialTimeoutMs,
147
149
  ...storage ? { pendingStore: new AsyncStorageV1PendingTargetStore({ scope, storage }) } : {}
148
150
  });
149
151
  }
150
152
  function createChatFileTransport(apiBaseURL, input, fetch) {
151
153
  return createChalkChatFileHttpTransport({ baseUrl: apiBaseURL, token: input.token, fetch });
152
154
  }
153
- function createWhiteboardClient(apiBaseURL, url, input, fetch, lifecycle, webSocket) {
155
+ function createWhiteboardClient(apiBaseURL, url, input, fetch, lifecycle, webSocket, dialTimeoutMs) {
154
156
  const files = createChalkWhiteboardV1FileDownloadTransport({
155
157
  baseUrl: apiBaseURL,
156
158
  token: input.token,
@@ -162,6 +164,7 @@ function createWhiteboardClient(apiBaseURL, url, input, fetch, lifecycle, webSoc
162
164
  files,
163
165
  lifecycle,
164
166
  webSocket,
167
+ dialTimeoutMs,
165
168
  onWatchdogReplacement: input.onWatchdogReplacement,
166
169
  onSummary: (summary) => {
167
170
  input.onSummary(summary);
@@ -14,4 +14,3 @@ export interface ClipboardTextStore {
14
14
  subscribe(listener: () => void): () => void;
15
15
  }
16
16
  export declare function createClipboardTextStore({ clipboard, shouldReadClipboard, subscribeToAppState }: ClipboardTextStoreOptions): ClipboardTextStore;
17
- //# sourceMappingURL=clipboard-store.d.ts.map
@@ -7,4 +7,3 @@ export interface UseClipboardInviteSuggestionOptions {
7
7
  getSuggestion: (clipboardText: string | null | undefined, currentInput: string) => string | null;
8
8
  }
9
9
  export declare function useClipboardInviteSuggestion(currentInput: string, { clipboard, getSuggestion }: UseClipboardInviteSuggestionOptions): string | null;
10
- //# sourceMappingURL=clipboard.d.ts.map
@@ -43,4 +43,3 @@ export declare const embeddedWhiteboardWebViewSecurityPolicy: Readonly<{
43
43
  thirdPartyCookiesEnabled: false;
44
44
  }>;
45
45
  export declare function EmbeddedWhiteboard({ transport, journeyId, traceparent, tracestate, canDraw, canClear, theme: themeOverride, localParticipantColor, rendererURL: rendererURLOverride, style, testID, onMetric, onError, onUserExport }: EmbeddedWhiteboardProps): React.JSX.Element;
46
- //# sourceMappingURL=EmbeddedWhiteboard.d.ts.map
@@ -1,4 +1,3 @@
1
1
  import { type RtcVideoViewProps } from "./rtc-video-view-availability";
2
2
  export declare function hasRtcVideoView(): boolean;
3
3
  export declare function RtcVideoView(props: RtcVideoViewProps): React.JSX.Element | null;
4
- //# sourceMappingURL=RtcVideoView.d.ts.map
@@ -30,4 +30,3 @@ export declare class AndroidConnectionServiceController {
30
30
  readonly subscribe: (listener: () => void) => (() => void);
31
31
  readonly update: (input: AndroidConnectionServiceControllerInput) => void;
32
32
  }
33
- //# sourceMappingURL=android-connection-service-controller.d.ts.map
@@ -6,4 +6,3 @@ export declare function shouldRenderNativeMediaTrack({ participant, track, media
6
6
  track: MediaStreamTrack | NativeMediaStreamTrack | null | undefined;
7
7
  mediaKind?: "camera" | "screen-share";
8
8
  }): boolean;
9
- //# sourceMappingURL=native-media-visibility.d.ts.map
@@ -36,4 +36,3 @@ export declare class SpaceCallKitController {
36
36
  readonly endCall: () => Promise<void>;
37
37
  readonly stop: () => void;
38
38
  }
39
- //# sourceMappingURL=native-space-callkit-controller.d.ts.map
@@ -9,4 +9,3 @@ export declare function resolveNativeScreenShareAvailability({ featureEnabled, p
9
9
  simulator: boolean;
10
10
  captureAvailable: boolean;
11
11
  }): NativeScreenShareAvailability;
12
- //# sourceMappingURL=screen-share-availability.d.ts.map
@@ -10,4 +10,3 @@ export interface RtcVideoViewProps extends ViewProps {
10
10
  type RtcVideoViewComponent = ComponentType<RtcVideoViewProps>;
11
11
  export declare function canRenderRtcVideoView(component: unknown): component is RtcVideoViewComponent;
12
12
  export {};
13
- //# sourceMappingURL=rtc-video-view-availability.d.ts.map
@@ -1,3 +1,2 @@
1
1
  /** Lifecycle phases used by native operating-system call integrations. */
2
2
  export type SpaceLifecyclePhase = "entrance" | "joining" | "live" | "left";
3
- //# sourceMappingURL=space-lifecycle.d.ts.map
@@ -5,4 +5,3 @@
5
5
  * to the foreground, because Android can refuse a start made while the app is in the background.
6
6
  */
7
7
  export declare function useAndroidCallService(): void;
8
- //# sourceMappingURL=useAndroidCallService.d.ts.map
@@ -11,4 +11,3 @@ interface UseAndroidConnectionServiceOptions {
11
11
  }
12
12
  export declare function useAndroidConnectionService({ displayName, enabled, hasVideo, joinNonce, onDisconnectRequest, phase, spaceId, spaceName }: UseAndroidConnectionServiceOptions): void;
13
13
  export {};
14
- //# sourceMappingURL=useAndroidConnectionService.d.ts.map
@@ -6,4 +6,3 @@ export type ChalkProviderProps = {
6
6
  };
7
7
  export declare function ChalkProvider({ children, client }: ChalkProviderProps): React.JSX.Element;
8
8
  export declare function useSpaceClient(): SpaceClient;
9
- //# sourceMappingURL=space-client-context.d.ts.map
package/dist/dev.d.ts CHANGED
@@ -7,4 +7,3 @@ export type { DevScenario } from "./frame/dev-scenario";
7
7
  export type { AudioRoute, AudioRouteKind, AudioRoutes } from "./dock/audio-route";
8
8
  export { setMeasurementRegistry } from "./frame/measurement";
9
9
  export type { MeasuredFrame, Measurement, MeasurementRegistry } from "./frame/measurement";
10
- //# sourceMappingURL=dev.d.ts.map
@@ -47,4 +47,3 @@ export declare function recordDiagnosticsFailure(source: string, message: string
47
47
  export declare function clearDevDiagnosticsLogs(): void;
48
48
  export declare function resetDevDiagnosticsState(): void;
49
49
  export declare function buildDevDiagnosticsCopyText(): string;
50
- //# sourceMappingURL=diagnostics.d.ts.map
@@ -20,4 +20,3 @@ export type DockProps = {
20
20
  * More and Leave. Spread across the phone in portrait, centred with 14 pt gaps in landscape.
21
21
  */
22
22
  export declare const Dock: import("react").MemoExoticComponent<({ arrangement, microphoneOn, cameraOn, onToggleMicrophone, onToggleCamera, onOpenMore, onLeave, moreOpen, leaveOpen, moreRef, leaveRef }: DockProps) => import("react").JSX.Element>;
23
- //# sourceMappingURL=Dock.d.ts.map
@@ -9,4 +9,3 @@ export type LeaveMenuProps = {
9
9
  };
10
10
  /** A host's Leave button asks whether to leave alone or end the call for everyone. */
11
11
  export declare function LeaveMenu({ open, onClose, anchorRef, onLeave, onEnd }: LeaveMenuProps): React.JSX.Element | null;
12
- //# sourceMappingURL=LeaveMenu.d.ts.map
@@ -14,4 +14,3 @@ export type MoreSheetProps = {
14
14
  * Chat, People and the stage layout. Actions that change the call close the sheet; copying keeps it open.
15
15
  */
16
16
  export declare function MoreSheet({ open, onClose, onOpenPeople, onOpenChat, inviteLink, returnFocusRef }: MoreSheetProps): React.JSX.Element;
17
- //# sourceMappingURL=MoreSheet.d.ts.map
@@ -5,4 +5,3 @@
5
5
  export declare const ReactionBurst: import("react").MemoExoticComponent<({ participantId }: {
6
6
  readonly participantId: string;
7
7
  }) => React.JSX.Element | null>;
8
- //# sourceMappingURL=ReactionBurst.d.ts.map
@@ -13,4 +13,3 @@ export type RoutePickerProps = {
13
13
  * button on iOS, where the mockup draws the system route menu, and a sheet on Android.
14
14
  */
15
15
  export declare function RoutePicker({ open, onClose, onSelect, output, anchorRef }: RoutePickerProps): React.JSX.Element | null;
16
- //# sourceMappingURL=RoutePicker.d.ts.map
@@ -22,4 +22,3 @@ export declare function routeName(route: AudioRoute): string;
22
22
  * native build doesn't include the module yet, so the dock leaves the button out.
23
23
  */
24
24
  export declare function useAudioOutput(): AudioOutput | null;
25
- //# sourceMappingURL=audio-route.d.ts.map
@@ -14,4 +14,3 @@ export type CallFrameProps = {
14
14
  * arrangement. Each region lives in its own folder so the part lanes can work in parallel.
15
15
  */
16
16
  export declare function CallFrame({ displayName, callName, inviteLink, onLeave, onOpenSettings, onRejoin, resumedAfterSettings }: CallFrameProps): React.JSX.Element;
17
- //# sourceMappingURL=CallFrame.d.ts.map
@@ -37,4 +37,3 @@ export type ChalkProps = {
37
37
  * off, and draws everything inside the safe area in portrait, landscape and on iPad.
38
38
  */
39
39
  export declare function Chalk({ client, colorScheme, onColorSchemeChange, soundsEnabled, onSoundsEnabledChange, ...frame }: ChalkProps): React.JSX.Element;
40
- //# sourceMappingURL=Chalk.d.ts.map
@@ -3,4 +3,3 @@
3
3
  * first, so the sheet or menu opened last closes first.
4
4
  */
5
5
  export declare function useBackHandler(active: boolean, onBack: () => void): void;
6
- //# sourceMappingURL=back-handler.d.ts.map
@@ -25,4 +25,3 @@ export type DevScenario = {
25
25
  };
26
26
  export declare function setDevScenario(next: DevScenario | null): void;
27
27
  export declare function useDevScenario(): DevScenario;
28
- //# sourceMappingURL=dev-scenario.d.ts.map
@@ -13,4 +13,3 @@ export declare function DeviceLayoutProvider({ children }: {
13
13
  readonly children: ReactNode;
14
14
  }): React.JSX.Element;
15
15
  export declare function useDeviceLayout(): DeviceLayout;
16
- //# sourceMappingURL=device-layout.d.ts.map
@@ -25,4 +25,3 @@ export declare function setMeasurementRegistry(next: MeasurementRegistry | null)
25
25
  /** A ref for the host view that carries `testID`; attach it to that view. */
26
26
  export declare function useMeasuredRef<TNode extends MeasurableNode>(testID: string | undefined, style: StyleProp<ViewStyle | TextStyle>): RefObject<TNode | null>;
27
27
  export {};
28
- //# sourceMappingURL=measurement.d.ts.map
@@ -21,4 +21,3 @@ export declare function PortalHost({ layer }: {
21
21
  * read this count, not the entries, or each publish re-renders the portal and loops.
22
22
  */
23
23
  export declare function usePortalCount(layer: PortalLayer): number;
24
- //# sourceMappingURL=portal.d.ts.map
@@ -18,4 +18,3 @@ type ProviderProps = {
18
18
  export declare function PreferencesProvider({ colorScheme, onColorSchemeChange, soundsEnabled, onSoundsEnabledChange, children }: ProviderProps): React.JSX.Element;
19
19
  export declare function usePreferences(): CallPreferences;
20
20
  export {};
21
- //# sourceMappingURL=preferences.d.ts.map
@@ -22,4 +22,3 @@ export declare const STAGE_GAP = 8;
22
22
  * `cardOpen` is the iPad side card, which takes 352 pt from the stage.
23
23
  */
24
24
  export declare function frameRegions(arrangement: Arrangement, width: number, height: number, insets: EdgeInsets, cardOpen?: boolean): FrameRegions;
25
- //# sourceMappingURL=regions.d.ts.map
@@ -9,4 +9,3 @@ export declare const haptics: {
9
9
  readonly sheetDetent: () => void;
10
10
  };
11
11
  export type HapticMoment = keyof typeof haptics;
12
- //# sourceMappingURL=haptics.d.ts.map
@@ -15,4 +15,3 @@ export type CallDetailsSheetProps = {
15
15
  export declare function CallDetailsSheet({ open, onClose, callName, inviteLink, returnFocusRef }: CallDetailsSheetProps): React.JSX.Element;
16
16
  /** The link as people read it, `chalkmeet.com/q9-team`, without the scheme or the invite token. */
17
17
  export declare function displayLink(link: string): string;
18
- //# sourceMappingURL=CallDetailsSheet.d.ts.map
@@ -14,4 +14,3 @@ export type HeaderProps = {
14
14
  */
15
15
  export declare const Header: import("react").NamedExoticComponent<HeaderProps & import("react").RefAttributes<View>>;
16
16
  export declare function formatElapsed(milliseconds: number): string;
17
- //# sourceMappingURL=Header.d.ts.map
@@ -3,4 +3,3 @@ export declare const QrCode: import("react").MemoExoticComponent<({ value, size
3
3
  readonly value: string;
4
4
  readonly size: number;
5
5
  }) => React.JSX.Element>;
6
- //# sourceMappingURL=QrCode.d.ts.map
@@ -7,4 +7,3 @@ export interface ExternalStore<State> {
7
7
  subscribe: (listener: () => void) => () => void;
8
8
  }
9
9
  export declare function useManagerState<State>(manager: ExternalStateManager<State>): State;
10
- //# sourceMappingURL=external-store.d.ts.map
@@ -8,4 +8,3 @@ export declare function useReactions(): SpaceSnapshot["reactions"];
8
8
  export declare function useRecording(): SpaceSnapshot["recording"];
9
9
  export declare function useWhiteboard(): SpaceSnapshot["whiteboard"];
10
10
  export declare function useCan(capability: Capability): boolean;
11
- //# sourceMappingURL=space-hooks.d.ts.map
@@ -9,4 +9,3 @@ export type IconProps = {
9
9
  };
10
10
  /** One icon from the mockup's 24-unit, 1.75-stroke line set. Icons are decorative; label the control that holds them. */
11
11
  export declare const Icon: import("react").MemoExoticComponent<({ name, color, size, strokeWidth }: IconProps) => React.JSX.Element>;
12
- //# sourceMappingURL=Icon.d.ts.map
@@ -21,4 +21,3 @@ export type IconElement = (Stroke & {
21
21
  readonly r: number;
22
22
  });
23
23
  export {};
24
- //# sourceMappingURL=icon-element.d.ts.map
@@ -527,4 +527,3 @@ export declare const iconElements: {
527
527
  readonly d: "M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z";
528
528
  }];
529
529
  };
530
- //# sourceMappingURL=icon-paths.d.ts.map
package/dist/index.d.ts CHANGED
@@ -10,4 +10,3 @@ export { useCan, useChat, useConnection, useMedia, useParticipants, useReactions
10
10
  export { extractSpaceInviteFromLink, getClipboardInviteSuggestion, parseSpaceInviteLink } from "./invites";
11
11
  export type { SpaceInviteLink } from "./invites";
12
12
  export { buildChalkInviteLink } from "./utils/build-chalk-invite-link";
13
- //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -53,7 +53,7 @@ import {
53
53
  useTheme,
54
54
  useToasts,
55
55
  viewer
56
- } from "./chunk-OIBT2FNM.js";
56
+ } from "./chunk-MBZRE4US.js";
57
57
  import {
58
58
  useMeasuredRef
59
59
  } from "./chunk-GYVZSOGQ.js";
@@ -294,13 +294,14 @@ function RoutePicker({ open, onClose, onSelect, output, anchorRef }) {
294
294
  // src/dock/Dock.tsx
295
295
  import { Fragment, jsx as jsx4, jsxs } from "react/jsx-runtime";
296
296
  var Dock = memo(function Dock2({ arrangement, microphoneOn, cameraOn, onToggleMicrophone, onToggleCamera, onOpenMore, onLeave, moreOpen, leaveOpen, moreRef, leaveRef }) {
297
+ const live = useConnection().status === "live";
297
298
  const size = arrangement === "pad" ? 44 : 52;
298
299
  const dockStyle = [styles.dock, arrangement === "pad" ? styles.pad : arrangement === "landscape" ? styles.landscape : styles.portrait];
299
300
  const dockRef = useMeasuredRef("frame.dock", dockStyle);
300
301
  const output = useAudioOutput();
301
302
  return /* @__PURE__ */ jsxs(View, { accessibilityLabel: "Call controls", accessibilityRole: "toolbar", pointerEvents: "box-none", ref: dockRef, style: dockStyle, testID: "frame.dock", children: [
302
- /* @__PURE__ */ jsx4(IconButton, { accessibilityLabel: microphoneOn ? "Mute microphone" : "Unmute microphone", icon: microphoneOn ? "mic" : "micOff", off: !microphoneOn, onCanvas: true, onPress: onToggleMicrophone, size, testID: "dock.microphone" }),
303
- /* @__PURE__ */ jsx4(IconButton, { accessibilityLabel: cameraOn ? "Turn off camera" : "Turn on camera", icon: cameraOn ? "cam" : "camOff", off: !cameraOn, onCanvas: true, onPress: onToggleCamera, size, testID: "dock.camera" }),
303
+ /* @__PURE__ */ jsx4(IconButton, { accessibilityLabel: microphoneOn ? "Mute microphone" : "Unmute microphone", icon: microphoneOn ? "mic" : "micOff", off: !microphoneOn, disabled: !live && !microphoneOn, onCanvas: true, onPress: onToggleMicrophone, size, testID: "dock.microphone" }),
304
+ /* @__PURE__ */ jsx4(IconButton, { accessibilityLabel: cameraOn ? "Turn off camera" : "Turn on camera", icon: cameraOn ? "cam" : "camOff", off: !cameraOn, disabled: !live && !cameraOn, onCanvas: true, onPress: onToggleCamera, size, testID: "dock.camera" }),
304
305
  output ? /* @__PURE__ */ jsx4(AudioOutputButton, { captioned: arrangement === "portrait", output, size }) : null,
305
306
  /* @__PURE__ */ jsx4(IconButton, { accessibilityLabel: "More options", expanded: moreOpen, icon: "more", onCanvas: true, onPress: onOpenMore, ref: moreRef, size, testID: "dock.more" }),
306
307
  arrangement === "pad" ? /* @__PURE__ */ jsx4(View, { style: styles.gap }) : null,
@@ -406,7 +407,8 @@ function MoreSheet({ open, onClose, onOpenPeople, onOpenChat, inviteLink, return
406
407
  const toasts = useToasts();
407
408
  const { soundsEnabled } = usePreferences();
408
409
  const canRaiseHand = useCan("raiseHand");
409
- const canReact = useCan("sendReaction");
410
+ const live = useConnection().status === "live";
411
+ const canReact = useCan("sendReaction") && live;
410
412
  const fail = useCallback5((message2) => () => toasts.show({ kind: "error", dismissible: true, message: message2 }), [toasts]);
411
413
  const toggleHand = useCallback5(() => {
412
414
  onClose();
@@ -1913,7 +1915,7 @@ function createNativeMediaStream(track) {
1913
1915
 
1914
1916
  // src/components/rtc-video-view-availability.ts
1915
1917
  function canRenderRtcVideoView(component) {
1916
- return typeof component === "function" || typeof component === "object" && component !== null;
1918
+ return typeof component === "string" && component.length > 0 || typeof component === "function" || typeof component === "object" && component !== null;
1917
1919
  }
1918
1920
 
1919
1921
  // src/components/RtcVideoView.tsx
@@ -2365,7 +2367,11 @@ function TileSheet({ participantId, open, onClose }) {
2365
2367
  icon: "flip",
2366
2368
  label: `Switch to the ${person.back ? "front" : "back"} camera`,
2367
2369
  onPress: run(() => {
2368
- if (person.otherCamera) client.media.selectCamera(person.otherCamera).then(() => announce(`Switched to the ${person.back ? "front" : "back"} camera`), failed("Couldn't switch the camera."));
2370
+ const otherCamera2 = person.otherCamera;
2371
+ if (otherCamera2)
2372
+ client.media.selectCamera(otherCamera2).then(() => {
2373
+ announce(`Switched to the ${person.back ? "front" : "back"} camera`);
2374
+ }, failed("Couldn't switch the camera."));
2369
2375
  }),
2370
2376
  testID: "tile-sheet.flip"
2371
2377
  }
@@ -2564,6 +2570,10 @@ var styles19 = StyleSheet20.create({
2564
2570
  // src/status/CallOverlays.tsx
2565
2571
  import { jsx as jsx30, jsxs as jsxs21 } from "react/jsx-runtime";
2566
2572
  function CallOverlays({ screen, callName, rejoining, onHold, onRejoin, onHome }) {
2573
+ const { colors } = useTheme();
2574
+ const layout = useDeviceLayout();
2575
+ const { header } = frameRegions(layout.arrangement, layout.width, layout.height, layout.insets);
2576
+ const connection = useConnection();
2567
2577
  const recording2 = useRecording().current?.status === "recording";
2568
2578
  const queuedMessages = useChat().pendingSends.filter((send) => send.status === "queued").length;
2569
2579
  useBackHandler(screen.kind === "status", onHome);
@@ -2572,10 +2582,11 @@ function CallOverlays({ screen, callName, rejoining, onHold, onRejoin, onHome })
2572
2582
  useEffect17(() => {
2573
2583
  if (clearsNotices) clear();
2574
2584
  }, [clear, clearsNotices]);
2575
- const limbo = screen.kind === "joining" ? { kind: "joining", rejoining } : screen.kind === "reconnecting" ? { kind: "reconnecting", queuedMessages } : screen.kind === "call" && onHold ? { kind: "hold" } : null;
2585
+ const limbo = screen.kind === "joining" ? { kind: "joining", rejoining } : screen.kind === "call" && onHold ? { kind: "hold" } : null;
2576
2586
  const veil = limbo === null ? "none" : limbo.kind === "joining" ? "limbo" : "paused";
2577
2587
  return /* @__PURE__ */ jsxs21(View20, { pointerEvents: "box-none", style: StyleSheet21.absoluteFill, children: [
2578
2588
  /* @__PURE__ */ jsx30(Veil, { level: screen.kind === "status" ? "none" : veil }),
2589
+ screen.kind === "reconnecting" || screen.kind === "call" && connection.syncHealth === "degraded" ? /* @__PURE__ */ jsx30(View20, { pointerEvents: "none", style: { position: "absolute", top: header.y + header.height + 4, left: layout.insets.left + 16, right: layout.insets.right + 16, alignItems: "center" }, testID: "connection.notice", children: /* @__PURE__ */ jsx30(ChalkText, { accessibilityLiveRegion: "polite", variant: "caption", style: { backgroundColor: colors.surface, borderRadius: 12, paddingHorizontal: 12, paddingVertical: 6 }, children: screen.kind === "reconnecting" ? `Reconnecting\u2026${queuedMessages ? ` ${queuedMessages} messages waiting to send.` : ""}` : "Connection is slow" }) }) : null,
2579
2590
  limbo ? /* @__PURE__ */ jsx30(Limbo, { callName, recording: recording2, state: limbo }) : null,
2580
2591
  screen.kind === "status" ? /* @__PURE__ */ jsx30(StatusPage, { callName, onHome, onRejoin, outcome: screen.outcome }) : null
2581
2592
  ] });
@@ -2622,6 +2633,15 @@ import { SpaceClientError } from "@q9labsai/chalk-client";
2622
2633
  import { useCallback as useCallback14, useEffect as useEffect18, useRef as useRef12 } from "react";
2623
2634
  import { Linking as Linking2, Platform as Platform7 } from "react-native";
2624
2635
 
2636
+ // src/toasts/media-failure-copy.ts
2637
+ var MEDIA_FAILURE_DETAILS = {
2638
+ "connection.invalid_state": "Still connecting. Try again in a moment.",
2639
+ "media.timeout": "The call did not respond. Try again."
2640
+ };
2641
+ function mediaFailureMessage(permission, code) {
2642
+ return code && MEDIA_FAILURE_DETAILS[code] || `Couldn\u2019t turn on your ${permission}. Try again.`;
2643
+ }
2644
+
2625
2645
  // src/toasts/notices.ts
2626
2646
  function callNotices(previous, next, ownMicrophoneChange) {
2627
2647
  if (previous.connection.status !== "live" || next.connection.status !== "live") return [];
@@ -2689,7 +2709,7 @@ function useCallEventToasts({ onOpenSettings, resumedAfterSettings }) {
2689
2709
  ownMicrophoneChange.current = true;
2690
2710
  }, []);
2691
2711
  const reportMediaFailure = useCallback14(
2692
- (permission, cause, retry) => {
2712
+ function reportMediaFailure2(permission, cause, retry) {
2693
2713
  const code = cause instanceof SpaceClientError ? cause.code : null;
2694
2714
  const icon = permission === "microphone" ? "micOff" : "camOff";
2695
2715
  const leading = /* @__PURE__ */ jsx32(Icon, { color: latest.current.colors.dangerText, name: icon });
@@ -2729,15 +2749,21 @@ function useCallEventToasts({ onOpenSettings, resumedAfterSettings }) {
2729
2749
  label: "Try again",
2730
2750
  testID: "toast.try-again",
2731
2751
  onPress: () => {
2732
- toasts.dismiss(id);
2733
- retry();
2752
+ void retry().then(
2753
+ () => toasts.dismiss(id),
2754
+ (cause2) => {
2755
+ if (cause2 instanceof SpaceClientError && cause2.code === "connection.invalid_state") return;
2756
+ toasts.dismiss(id);
2757
+ reportMediaFailure2(permission, cause2, retry);
2758
+ }
2759
+ );
2734
2760
  }
2735
2761
  }
2736
2762
  ]
2737
2763
  });
2738
2764
  return;
2739
2765
  }
2740
- toasts.show({ kind: "error", leading, dismissible: true, wrap: true, message: cause instanceof Error ? `Couldn\u2019t turn on your ${permission}. ${cause.message}` : `Couldn\u2019t turn on your ${permission}.` });
2766
+ toasts.show({ kind: "error", leading, dismissible: true, wrap: true, message: mediaFailureMessage(permission, code) });
2741
2767
  },
2742
2768
  [onOpenSettings, toasts]
2743
2769
  );
@@ -2776,8 +2802,10 @@ function noticeToast(notice, { client, toasts, colors, dismiss }) {
2776
2802
  const who = request.actorDisplayName ? firstName2(request.actorDisplayName) : "The host";
2777
2803
  const unmute2 = request.kind === "unmute";
2778
2804
  const accept = () => {
2779
- dismiss();
2780
- client.media.acceptRequest(request.requestId).catch(() => toasts.show({ kind: "error", dismissible: true, message: unmute2 ? "Couldn\u2019t unmute you." : "Couldn\u2019t turn on your camera." }));
2805
+ void client.media.acceptRequest(request.requestId).then(dismiss, (cause) => {
2806
+ if (cause instanceof SpaceClientError && cause.code === "connection.invalid_state") return;
2807
+ toasts.show({ kind: "error", dismissible: true, message: unmute2 ? "Couldn\u2019t unmute you." : "Couldn\u2019t turn on your camera." });
2808
+ });
2781
2809
  };
2782
2810
  return {
2783
2811
  input: {
@@ -2838,14 +2866,14 @@ function CallFrame({ displayName, callName = "Call", inviteLink, onLeave, onOpen
2838
2866
  haptics.mute();
2839
2867
  playSound(microphoneOn ? "mute" : "unmute", soundsEnabled);
2840
2868
  if (microphoneOn) noteOwnMicrophoneChange();
2841
- const turnOn = () => client.media.setMicrophoneEnabled(true).catch((cause) => reportMediaFailure("microphone", cause, turnOn));
2869
+ const turnOn = () => client.media.setMicrophoneEnabled(true);
2842
2870
  if (microphoneOn) client.media.setMicrophoneEnabled(false).catch(() => toasts.show({ kind: "error", dismissible: true, message: "Couldn\u2019t mute your microphone." }));
2843
- else void turnOn();
2871
+ else void turnOn().catch((cause) => reportMediaFailure("microphone", cause, turnOn));
2844
2872
  }, [client, microphoneOn, noteOwnMicrophoneChange, reportMediaFailure, soundsEnabled, toasts]);
2845
2873
  const toggleCamera = useCallback15(() => {
2846
- const turnOn = () => client.media.setCameraEnabled(true).catch((cause) => reportMediaFailure("camera", cause, turnOn));
2874
+ const turnOn = () => client.media.setCameraEnabled(true);
2847
2875
  if (cameraOn) client.media.setCameraEnabled(false).catch(() => toasts.show({ kind: "error", dismissible: true, message: "Couldn\u2019t turn off your camera." }));
2848
- else void turnOn();
2876
+ else void turnOn().catch((cause) => reportMediaFailure("camera", cause, turnOn));
2849
2877
  }, [cameraOn, client, reportMediaFailure, toasts]);
2850
2878
  const exit = useCallback15(
2851
2879
  (how) => {
package/dist/invites.d.ts CHANGED
@@ -5,4 +5,3 @@ export type SpaceInviteLink = {
5
5
  export declare function parseSpaceInviteLink(input: string): SpaceInviteLink | null;
6
6
  export declare function extractSpaceInviteFromLink(input: string): SpaceInviteLink | null;
7
7
  export declare function getClipboardInviteSuggestion(clipboardText: string | null | undefined, currentInput?: string): string | null;
8
- //# sourceMappingURL=invites.d.ts.map
@@ -22,4 +22,3 @@ export type LimboProps = {
22
22
  };
23
23
  /** The limbo card (`.lmsg`) centred over the veiled call, with the mockup's copy for each state. */
24
24
  export declare function Limbo({ state, callName, recording }: LimboProps): React.JSX.Element;
25
- //# sourceMappingURL=Limbo.d.ts.map
@@ -7,4 +7,3 @@ export type VeilLevel = "none" | "limbo" | "paused";
7
7
  export declare function Veil({ level }: {
8
8
  readonly level: VeilLevel;
9
9
  }): React.JSX.Element;
10
- //# sourceMappingURL=Veil.d.ts.map
@@ -4,4 +4,3 @@
4
4
  * web, so the native adapter gives it that name and the call can offer Open Settings.
5
5
  */
6
6
  export declare function toNativeCaptureError(cause: unknown): unknown;
7
- //# sourceMappingURL=native-capture-error.d.ts.map
@@ -3,4 +3,3 @@ import type { MediaStream as NativeMediaStream, MediaStreamTrack as NativeMediaS
3
3
  export { MediaStream, RTCView, mediaDevices };
4
4
  export type { NativeMediaStream, NativeMediaStreamTrack };
5
5
  export declare function createNativeMediaStream(track: MediaStreamTrack | NativeMediaStreamTrack): NativeMediaStream;
6
- //# sourceMappingURL=native-webrtc.d.ts.map