@q9labsai/chalk-react-native 4.1.17 → 5.0.1
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.
- package/README.md +134 -29
- package/android/build.gradle +35 -0
- package/android/compatibility/ModuleApiCompatibility.java +215 -0
- package/android/src/main/AndroidManifest.xml +2 -1
- package/android/src/main/java/ai/q9labs/chalk/reactnative/ChalkSpaceForegroundService.java +105 -31
- package/android/src/main/kotlin/ai/q9labs/chalk/reactnative/ChalkAndroidConnectionServicePackage.kt +2 -0
- package/android/src/main/kotlin/ai/q9labs/chalk/reactnative/ChalkAudioRouteModule.kt +137 -0
- package/android/src/main/kotlin/ai/q9labs/chalk/reactnative/ChalkCallServiceModule.kt +32 -0
- package/android/src/main/kotlin/ai/q9labs/chalk/reactnative/CommunicationDeviceListener.kt +23 -0
- package/android/src/test/kotlin/ai/q9labs/chalk/compatibility/UnsafeSignatures.kt +29 -0
- package/dist/android/call-service.d.ts +4 -0
- package/dist/android/call-service.d.ts.map +1 -0
- package/dist/avatar/FaceAvatar.d.ts +19 -0
- package/dist/avatar/FaceAvatar.d.ts.map +1 -0
- package/dist/avatar/tile-avatar-size.d.ts +3 -0
- package/dist/avatar/tile-avatar-size.d.ts.map +1 -0
- package/dist/chunk-GYVZSOGQ.js +30 -0
- package/dist/chunk-IHE6EA3T.js +25 -0
- package/dist/chunk-OIBT2FNM.js +1479 -0
- package/dist/client.d.ts +1 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +185 -2
- package/dist/components/EmbeddedWhiteboard.d.ts.map +1 -1
- package/dist/components/native-media-visibility.d.ts +3 -2
- package/dist/components/native-media-visibility.d.ts.map +1 -1
- package/dist/components/useAndroidCallService.d.ts +8 -0
- package/dist/components/useAndroidCallService.d.ts.map +1 -0
- package/dist/dev.d.ts +10 -0
- package/dist/dev.d.ts.map +1 -0
- package/dist/dev.js +10 -0
- package/dist/dock/Dock.d.ts +23 -0
- package/dist/dock/Dock.d.ts.map +1 -0
- package/dist/dock/LeaveMenu.d.ts +12 -0
- package/dist/dock/LeaveMenu.d.ts.map +1 -0
- package/dist/dock/MoreSheet.d.ts +17 -0
- package/dist/dock/MoreSheet.d.ts.map +1 -0
- package/dist/dock/ReactionBurst.d.ts +8 -0
- package/dist/dock/ReactionBurst.d.ts.map +1 -0
- package/dist/dock/RoutePicker.d.ts +16 -0
- package/dist/dock/RoutePicker.d.ts.map +1 -0
- package/dist/dock/audio-route.d.ts +25 -0
- package/dist/dock/audio-route.d.ts.map +1 -0
- package/dist/error-YOPTEH5N.wav +0 -0
- package/dist/frame/CallFrame.d.ts +17 -0
- package/dist/frame/CallFrame.d.ts.map +1 -0
- package/dist/frame/Chalk.d.ts +40 -0
- package/dist/frame/Chalk.d.ts.map +1 -0
- package/dist/frame/back-handler.d.ts +6 -0
- package/dist/frame/back-handler.d.ts.map +1 -0
- package/dist/frame/dev-scenario.d.ts +28 -0
- package/dist/frame/dev-scenario.d.ts.map +1 -0
- package/dist/frame/device-layout.d.ts +16 -0
- package/dist/frame/device-layout.d.ts.map +1 -0
- package/dist/frame/measurement.d.ts +28 -0
- package/dist/frame/measurement.d.ts.map +1 -0
- package/dist/frame/portal.d.ts +24 -0
- package/dist/frame/portal.d.ts.map +1 -0
- package/dist/frame/preferences.d.ts +21 -0
- package/dist/frame/preferences.d.ts.map +1 -0
- package/dist/frame/regions.d.ts +25 -0
- package/dist/frame/regions.d.ts.map +1 -0
- package/dist/hand-DFWVXPH2.wav +0 -0
- package/dist/haptics/haptics.d.ts +12 -0
- package/dist/haptics/haptics.d.ts.map +1 -0
- package/dist/header/CallDetailsSheet.d.ts +18 -0
- package/dist/header/CallDetailsSheet.d.ts.map +1 -0
- package/dist/header/Header.d.ts +17 -0
- package/dist/header/Header.d.ts.map +1 -0
- package/dist/header/QrCode.d.ts +6 -0
- package/dist/header/QrCode.d.ts.map +1 -0
- package/dist/icons/Icon.d.ts +12 -0
- package/dist/icons/Icon.d.ts.map +1 -0
- package/dist/icons/icon-element.d.ts +24 -0
- package/dist/icons/icon-element.d.ts.map +1 -0
- package/dist/icons/icon-paths.d.ts +530 -0
- package/dist/icons/icon-paths.d.ts.map +1 -0
- package/dist/index.d.ts +6 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2956 -38
- package/dist/join-Z6RL5AHE.wav +0 -0
- package/dist/knock-4VBQSHK4.wav +0 -0
- package/dist/leave-MQLZOWQD.wav +0 -0
- package/dist/limbo/Limbo.d.ts +25 -0
- package/dist/limbo/Limbo.d.ts.map +1 -0
- package/dist/limbo/Veil.d.ts +10 -0
- package/dist/limbo/Veil.d.ts.map +1 -0
- package/dist/media/native-capture-error.d.ts +7 -0
- package/dist/media/native-capture-error.d.ts.map +1 -0
- package/dist/message-6Y6WJGTB.wav +0 -0
- package/dist/motion/MovingFrame.d.ts +36 -0
- package/dist/motion/MovingFrame.d.ts.map +1 -0
- package/dist/motion/motion.d.ts +82 -0
- package/dist/motion/motion.d.ts.map +1 -0
- package/dist/motion/presence.d.ts +6 -0
- package/dist/motion/presence.d.ts.map +1 -0
- package/dist/motion/press.d.ts +15 -0
- package/dist/motion/press.d.ts.map +1 -0
- package/dist/mute-H5SJFXVI.wav +0 -0
- package/dist/primitives/BottomSheet.d.ts +36 -0
- package/dist/primitives/BottomSheet.d.ts.map +1 -0
- package/dist/primitives/ChalkText.d.ts +13 -0
- package/dist/primitives/ChalkText.d.ts.map +1 -0
- package/dist/primitives/CopyButton.d.ts +11 -0
- package/dist/primitives/CopyButton.d.ts.map +1 -0
- package/dist/primitives/IconButton.d.ts +26 -0
- package/dist/primitives/IconButton.d.ts.map +1 -0
- package/dist/primitives/Menu.d.ts +39 -0
- package/dist/primitives/Menu.d.ts.map +1 -0
- package/dist/primitives/NameTag.d.ts +19 -0
- package/dist/primitives/NameTag.d.ts.map +1 -0
- package/dist/primitives/PillButton.d.ts +19 -0
- package/dist/primitives/PillButton.d.ts.map +1 -0
- package/dist/primitives/SegmentedControl.d.ts +17 -0
- package/dist/primitives/SegmentedControl.d.ts.map +1 -0
- package/dist/primitives/SheetGroup.d.ts +24 -0
- package/dist/primitives/SheetGroup.d.ts.map +1 -0
- package/dist/primitives/Switch.d.ts +9 -0
- package/dist/primitives/Switch.d.ts.map +1 -0
- package/dist/primitives/TileShell.d.ts +18 -0
- package/dist/primitives/TileShell.d.ts.map +1 -0
- package/dist/primitives/announce.d.ts +3 -0
- package/dist/primitives/announce.d.ts.map +1 -0
- package/dist/primitives/menu-placement.d.ts +32 -0
- package/dist/primitives/menu-placement.d.ts.map +1 -0
- package/dist/primitives/toast/Toast.d.ts +8 -0
- package/dist/primitives/toast/Toast.d.ts.map +1 -0
- package/dist/primitives/toast/ToastStack.d.ts +18 -0
- package/dist/primitives/toast/ToastStack.d.ts.map +1 -0
- package/dist/primitives/toast/toast-store.d.ts +39 -0
- package/dist/primitives/toast/toast-store.d.ts.map +1 -0
- package/dist/recording-Q4GB77Y4.wav +0 -0
- package/dist/sheets/people-chat/ChatNotices.d.ts +14 -0
- package/dist/sheets/people-chat/ChatNotices.d.ts.map +1 -0
- package/dist/sheets/people-chat/ChatTab.d.ts +6 -0
- package/dist/sheets/people-chat/ChatTab.d.ts.map +1 -0
- package/dist/sheets/people-chat/Composer.d.ts +7 -0
- package/dist/sheets/people-chat/Composer.d.ts.map +1 -0
- package/dist/sheets/people-chat/PeopleChatSheet.d.ts +17 -0
- package/dist/sheets/people-chat/PeopleChatSheet.d.ts.map +1 -0
- package/dist/sheets/people-chat/PeopleTab.d.ts +3 -0
- package/dist/sheets/people-chat/PeopleTab.d.ts.map +1 -0
- package/dist/sheets/people-chat/PhotoViewer.d.ts +19 -0
- package/dist/sheets/people-chat/PhotoViewer.d.ts.map +1 -0
- package/dist/sheets/people-chat/TextField.d.ts +4 -0
- package/dist/sheets/people-chat/TextField.d.ts.map +1 -0
- package/dist/sheets/people-chat/attachments.d.ts +33 -0
- package/dist/sheets/people-chat/attachments.d.ts.map +1 -0
- package/dist/sheets/people-chat/chat-model.d.ts +64 -0
- package/dist/sheets/people-chat/chat-model.d.ts.map +1 -0
- package/dist/sheets/people-chat/people-model.d.ts +43 -0
- package/dist/sheets/people-chat/people-model.d.ts.map +1 -0
- package/dist/sounds/sounds.d.ts +33 -0
- package/dist/sounds/sounds.d.ts.map +1 -0
- package/dist/space-client/create-native-space-client.d.ts +0 -4
- package/dist/space-client/create-native-space-client.d.ts.map +1 -1
- package/dist/space-client/random-uuid.d.ts +7 -0
- package/dist/space-client/random-uuid.d.ts.map +1 -0
- package/dist/stage/ContentTile.d.ts +18 -0
- package/dist/stage/ContentTile.d.ts.map +1 -0
- package/dist/stage/ParticipantTile.d.ts +18 -0
- package/dist/stage/ParticipantTile.d.ts.map +1 -0
- package/dist/stage/Stage.d.ts +14 -0
- package/dist/stage/Stage.d.ts.map +1 -0
- package/dist/stage/TileSheet.d.ts +12 -0
- package/dist/stage/TileSheet.d.ts.map +1 -0
- package/dist/stage/camera.d.ts +7 -0
- package/dist/stage/camera.d.ts.map +1 -0
- package/dist/stage/layout.d.ts +57 -0
- package/dist/stage/layout.d.ts.map +1 -0
- package/dist/stage/space-selector.d.ts +10 -0
- package/dist/stage/space-selector.d.ts.map +1 -0
- package/dist/stage/stage-view.d.ts +23 -0
- package/dist/stage/stage-view.d.ts.map +1 -0
- package/dist/status/CallOverlays.d.ts +17 -0
- package/dist/status/CallOverlays.d.ts.map +1 -0
- package/dist/status/ChalkArrival.d.ts +24 -0
- package/dist/status/ChalkArrival.d.ts.map +1 -0
- package/dist/status/StatusPage.d.ts +14 -0
- package/dist/status/StatusPage.d.ts.map +1 -0
- package/dist/status/call-screen.d.ts +20 -0
- package/dist/status/call-screen.d.ts.map +1 -0
- package/dist/test-VD2KAM4D.wav +0 -0
- package/dist/theme/theme.d.ts +15 -0
- package/dist/theme/theme.d.ts.map +1 -0
- package/dist/theme/tokens.d.ts +248 -0
- package/dist/theme/tokens.d.ts.map +1 -0
- package/dist/toasts/CallEventToasts.d.ts +21 -0
- package/dist/toasts/CallEventToasts.d.ts.map +1 -0
- package/dist/toasts/notices.d.ts +34 -0
- package/dist/toasts/notices.d.ts.map +1 -0
- package/dist/ui/ChalkUI.d.ts +12 -0
- package/dist/ui/ChalkUI.d.ts.map +1 -0
- package/dist/ui.d.ts +25 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +77 -0
- package/dist/unmute-2XR2LICU.wav +0 -0
- package/embedded/chalk-whiteboard/asset-manifest.json +2 -2
- package/embedded/chalk-whiteboard/renderer.js +510 -510
- package/ios/ChalkAudioRouteModule.swift +93 -0
- package/ios/ChalkAudioRouteModuleBridge.m +9 -0
- package/package.json +46 -76
- package/src/android/call-service.ts +19 -0
- package/src/avatar/FaceAvatar.tsx +145 -0
- package/src/avatar/tile-avatar-size.ts +4 -0
- package/src/client.ts +1 -5
- package/src/components/EmbeddedWhiteboard.tsx +14 -71
- package/src/components/native-media-visibility.ts +1 -2
- package/src/components/useAndroidCallService.ts +41 -0
- package/src/dev.ts +9 -0
- package/src/dock/Dock.tsx +95 -0
- package/src/dock/LeaveMenu.tsx +21 -0
- package/src/dock/MoreSheet.tsx +233 -0
- package/src/dock/ReactionBurst.tsx +55 -0
- package/src/dock/RoutePicker.tsx +42 -0
- package/src/dock/audio-route.ts +69 -0
- package/src/frame/CallFrame.tsx +209 -0
- package/src/frame/Chalk.tsx +83 -0
- package/src/frame/back-handler.ts +19 -0
- package/src/frame/dev-scenario.ts +48 -0
- package/src/frame/device-layout.tsx +31 -0
- package/src/frame/measurement.ts +44 -0
- package/src/frame/portal.tsx +107 -0
- package/src/frame/preferences.tsx +48 -0
- package/src/frame/regions.test.ts +38 -0
- package/src/frame/regions.ts +60 -0
- package/src/haptics/haptics.ts +19 -0
- package/src/header/CallDetailsSheet.tsx +139 -0
- package/src/header/Header.tsx +107 -0
- package/src/header/QrCode.tsx +34 -0
- package/src/icons/Icon.tsx +35 -0
- package/src/icons/icon-element.ts +11 -0
- package/src/icons/icon-paths.ts +199 -0
- package/src/index.ts +6 -9
- package/src/limbo/Limbo.tsx +159 -0
- package/src/limbo/Veil.tsx +36 -0
- package/src/media/native-capture-error.test.ts +19 -0
- package/src/media/native-capture-error.ts +13 -0
- package/src/motion/MovingFrame.tsx +101 -0
- package/src/motion/motion.ts +33 -0
- package/src/motion/presence.ts +20 -0
- package/src/motion/press.ts +35 -0
- package/src/primitives/BottomSheet.tsx +211 -0
- package/src/primitives/ChalkText.tsx +23 -0
- package/src/primitives/CopyButton.tsx +78 -0
- package/src/primitives/IconButton.tsx +90 -0
- package/src/primitives/Menu.tsx +212 -0
- package/src/primitives/NameTag.tsx +68 -0
- package/src/primitives/PillButton.tsx +56 -0
- package/src/primitives/SegmentedControl.tsx +55 -0
- package/src/primitives/SheetGroup.tsx +72 -0
- package/src/primitives/Switch.tsx +39 -0
- package/src/primitives/TileShell.tsx +53 -0
- package/src/primitives/announce.ts +7 -0
- package/src/primitives/menu-placement.test.ts +50 -0
- package/src/primitives/menu-placement.ts +43 -0
- package/src/primitives/toast/Toast.tsx +50 -0
- package/src/primitives/toast/ToastStack.tsx +89 -0
- package/src/primitives/toast/toast-store.ts +86 -0
- package/src/sheets/people-chat/ChatNotices.tsx +69 -0
- package/src/sheets/people-chat/ChatTab.tsx +186 -0
- package/src/sheets/people-chat/Composer.tsx +182 -0
- package/src/sheets/people-chat/PeopleChatSheet.tsx +100 -0
- package/src/sheets/people-chat/PeopleTab.tsx +326 -0
- package/src/sheets/people-chat/PhotoViewer.tsx +132 -0
- package/src/sheets/people-chat/TextField.tsx +14 -0
- package/src/sheets/people-chat/attachments.tsx +183 -0
- package/src/sheets/people-chat/chat-model.ts +157 -0
- package/src/sheets/people-chat/people-chat-model.test.ts +98 -0
- package/src/sheets/people-chat/people-model.ts +68 -0
- package/src/sounds/assets/error.wav +0 -0
- package/src/sounds/assets/hand.wav +0 -0
- package/src/sounds/assets/join.wav +0 -0
- package/src/sounds/assets/knock.wav +0 -0
- package/src/sounds/assets/leave.wav +0 -0
- package/src/sounds/assets/message.wav +0 -0
- package/src/sounds/assets/mute.wav +0 -0
- package/src/sounds/assets/recording.wav +0 -0
- package/src/sounds/assets/test.wav +0 -0
- package/src/sounds/assets/unmute.wav +0 -0
- package/src/sounds/assets.d.ts +5 -0
- package/src/sounds/sounds.ts +50 -0
- package/src/space-client/create-native-space-client.ts +20 -181
- package/src/space-client/random-uuid.ts +17 -0
- package/src/space-client/whiteboard-watchdog.test.ts +23 -0
- package/src/stage/ContentTile.tsx +100 -0
- package/src/stage/ParticipantTile.tsx +140 -0
- package/src/stage/Stage.tsx +152 -0
- package/src/stage/TileSheet.tsx +116 -0
- package/src/stage/camera.ts +20 -0
- package/src/stage/layout.test.ts +77 -0
- package/src/stage/layout.ts +226 -0
- package/src/stage/space-selector.ts +31 -0
- package/src/stage/stage-view.tsx +68 -0
- package/src/status/CallOverlays.tsx +47 -0
- package/src/status/ChalkArrival.tsx +53 -0
- package/src/status/StatusPage.tsx +123 -0
- package/src/status/call-screen.test.ts +42 -0
- package/src/status/call-screen.ts +29 -0
- package/src/theme/theme.tsx +28 -0
- package/src/theme/tokens.ts +247 -0
- package/src/toasts/CallEventToasts.tsx +192 -0
- package/src/toasts/notices.test.ts +92 -0
- package/src/toasts/notices.ts +62 -0
- package/src/ui/ChalkUI.tsx +49 -0
- package/src/ui.ts +24 -0
- package/dist/android.d.ts +0 -2
- package/dist/android.d.ts.map +0 -1
- package/dist/android.js +0 -62
- package/dist/chunk-2OS7SSXE.js +0 -552
- package/dist/chunk-5DQ4KBRH.js +0 -690
- package/dist/chunk-ITLUHTVS.js +0 -5271
- package/dist/chunk-JB4LNWVP.js +0 -247
- package/dist/components/Chalk.d.ts +0 -79
- package/dist/components/Chalk.d.ts.map +0 -1
- package/dist/components/ChatMessageList.d.ts +0 -11
- package/dist/components/ChatMessageList.d.ts.map +0 -1
- package/dist/components/Entrance.d.ts +0 -22
- package/dist/components/Entrance.d.ts.map +0 -1
- package/dist/components/EntranceView.android.d.ts +0 -4
- package/dist/components/EntranceView.android.d.ts.map +0 -1
- package/dist/components/EntranceView.d.ts +0 -18
- package/dist/components/EntranceView.d.ts.map +0 -1
- package/dist/components/EntranceView.ios-pad.d.ts +0 -3
- package/dist/components/EntranceView.ios-pad.d.ts.map +0 -1
- package/dist/components/EntranceView.ios-phone.d.ts +0 -3
- package/dist/components/EntranceView.ios-phone.d.ts.map +0 -1
- package/dist/components/EntranceView.macos.d.ts +0 -4
- package/dist/components/EntranceView.macos.d.ts.map +0 -1
- package/dist/components/FaceAvatar.d.ts +0 -16
- package/dist/components/FaceAvatar.d.ts.map +0 -1
- package/dist/components/GradientSurface.d.ts +0 -14
- package/dist/components/GradientSurface.d.ts.map +0 -1
- package/dist/components/MediaView.d.ts +0 -14
- package/dist/components/MediaView.d.ts.map +0 -1
- package/dist/components/ReactionPicker.d.ts +0 -10
- package/dist/components/ReactionPicker.d.ts.map +0 -1
- package/dist/components/SpaceView.android.d.ts +0 -2
- package/dist/components/SpaceView.android.d.ts.map +0 -1
- package/dist/components/SpaceView.d.ts +0 -33
- package/dist/components/SpaceView.d.ts.map +0 -1
- package/dist/components/SpaceView.ios-pad.d.ts +0 -2
- package/dist/components/SpaceView.ios-pad.d.ts.map +0 -1
- package/dist/components/SpaceView.ios-phone.d.ts +0 -2
- package/dist/components/SpaceView.ios-phone.d.ts.map +0 -1
- package/dist/components/SpaceView.macos.d.ts +0 -2
- package/dist/components/SpaceView.macos.d.ts.map +0 -1
- package/dist/components/SpaceView.shared.d.ts +0 -3
- package/dist/components/SpaceView.shared.d.ts.map +0 -1
- package/dist/components/episode-diagnostic-render-observer.d.ts +0 -2
- package/dist/components/episode-diagnostic-render-observer.d.ts.map +0 -1
- package/dist/components/logo/Logo.d.ts +0 -11
- package/dist/components/logo/Logo.d.ts.map +0 -1
- package/dist/components/native-animation-controller.d.ts +0 -7
- package/dist/components/native-animation-controller.d.ts.map +0 -1
- package/dist/components/native-chat.d.ts +0 -8
- package/dist/components/native-chat.d.ts.map +0 -1
- package/dist/components/native-entrance/entrance-controller-store.d.ts +0 -34
- package/dist/components/native-entrance/entrance-controller-store.d.ts.map +0 -1
- package/dist/components/native-entrance/useEntranceController.d.ts +0 -19
- package/dist/components/native-entrance/useEntranceController.d.ts.map +0 -1
- package/dist/components/native-joining-loading-animation.d.ts +0 -9
- package/dist/components/native-joining-loading-animation.d.ts.map +0 -1
- package/dist/components/native-space-view/AppearanceSettings.d.ts +0 -2
- package/dist/components/native-space-view/AppearanceSettings.d.ts.map +0 -1
- package/dist/components/native-space-view/FeedbackSheet.d.ts +0 -12
- package/dist/components/native-space-view/FeedbackSheet.d.ts.map +0 -1
- package/dist/components/native-space-view/ParticipantActionSheet.d.ts +0 -9
- package/dist/components/native-space-view/ParticipantActionSheet.d.ts.map +0 -1
- package/dist/components/native-space-view/SettingsSheet.d.ts +0 -7
- package/dist/components/native-space-view/SettingsSheet.d.ts.map +0 -1
- package/dist/components/native-space-view/SpaceActionMenu.d.ts +0 -10
- package/dist/components/native-space-view/SpaceActionMenu.d.ts.map +0 -1
- package/dist/components/native-space-view/SpaceBottomDock.android.d.ts +0 -4
- package/dist/components/native-space-view/SpaceBottomDock.android.d.ts.map +0 -1
- package/dist/components/native-space-view/SpaceChatAttachment.d.ts +0 -8
- package/dist/components/native-space-view/SpaceChatAttachment.d.ts.map +0 -1
- package/dist/components/native-space-view/SpaceChatSheet.d.ts +0 -5
- package/dist/components/native-space-view/SpaceChatSheet.d.ts.map +0 -1
- package/dist/components/native-space-view/SpaceGrid.android.d.ts +0 -8
- package/dist/components/native-space-view/SpaceGrid.android.d.ts.map +0 -1
- package/dist/components/native-space-view/SpaceMoreSheet.d.ts +0 -7
- package/dist/components/native-space-view/SpaceMoreSheet.d.ts.map +0 -1
- package/dist/components/native-space-view/SpacePanelSheet.d.ts +0 -5
- package/dist/components/native-space-view/SpacePanelSheet.d.ts.map +0 -1
- package/dist/components/native-space-view/SpacePeopleSheet.d.ts +0 -5
- package/dist/components/native-space-view/SpacePeopleSheet.d.ts.map +0 -1
- package/dist/components/native-space-view/SpaceStage.android.d.ts +0 -29
- package/dist/components/native-space-view/SpaceStage.android.d.ts.map +0 -1
- package/dist/components/native-space-view/SpaceSurfacePrimitives.d.ts +0 -30
- package/dist/components/native-space-view/SpaceSurfacePrimitives.d.ts.map +0 -1
- package/dist/components/native-space-view/SpaceTopBar.android.d.ts +0 -11
- package/dist/components/native-space-view/SpaceTopBar.android.d.ts.map +0 -1
- package/dist/components/native-space-view/SpaceWhiteboardSurface.d.ts +0 -15
- package/dist/components/native-space-view/SpaceWhiteboardSurface.d.ts.map +0 -1
- package/dist/components/native-space-view/diagnostics.d.ts +0 -48
- package/dist/components/native-space-view/diagnostics.d.ts.map +0 -1
- package/dist/components/native-space-view/format-space-duration.d.ts +0 -2
- package/dist/components/native-space-view/format-space-duration.d.ts.map +0 -1
- package/dist/components/native-space-view/native-space-grid-keys.d.ts +0 -3
- package/dist/components/native-space-view/native-space-grid-keys.d.ts.map +0 -1
- package/dist/components/native-space-view/native-space-page-store.d.ts +0 -8
- package/dist/components/native-space-view/native-space-page-store.d.ts.map +0 -1
- package/dist/components/native-space-view/space-chat-attachments.d.ts +0 -15
- package/dist/components/native-space-view/space-chat-attachments.d.ts.map +0 -1
- package/dist/components/native-space-view/space-panel-layout.d.ts +0 -10
- package/dist/components/native-space-view/space-panel-layout.d.ts.map +0 -1
- package/dist/components/native-space-view/space-progressive-surface-helpers.d.ts +0 -16
- package/dist/components/native-space-view/space-progressive-surface-helpers.d.ts.map +0 -1
- package/dist/components/native-space-view/space-progressive-surface-types.d.ts +0 -3
- package/dist/components/native-space-view/space-progressive-surface-types.d.ts.map +0 -1
- package/dist/components/native-space-view/types.d.ts +0 -24
- package/dist/components/native-space-view/types.d.ts.map +0 -1
- package/dist/components/native-space-view/useSpaceViewController.contract.d.ts +0 -41
- package/dist/components/native-space-view/useSpaceViewController.contract.d.ts.map +0 -1
- package/dist/components/native-space-view/useSpaceViewController.d.ts +0 -156
- package/dist/components/native-space-view/useSpaceViewController.d.ts.map +0 -1
- package/dist/components/native-space-view/useSpaceViewDerived.d.ts +0 -12
- package/dist/components/native-space-view/useSpaceViewDerived.d.ts.map +0 -1
- package/dist/components/native-space-view/useSpaceViewPanels.d.ts +0 -70
- package/dist/components/native-space-view/useSpaceViewPanels.d.ts.map +0 -1
- package/dist/feedback/native-capture.d.ts +0 -9
- package/dist/feedback/native-capture.d.ts.map +0 -1
- package/dist/feedback/native-evidence.d.ts +0 -3
- package/dist/feedback/native-evidence.d.ts.map +0 -1
- package/dist/hooks/entrance-preview-store.d.ts +0 -16
- package/dist/hooks/entrance-preview-store.d.ts.map +0 -1
- package/dist/hooks/useEntrancePreview.d.ts +0 -7
- package/dist/hooks/useEntrancePreview.d.ts.map +0 -1
- package/dist/hooks/useLayout.d.ts +0 -16
- package/dist/hooks/useLayout.d.ts.map +0 -1
- package/dist/hooks/usePanels.d.ts +0 -12
- package/dist/hooks/usePanels.d.ts.map +0 -1
- package/dist/ios-pad.d.ts +0 -2
- package/dist/ios-pad.d.ts.map +0 -1
- package/dist/ios-pad.js +0 -62
- package/dist/ios-phone.d.ts +0 -2
- package/dist/ios-phone.d.ts.map +0 -1
- package/dist/ios-phone.js +0 -62
- package/dist/ios.d.ts +0 -2
- package/dist/ios.d.ts.map +0 -1
- package/dist/ios.js +0 -62
- package/dist/macos.d.ts +0 -2
- package/dist/macos.d.ts.map +0 -1
- package/dist/macos.js +0 -62
- package/dist/space-client/cloudflare-rtk-native.d.ts +0 -3
- package/dist/space-client/cloudflare-rtk-native.d.ts.map +0 -1
- package/dist/telemetry.d.ts +0 -63
- package/dist/telemetry.d.ts.map +0 -1
- package/dist/ui/appearance.d.ts +0 -246
- package/dist/ui/appearance.d.ts.map +0 -1
- package/dist/ui/appearance.js +0 -14
- package/dist/ui/native-appearance-context.d.ts +0 -15
- package/dist/ui/native-appearance-context.d.ts.map +0 -1
- package/dist/ui/native-theme.d.ts +0 -17
- package/dist/ui/native-theme.d.ts.map +0 -1
- package/dist/ui/native-types.d.ts +0 -38
- package/dist/ui/native-types.d.ts.map +0 -1
- package/dist/ui/participant-avatar.d.ts +0 -21
- package/dist/ui/participant-avatar.d.ts.map +0 -1
- package/dist/ui/theme-tokens.d.ts +0 -25
- package/dist/ui/theme-tokens.d.ts.map +0 -1
- package/dist/ui/theme.d.ts +0 -404
- package/dist/ui/theme.d.ts.map +0 -1
- package/dist/ui/theme.js +0 -8
- package/dist/utils/native-space-layout.d.ts +0 -42
- package/dist/utils/native-space-layout.d.ts.map +0 -1
- package/src/android.ts +0 -1
- package/src/components/Chalk.tsx +0 -363
- package/src/components/ChatMessageList.tsx +0 -209
- package/src/components/Entrance.tsx +0 -42
- package/src/components/EntranceView.android.tsx +0 -274
- package/src/components/EntranceView.ios-pad.tsx +0 -326
- package/src/components/EntranceView.ios-phone.tsx +0 -271
- package/src/components/EntranceView.macos.tsx +0 -278
- package/src/components/EntranceView.tsx +0 -38
- package/src/components/FaceAvatar.tsx +0 -120
- package/src/components/GradientSurface.tsx +0 -23
- package/src/components/MediaView.tsx +0 -76
- package/src/components/ReactionPicker.tsx +0 -98
- package/src/components/SpaceView.android.tsx +0 -1
- package/src/components/SpaceView.ios-pad.tsx +0 -1
- package/src/components/SpaceView.ios-phone.tsx +0 -1
- package/src/components/SpaceView.macos.tsx +0 -1
- package/src/components/SpaceView.shared.tsx +0 -98
- package/src/components/SpaceView.tsx +0 -54
- package/src/components/episode-diagnostic-render-observer.ts +0 -12
- package/src/components/logo/Logo.tsx +0 -309
- package/src/components/native-animation-controller.ts +0 -36
- package/src/components/native-chat.ts +0 -23
- package/src/components/native-entrance/entrance-controller-store.ts +0 -112
- package/src/components/native-entrance/useEntranceController.ts +0 -60
- package/src/components/native-joining-loading-animation.ts +0 -26
- package/src/components/native-space-view/AppearanceSettings.tsx +0 -114
- package/src/components/native-space-view/FeedbackSheet.tsx +0 -296
- package/src/components/native-space-view/ParticipantActionSheet.tsx +0 -99
- package/src/components/native-space-view/SettingsSheet.tsx +0 -164
- package/src/components/native-space-view/SpaceActionMenu.tsx +0 -109
- package/src/components/native-space-view/SpaceBottomDock.android.tsx +0 -115
- package/src/components/native-space-view/SpaceChatAttachment.tsx +0 -105
- package/src/components/native-space-view/SpaceChatSheet.tsx +0 -184
- package/src/components/native-space-view/SpaceGrid.android.tsx +0 -323
- package/src/components/native-space-view/SpaceMoreSheet.tsx +0 -190
- package/src/components/native-space-view/SpacePanelSheet.tsx +0 -45
- package/src/components/native-space-view/SpacePeopleSheet.tsx +0 -116
- package/src/components/native-space-view/SpaceStage.android.tsx +0 -372
- package/src/components/native-space-view/SpaceSurfacePrimitives.tsx +0 -75
- package/src/components/native-space-view/SpaceTopBar.android.tsx +0 -113
- package/src/components/native-space-view/SpaceWhiteboardSurface.tsx +0 -69
- package/src/components/native-space-view/diagnostics.ts +0 -84
- package/src/components/native-space-view/format-space-duration.ts +0 -3
- package/src/components/native-space-view/native-space-grid-keys.ts +0 -6
- package/src/components/native-space-view/native-space-page-store.ts +0 -41
- package/src/components/native-space-view/space-chat-attachments.test.ts +0 -26
- package/src/components/native-space-view/space-chat-attachments.ts +0 -37
- package/src/components/native-space-view/space-panel-layout.ts +0 -10
- package/src/components/native-space-view/space-progressive-surface-helpers.ts +0 -33
- package/src/components/native-space-view/space-progressive-surface-types.ts +0 -3
- package/src/components/native-space-view/types.ts +0 -25
- package/src/components/native-space-view/useSpaceViewController.contract.ts +0 -34
- package/src/components/native-space-view/useSpaceViewController.ts +0 -416
- package/src/components/native-space-view/useSpaceViewDerived.ts +0 -29
- package/src/components/native-space-view/useSpaceViewPanels.ts +0 -170
- package/src/feedback/native-capture.ts +0 -62
- package/src/feedback/native-evidence.ts +0 -37
- package/src/hooks/entrance-preview-store.ts +0 -99
- package/src/hooks/useEntrancePreview.ts +0 -26
- package/src/hooks/useLayout.ts +0 -37
- package/src/hooks/usePanels.ts +0 -30
- package/src/ios-pad.ts +0 -1
- package/src/ios-phone.ts +0 -1
- package/src/ios.ts +0 -1
- package/src/macos.ts +0 -1
- package/src/space-client/cloudflare-rtk-native.ts +0 -104
- package/src/telemetry.ts +0 -234
- package/src/types/hugeicons-direct.d.ts +0 -4
- package/src/types/react-native-safe-area-context.d.ts +0 -8
- package/src/ui/appearance.ts +0 -808
- package/src/ui/native-appearance-context.tsx +0 -74
- package/src/ui/native-theme.tsx +0 -54
- package/src/ui/native-types.ts +0 -40
- package/src/ui/participant-avatar.ts +0 -47
- package/src/ui/theme-tokens.ts +0 -41
- package/src/ui/theme.ts +0 -214
- package/src/utils/native-space-layout.ts +0 -135
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/// <reference path="./assets.d.ts" />
|
|
2
|
+
import { createAudioPlayer, type AudioPlayer } from "expo-audio";
|
|
3
|
+
import error from "./assets/error.wav";
|
|
4
|
+
import hand from "./assets/hand.wav";
|
|
5
|
+
import join from "./assets/join.wav";
|
|
6
|
+
import knock from "./assets/knock.wav";
|
|
7
|
+
import leave from "./assets/leave.wav";
|
|
8
|
+
import message from "./assets/message.wav";
|
|
9
|
+
import mute from "./assets/mute.wav";
|
|
10
|
+
import recording from "./assets/recording.wav";
|
|
11
|
+
import test from "./assets/test.wav";
|
|
12
|
+
import unmute from "./assets/unmute.wav";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The call's sounds, rendered offline from the mockup's WebAudio synth so they sound the same:
|
|
16
|
+
* two rising notes for a join, two falling for a leave, two thuds for a knock, one light tone for
|
|
17
|
+
* a message, two bell notes for a raised hand, a tick for mute and unmute, three notes when
|
|
18
|
+
* recording starts, two low notes for an error, and three rising notes for Test speaker.
|
|
19
|
+
*/
|
|
20
|
+
const sources = { join, leave, knock, message, hand, mute, unmute, recording, error, test } as const;
|
|
21
|
+
|
|
22
|
+
export type SoundName = keyof typeof sources;
|
|
23
|
+
|
|
24
|
+
const players = new Map<SoundName, AudioPlayer>();
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Plays one sound when `enabled` (the persisted Sounds setting); Test speaker ignores the setting.
|
|
28
|
+
*
|
|
29
|
+
* Players keep the audio session active: expo-audio otherwise deactivates the shared iOS session
|
|
30
|
+
* after each sound, which would cut the call's audio. This module never calls `setAudioModeAsync`,
|
|
31
|
+
* because on Android that resets the audio mode and turns on the speakerphone mid-call. On iOS the
|
|
32
|
+
* silent switch mutes these sounds only outside a call; during a call WebRTC's play-and-record
|
|
33
|
+
* session plays them regardless.
|
|
34
|
+
*/
|
|
35
|
+
export function playSound(name: SoundName, enabled: boolean): void {
|
|
36
|
+
if (!enabled && name !== "test") return;
|
|
37
|
+
let player = players.get(name);
|
|
38
|
+
if (!player) {
|
|
39
|
+
player = createAudioPlayer(sources[name], { keepAudioSessionActive: true });
|
|
40
|
+
players.set(name, player);
|
|
41
|
+
}
|
|
42
|
+
void player.seekTo(0);
|
|
43
|
+
player.play();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Frees the players when the call view goes away. */
|
|
47
|
+
export function releaseSounds(): void {
|
|
48
|
+
for (const player of players.values()) player.remove();
|
|
49
|
+
players.clear();
|
|
50
|
+
}
|
|
@@ -1,36 +1,29 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AsyncStorageV1PendingTargetStore,
|
|
3
|
-
CloudflareRTKClient,
|
|
4
3
|
CloudflareSFUClient,
|
|
5
4
|
createChalkChatFileHttpTransport,
|
|
6
5
|
createChalkWhiteboardV1Client,
|
|
7
|
-
|
|
6
|
+
createChalkWhiteboardV1FileDownloadTransport,
|
|
8
7
|
createCloudflareSFUHTTPTransport,
|
|
9
8
|
createReactNativeSyncLifecycle,
|
|
10
9
|
createReactNativeWebSocketFactory,
|
|
11
10
|
createV1SyncClient,
|
|
12
|
-
type DiagnosticObservation,
|
|
13
11
|
type GetAccess,
|
|
14
|
-
type ReactNativeWebSocket,
|
|
15
12
|
type ReactNativeWebSocketConstructor,
|
|
16
13
|
type ReactNativeAsyncStorage,
|
|
17
14
|
} from "@q9labsai/chalk-client";
|
|
18
15
|
import { createSpaceClientForPlatform, type SpaceClientPlatform } from "@q9labsai/chalk-client/effect";
|
|
19
|
-
import type { FeedbackSource } from "@q9labsai/chalk-client";
|
|
20
16
|
import type { SpaceClient } from "@q9labsai/chalk-client";
|
|
21
17
|
import { RTCPeerConnection, mediaDevices } from "@cloudflare/react-native-webrtc";
|
|
22
18
|
import { AppState } from "react-native";
|
|
23
|
-
|
|
24
|
-
import {
|
|
25
|
-
import { createNativeRealtimeKitClient } from "./cloudflare-rtk-native";
|
|
26
|
-
|
|
19
|
+
import { toNativeCaptureError } from "../media/native-capture-error";
|
|
20
|
+
import { ensureRandomUUID } from "./random-uuid";
|
|
27
21
|
type PlatformDependencies = NonNullable<SpaceClientPlatform["dependencies"]>;
|
|
28
22
|
type NativeMediaClient = ReturnType<NonNullable<PlatformDependencies["createMediaClient"]>>;
|
|
29
23
|
type MediaFactoryInput = Parameters<NonNullable<PlatformDependencies["createMediaClient"]>>[0];
|
|
30
24
|
type SyncFactoryInput = Parameters<NonNullable<PlatformDependencies["createSyncClient"]>>[0];
|
|
31
25
|
type ChatFileFactoryInput = Parameters<NonNullable<PlatformDependencies["createChatFileTransport"]>>[0];
|
|
32
26
|
type WhiteboardFactoryInput = Parameters<NonNullable<PlatformDependencies["createWhiteboardClient"]>>[0];
|
|
33
|
-
|
|
34
27
|
export type NativeSpaceClientOptions = {
|
|
35
28
|
readonly space: string;
|
|
36
29
|
readonly getAccess: GetAccess;
|
|
@@ -41,18 +34,15 @@ export type NativeSpaceClientOptions = {
|
|
|
41
34
|
readonly camera?: boolean;
|
|
42
35
|
readonly syncStartupTimeoutMs?: number;
|
|
43
36
|
readonly storage?: ReactNativeAsyncStorage;
|
|
44
|
-
readonly telemetry?: TelemetryJourney;
|
|
45
|
-
readonly feedbackSource?: FeedbackSource;
|
|
46
37
|
};
|
|
47
|
-
|
|
48
38
|
export function createNativeSpaceClient(options: NativeSpaceClientOptions): SpaceClient {
|
|
49
|
-
|
|
39
|
+
ensureRandomUUID();
|
|
40
|
+
const { storage } = options;
|
|
50
41
|
const apiBaseURL = options.baseUrl ?? "https://api.chalkmeet.com";
|
|
51
42
|
const syncURL = options.syncUrl ?? defaultSyncURL(apiBaseURL);
|
|
52
|
-
const
|
|
53
|
-
const fetch = telemetryFetch(journey);
|
|
43
|
+
const fetch = globalThis.fetch;
|
|
54
44
|
const lifecycle = createReactNativeSyncLifecycle({ appState: AppState });
|
|
55
|
-
const webSocket = createReactNativeWebSocketFactory(
|
|
45
|
+
const webSocket = createReactNativeWebSocketFactory(globalThis.WebSocket as unknown as ReactNativeWebSocketConstructor);
|
|
56
46
|
const dependencies: PlatformDependencies = {
|
|
57
47
|
clock: {
|
|
58
48
|
now: () => Date.now(),
|
|
@@ -60,10 +50,16 @@ export function createNativeSpaceClient(options: NativeSpaceClientOptions): Spac
|
|
|
60
50
|
clearTimeout: (handle) => globalThis.clearTimeout(handle as ReturnType<typeof globalThis.setTimeout>),
|
|
61
51
|
},
|
|
62
52
|
mediaDevices: {
|
|
63
|
-
getUserMedia: async (constraints) =>
|
|
53
|
+
getUserMedia: async (constraints) => {
|
|
54
|
+
try {
|
|
55
|
+
return (await mediaDevices.getUserMedia(constraints)) as unknown as globalThis.MediaStream;
|
|
56
|
+
} catch (cause) {
|
|
57
|
+
throw toNativeCaptureError(cause);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
64
60
|
getDisplayMedia: async () => (await mediaDevices.getDisplayMedia()) as unknown as globalThis.MediaStream,
|
|
65
61
|
},
|
|
66
|
-
createMediaClient: (input) => createMediaClient(apiBaseURL, input, fetch
|
|
62
|
+
createMediaClient: (input) => createMediaClient(apiBaseURL, input, fetch),
|
|
67
63
|
createSyncClient: (input) => createSyncClient(syncURL, input, lifecycle, webSocket, storage),
|
|
68
64
|
createChatFileTransport: (input) => createChatFileTransport(apiBaseURL, input, fetch),
|
|
69
65
|
createWhiteboardClient: options.whiteboardURL === null ? undefined : (input) => createWhiteboardClient(apiBaseURL, options.whiteboardURL ?? whiteboardURL(syncURL), input, fetch, lifecycle, webSocket),
|
|
@@ -74,88 +70,30 @@ export function createNativeSpaceClient(options: NativeSpaceClientOptions): Spac
|
|
|
74
70
|
return () => subscription.remove();
|
|
75
71
|
},
|
|
76
72
|
};
|
|
77
|
-
|
|
78
73
|
const client = createSpaceClientForPlatform(
|
|
79
74
|
{ space: options.space, getAccess: options.getAccess, baseUrl: apiBaseURL },
|
|
80
75
|
{
|
|
81
76
|
apiBaseUrl: apiBaseURL,
|
|
82
77
|
syncUrl: syncURL,
|
|
83
78
|
whiteboardUrl: options.whiteboardURL,
|
|
84
|
-
telemetry: journey?.context,
|
|
85
79
|
dependencies,
|
|
86
80
|
fetch,
|
|
87
|
-
syncStartupTimeoutMs: options.syncStartupTimeoutMs ??
|
|
81
|
+
syncStartupTimeoutMs: options.syncStartupTimeoutMs ?? 30000,
|
|
88
82
|
initialMicrophoneEnabled: options.microphone,
|
|
89
83
|
initialCameraEnabled: options.camera,
|
|
90
|
-
onConnectionDiagnostic: (event) => journey?.recordDiagnostic(connectionDiagnostic(event)),
|
|
91
|
-
...(journey ? { recordReconnect: (observation) => journey.recordDiagnostic(observation) } : {}),
|
|
92
|
-
feedbackSource: options.feedbackSource ?? "embedded",
|
|
93
84
|
},
|
|
94
85
|
);
|
|
95
|
-
bindNativeAuthenticatedTelemetry(client, journey);
|
|
96
|
-
registerNativeJourneyContext(client, journey, telemetry);
|
|
97
86
|
return client;
|
|
98
87
|
}
|
|
99
|
-
|
|
100
|
-
type PlatformDiagnostic = Parameters<NonNullable<SpaceClientPlatform["onConnectionDiagnostic"]>>[0];
|
|
101
|
-
|
|
102
|
-
function connectionDiagnostic(event: PlatformDiagnostic): DiagnosticObservation {
|
|
103
|
-
if (event.event === "space_join_span" && event.step && event.spanId && event.outcome) {
|
|
104
|
-
return {
|
|
105
|
-
category: "connection",
|
|
106
|
-
code: `space.join.${event.step}.${event.outcome}`,
|
|
107
|
-
phase: joinTracePhase(event.step),
|
|
108
|
-
state: event.outcome === "succeeded" ? "succeeded" : event.outcome === "failed" ? "failed" : "observed",
|
|
109
|
-
...(event.durationMs === undefined ? {} : { metricValue: event.durationMs }),
|
|
110
|
-
attributes: {
|
|
111
|
-
span_id: event.spanId,
|
|
112
|
-
...(event.parentSpanId ? { parent_span_id: event.parentSpanId } : {}),
|
|
113
|
-
step: event.step,
|
|
114
|
-
outcome: event.outcome,
|
|
115
|
-
epoch: event.epoch,
|
|
116
|
-
...(event.code ? { failure_code: event.code } : {}),
|
|
117
|
-
},
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
return {
|
|
121
|
-
category: "connection",
|
|
122
|
-
code: event.event,
|
|
123
|
-
phase: event.state === "joining" ? "signaling" : event.state === "leaving" || event.state === "left" ? "terminal" : "recovery",
|
|
124
|
-
state: event.event.endsWith("_failed") || event.event.endsWith("_exhausted") ? "failed" : "observed",
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function joinTracePhase(step: NonNullable<PlatformDiagnostic["step"]>): "authentication" | "signaling" | "media" | "recovery" {
|
|
129
|
-
switch (step) {
|
|
130
|
-
case "acquire_initial_media":
|
|
131
|
-
case "create_media_client":
|
|
132
|
-
case "start_media":
|
|
133
|
-
return "media";
|
|
134
|
-
default:
|
|
135
|
-
return "signaling";
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function createMediaClient(apiBaseURL: string, input: MediaFactoryInput, fetch: typeof globalThis.fetch, observePeerConnection: ((peerConnection: RtcPeerConnection) => () => void) | undefined, journey: TelemetryJourney | undefined): NativeMediaClient {
|
|
88
|
+
function createMediaClient(apiBaseURL: string, input: MediaFactoryInput, fetch: typeof globalThis.fetch): NativeMediaClient {
|
|
140
89
|
const { subject } = input.access;
|
|
141
|
-
if (input.access.media.provider === "cloudflare_rtk") {
|
|
142
|
-
const client = new CloudflareRTKClient({
|
|
143
|
-
authToken: input.access.media.clientPayload.token,
|
|
144
|
-
participantId: subject.participantId,
|
|
145
|
-
clientFactory: createNativeRealtimeKitClient,
|
|
146
|
-
onError: input.onFailure,
|
|
147
|
-
onScreenEnded: input.onScreenEnded,
|
|
148
|
-
});
|
|
149
|
-
return createRTKConnectionMediaClient(client);
|
|
150
|
-
}
|
|
151
90
|
const replaceMediaConnection = input.replaceMediaConnection;
|
|
152
91
|
const client = new CloudflareSFUClient({
|
|
153
92
|
bootstrap: input.access.media.clientPayload,
|
|
154
93
|
participantId: subject.participantId,
|
|
155
94
|
transport: createCloudflareSFUHTTPTransport({
|
|
156
95
|
apiBaseURL,
|
|
157
|
-
|
|
158
|
-
credential: () => authenticatedNativeCredential(input.credential, journey),
|
|
96
|
+
credential: input.credential,
|
|
159
97
|
tenantId: subject.tenantId,
|
|
160
98
|
spaceId: subject.spaceId,
|
|
161
99
|
episodeId: subject.episodeId,
|
|
@@ -171,34 +109,13 @@ function createMediaClient(apiBaseURL: string, input: MediaFactoryInput, fetch:
|
|
|
171
109
|
: undefined,
|
|
172
110
|
peerConnectionFactory: (configuration) => {
|
|
173
111
|
const connection = new RTCPeerConnection(configuration);
|
|
174
|
-
observePeerConnection?.(connection as unknown as RtcPeerConnection);
|
|
175
112
|
return connection as unknown as globalThis.RTCPeerConnection;
|
|
176
113
|
},
|
|
177
|
-
recordReconnect: input.recordReconnect,
|
|
178
114
|
onError: input.onFailure,
|
|
179
115
|
onScreenEnded: input.onScreenEnded,
|
|
180
116
|
});
|
|
181
117
|
return createSFUConnectionMediaClient(client);
|
|
182
118
|
}
|
|
183
|
-
|
|
184
|
-
function createRTKConnectionMediaClient(client: CloudflareRTKClient): NativeMediaClient {
|
|
185
|
-
return {
|
|
186
|
-
setLocalPublicationTarget: client.setLocalPublicationTarget.bind(client),
|
|
187
|
-
observeLocalPublications: client.observeLocalPublications.bind(client),
|
|
188
|
-
observeRemotePublications: client.observeRemotePublications.bind(client),
|
|
189
|
-
start: client.start.bind(client),
|
|
190
|
-
stop: client.stop.bind(client),
|
|
191
|
-
restart: (input) => {
|
|
192
|
-
if (!("provider" in input) || input.provider !== "cloudflare_rtk") throw new TypeError("The RealtimeKit adapter requires a Cloudflare RealtimeKit access grant");
|
|
193
|
-
return client.restart(input);
|
|
194
|
-
},
|
|
195
|
-
prepareLocalTrack: client.prepareLocalTrack.bind(client),
|
|
196
|
-
clearPreparedLocalTrack: client.clearPreparedLocalTrack.bind(client),
|
|
197
|
-
getSnapshot: client.getSnapshot.bind(client),
|
|
198
|
-
subscribe: client.subscribe.bind(client),
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
|
|
202
119
|
function createSFUConnectionMediaClient(client: CloudflareSFUClient): NativeMediaClient {
|
|
203
120
|
return {
|
|
204
121
|
setLocalPublicationTarget: client.setLocalPublicationTarget.bind(client),
|
|
@@ -219,7 +136,6 @@ function createSFUConnectionMediaClient(client: CloudflareSFUClient): NativeMedi
|
|
|
219
136
|
subscribe: client.subscribe.bind(client),
|
|
220
137
|
};
|
|
221
138
|
}
|
|
222
|
-
|
|
223
139
|
function createSyncClient(syncURL: string, input: SyncFactoryInput, lifecycle: ReturnType<typeof createReactNativeSyncLifecycle>, webSocket: ReturnType<typeof createReactNativeWebSocketFactory>, storage: ReactNativeAsyncStorage | undefined) {
|
|
224
140
|
const subject = input.access.subject;
|
|
225
141
|
const scope = `${subject.tenantId}:${subject.episodeId}:${subject.participantId}`;
|
|
@@ -229,25 +145,16 @@ function createSyncClient(syncURL: string, input: SyncFactoryInput, lifecycle: R
|
|
|
229
145
|
mediaPlane: input.media,
|
|
230
146
|
lifecycle,
|
|
231
147
|
webSocket,
|
|
232
|
-
telemetry: input.telemetry,
|
|
233
|
-
recordReconnect: input.recordReconnect,
|
|
234
148
|
...(storage ? { pendingStore: new AsyncStorageV1PendingTargetStore({ scope, storage }) } : {}),
|
|
235
149
|
});
|
|
236
150
|
}
|
|
237
|
-
|
|
238
151
|
function createChatFileTransport(apiBaseURL: string, input: ChatFileFactoryInput, fetch: typeof globalThis.fetch) {
|
|
239
152
|
return createChalkChatFileHttpTransport({ baseUrl: apiBaseURL, token: input.token, fetch });
|
|
240
153
|
}
|
|
241
|
-
|
|
242
154
|
function createWhiteboardClient(apiBaseURL: string, url: string, input: WhiteboardFactoryInput, fetch: typeof globalThis.fetch, lifecycle: ReturnType<typeof createReactNativeSyncLifecycle>, webSocket: ReturnType<typeof createReactNativeWebSocketFactory>) {
|
|
243
|
-
|
|
244
|
-
const files = createChalkWhiteboardV1FileHttpTransport({
|
|
155
|
+
const files = createChalkWhiteboardV1FileDownloadTransport({
|
|
245
156
|
baseUrl: apiBaseURL,
|
|
246
157
|
token: input.token,
|
|
247
|
-
sceneId: () => {
|
|
248
|
-
if (sceneId === null) throw new TypeError("Whiteboard scene is not ready");
|
|
249
|
-
return sceneId;
|
|
250
|
-
},
|
|
251
158
|
fetch,
|
|
252
159
|
});
|
|
253
160
|
return createChalkWhiteboardV1Client({
|
|
@@ -256,79 +163,12 @@ function createWhiteboardClient(apiBaseURL: string, url: string, input: Whiteboa
|
|
|
256
163
|
files,
|
|
257
164
|
lifecycle,
|
|
258
165
|
webSocket,
|
|
166
|
+
onWatchdogReplacement: input.onWatchdogReplacement,
|
|
259
167
|
onSummary: (summary) => {
|
|
260
|
-
sceneId = summary.sceneId;
|
|
261
168
|
input.onSummary(summary);
|
|
262
169
|
},
|
|
263
170
|
});
|
|
264
171
|
}
|
|
265
|
-
|
|
266
|
-
function telemetryFetch(journey: TelemetryJourney | undefined): typeof globalThis.fetch {
|
|
267
|
-
if (!journey) return globalThis.fetch;
|
|
268
|
-
return (input, init) => {
|
|
269
|
-
const headers = new Headers(init?.headers);
|
|
270
|
-
for (const [name, value] of Object.entries(journey.headers)) headers.set(name, value);
|
|
271
|
-
return globalThis.fetch(input, { ...init, headers });
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
function nativeWebSocketConstructor(journey: TelemetryJourney | undefined): ReactNativeWebSocketConstructor {
|
|
276
|
-
const RuntimeWebSocket = globalThis.WebSocket as unknown as new (url: string, protocols?: string | string[], options?: { readonly headers?: Readonly<Record<string, string>> }) => ReactNativeWebSocket;
|
|
277
|
-
|
|
278
|
-
return class ChalkNativeWebSocket implements ReactNativeWebSocket {
|
|
279
|
-
onopen: ((event: unknown) => void) | null = null;
|
|
280
|
-
onmessage: ((event: { readonly data: unknown }) => void) | null = null;
|
|
281
|
-
onclose: ((event: { readonly code?: unknown; readonly reason?: unknown }) => void) | null = null;
|
|
282
|
-
onerror: ((event: unknown) => void) | null = null;
|
|
283
|
-
readonly #socket: ReactNativeWebSocket;
|
|
284
|
-
|
|
285
|
-
constructor(url: string) {
|
|
286
|
-
this.#socket = new RuntimeWebSocket(url, undefined, journey ? { headers: journey.headers } : undefined);
|
|
287
|
-
this.#socket.onopen = (event) => this.onopen?.(event);
|
|
288
|
-
this.#socket.onmessage = (event) => {
|
|
289
|
-
recordSyncFrame(journey, "server_to_client", event.data);
|
|
290
|
-
this.onmessage?.(event);
|
|
291
|
-
};
|
|
292
|
-
this.#socket.onclose = (event) => {
|
|
293
|
-
recordSyncTransportClose(journey, event);
|
|
294
|
-
this.onclose?.(event);
|
|
295
|
-
};
|
|
296
|
-
this.#socket.onerror = (event) => {
|
|
297
|
-
journey?.recordDiagnostic({ category: "network", code: "sync_websocket_error", phase: "signaling", state: "failed" });
|
|
298
|
-
this.onerror?.(event);
|
|
299
|
-
};
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
send(data: string): void {
|
|
303
|
-
recordSyncFrame(journey, "client_to_server", data);
|
|
304
|
-
this.#socket.send(data);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
close(code?: number, reason?: string): void {
|
|
308
|
-
this.#socket.close(code, reason);
|
|
309
|
-
}
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
function recordSyncTransportClose(journey: TelemetryJourney | undefined, event: { readonly code?: unknown; readonly reason?: unknown }): void {
|
|
314
|
-
if (!journey) return;
|
|
315
|
-
journey.recordDiagnostic(syncTransportCloseDiagnostic(event));
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
function recordSyncFrame(journey: TelemetryJourney | undefined, direction: "client_to_server" | "server_to_client", data: unknown): void {
|
|
319
|
-
if (!journey) return;
|
|
320
|
-
let frameType = "binary";
|
|
321
|
-
if (typeof data === "string") {
|
|
322
|
-
try {
|
|
323
|
-
const frame = JSON.parse(data) as { readonly type?: unknown };
|
|
324
|
-
frameType = typeof frame.type === "string" ? frame.type : "unknown";
|
|
325
|
-
} catch {
|
|
326
|
-
frameType = "invalid_json";
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
journey.recordSyncFrame({ direction, frameType });
|
|
330
|
-
}
|
|
331
|
-
|
|
332
172
|
function whiteboardURL(syncURL: string): string {
|
|
333
173
|
const url = new URL(syncURL);
|
|
334
174
|
url.pathname = "/v1/whiteboard";
|
|
@@ -336,7 +176,6 @@ function whiteboardURL(syncURL: string): string {
|
|
|
336
176
|
url.hash = "";
|
|
337
177
|
return url.toString();
|
|
338
178
|
}
|
|
339
|
-
|
|
340
179
|
function defaultSyncURL(apiBaseURL: string): string {
|
|
341
180
|
const url = new URL(apiBaseURL);
|
|
342
181
|
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { randomUUID } from "expo-crypto";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* JavaScriptCore on React Native has no Web Crypto, and the client calls `crypto.randomUUID()` for request and command keys
|
|
5
|
+
* and for its connection id, which must come from a secure source. Without it, Leave and media commands fail. This fills only
|
|
6
|
+
* what is missing with Expo's native secure generator, so runtimes with Web Crypto keep theirs.
|
|
7
|
+
*/
|
|
8
|
+
export function ensureRandomUUID(): void {
|
|
9
|
+
const existing: Partial<Crypto> | undefined = globalThis.crypto;
|
|
10
|
+
if (typeof existing?.randomUUID === "function") return;
|
|
11
|
+
if (existing === undefined) {
|
|
12
|
+
Object.defineProperty(globalThis, "crypto", { configurable: true, value: { randomUUID } });
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
// A partial Web Crypto, such as a getRandomValues polyfill, keeps its members and gains randomUUID.
|
|
16
|
+
Object.defineProperty(existing, "randomUUID", { configurable: true, value: randomUUID });
|
|
17
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import type { SpaceClientPlatform } from "@q9labsai/chalk-client/effect";
|
|
3
|
+
const mocks = vi.hoisted(() => ({ platform: vi.fn(), whiteboard: vi.fn() }));
|
|
4
|
+
vi.mock("react-native", () => ({ AppState: { currentState: "active", addEventListener: vi.fn(() => ({ remove: vi.fn() })) } }));
|
|
5
|
+
vi.mock("@cloudflare/react-native-webrtc", () => ({ RTCPeerConnection: vi.fn(), mediaDevices: {} }));
|
|
6
|
+
vi.mock("@q9labsai/chalk-client/effect", () => ({ createSpaceClientForPlatform: mocks.platform }));
|
|
7
|
+
vi.mock("@q9labsai/chalk-client", async (original) => ({ ...(await original<typeof import("@q9labsai/chalk-client")>()), createChalkWhiteboardV1Client: mocks.whiteboard }));
|
|
8
|
+
import { createNativeSpaceClient } from "./create-native-space-client";
|
|
9
|
+
describe("native whiteboard watchdog adapter", () => {
|
|
10
|
+
it("passes the shared core's replacement recorder without a journey option", () => {
|
|
11
|
+
createNativeSpaceClient({
|
|
12
|
+
space: "test",
|
|
13
|
+
getAccess: async () => {
|
|
14
|
+
throw new Error("unused");
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
const platform: SpaceClientPlatform | undefined = mocks.platform.mock.calls[0]?.[1];
|
|
18
|
+
const onWatchdogReplacement = vi.fn();
|
|
19
|
+
platform?.dependencies?.createWhiteboardClient?.({ token: async () => "unused", onSummary: vi.fn(), onWatchdogReplacement });
|
|
20
|
+
expect(mocks.whiteboard).toHaveBeenCalledOnce();
|
|
21
|
+
expect(mocks.whiteboard.mock.calls[0]?.[0].onWatchdogReplacement).toBe(onWatchdogReplacement);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { SpaceSnapshot } from "@q9labsai/chalk-client";
|
|
2
|
+
import { memo, useMemo, useRef } from "react";
|
|
3
|
+
import { Pressable, StyleSheet, View } from "react-native";
|
|
4
|
+
import { EmbeddedWhiteboard } from "../components/EmbeddedWhiteboard";
|
|
5
|
+
import { RtcVideoView } from "../components/RtcVideoView";
|
|
6
|
+
import { useSpaceClient } from "../context/space-client-context";
|
|
7
|
+
import { useDevScenario } from "../frame/dev-scenario";
|
|
8
|
+
import { useMeasuredRef } from "../frame/measurement";
|
|
9
|
+
import { Icon } from "../icons/Icon";
|
|
10
|
+
import { createNativeMediaStream } from "../media/native-webrtc";
|
|
11
|
+
import type { Frame } from "../motion/MovingFrame";
|
|
12
|
+
import { ChalkText } from "../primitives/ChalkText";
|
|
13
|
+
import { NameTag } from "../primitives/NameTag";
|
|
14
|
+
import { useTheme } from "../theme/theme";
|
|
15
|
+
import { radii } from "../theme/tokens";
|
|
16
|
+
import { useSpaceSelector } from "./space-selector";
|
|
17
|
+
|
|
18
|
+
export type SharedContent = { readonly kind: "screen"; readonly sharerId: string } | { readonly kind: "board" };
|
|
19
|
+
|
|
20
|
+
export type ContentTileProps = {
|
|
21
|
+
readonly content: SharedContent;
|
|
22
|
+
/** The content's box inside the tile, letterboxed to its aspect. */
|
|
23
|
+
readonly inner: Frame;
|
|
24
|
+
/** A small tile in the rows; tapping it brings the content back to the spotlight. */
|
|
25
|
+
readonly mini: boolean;
|
|
26
|
+
readonly onShowInSpotlight: () => void;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/** The shared screen or board as one stage tile (`.tile.content`), kept mounted while it moves. */
|
|
30
|
+
export const ContentTile = memo(function ContentTile({ content, inner, mini, onShowInSpotlight }: ContentTileProps): React.JSX.Element {
|
|
31
|
+
const { colors } = useTheme();
|
|
32
|
+
const tileStyle = [styles.tile, { backgroundColor: colors.tile }];
|
|
33
|
+
const tileRef = useMeasuredRef<View>("tile.content", tileStyle);
|
|
34
|
+
return (
|
|
35
|
+
<View ref={tileRef} style={tileStyle} testID="tile.content">
|
|
36
|
+
{content.kind === "screen" ? <ScreenShare inner={inner} mini={mini} onShowInSpotlight={onShowInSpotlight} sharerId={content.sharerId} /> : <Board mini={mini} onShowInSpotlight={onShowInSpotlight} />}
|
|
37
|
+
</View>
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
function ScreenShare({ sharerId, inner, mini, onShowInSpotlight }: { readonly sharerId: string; readonly inner: Frame; readonly mini: boolean; readonly onShowInSpotlight: () => void }): React.JSX.Element {
|
|
42
|
+
const { colors } = useTheme();
|
|
43
|
+
const select = useMemo(() => (snapshot: SpaceSnapshot) => snapshot.media.remote.find((media) => media.participantId === sharerId && media.source === "screen")?.track ?? null, [sharerId]);
|
|
44
|
+
const track = useSpaceSelector(select);
|
|
45
|
+
const selectName = useMemo(() => (snapshot: SpaceSnapshot) => snapshot.participants.roster.find((person) => person.participantId === sharerId)?.displayName ?? "", [sharerId]);
|
|
46
|
+
const sharerName = useSpaceSelector(selectName);
|
|
47
|
+
const slot = useDevScenario().screenSlots?.[sharerId];
|
|
48
|
+
const streamURL = useMemo(() => (track ? createNativeMediaStream(track).toURL() : null), [track]);
|
|
49
|
+
const name = `${sharerName.split(" ")[0]}’s screen`;
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<>
|
|
53
|
+
<View style={[styles.box, { left: inner.x, top: inner.y, width: inner.width, height: inner.height, backgroundColor: colors.tile }]} testID="tile.content.screen">
|
|
54
|
+
{slot ?? (streamURL ? <RtcVideoView objectFit="contain" streamURL={streamURL} style={StyleSheet.absoluteFill} /> : null)}
|
|
55
|
+
</View>
|
|
56
|
+
{mini ? <Pressable accessibilityLabel={`Show ${name} in spotlight`} accessibilityRole="button" onPress={onShowInSpotlight} style={StyleSheet.absoluteFill} testID="tile.content.open" /> : null}
|
|
57
|
+
<NameTag icon="share" name={name} testID="tile.content.name" />
|
|
58
|
+
</>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const selectBoard = (snapshot: SpaceSnapshot) => snapshot.whiteboard.engine.status;
|
|
63
|
+
|
|
64
|
+
/** The shared board, view-only today, through the embedded whiteboard. It loads only while a board is shared. */
|
|
65
|
+
function Board({ mini, onShowInSpotlight }: { readonly mini: boolean; readonly onShowInSpotlight: () => void }): React.JSX.Element {
|
|
66
|
+
const client = useSpaceClient();
|
|
67
|
+
const { colors, scheme } = useTheme();
|
|
68
|
+
const status = useSpaceSelector(selectBoard);
|
|
69
|
+
const chipStyle = [styles.viewOnly, { backgroundColor: colors.surface, borderColor: colors.lineStrong }];
|
|
70
|
+
const chipRef = useMeasuredRef<View>("tile.content.view-only", chipStyle);
|
|
71
|
+
// The transport changes when the engine resubscribes.
|
|
72
|
+
const transport = useMemo(() => client.whiteboard.transport(), [client, status]);
|
|
73
|
+
const journeyId = useRef(`board-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`).current;
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<>
|
|
77
|
+
{transport ? <EmbeddedWhiteboard canClear={false} canDraw={false} journeyId={journeyId} style={StyleSheet.absoluteFill} testID="tile.content.board" theme={scheme} transport={transport} /> : null}
|
|
78
|
+
{mini ? (
|
|
79
|
+
<>
|
|
80
|
+
<Pressable accessibilityLabel="Show the board in spotlight" accessibilityRole="button" onPress={onShowInSpotlight} style={StyleSheet.absoluteFill} testID="tile.content.open" />
|
|
81
|
+
<NameTag icon="pen" name="Board" testID="tile.content.name" />
|
|
82
|
+
</>
|
|
83
|
+
) : (
|
|
84
|
+
<View accessibilityLiveRegion="polite" accessibilityRole="text" accessible ref={chipRef} style={chipStyle} testID="tile.content.view-only">
|
|
85
|
+
<Icon color={colors.textMuted} name="lock" size={16} />
|
|
86
|
+
<ChalkText tone="textSoft" variant="section">
|
|
87
|
+
View only
|
|
88
|
+
</ChalkText>
|
|
89
|
+
</View>
|
|
90
|
+
)}
|
|
91
|
+
</>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const styles = StyleSheet.create({
|
|
96
|
+
tile: { flex: 1, overflow: "hidden", borderRadius: radii.tilePhone },
|
|
97
|
+
box: { position: "absolute", overflow: "hidden" },
|
|
98
|
+
// `.vchip`: a 30 pt pill 12 pt in from the board's top-left corner, with a one-pixel ring.
|
|
99
|
+
viewOnly: { position: "absolute", left: 12, top: 12, height: 30, paddingHorizontal: 12, borderRadius: radii.round, borderWidth: 1, flexDirection: "row", alignItems: "center", gap: 6, zIndex: 3 },
|
|
100
|
+
});
|