@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
|
@@ -1,416 +0,0 @@
|
|
|
1
|
-
import type { ChatSendInput, Reaction } from "@q9labsai/chalk-client";
|
|
2
|
-
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
3
|
-
import { Alert, Linking, Platform } from "react-native";
|
|
4
|
-
import { mediaDevices } from "@cloudflare/react-native-webrtc";
|
|
5
|
-
|
|
6
|
-
import { useSpaceClient } from "../../context/space-client-context";
|
|
7
|
-
import { useChat as useSpaceChat, useMedia as useSpaceMedia, useParticipants as useSpaceParticipants, useReactions as useSpaceReactions, useSelf, useWhiteboard, useRecording, useConnection } from "../../hooks/space-hooks";
|
|
8
|
-
import { getNativeJourneyContext } from "../../telemetry";
|
|
9
|
-
import type { NativeChatMessage, NativeParticipant, NativeReaction } from "../../ui/native-types";
|
|
10
|
-
import { isIosSimulator } from "../../utils/ios-simulator";
|
|
11
|
-
import type { SpaceViewProps } from "../SpaceView";
|
|
12
|
-
import { buildSpaceViewDiagnosticsSnapshot } from "./diagnostics";
|
|
13
|
-
import { useSpaceViewDerived } from "./useSpaceViewDerived";
|
|
14
|
-
import { useSpaceViewPanels } from "./useSpaceViewPanels";
|
|
15
|
-
import { resolveNativeScreenShareAvailability } from "./screen-share-availability";
|
|
16
|
-
import { normalizeChatFileDrafts, uploadAndSendNativeChatAttachments, type NativeChatFileDraft } from "./space-chat-attachments";
|
|
17
|
-
|
|
18
|
-
const spaceReactions = new Set<Reaction>(["👍", "❤️", "😂", "😮", "😢", "🎉"]);
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* The native Space UI consumes the canonical SpaceClient snapshot directly.
|
|
22
|
-
* This keeps the mature native renderer intact without re-projecting client
|
|
23
|
-
* state through a retired compatibility layer.
|
|
24
|
-
*/
|
|
25
|
-
export function useSpaceViewController({ spaceName, inviteLink, layout: controlledLayout, onLayoutChange, features, onLeave, onEndEpisode, onDiagnosticsChange, pickChatFiles: pickChatFilesInput }: SpaceViewProps) {
|
|
26
|
-
const client = useSpaceClient();
|
|
27
|
-
const self = useSelf();
|
|
28
|
-
const participantSlice = useSpaceParticipants();
|
|
29
|
-
const media = useSpaceMedia();
|
|
30
|
-
const chatSlice = useSpaceChat();
|
|
31
|
-
const reactionSlice = useSpaceReactions();
|
|
32
|
-
const whiteboardSlice = useWhiteboard();
|
|
33
|
-
const recording = useRecording().current;
|
|
34
|
-
const connection = useConnection();
|
|
35
|
-
|
|
36
|
-
const journeyContext = getNativeJourneyContext(client);
|
|
37
|
-
const [actionsOpen, setActionsOpen] = useState(false);
|
|
38
|
-
const [reactionPickerOpen, setReactionPickerOpen] = useState(false);
|
|
39
|
-
const [chatDraft, setChatDraft] = useState("");
|
|
40
|
-
const [chatAttachments, setChatAttachments] = useState<readonly NativeChatFileDraft[]>([]);
|
|
41
|
-
const [chatAttachmentError, setChatAttachmentError] = useState<string | null>(null);
|
|
42
|
-
const [chatAttachmentPicking, setChatAttachmentPicking] = useState(false);
|
|
43
|
-
const [chatAttachmentUploading, setChatAttachmentUploading] = useState(false);
|
|
44
|
-
|
|
45
|
-
const run = useCallback(async (action: () => unknown | Promise<unknown>) => {
|
|
46
|
-
try {
|
|
47
|
-
await action();
|
|
48
|
-
} catch (cause) {
|
|
49
|
-
Alert.alert("Action failed", cause instanceof Error ? cause.message : "Chalk could not complete the action.");
|
|
50
|
-
}
|
|
51
|
-
}, []);
|
|
52
|
-
|
|
53
|
-
const localParticipantId = self.participantId;
|
|
54
|
-
const participants = useMemo(
|
|
55
|
-
() =>
|
|
56
|
-
participantSlice.roster.map((participant): NativeParticipant => {
|
|
57
|
-
const local = participant.participantId === localParticipantId;
|
|
58
|
-
const remoteMedia = media.remote.filter((publication) => publication.participantId === participant.participantId);
|
|
59
|
-
return {
|
|
60
|
-
...participant,
|
|
61
|
-
id: participant.participantId,
|
|
62
|
-
audioEnabled: local ? media.local.microphone.state === "enabled" : participant.media.microphone === "active",
|
|
63
|
-
videoEnabled: local ? media.local.camera.state === "enabled" || media.local.camera.state === "requesting" : participant.media.camera === "active",
|
|
64
|
-
audioTrack: local ? media.local.microphone.track : (remoteMedia.find((publication) => publication.source === "microphone")?.track ?? null),
|
|
65
|
-
videoTrack: local ? media.local.camera.track : (remoteMedia.find((publication) => publication.source === "camera")?.track ?? null),
|
|
66
|
-
screenShareTrack: local ? media.screenShare.track : (remoteMedia.find((publication) => publication.source === "screen")?.track ?? null),
|
|
67
|
-
};
|
|
68
|
-
}),
|
|
69
|
-
[localParticipantId, media.local.camera, media.local.microphone, media.remote, media.screenShare.track, participantSlice.roster],
|
|
70
|
-
);
|
|
71
|
-
const localParticipant = useMemo(() => participants.find((participant) => participant.id === localParticipantId) ?? null, [localParticipantId, participants]);
|
|
72
|
-
const spaceParticipants = useMemo(
|
|
73
|
-
() => ({
|
|
74
|
-
participants,
|
|
75
|
-
localParticipant,
|
|
76
|
-
remoteParticipants: participants.filter((participant) => participant.id !== localParticipantId),
|
|
77
|
-
activeSpeaker: null,
|
|
78
|
-
count: participants.length,
|
|
79
|
-
participantCount: participants.length,
|
|
80
|
-
getParticipant: (participantId: string) => participants.find((participant) => participant.id === participantId),
|
|
81
|
-
updateDisplayName: (displayName: string) => client.participants.renameSelf(displayName),
|
|
82
|
-
}),
|
|
83
|
-
[client.participants, localParticipant, localParticipantId, participants],
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
const isLocalSharing = media.screenShare.state === "enabled" || media.screenShare.state === "requesting";
|
|
87
|
-
const remoteScreenShare = useMemo(() => media.remote.find((publication) => publication.source === "screen") ?? null, [media.remote]);
|
|
88
|
-
const screenShare = useMemo(
|
|
89
|
-
() => ({
|
|
90
|
-
isActive: isLocalSharing || remoteScreenShare !== null,
|
|
91
|
-
isStarting: media.screenShare.state === "requesting",
|
|
92
|
-
isLocalSharing,
|
|
93
|
-
sharerParticipantId: isLocalSharing ? localParticipantId : (remoteScreenShare?.participantId ?? null),
|
|
94
|
-
videoTrack: isLocalSharing ? media.screenShare.track : (remoteScreenShare?.track ?? null),
|
|
95
|
-
audioTrack: null,
|
|
96
|
-
start: async () => {
|
|
97
|
-
await client.media.setScreenShareEnabled(true);
|
|
98
|
-
return true;
|
|
99
|
-
},
|
|
100
|
-
stop: () => client.media.setScreenShareEnabled(false),
|
|
101
|
-
toggle: async () => {
|
|
102
|
-
const enabled = !isLocalSharing;
|
|
103
|
-
await client.media.setScreenShareEnabled(enabled);
|
|
104
|
-
return enabled;
|
|
105
|
-
},
|
|
106
|
-
}),
|
|
107
|
-
[client.media, isLocalSharing, localParticipantId, media.screenShare.state, media.screenShare.track, remoteScreenShare],
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
const interactionState = useMemo(() => {
|
|
111
|
-
const raisedHands = participantSlice.roster.filter((participant) => participant.handRaised).map((participant) => participant.participantId);
|
|
112
|
-
const activeReactions: NativeReaction[] = reactionSlice.active.map((reaction) => ({
|
|
113
|
-
id: reaction.eventId,
|
|
114
|
-
emoji: reaction.reaction,
|
|
115
|
-
participantId: reaction.participantId,
|
|
116
|
-
participantName: reaction.displayName,
|
|
117
|
-
}));
|
|
118
|
-
return {
|
|
119
|
-
isHandRaised: self.handRaised,
|
|
120
|
-
raisedHands,
|
|
121
|
-
raisedHandCount: raisedHands.length,
|
|
122
|
-
activeReactions,
|
|
123
|
-
reactionEnabled: self.can("sendReaction"),
|
|
124
|
-
raiseHand: () => client.participants.raiseHand(),
|
|
125
|
-
lowerHand: () => client.participants.lowerHand(),
|
|
126
|
-
toggleHand: () => (self.handRaised ? client.participants.lowerHand() : client.participants.raiseHand()),
|
|
127
|
-
sendReaction: (reaction: Reaction) => client.reactions.send(reaction),
|
|
128
|
-
};
|
|
129
|
-
}, [client.participants, client.reactions, participantSlice.roster, reactionSlice.active, self]);
|
|
130
|
-
|
|
131
|
-
const chat = useMemo(() => {
|
|
132
|
-
const messages: NativeChatMessage[] = chatSlice.messages.map((message) => ({
|
|
133
|
-
id: message.messageId,
|
|
134
|
-
sequence: message.sequence,
|
|
135
|
-
senderId: message.participantId,
|
|
136
|
-
senderName: message.displayName,
|
|
137
|
-
text: message.text,
|
|
138
|
-
content: message.text,
|
|
139
|
-
attachments: message.attachments,
|
|
140
|
-
readBy: chatSlice.readReceipts
|
|
141
|
-
.filter((receipt) => receipt.participantId !== message.participantId && receipt.participantId !== localParticipantId && sequenceAtOrAfter(receipt.readThroughSequence, message.sequence))
|
|
142
|
-
.map((receipt) => ({
|
|
143
|
-
...receipt,
|
|
144
|
-
displayName: participantSlice.roster.find((participant) => participant.participantId === receipt.participantId)?.displayName ?? "Participant",
|
|
145
|
-
})),
|
|
146
|
-
timestamp: Date.parse(message.createdAt),
|
|
147
|
-
}));
|
|
148
|
-
const pendingMessages = chatSlice.pendingSends.map((pending) => ({ ...pending, state: pending.status }));
|
|
149
|
-
const sendMessage = (content: string | ChatSendInput) => client.chat.send(typeof content === "string" ? { text: content } : content).then(() => undefined);
|
|
150
|
-
const markAsRead = (throughSequence?: string) => {
|
|
151
|
-
const target = throughSequence ? chatSlice.messages.find((message) => message.sequence === throughSequence) : chatSlice.messages.at(-1);
|
|
152
|
-
return target ? client.chat.markRead(target.messageId) : Promise.resolve(null);
|
|
153
|
-
};
|
|
154
|
-
return {
|
|
155
|
-
messages,
|
|
156
|
-
isEnabled: self.can("sendChat"),
|
|
157
|
-
count: messages.length,
|
|
158
|
-
unreadCount: chatSlice.unreadCount,
|
|
159
|
-
pendingMessages,
|
|
160
|
-
hasMore: chatSlice.pagination.hasOlder,
|
|
161
|
-
isLoadingOlder: chatSlice.status === "loading",
|
|
162
|
-
sendMessage,
|
|
163
|
-
retryMessage: (clientMessageId: string) => {
|
|
164
|
-
const pending = chatSlice.pendingSends.find((message) => message.clientMessageId === clientMessageId);
|
|
165
|
-
return pending ? client.chat.send({ text: pending.text, attachments: pending.attachments }).then(() => undefined) : Promise.reject(new Error("The pending message is no longer available."));
|
|
166
|
-
},
|
|
167
|
-
loadOlderMessages: () => client.chat.loadOlder().then(() => undefined),
|
|
168
|
-
reactToMessage: () => {
|
|
169
|
-
throw new Error("Per-message reactions are not part of the actions contract.");
|
|
170
|
-
},
|
|
171
|
-
markAsRead,
|
|
172
|
-
markAsHidden: markAsRead,
|
|
173
|
-
getMessage: (id: string) => messages.find((message) => message.id === id),
|
|
174
|
-
};
|
|
175
|
-
}, [chatSlice, client.chat, localParticipantId, participantSlice.roster, self]);
|
|
176
|
-
|
|
177
|
-
const canWhiteboard = features?.whiteboard !== false && whiteboardSlice.engine.status !== "unsubscribed";
|
|
178
|
-
const canDraw = canWhiteboard && self.can("drawWhiteboard");
|
|
179
|
-
const canClear = canWhiteboard && self.can("manageWhiteboard");
|
|
180
|
-
const whiteboardTransport = useMemo(() => client.whiteboard.transport(), [client.whiteboard, whiteboardSlice.engine.status]);
|
|
181
|
-
const canEndEpisode = self.can("endEpisode");
|
|
182
|
-
const screenShareAvailability = useMemo(() => resolveNativeScreenShareAvailability({ featureEnabled: features?.screenShare !== false, platform: Platform.OS, simulator: isIosSimulator(), captureAvailable: typeof mediaDevices.getDisplayMedia === "function" }), [features?.screenShare]);
|
|
183
|
-
const capabilities = useMemo(
|
|
184
|
-
() => ({
|
|
185
|
-
canEndEpisode,
|
|
186
|
-
canChat: features?.chat !== false && self.can("sendChat"),
|
|
187
|
-
canParticipants: features?.participants !== false,
|
|
188
|
-
canScreenShare: screenShareAvailability.enabled && self.can("publishScreen"),
|
|
189
|
-
canReactions: features?.reactions !== false && self.can("sendReaction"),
|
|
190
|
-
canHandRaise: features?.handRaise !== false && self.can("raiseHand"),
|
|
191
|
-
canInvite: features?.info !== false && Boolean(inviteLink),
|
|
192
|
-
canSettings: features?.settings !== false,
|
|
193
|
-
canWhiteboard,
|
|
194
|
-
canManageAdmission: features?.admission !== false && self.can("manageAdmission"),
|
|
195
|
-
canRequestMedia: self.can("requestMediaOthers"),
|
|
196
|
-
canMuteParticipants: self.can("muteOthers"),
|
|
197
|
-
canRemoveParticipants: self.can("removeParticipant"),
|
|
198
|
-
canStopParticipantCamera: self.can("stopVideoOthers"),
|
|
199
|
-
canStopParticipantScreenShare: self.can("stopScreenOthers"),
|
|
200
|
-
canModerate: self.can("manageAdmission") || self.can("assignRoles") || self.can("requestMediaOthers") || self.can("muteOthers") || self.can("removeParticipant") || self.can("stopVideoOthers") || self.can("stopScreenOthers"),
|
|
201
|
-
screenShareAvailability,
|
|
202
|
-
}),
|
|
203
|
-
[canEndEpisode, canWhiteboard, features?.admission, features?.chat, features?.handRaise, features?.info, features?.participants, features?.reactions, features?.settings, inviteLink, screenShareAvailability, self],
|
|
204
|
-
);
|
|
205
|
-
|
|
206
|
-
const spacePanels = useSpaceViewPanels({
|
|
207
|
-
spaceName,
|
|
208
|
-
inviteLink,
|
|
209
|
-
layout: controlledLayout,
|
|
210
|
-
onLayoutChange,
|
|
211
|
-
canWhiteboard,
|
|
212
|
-
canDraw,
|
|
213
|
-
canClear,
|
|
214
|
-
canEndEpisode,
|
|
215
|
-
transport: whiteboardTransport,
|
|
216
|
-
onLeave,
|
|
217
|
-
onEndEpisode,
|
|
218
|
-
run,
|
|
219
|
-
journeyContext,
|
|
220
|
-
});
|
|
221
|
-
const derived = useSpaceViewDerived({ participants, localParticipant, screenShare, isWhiteboardOpen: spacePanels.whiteboard.isOpen });
|
|
222
|
-
|
|
223
|
-
useEffect(() => {
|
|
224
|
-
const request = media.incomingRequests[0];
|
|
225
|
-
if (!request) return;
|
|
226
|
-
Alert.alert(request.kind === "unmute" ? "Unmute request" : "Camera request", `${request.actorDisplayName ?? "A Space organizer"} is asking you to ${request.kind === "unmute" ? "unmute" : "start your camera"}.`, [
|
|
227
|
-
{ text: "Not now", style: "cancel", onPress: () => void run(() => client.media.declineRequest(request.requestId)) },
|
|
228
|
-
{ text: "Allow", onPress: () => void run(() => client.media.acceptRequest(request.requestId)) },
|
|
229
|
-
]);
|
|
230
|
-
}, [client.media, media.incomingRequests, run]);
|
|
231
|
-
|
|
232
|
-
const spaceDiagnostics = useMemo(
|
|
233
|
-
() =>
|
|
234
|
-
buildSpaceViewDiagnosticsSnapshot({
|
|
235
|
-
featureFlags: {
|
|
236
|
-
chat: capabilities.canChat,
|
|
237
|
-
participants: capabilities.canParticipants,
|
|
238
|
-
screenShare: capabilities.canScreenShare,
|
|
239
|
-
reactions: capabilities.canReactions,
|
|
240
|
-
handRaise: capabilities.canHandRaise,
|
|
241
|
-
whiteboard: capabilities.canWhiteboard,
|
|
242
|
-
},
|
|
243
|
-
canEndEpisode: capabilities.canEndEpisode,
|
|
244
|
-
participantCount: spaceParticipants.participantCount,
|
|
245
|
-
raisedHandCount: interactionState.raisedHandCount,
|
|
246
|
-
unreadChatCount: chat.unreadCount,
|
|
247
|
-
isScreenShareActive: screenShare.isActive,
|
|
248
|
-
isLocalScreenSharing: screenShare.isLocalSharing,
|
|
249
|
-
screenShareSharerParticipantId: screenShare.sharerParticipantId,
|
|
250
|
-
canModerate: capabilities.canModerate,
|
|
251
|
-
screenShareAvailability,
|
|
252
|
-
}),
|
|
253
|
-
[capabilities, chat.unreadCount, interactionState.raisedHandCount, spaceParticipants.participantCount, screenShare.isActive, screenShare.isLocalSharing, screenShare.sharerParticipantId, screenShareAvailability],
|
|
254
|
-
);
|
|
255
|
-
useEffect(() => onDiagnosticsChange?.(spaceDiagnostics), [onDiagnosticsChange, spaceDiagnostics]);
|
|
256
|
-
|
|
257
|
-
const pickChatFiles = useCallback(async () => {
|
|
258
|
-
if (!pickChatFilesInput) return;
|
|
259
|
-
setChatAttachmentPicking(true);
|
|
260
|
-
try {
|
|
261
|
-
const picked = normalizeChatFileDrafts(await pickChatFilesInput());
|
|
262
|
-
if (picked.error) {
|
|
263
|
-
setChatAttachmentError(picked.error);
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
const combined = normalizeChatFileDrafts([...chatAttachments.map((draft) => draft.file), ...picked.files.map((draft) => draft.file)]);
|
|
267
|
-
if (combined.error) {
|
|
268
|
-
setChatAttachmentError(combined.error);
|
|
269
|
-
return;
|
|
270
|
-
}
|
|
271
|
-
setChatAttachmentError(null);
|
|
272
|
-
setChatAttachments(combined.files);
|
|
273
|
-
} catch (cause) {
|
|
274
|
-
setChatAttachmentError(cause instanceof Error ? cause.message : "Could not read the selected files.");
|
|
275
|
-
} finally {
|
|
276
|
-
setChatAttachmentPicking(false);
|
|
277
|
-
}
|
|
278
|
-
}, [chatAttachments, pickChatFilesInput]);
|
|
279
|
-
|
|
280
|
-
const removeChatAttachment = useCallback((index: number) => {
|
|
281
|
-
setChatAttachments((current) => current.filter((_, currentIndex) => currentIndex !== index));
|
|
282
|
-
setChatAttachmentError(null);
|
|
283
|
-
}, []);
|
|
284
|
-
|
|
285
|
-
const sendChatMessage = useCallback(() => {
|
|
286
|
-
const text = chatDraft.trim();
|
|
287
|
-
if (!text && chatAttachments.length === 0) return;
|
|
288
|
-
void run(async () => {
|
|
289
|
-
setChatAttachmentUploading(true);
|
|
290
|
-
setChatAttachmentError(null);
|
|
291
|
-
try {
|
|
292
|
-
await uploadAndSendNativeChatAttachments(chatAttachments, text, client.chat.files.upload, chat.sendMessage);
|
|
293
|
-
setChatDraft("");
|
|
294
|
-
setChatAttachments([]);
|
|
295
|
-
} catch (cause) {
|
|
296
|
-
setChatAttachmentError(cause instanceof Error ? cause.message : "Could not send the attachments.");
|
|
297
|
-
throw cause;
|
|
298
|
-
} finally {
|
|
299
|
-
setChatAttachmentUploading(false);
|
|
300
|
-
}
|
|
301
|
-
});
|
|
302
|
-
}, [chat, chatAttachments, chatDraft, client.chat.files, run]);
|
|
303
|
-
|
|
304
|
-
const resolveChatAttachmentUrl = useCallback(
|
|
305
|
-
async (attachmentId: string) => {
|
|
306
|
-
const attachment = chatSlice.messages.flatMap((message) => message.attachments).find((candidate) => candidate.attachmentId === attachmentId);
|
|
307
|
-
return attachment ? client.chat.files.resolveUrl(attachment) : null;
|
|
308
|
-
},
|
|
309
|
-
[chatSlice.messages, client.chat.files],
|
|
310
|
-
);
|
|
311
|
-
|
|
312
|
-
return {
|
|
313
|
-
recording,
|
|
314
|
-
canManageRecording: self.can("manageRecording"),
|
|
315
|
-
canToggleRecording: connection.status === "live" && recording?.status !== "starting" && recording?.status !== "stopping",
|
|
316
|
-
toggleRecording: () => void run(() => (recording?.status === "recording" ? client.recording.stop() : client.recording.start())),
|
|
317
|
-
simulatorMediaDisabled: isIosSimulator(),
|
|
318
|
-
spaceName: spaceName || "Space",
|
|
319
|
-
panel: spacePanels.panel,
|
|
320
|
-
selfName: self.displayName || "Participant",
|
|
321
|
-
isMuted: media.local.microphone.state !== "enabled",
|
|
322
|
-
isCameraOff: !(media.local.camera.state === "enabled" || media.local.camera.state === "requesting"),
|
|
323
|
-
handRaised: interactionState.isHandRaised,
|
|
324
|
-
raisedHandCount: interactionState.raisedHandCount,
|
|
325
|
-
activeReactions: interactionState.activeReactions.slice(-3),
|
|
326
|
-
secondsElapsed: spacePanels.secondsElapsed,
|
|
327
|
-
formattedDuration: spacePanels.formattedDuration,
|
|
328
|
-
actionsOpen,
|
|
329
|
-
reactionPickerOpen,
|
|
330
|
-
chatDraft,
|
|
331
|
-
chatAttachments,
|
|
332
|
-
chatAttachmentError,
|
|
333
|
-
chatAttachmentPicking,
|
|
334
|
-
chatAttachmentUploading,
|
|
335
|
-
canPickChatFiles: Boolean(pickChatFilesInput),
|
|
336
|
-
participantCount: spaceParticipants.participantCount,
|
|
337
|
-
canChat: capabilities.canChat,
|
|
338
|
-
canParticipants: capabilities.canParticipants,
|
|
339
|
-
canScreenShare: capabilities.canScreenShare,
|
|
340
|
-
screenShareUnavailableReason: features?.screenShare !== false && self.can("publishScreen") ? screenShareAvailability.detail : null,
|
|
341
|
-
canReactions: capabilities.canReactions,
|
|
342
|
-
canHandRaise: capabilities.canHandRaise,
|
|
343
|
-
canInvite: capabilities.canInvite,
|
|
344
|
-
canSettings: capabilities.canSettings,
|
|
345
|
-
canWhiteboard: capabilities.canWhiteboard,
|
|
346
|
-
canManageAdmission: capabilities.canManageAdmission,
|
|
347
|
-
canRequestMedia: capabilities.canRequestMedia,
|
|
348
|
-
canMuteParticipants: capabilities.canMuteParticipants,
|
|
349
|
-
canRemoveParticipants: capabilities.canRemoveParticipants,
|
|
350
|
-
canStopParticipantCamera: capabilities.canStopParticipantCamera,
|
|
351
|
-
canStopParticipantScreenShare: capabilities.canStopParticipantScreenShare,
|
|
352
|
-
admissionRequests: participantSlice.admissionQueue,
|
|
353
|
-
spaceDiagnostics,
|
|
354
|
-
participants: spaceParticipants,
|
|
355
|
-
settings: {
|
|
356
|
-
displayName: self.displayName ?? "",
|
|
357
|
-
microphoneEnabled: media.local.microphone.state === "enabled",
|
|
358
|
-
cameraEnabled: media.local.camera.state === "enabled" || media.local.camera.state === "requesting",
|
|
359
|
-
devices: media.devices,
|
|
360
|
-
selection: media.selection,
|
|
361
|
-
updateDisplayName: (displayName: string) => {
|
|
362
|
-
const nextDisplayName = displayName.trim();
|
|
363
|
-
if (nextDisplayName) void run(() => client.participants.renameSelf(nextDisplayName));
|
|
364
|
-
},
|
|
365
|
-
selectMicrophone: (deviceId: string) => void run(() => client.media.selectMicrophone(deviceId)),
|
|
366
|
-
selectCamera: (deviceId: string) => void run(() => client.media.selectCamera(deviceId)),
|
|
367
|
-
selectSpeaker: (deviceId: string) => void run(() => client.media.selectSpeaker(deviceId)),
|
|
368
|
-
},
|
|
369
|
-
chat,
|
|
370
|
-
interactions: interactionState,
|
|
371
|
-
screenShare,
|
|
372
|
-
layout: spacePanels.layout,
|
|
373
|
-
whiteboard: spacePanels.whiteboard,
|
|
374
|
-
derived,
|
|
375
|
-
setActionsOpen,
|
|
376
|
-
setReactionPickerOpen,
|
|
377
|
-
setChatDraft,
|
|
378
|
-
pickChatFiles,
|
|
379
|
-
removeChatAttachment,
|
|
380
|
-
handleLeave: spacePanels.handleLeave,
|
|
381
|
-
openPanel: spacePanels.openPanel,
|
|
382
|
-
closePanel: spacePanels.closePanel,
|
|
383
|
-
handleInviteParticipants: spacePanels.handleInviteParticipants,
|
|
384
|
-
toggleAudio: () => void run(() => client.media.setMicrophoneEnabled(!(media.local.microphone.state === "enabled" || media.local.microphone.state === "requesting"))),
|
|
385
|
-
toggleVideo: () => void run(() => client.media.setCameraEnabled(!(media.local.camera.state === "enabled" || media.local.camera.state === "requesting"))),
|
|
386
|
-
toggleScreenShare: () => void run(screenShare.toggle),
|
|
387
|
-
toggleHand: () => void run(interactionState.toggleHand),
|
|
388
|
-
sendReaction: (reaction: Reaction) => {
|
|
389
|
-
if (!spaceReactions.has(reaction)) return;
|
|
390
|
-
void run(() => interactionState.sendReaction(reaction));
|
|
391
|
-
},
|
|
392
|
-
sendChatMessage,
|
|
393
|
-
resolveChatAttachmentUrl,
|
|
394
|
-
openChatAttachment: (attachmentId: string) => {
|
|
395
|
-
void run(async () => {
|
|
396
|
-
const url = await resolveChatAttachmentUrl(attachmentId);
|
|
397
|
-
if (url) await Linking.openURL(url);
|
|
398
|
-
});
|
|
399
|
-
},
|
|
400
|
-
markChatMessageVisible: (sequence: string) => void run(() => chat.markAsRead(sequence)),
|
|
401
|
-
admitParticipant: (requestId: string) => void run(() => client.participants.admit(requestId)),
|
|
402
|
-
denyAdmission: (requestId: string) => void run(() => client.participants.deny(requestId)),
|
|
403
|
-
removeParticipant: (participantId: string) => void run(() => client.participants.remove(participantId)),
|
|
404
|
-
muteParticipant: (participantId: string) => void run(() => client.participants.mute(participantId)),
|
|
405
|
-
requestUnmuteParticipant: (participantId: string) => void run(() => client.participants.requestMedia(participantId, "microphone")),
|
|
406
|
-
requestStartParticipantCamera: (participantId: string) => void run(() => client.participants.requestMedia(participantId, "camera")),
|
|
407
|
-
stopParticipantCamera: (participantId: string) => void run(() => client.participants.stopVideo(participantId)),
|
|
408
|
-
stopParticipantScreenShare: (participantId: string) => void run(() => client.participants.stopScreenShare(participantId)),
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
function sequenceAtOrAfter(value: string, floor: string): boolean {
|
|
413
|
-
const normalizedValue = value.replace(/^0+(?=\d)/, "");
|
|
414
|
-
const normalizedFloor = floor.replace(/^0+(?=\d)/, "");
|
|
415
|
-
return normalizedValue.length > normalizedFloor.length || (normalizedValue.length === normalizedFloor.length && normalizedValue >= normalizedFloor);
|
|
416
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { NativeParticipantState } from "../../ui/native-types";
|
|
2
|
-
import { useMemo } from "react";
|
|
3
|
-
import { useWindowDimensions } from "react-native";
|
|
4
|
-
import { NATIVE_COMPACT_VIEWPORT_MAX_WIDTH, resolveNativeSpaceLayout, type NativeScreenShareStateLike } from "../../utils/native-space-layout";
|
|
5
|
-
|
|
6
|
-
type SpaceParticipant = NativeParticipantState["participants"][number];
|
|
7
|
-
|
|
8
|
-
interface UseSpaceViewDerivedOptions {
|
|
9
|
-
participants: readonly SpaceParticipant[];
|
|
10
|
-
localParticipant: SpaceParticipant | null;
|
|
11
|
-
screenShare: NativeScreenShareStateLike;
|
|
12
|
-
isWhiteboardOpen: boolean;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function useSpaceViewDerived({ participants, localParticipant, screenShare, isWhiteboardOpen }: UseSpaceViewDerivedOptions) {
|
|
16
|
-
const { width } = useWindowDimensions();
|
|
17
|
-
|
|
18
|
-
return useMemo(
|
|
19
|
-
() =>
|
|
20
|
-
resolveNativeSpaceLayout({
|
|
21
|
-
participants,
|
|
22
|
-
localParticipant,
|
|
23
|
-
screenShare,
|
|
24
|
-
isWhiteboardOpen,
|
|
25
|
-
isCompactViewport: width < NATIVE_COMPACT_VIEWPORT_MAX_WIDTH,
|
|
26
|
-
}),
|
|
27
|
-
[participants, localParticipant, screenShare, isWhiteboardOpen, width],
|
|
28
|
-
);
|
|
29
|
-
}
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import type { ChalkWhiteboardV1Transport } from "@q9labsai/chalk-client";
|
|
2
|
-
import { useCallback, useEffect, useMemo, useRef, useState, type Dispatch, type SetStateAction } from "react";
|
|
3
|
-
import { Alert, type AlertButton, Share } from "react-native";
|
|
4
|
-
|
|
5
|
-
import { useLayout, type UseLayoutReturn } from "../../hooks/useLayout";
|
|
6
|
-
import type { NativeJourneyContext, WhiteboardMetric } from "../../telemetry";
|
|
7
|
-
import type { SpaceViewProps } from "../SpaceView";
|
|
8
|
-
import { formatSpaceDuration } from "./format-space-duration";
|
|
9
|
-
import type { SpaceViewActionRunner, SpacePanelName } from "./types";
|
|
10
|
-
|
|
11
|
-
const emptyElements: readonly unknown[] = Object.freeze([]);
|
|
12
|
-
const emptyParticipants: readonly string[] = Object.freeze([]);
|
|
13
|
-
|
|
14
|
-
export interface SpaceWhiteboardState {
|
|
15
|
-
readonly isOpen: boolean;
|
|
16
|
-
readonly canDraw: boolean;
|
|
17
|
-
readonly canClear: boolean;
|
|
18
|
-
readonly elements: readonly unknown[];
|
|
19
|
-
readonly openParticipants: readonly string[];
|
|
20
|
-
readonly transport: ChalkWhiteboardV1Transport | null;
|
|
21
|
-
readonly journeyId: string;
|
|
22
|
-
readonly traceparent?: string;
|
|
23
|
-
readonly tracestate?: string;
|
|
24
|
-
readonly onMetric?: (metric: WhiteboardMetric) => void;
|
|
25
|
-
readonly open: () => void;
|
|
26
|
-
readonly close: () => void;
|
|
27
|
-
readonly toggle: () => void;
|
|
28
|
-
readonly requestSync: () => void;
|
|
29
|
-
readonly clear: () => void;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface SpaceViewPanels {
|
|
33
|
-
readonly layout: UseLayoutReturn;
|
|
34
|
-
readonly panel: SpacePanelName | null;
|
|
35
|
-
readonly secondsElapsed: number;
|
|
36
|
-
readonly formattedDuration: string;
|
|
37
|
-
readonly actionsOpen: boolean;
|
|
38
|
-
readonly reactionPickerOpen: boolean;
|
|
39
|
-
readonly settingsOpen: boolean;
|
|
40
|
-
readonly whiteboard: SpaceWhiteboardState;
|
|
41
|
-
readonly setActionsOpen: Dispatch<SetStateAction<boolean>>;
|
|
42
|
-
readonly setReactionPickerOpen: Dispatch<SetStateAction<boolean>>;
|
|
43
|
-
readonly handleLeave: () => void;
|
|
44
|
-
readonly openPanel: (nextPanel: SpacePanelName) => void;
|
|
45
|
-
readonly closePanel: () => void;
|
|
46
|
-
readonly handleInviteParticipants: () => void;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
interface UseSpaceViewPanelsOptions {
|
|
50
|
-
readonly spaceName?: string;
|
|
51
|
-
readonly inviteLink?: string;
|
|
52
|
-
readonly layout?: SpaceViewProps["layout"];
|
|
53
|
-
readonly onLayoutChange?: SpaceViewProps["onLayoutChange"];
|
|
54
|
-
readonly canWhiteboard: boolean;
|
|
55
|
-
readonly canDraw: boolean;
|
|
56
|
-
readonly canClear: boolean;
|
|
57
|
-
readonly canEndEpisode: boolean;
|
|
58
|
-
readonly transport: ChalkWhiteboardV1Transport | null;
|
|
59
|
-
readonly onLeave: SpaceViewProps["onLeave"];
|
|
60
|
-
readonly onEndEpisode: SpaceViewProps["onEndEpisode"];
|
|
61
|
-
readonly run: SpaceViewActionRunner;
|
|
62
|
-
readonly journeyContext?: NativeJourneyContext;
|
|
63
|
-
/** Test-fixture state only; SpaceView does not expose controlled panel state publicly. */
|
|
64
|
-
readonly initialState?: SpaceViewFixtureState;
|
|
65
|
-
/** Test-fixture state only; SpaceView does not expose controlled panel state publicly. */
|
|
66
|
-
readonly controlledState?: SpaceViewFixtureState;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
type SpaceViewFixtureState = {
|
|
70
|
-
readonly layout?: SpaceViewProps["layout"];
|
|
71
|
-
readonly panel?: SpacePanelName | null;
|
|
72
|
-
readonly actionsOpen?: boolean;
|
|
73
|
-
readonly reactionPickerOpen?: boolean;
|
|
74
|
-
readonly settingsOpen?: boolean;
|
|
75
|
-
readonly durationSeconds?: number;
|
|
76
|
-
readonly whiteboardOpen?: boolean;
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
export function useSpaceViewPanels({ spaceName, inviteLink, layout: controlledLayout, onLayoutChange, canWhiteboard, canDraw, canClear, canEndEpisode, transport, onLeave, onEndEpisode, run, journeyContext, initialState, controlledState }: UseSpaceViewPanelsOptions): SpaceViewPanels {
|
|
80
|
-
const fixtureLayout = controlledState?.layout ?? initialState?.layout ?? controlledLayout;
|
|
81
|
-
const layout = useLayout({ layout: fixtureLayout, onLayoutChange });
|
|
82
|
-
const [panel, setPanel] = useState<SpacePanelName | null>(initialState?.panel ?? null);
|
|
83
|
-
const [actionsOpen, setActionsOpen] = useState(initialState?.actionsOpen ?? false);
|
|
84
|
-
const [reactionPickerOpen, setReactionPickerOpen] = useState(initialState?.reactionPickerOpen ?? false);
|
|
85
|
-
const [secondsElapsed, setSecondsElapsed] = useState(0);
|
|
86
|
-
const [settingsOpen, setSettingsOpen] = useState(initialState?.settingsOpen ?? false);
|
|
87
|
-
const [whiteboardOpen, setWhiteboardOpen] = useState(initialState?.whiteboardOpen ?? false);
|
|
88
|
-
const generatedJourneyId = useRef(globalThis.crypto?.randomUUID?.() ?? `native-whiteboard-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
89
|
-
|
|
90
|
-
useEffect(() => {
|
|
91
|
-
const durationSeconds = Math.max(0, Math.floor(controlledState?.durationSeconds ?? initialState?.durationSeconds ?? 0));
|
|
92
|
-
const startedAt = Date.now() - durationSeconds * 1_000;
|
|
93
|
-
const update = () => setSecondsElapsed(Math.max(0, Math.floor((Date.now() - startedAt) / 1_000)));
|
|
94
|
-
update();
|
|
95
|
-
const timer = globalThis.setInterval(update, 1_000);
|
|
96
|
-
return () => globalThis.clearInterval(timer);
|
|
97
|
-
}, [controlledState?.durationSeconds, initialState?.durationSeconds]);
|
|
98
|
-
|
|
99
|
-
useEffect(() => {
|
|
100
|
-
if (controlledState?.panel !== undefined) setPanel(controlledState.panel ?? null);
|
|
101
|
-
if (controlledState?.actionsOpen !== undefined) setActionsOpen(controlledState.actionsOpen);
|
|
102
|
-
if (controlledState?.reactionPickerOpen !== undefined) setReactionPickerOpen(controlledState.reactionPickerOpen);
|
|
103
|
-
if (controlledState?.settingsOpen !== undefined) setSettingsOpen(controlledState.settingsOpen);
|
|
104
|
-
if (controlledState?.whiteboardOpen !== undefined) setWhiteboardOpen(controlledState.whiteboardOpen);
|
|
105
|
-
}, [controlledState]);
|
|
106
|
-
|
|
107
|
-
const whiteboard = useMemo<SpaceWhiteboardState>(
|
|
108
|
-
() => ({
|
|
109
|
-
isOpen: canWhiteboard && whiteboardOpen,
|
|
110
|
-
canDraw: canWhiteboard && canDraw,
|
|
111
|
-
canClear: canWhiteboard && canClear,
|
|
112
|
-
elements: emptyElements,
|
|
113
|
-
openParticipants: emptyParticipants,
|
|
114
|
-
transport,
|
|
115
|
-
journeyId: journeyContext?.journeyId ?? generatedJourneyId.current,
|
|
116
|
-
...(journeyContext?.traceparent ? { traceparent: journeyContext.traceparent } : {}),
|
|
117
|
-
...(journeyContext?.tracestate ? { tracestate: journeyContext.tracestate } : {}),
|
|
118
|
-
...(journeyContext ? { onMetric: journeyContext.recordWhiteboardMetric } : {}),
|
|
119
|
-
open: () => canWhiteboard && setWhiteboardOpen(true),
|
|
120
|
-
close: () => setWhiteboardOpen(false),
|
|
121
|
-
toggle: () => canWhiteboard && setWhiteboardOpen((value) => !value),
|
|
122
|
-
requestSync: () => void run(() => transport?.requestSnapshot()),
|
|
123
|
-
clear: () => void run(() => transport?.clear()),
|
|
124
|
-
}),
|
|
125
|
-
[canClear, canDraw, canWhiteboard, journeyContext, run, transport, whiteboardOpen],
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
const handleLeave = useCallback(() => {
|
|
129
|
-
const buttons: AlertButton[] = [
|
|
130
|
-
{ text: "Cancel", style: "cancel" },
|
|
131
|
-
{ text: "Leave", style: "destructive", onPress: () => void run(onLeave) },
|
|
132
|
-
];
|
|
133
|
-
if (canEndEpisode && onEndEpisode) {
|
|
134
|
-
buttons.splice(1, 0, {
|
|
135
|
-
text: "End for All",
|
|
136
|
-
style: "destructive",
|
|
137
|
-
onPress: () => void run(onEndEpisode),
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
Alert.alert("Leave Space?", "Choose how you want to leave.", buttons);
|
|
141
|
-
}, [canEndEpisode, onEndEpisode, onLeave, run]);
|
|
142
|
-
|
|
143
|
-
const handleInviteParticipants = useCallback(() => {
|
|
144
|
-
void run(async () => {
|
|
145
|
-
if (!inviteLink) throw new Error("The Space invite is not ready yet.");
|
|
146
|
-
await Share.share({ message: inviteLink, title: spaceName || "Chalk Space", url: inviteLink });
|
|
147
|
-
});
|
|
148
|
-
}, [inviteLink, run, spaceName]);
|
|
149
|
-
|
|
150
|
-
return {
|
|
151
|
-
layout,
|
|
152
|
-
panel,
|
|
153
|
-
secondsElapsed,
|
|
154
|
-
formattedDuration: formatSpaceDuration(secondsElapsed),
|
|
155
|
-
actionsOpen,
|
|
156
|
-
reactionPickerOpen,
|
|
157
|
-
whiteboard,
|
|
158
|
-
settingsOpen,
|
|
159
|
-
setActionsOpen,
|
|
160
|
-
setReactionPickerOpen,
|
|
161
|
-
handleLeave,
|
|
162
|
-
openPanel: (nextPanel: SpacePanelName) => {
|
|
163
|
-
setActionsOpen(false);
|
|
164
|
-
if (nextPanel === "whiteboard") whiteboard.open();
|
|
165
|
-
else setPanel(nextPanel);
|
|
166
|
-
},
|
|
167
|
-
closePanel: () => setPanel(null),
|
|
168
|
-
handleInviteParticipants,
|
|
169
|
-
};
|
|
170
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import type { FeedbackScreenshotCapture, FeedbackScreenshotUnavailable } from "@q9labsai/chalk-client";
|
|
2
|
-
import { Platform, type View } from "react-native";
|
|
3
|
-
import { captureRef } from "react-native-view-shot";
|
|
4
|
-
|
|
5
|
-
export type FeedbackCaptureTarget = React.RefObject<View | null>;
|
|
6
|
-
|
|
7
|
-
export type FeedbackCaptureSize = Readonly<{
|
|
8
|
-
width: number;
|
|
9
|
-
height: number;
|
|
10
|
-
}>;
|
|
11
|
-
|
|
12
|
-
const MAX_SCREENSHOT_BYTES = 450 * 1024;
|
|
13
|
-
const MAX_SCREENSHOT_WIDTH = 1_920;
|
|
14
|
-
const MAX_SCREENSHOT_HEIGHT = 1_080;
|
|
15
|
-
|
|
16
|
-
export async function captureNativeFeedbackView(target: FeedbackCaptureTarget, size: FeedbackCaptureSize): Promise<FeedbackScreenshotCapture | FeedbackScreenshotUnavailable> {
|
|
17
|
-
if (Platform.OS === "macos") return { state: "unavailable", failure_code: "unsupported" };
|
|
18
|
-
if (!target.current) return { state: "unavailable", failure_code: "capture_failed" };
|
|
19
|
-
|
|
20
|
-
const outputSize = boundedOutputSize(size);
|
|
21
|
-
if (!outputSize) return { state: "unavailable", failure_code: "capture_failed" };
|
|
22
|
-
try {
|
|
23
|
-
const captured = await captureRef(target, {
|
|
24
|
-
format: "jpg",
|
|
25
|
-
quality: 0.72,
|
|
26
|
-
result: "base64",
|
|
27
|
-
...outputSize,
|
|
28
|
-
});
|
|
29
|
-
const dataBase64 = normalizeBase64(captured);
|
|
30
|
-
if (!dataBase64) return { state: "unavailable", failure_code: "capture_failed" };
|
|
31
|
-
if (base64ByteLength(dataBase64) > MAX_SCREENSHOT_BYTES) return { state: "unavailable", failure_code: "too_large" };
|
|
32
|
-
|
|
33
|
-
return {
|
|
34
|
-
state: "captured",
|
|
35
|
-
mime_type: "image/jpeg",
|
|
36
|
-
width: outputSize.width,
|
|
37
|
-
height: outputSize.height,
|
|
38
|
-
captured_at: new Date().toISOString(),
|
|
39
|
-
data_base64: dataBase64,
|
|
40
|
-
};
|
|
41
|
-
} catch {
|
|
42
|
-
return { state: "unavailable", failure_code: "capture_failed" };
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function boundedOutputSize(size: FeedbackCaptureSize): Readonly<{ width: number; height: number }> | undefined {
|
|
47
|
-
if (!Number.isFinite(size.width) || !Number.isFinite(size.height) || size.width <= 0 || size.height <= 0) return undefined;
|
|
48
|
-
const scale = Math.min(1, MAX_SCREENSHOT_WIDTH / size.width, MAX_SCREENSHOT_HEIGHT / size.height);
|
|
49
|
-
return {
|
|
50
|
-
width: Math.max(1, Math.floor(size.width * scale)),
|
|
51
|
-
height: Math.max(1, Math.floor(size.height * scale)),
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function normalizeBase64(value: string): string {
|
|
56
|
-
return value.replace(/^data:[^;]+;base64,/u, "").replaceAll(/\s/gu, "");
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function base64ByteLength(value: string): number {
|
|
60
|
-
const padding = value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0;
|
|
61
|
-
return Math.floor((value.length * 3) / 4) - padding;
|
|
62
|
-
}
|