@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
package/src/dev.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Development-only seams for a state harness and parity checks. Import this entry behind `__DEV__`
|
|
3
|
+
* with `require`, so Metro drops it, and everything only it reaches, from release bundles.
|
|
4
|
+
*/
|
|
5
|
+
export { setDevScenario } from "./frame/dev-scenario";
|
|
6
|
+
export type { DevScenario } from "./frame/dev-scenario";
|
|
7
|
+
export type { AudioRoute, AudioRouteKind, AudioRoutes } from "./dock/audio-route";
|
|
8
|
+
export { setMeasurementRegistry } from "./frame/measurement";
|
|
9
|
+
export type { MeasuredFrame, Measurement, MeasurementRegistry } from "./frame/measurement";
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { memo, useCallback, useEffect, useRef, useState, type RefObject } from "react";
|
|
2
|
+
import { StyleSheet, View } from "react-native";
|
|
3
|
+
import { useDevScenario } from "../frame/dev-scenario";
|
|
4
|
+
import type { Arrangement } from "../frame/regions";
|
|
5
|
+
import { useMeasuredRef } from "../frame/measurement";
|
|
6
|
+
import { announce } from "../primitives/announce";
|
|
7
|
+
import { IconButton } from "../primitives/IconButton";
|
|
8
|
+
import { useToasts } from "../primitives/toast/ToastStack";
|
|
9
|
+
import { routeIcons, routeName, useAudioOutput, type AudioOutput } from "./audio-route";
|
|
10
|
+
import { RoutePicker } from "./RoutePicker";
|
|
11
|
+
|
|
12
|
+
export type DockProps = {
|
|
13
|
+
readonly arrangement: Arrangement;
|
|
14
|
+
readonly microphoneOn: boolean;
|
|
15
|
+
readonly cameraOn: boolean;
|
|
16
|
+
readonly onToggleMicrophone: () => void;
|
|
17
|
+
readonly onToggleCamera: () => void;
|
|
18
|
+
readonly onOpenMore: () => void;
|
|
19
|
+
readonly onLeave: () => void;
|
|
20
|
+
readonly moreOpen: boolean;
|
|
21
|
+
/** Set only when Leave opens a menu (hosts), so others hear a plain button. */
|
|
22
|
+
readonly leaveOpen?: boolean;
|
|
23
|
+
readonly moreRef: RefObject<View | null>;
|
|
24
|
+
readonly leaveRef: RefObject<View | null>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The call controls (`.dock`): microphone, camera, audio output with its name under it (R1),
|
|
29
|
+
* More and Leave. Spread across the phone in portrait, centred with 14 pt gaps in landscape.
|
|
30
|
+
*/
|
|
31
|
+
export const Dock = memo(function Dock({ arrangement, microphoneOn, cameraOn, onToggleMicrophone, onToggleCamera, onOpenMore, onLeave, moreOpen, leaveOpen, moreRef, leaveRef }: DockProps) {
|
|
32
|
+
const size = arrangement === "pad" ? 44 : 52;
|
|
33
|
+
const dockStyle = [styles.dock, arrangement === "pad" ? styles.pad : arrangement === "landscape" ? styles.landscape : styles.portrait];
|
|
34
|
+
const dockRef = useMeasuredRef<View>("frame.dock", dockStyle);
|
|
35
|
+
const output = useAudioOutput();
|
|
36
|
+
return (
|
|
37
|
+
<View accessibilityLabel="Call controls" accessibilityRole="toolbar" pointerEvents="box-none" ref={dockRef} style={dockStyle} testID="frame.dock">
|
|
38
|
+
<IconButton accessibilityLabel={microphoneOn ? "Mute microphone" : "Unmute microphone"} icon={microphoneOn ? "mic" : "micOff"} off={!microphoneOn} onCanvas onPress={onToggleMicrophone} size={size} testID="dock.microphone" />
|
|
39
|
+
<IconButton accessibilityLabel={cameraOn ? "Turn off camera" : "Turn on camera"} icon={cameraOn ? "cam" : "camOff"} off={!cameraOn} onCanvas onPress={onToggleCamera} size={size} testID="dock.camera" />
|
|
40
|
+
{output ? <AudioOutputButton captioned={arrangement === "portrait"} output={output} size={size} /> : null}
|
|
41
|
+
<IconButton accessibilityLabel="More options" expanded={moreOpen} icon="more" onCanvas onPress={onOpenMore} ref={moreRef} size={size} testID="dock.more" />
|
|
42
|
+
{arrangement === "pad" ? <View style={styles.gap} /> : null}
|
|
43
|
+
<IconButton accessibilityLabel="Leave call" expanded={leaveOpen} icon="hang" onPress={onLeave} ref={leaveRef} size={size} testID="dock.leave" tone="danger" />
|
|
44
|
+
</View>
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* With only the earpiece and the speaker, a press switches between them. Once a headset is
|
|
50
|
+
* connected there are more than two places to play, so a press opens the choice.
|
|
51
|
+
*/
|
|
52
|
+
function AudioOutputButton({ output, size, captioned }: { readonly output: AudioOutput; readonly size: 44 | 52; readonly captioned: boolean }): React.JSX.Element {
|
|
53
|
+
const toasts = useToasts();
|
|
54
|
+
const ref = useRef<View>(null);
|
|
55
|
+
const [open, setOpen] = useState(false);
|
|
56
|
+
const devScenario = useDevScenario();
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (devScenario.sheet === "route" || devScenario.menu === "route") setOpen(true);
|
|
59
|
+
}, [devScenario]);
|
|
60
|
+
|
|
61
|
+
const name = routeName(output.current);
|
|
62
|
+
const choosing = output.routes.length > 2;
|
|
63
|
+
const other = output.routes.find((route) => route.id !== output.selected);
|
|
64
|
+
const select = useCallback(
|
|
65
|
+
(id: string) => {
|
|
66
|
+
setOpen(false);
|
|
67
|
+
const route = output.routes.find((candidate) => candidate.id === id);
|
|
68
|
+
output
|
|
69
|
+
.select(id)
|
|
70
|
+
.then(() => route && announce(`Audio output: ${routeName(route)}`))
|
|
71
|
+
.catch(() => toasts.show({ kind: "error", dismissible: true, message: "Couldn't switch the audio output." }));
|
|
72
|
+
},
|
|
73
|
+
[output, toasts],
|
|
74
|
+
);
|
|
75
|
+
const press = useCallback(() => {
|
|
76
|
+
if (choosing) setOpen((was) => !was);
|
|
77
|
+
else if (other) select(other.id);
|
|
78
|
+
}, [choosing, other, select]);
|
|
79
|
+
|
|
80
|
+
const hint = choosing || !other ? "Choose output" : output.current.kind === "speaker" ? `Switch to ${routeName(other)}` : "Switch to speaker";
|
|
81
|
+
return (
|
|
82
|
+
<>
|
|
83
|
+
<IconButton accessibilityLabel={`Audio output: ${name}. ${hint}`} caption={captioned ? name : undefined} expanded={choosing ? open : undefined} icon={routeIcons[output.current.kind]} onCanvas onPress={press} ref={ref} size={size} testID="dock.route" />
|
|
84
|
+
{choosing ? <RoutePicker anchorRef={ref} onClose={() => setOpen(false)} onSelect={select} open={open} output={output} /> : null}
|
|
85
|
+
</>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const styles = StyleSheet.create({
|
|
90
|
+
dock: { flex: 1, flexDirection: "row", alignItems: "center" },
|
|
91
|
+
portrait: { justifyContent: "space-between", paddingHorizontal: 20 },
|
|
92
|
+
landscape: { justifyContent: "center", gap: 14 },
|
|
93
|
+
pad: { justifyContent: "center", gap: 8 },
|
|
94
|
+
gap: { width: 8 },
|
|
95
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { RefObject } from "react";
|
|
2
|
+
import type { View } from "react-native";
|
|
3
|
+
import { Menu, MenuItem } from "../primitives/Menu";
|
|
4
|
+
|
|
5
|
+
export type LeaveMenuProps = {
|
|
6
|
+
readonly open: boolean;
|
|
7
|
+
readonly onClose: () => void;
|
|
8
|
+
readonly anchorRef: RefObject<View | null>;
|
|
9
|
+
readonly onLeave: () => void;
|
|
10
|
+
readonly onEnd: () => void;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/** A host's Leave button asks whether to leave alone or end the call for everyone. */
|
|
14
|
+
export function LeaveMenu({ open, onClose, anchorRef, onLeave, onEnd }: LeaveMenuProps): React.JSX.Element | null {
|
|
15
|
+
return (
|
|
16
|
+
<Menu accessibilityLabel="Leave" anchorRef={anchorRef} onClose={onClose} open={open} testID="menu.leave">
|
|
17
|
+
<MenuItem label="Leave call" onPress={onLeave} testID="menu.leave.leave" />
|
|
18
|
+
<MenuItem danger label="End call for everyone" onPress={onEnd} testID="menu.leave.end" />
|
|
19
|
+
</Menu>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import type { Reaction } from "@q9labsai/chalk-client";
|
|
2
|
+
import { setStringAsync } from "expo-clipboard";
|
|
3
|
+
import { useCallback, useEffect, useRef, useState, type RefObject } from "react";
|
|
4
|
+
import { Platform, Pressable, Share, StyleSheet, Text, View } from "react-native";
|
|
5
|
+
import Animated, { useAnimatedStyle } from "react-native-reanimated";
|
|
6
|
+
import { useSpaceClient } from "../context/space-client-context";
|
|
7
|
+
import { useMeasuredRef } from "../frame/measurement";
|
|
8
|
+
import { usePreferences } from "../frame/preferences";
|
|
9
|
+
import { haptics } from "../haptics/haptics";
|
|
10
|
+
import { useCan, useChat, useParticipants, useRecording, useSelf } from "../hooks/space-hooks";
|
|
11
|
+
import { Icon } from "../icons/Icon";
|
|
12
|
+
import { usePressAnimation } from "../motion/press";
|
|
13
|
+
import { announce } from "../primitives/announce";
|
|
14
|
+
import { BottomSheet } from "../primitives/BottomSheet";
|
|
15
|
+
import { ChalkText } from "../primitives/ChalkText";
|
|
16
|
+
import { SegmentedControl } from "../primitives/SegmentedControl";
|
|
17
|
+
import { SheetGroup, SheetRow } from "../primitives/SheetGroup";
|
|
18
|
+
import { useToasts } from "../primitives/toast/ToastStack";
|
|
19
|
+
import { playSound } from "../sounds/sounds";
|
|
20
|
+
import { useStageView, type StageLayoutChoice } from "../stage/stage-view";
|
|
21
|
+
import { useTheme } from "../theme/theme";
|
|
22
|
+
import { durations, fixed } from "../theme/tokens";
|
|
23
|
+
|
|
24
|
+
export type MoreSheetProps = {
|
|
25
|
+
readonly open: boolean;
|
|
26
|
+
readonly onClose: () => void;
|
|
27
|
+
readonly onOpenPeople: () => void;
|
|
28
|
+
readonly onOpenChat: () => void;
|
|
29
|
+
/** The call's link; without it the sheet leaves out Copy link and Share link. */
|
|
30
|
+
readonly inviteLink?: string;
|
|
31
|
+
readonly returnFocusRef?: RefObject<View | null>;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/** The call's one reaction set, in the mockup's order, with the names screen readers say. */
|
|
35
|
+
const REACTIONS: readonly (readonly [Reaction, string])[] = [
|
|
36
|
+
["👍", "thumbs up"],
|
|
37
|
+
["❤️", "heart"],
|
|
38
|
+
["😂", "laughter"],
|
|
39
|
+
["😮", "surprise"],
|
|
40
|
+
["🎉", "celebration"],
|
|
41
|
+
["😢", "sadness"],
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* More (`#more`): raise hand and reactions on top, then the call's link, recording for hosts,
|
|
46
|
+
* Chat, People and the stage layout. Actions that change the call close the sheet; copying keeps it open.
|
|
47
|
+
*/
|
|
48
|
+
export function MoreSheet({ open, onClose, onOpenPeople, onOpenChat, inviteLink, returnFocusRef }: MoreSheetProps): React.JSX.Element {
|
|
49
|
+
const client = useSpaceClient();
|
|
50
|
+
const self = useSelf();
|
|
51
|
+
const people = useParticipants().roster.length;
|
|
52
|
+
const toasts = useToasts();
|
|
53
|
+
const { soundsEnabled } = usePreferences();
|
|
54
|
+
const canRaiseHand = useCan("raiseHand");
|
|
55
|
+
const canReact = useCan("sendReaction");
|
|
56
|
+
|
|
57
|
+
const fail = useCallback((message: string) => () => toasts.show({ kind: "error", dismissible: true, message }), [toasts]);
|
|
58
|
+
const toggleHand = useCallback(() => {
|
|
59
|
+
onClose();
|
|
60
|
+
haptics.handRaise();
|
|
61
|
+
if (self.handRaised) {
|
|
62
|
+
client.participants.lowerHand().catch(fail("Couldn't lower your hand."));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
playSound("hand", soundsEnabled);
|
|
66
|
+
announce("You raised a hand");
|
|
67
|
+
client.participants.raiseHand().catch(fail("Couldn't raise your hand."));
|
|
68
|
+
}, [client, fail, onClose, self.handRaised, soundsEnabled]);
|
|
69
|
+
const react = useCallback(
|
|
70
|
+
(emoji: Reaction) => {
|
|
71
|
+
onClose();
|
|
72
|
+
client.reactions.send(emoji).catch(fail("Couldn't send your reaction."));
|
|
73
|
+
},
|
|
74
|
+
[client, fail, onClose],
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<BottomSheet accessibilityLabel="More options" onClose={onClose} open={open} returnFocusRef={returnFocusRef} testID="sheet.more">
|
|
79
|
+
{canRaiseHand || canReact ? (
|
|
80
|
+
<View accessibilityLabel="Reactions" accessibilityRole="toolbar" style={styles.reactions}>
|
|
81
|
+
{canRaiseHand ? <HandButton onPress={toggleHand} raised={self.handRaised} /> : null}
|
|
82
|
+
{canReact ? REACTIONS.map(([emoji, name], index) => <EmojiButton emoji={emoji} key={emoji} name={name} onPress={react} testID={`more.reaction.${index}`} />) : null}
|
|
83
|
+
</View>
|
|
84
|
+
) : null}
|
|
85
|
+
<SheetGroup>
|
|
86
|
+
{inviteLink ? <CopyLinkRow link={inviteLink} /> : null}
|
|
87
|
+
{inviteLink ? <SheetRow icon="iosShare" label="Share link" onPress={() => shareLink(inviteLink)} testID="more.share" /> : null}
|
|
88
|
+
<RecordingRow onDone={onClose} />
|
|
89
|
+
<ChatRow onPress={onOpenChat} />
|
|
90
|
+
<SheetRow end={<PeopleCount count={people} />} icon="users" label="People" onPress={onOpenPeople} testID="more.people" />
|
|
91
|
+
<LayoutRow />
|
|
92
|
+
</SheetGroup>
|
|
93
|
+
</BottomSheet>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function shareLink(link: string): void {
|
|
98
|
+
// iOS shares a URL as a link with its preview; Android takes it as the message text.
|
|
99
|
+
Share.share(Platform.OS === "ios" ? { url: link } : { message: link }).catch(() => undefined);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** `.hand2`: a raised hand turns the button yellow until it's lowered. */
|
|
103
|
+
function HandButton({ raised, onPress }: { readonly raised: boolean; readonly onPress: () => void }): React.JSX.Element {
|
|
104
|
+
const { colors } = useTheme();
|
|
105
|
+
const press = usePressAnimation("pill");
|
|
106
|
+
const foreground = raised ? fixed.handText : colors.text;
|
|
107
|
+
return (
|
|
108
|
+
<Pressable accessibilityLabel={raised ? "Lower hand" : "Raise hand"} accessibilityRole="button" accessibilityState={{ selected: raised }} onPress={onPress} onPressIn={press.onPressIn} onPressOut={press.onPressOut} testID="more.hand">
|
|
109
|
+
<Animated.View style={[styles.hand, { backgroundColor: raised ? fixed.hand : colors.raised }, press.scaleStyle]}>
|
|
110
|
+
<Icon color={foreground} name="hand" />
|
|
111
|
+
<ChalkText color={foreground} variant="bodyStrong">
|
|
112
|
+
{raised ? "Lower hand" : "Raise hand"}
|
|
113
|
+
</ChalkText>
|
|
114
|
+
</Animated.View>
|
|
115
|
+
</Pressable>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function EmojiButton({ emoji, name, onPress, testID }: { readonly emoji: Reaction; readonly name: string; readonly onPress: (emoji: Reaction) => void; readonly testID: string }): React.JSX.Element {
|
|
120
|
+
const { colors } = useTheme();
|
|
121
|
+
const press = usePressAnimation("small");
|
|
122
|
+
const { down } = press;
|
|
123
|
+
const pressed = colors.hover;
|
|
124
|
+
const background = useAnimatedStyle(() => {
|
|
125
|
+
"worklet";
|
|
126
|
+
return { backgroundColor: down.value ? pressed : fixed.transparent };
|
|
127
|
+
});
|
|
128
|
+
return (
|
|
129
|
+
<Pressable accessibilityLabel={`Send ${name}`} accessibilityRole="button" onPress={() => onPress(emoji)} onPressIn={press.onPressIn} onPressOut={press.onPressOut} style={styles.emojiSlot} testID={testID}>
|
|
130
|
+
<Animated.View style={[styles.emoji, background, press.scaleStyle]}>
|
|
131
|
+
<Text allowFontScaling={false} style={styles.emojiText}>
|
|
132
|
+
{emoji}
|
|
133
|
+
</Text>
|
|
134
|
+
</Animated.View>
|
|
135
|
+
</Pressable>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Copy link: the icon turns into a check for two seconds and the screen reader hears "Link copied". */
|
|
140
|
+
function CopyLinkRow({ link }: { readonly link: string }): React.JSX.Element {
|
|
141
|
+
const [copied, setCopied] = useState(false);
|
|
142
|
+
const reset = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
143
|
+
useEffect(() => () => clearTimeout(reset.current ?? undefined), []);
|
|
144
|
+
const copy = useCallback(async () => {
|
|
145
|
+
await setStringAsync(link);
|
|
146
|
+
setCopied(true);
|
|
147
|
+
announce("Link copied");
|
|
148
|
+
clearTimeout(reset.current ?? undefined);
|
|
149
|
+
reset.current = setTimeout(() => setCopied(false), durations.copyReset);
|
|
150
|
+
}, [link]);
|
|
151
|
+
return <SheetRow icon={copied ? "check" : "copy"} label="Copy link" onPress={() => void copy()} testID="more.copy" />;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const LAYOUTS = [
|
|
155
|
+
{ value: "spotlight", label: "Spotlight", testID: "more.layout.spotlight" },
|
|
156
|
+
{ value: "grid", label: "Grid", testID: "more.layout.grid" },
|
|
157
|
+
] as const;
|
|
158
|
+
|
|
159
|
+
/** Layout (`#mLay`): Spotlight or Grid for the stage, switched in place without closing the sheet. */
|
|
160
|
+
function LayoutRow(): React.JSX.Element {
|
|
161
|
+
const { layout, setLayout } = useStageView();
|
|
162
|
+
return <SheetRow end={<SegmentedControl<StageLayoutChoice> accessibilityLabel="Layout" onChange={setLayout} options={LAYOUTS} testID="more.layout.control" value={layout} />} icon="grid" label="Layout" testID="more.layout" />;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function UnreadDot(): React.JSX.Element {
|
|
166
|
+
const { colors } = useTheme();
|
|
167
|
+
const style = [styles.unread, { backgroundColor: colors.info }];
|
|
168
|
+
const ref = useMeasuredRef<View>("more.chat.unread", style);
|
|
169
|
+
return <View ref={ref} style={style} testID="more.chat.unread" />;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Chat, with the accent dot after its name while messages are unread. */
|
|
173
|
+
function ChatRow({ onPress }: { readonly onPress: () => void }): React.JSX.Element {
|
|
174
|
+
const { colors } = useTheme();
|
|
175
|
+
const unread = useChat().unreadCount > 0;
|
|
176
|
+
return <SheetRow accessibilityLabel={unread ? "Chat, new messages" : "Chat"} badge={unread ? <UnreadDot /> : null} end={<Icon color={colors.textMuted} name="right" />} icon="chat" label="Chat" onPress={onPress} testID="more.chat" />;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function PeopleCount({ count }: { readonly count: number }): React.JSX.Element {
|
|
180
|
+
const { colors } = useTheme();
|
|
181
|
+
return (
|
|
182
|
+
<View style={styles.end}>
|
|
183
|
+
<ChalkText tabular tone="textMuted" variant="phoneRow">
|
|
184
|
+
{count}
|
|
185
|
+
</ChalkText>
|
|
186
|
+
<Icon color={colors.textMuted} name="right" />
|
|
187
|
+
</View>
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** Hosts start and stop recording; the header's Rec dot shows it to everyone (K5). */
|
|
192
|
+
function RecordingRow({ onDone }: { readonly onDone: () => void }): React.JSX.Element | null {
|
|
193
|
+
const client = useSpaceClient();
|
|
194
|
+
const toasts = useToasts();
|
|
195
|
+
const { soundsEnabled } = usePreferences();
|
|
196
|
+
const { colors } = useTheme();
|
|
197
|
+
const canRecord = useCan("manageRecording");
|
|
198
|
+
const status = useRecording().current?.status;
|
|
199
|
+
if (!canRecord) return null;
|
|
200
|
+
const recording = status === "starting" || status === "recording";
|
|
201
|
+
const toggle = () => {
|
|
202
|
+
onDone();
|
|
203
|
+
if (recording) {
|
|
204
|
+
client.recording
|
|
205
|
+
.stop()
|
|
206
|
+
.then(() => {
|
|
207
|
+
toasts.show({ leading: <Icon color={colors.textMuted} name="rec" />, message: "Recording stopped" });
|
|
208
|
+
})
|
|
209
|
+
.catch(() => toasts.show({ kind: "error", dismissible: true, message: "Couldn't stop recording." }));
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
client.recording
|
|
213
|
+
.start()
|
|
214
|
+
.then(() => {
|
|
215
|
+
playSound("recording", soundsEnabled);
|
|
216
|
+
toasts.show({ leading: <Icon color={colors.dangerText} name="rec" />, message: [{ strong: "Recording started." }, " Everyone in the call can see it."] });
|
|
217
|
+
})
|
|
218
|
+
.catch(() => toasts.show({ kind: "error", dismissible: true, message: "Couldn't start recording." }));
|
|
219
|
+
};
|
|
220
|
+
return <SheetRow icon="rec" label={recording ? "Stop recording" : "Start recording"} onPress={toggle} testID="more.recording" />;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const styles = StyleSheet.create({
|
|
224
|
+
// `.rxrow`: wraps onto a second line on narrow phones.
|
|
225
|
+
// One line on every phone: the reactions narrow from 44 pt to 32 pt before they would wrap beside the hand.
|
|
226
|
+
reactions: { flexDirection: "row", alignItems: "center", gap: 2, paddingBottom: 12 },
|
|
227
|
+
hand: { flexDirection: "row", alignItems: "center", gap: 8, height: 44, paddingLeft: 12, paddingRight: 16, marginRight: 6, borderRadius: 999 },
|
|
228
|
+
emojiSlot: { flexBasis: 44, flexShrink: 1, minWidth: 32 },
|
|
229
|
+
emoji: { height: 44, borderRadius: 22, alignItems: "center", justifyContent: "center" },
|
|
230
|
+
emojiText: { fontSize: 22 },
|
|
231
|
+
end: { flexDirection: "row", alignItems: "center", gap: 14 },
|
|
232
|
+
unread: { width: 8, height: 8, borderRadius: 4 },
|
|
233
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { ActiveReaction } from "@q9labsai/chalk-client";
|
|
2
|
+
import { memo, useEffect } from "react";
|
|
3
|
+
import { StyleSheet, Text, View } from "react-native";
|
|
4
|
+
import Animated, { useAnimatedStyle, useReducedMotion, useSharedValue, withTiming } from "react-native-reanimated";
|
|
5
|
+
import { useReactions } from "../hooks/space-hooks";
|
|
6
|
+
import { easings } from "../theme/tokens";
|
|
7
|
+
|
|
8
|
+
/** The mockup's `@keyframes rx`: 2 s ease-out, fading in over the first 15 % while rising 82 pt. */
|
|
9
|
+
const DURATION = 2000;
|
|
10
|
+
const FADE_IN = 0.15;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Reactions a person sends (F12), floating up from the lower middle of their tile. Mount it inside
|
|
14
|
+
* the tile; it draws nothing while that person has no reaction showing.
|
|
15
|
+
*/
|
|
16
|
+
export const ReactionBurst = memo(function ReactionBurst({ participantId }: { readonly participantId: string }): React.JSX.Element | null {
|
|
17
|
+
const active = useReactions().active.filter((reaction) => reaction.participantId === participantId);
|
|
18
|
+
if (active.length === 0) return null;
|
|
19
|
+
return (
|
|
20
|
+
<View pointerEvents="none" style={styles.layer}>
|
|
21
|
+
{active.map((reaction) => (
|
|
22
|
+
<FloatingEmoji key={reaction.eventId} reaction={reaction} />
|
|
23
|
+
))}
|
|
24
|
+
</View>
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
function FloatingEmoji({ reaction }: { readonly reaction: ActiveReaction }): React.JSX.Element {
|
|
29
|
+
const reduceMotion = useReducedMotion();
|
|
30
|
+
const progress = useSharedValue(0);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
progress.value = withTiming(1, { duration: DURATION, easing: easings.easeOut });
|
|
33
|
+
}, [progress]);
|
|
34
|
+
const style = useAnimatedStyle(() => {
|
|
35
|
+
"worklet";
|
|
36
|
+
const t = progress.value;
|
|
37
|
+
const opacity = t < FADE_IN ? t / FADE_IN : 1 - (t - FADE_IN) / (1 - FADE_IN);
|
|
38
|
+
// Reduced motion keeps the fade (`@keyframes rxf`) and drops the rise.
|
|
39
|
+
return { opacity, transform: [{ translateY: reduceMotion ? 0 : 12 - 82 * t }] };
|
|
40
|
+
});
|
|
41
|
+
return (
|
|
42
|
+
<Animated.View style={[styles.emoji, style]}>
|
|
43
|
+
<Text allowFontScaling={false} style={styles.text}>
|
|
44
|
+
{reaction.reaction}
|
|
45
|
+
</Text>
|
|
46
|
+
</Animated.View>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const styles = StyleSheet.create({
|
|
51
|
+
layer: { ...StyleSheet.absoluteFillObject, zIndex: 6 },
|
|
52
|
+
// `.rx`: centred, its bottom 28 % up the tile.
|
|
53
|
+
emoji: { position: "absolute", left: 0, right: 0, bottom: "28%", alignItems: "center" },
|
|
54
|
+
text: { fontSize: 44 },
|
|
55
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { RefObject } from "react";
|
|
2
|
+
import { Platform, type View } from "react-native";
|
|
3
|
+
import { Icon } from "../icons/Icon";
|
|
4
|
+
import { BottomSheet } from "../primitives/BottomSheet";
|
|
5
|
+
import { Menu, MenuItem } from "../primitives/Menu";
|
|
6
|
+
import { SheetGroup, SheetRow } from "../primitives/SheetGroup";
|
|
7
|
+
import { useTheme } from "../theme/theme";
|
|
8
|
+
import { routeIcons, routeName, type AudioOutput } from "./audio-route";
|
|
9
|
+
|
|
10
|
+
export type RoutePickerProps = {
|
|
11
|
+
readonly open: boolean;
|
|
12
|
+
readonly onClose: () => void;
|
|
13
|
+
readonly onSelect: (id: string) => void;
|
|
14
|
+
readonly output: AudioOutput;
|
|
15
|
+
readonly anchorRef: RefObject<View | null>;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The audio output choice once a headset joins the earpiece and the speaker: a menu next to the
|
|
20
|
+
* button on iOS, where the mockup draws the system route menu, and a sheet on Android.
|
|
21
|
+
*/
|
|
22
|
+
export function RoutePicker({ open, onClose, onSelect, output, anchorRef }: RoutePickerProps): React.JSX.Element | null {
|
|
23
|
+
const { colors } = useTheme();
|
|
24
|
+
if (Platform.OS === "ios") {
|
|
25
|
+
return (
|
|
26
|
+
<Menu accessibilityLabel="Audio output" anchorRef={anchorRef} onClose={onClose} open={open} testID="menu.route">
|
|
27
|
+
{output.routes.map((route) => (
|
|
28
|
+
<MenuItem checked={route.id === output.selected} icon={routeIcons[route.kind]} key={route.id} label={routeName(route)} onPress={() => onSelect(route.id)} testID={`menu.route.${route.kind}`} />
|
|
29
|
+
))}
|
|
30
|
+
</Menu>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return (
|
|
34
|
+
<BottomSheet accessibilityLabel="Audio output" onClose={onClose} open={open} returnFocusRef={anchorRef} testID="sheet.route" title="Audio output">
|
|
35
|
+
<SheetGroup>
|
|
36
|
+
{output.routes.map((route) => (
|
|
37
|
+
<SheetRow end={route.id === output.selected ? <Icon color={colors.text} name="check" /> : null} icon={routeIcons[route.kind]} key={route.id} label={routeName(route)} onPress={() => onSelect(route.id)} testID={`sheet.route.${route.kind}`} />
|
|
38
|
+
))}
|
|
39
|
+
</SheetGroup>
|
|
40
|
+
</BottomSheet>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from "react";
|
|
2
|
+
import { NativeEventEmitter, NativeModules, Platform } from "react-native";
|
|
3
|
+
import { useDevScenario } from "../frame/dev-scenario";
|
|
4
|
+
import type { IconName } from "../icons/Icon";
|
|
5
|
+
|
|
6
|
+
export type AudioRouteKind = "earpiece" | "speaker" | "bluetooth" | "wired";
|
|
7
|
+
|
|
8
|
+
/** One place the call's sound can play. Bluetooth and wired headsets carry their device name. */
|
|
9
|
+
export type AudioRoute = { readonly id: string; readonly kind: AudioRouteKind; readonly name: string };
|
|
10
|
+
|
|
11
|
+
export type AudioRoutes = { readonly routes: readonly AudioRoute[]; readonly selected: string };
|
|
12
|
+
|
|
13
|
+
export type AudioOutput = AudioRoutes & {
|
|
14
|
+
readonly current: AudioRoute;
|
|
15
|
+
readonly select: (id: string) => Promise<void>;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
type NativeAudioRouteModule = {
|
|
19
|
+
readonly eventName: string;
|
|
20
|
+
readonly addListener: (eventName: string) => void;
|
|
21
|
+
readonly removeListeners: (count: number) => void;
|
|
22
|
+
readonly getRoutes: () => Promise<AudioRoutes>;
|
|
23
|
+
readonly selectRoute: (id: string) => Promise<AudioRoutes>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const nativeModule: NativeAudioRouteModule | undefined = NativeModules.ChalkAudioRouteModule;
|
|
27
|
+
const emitter = nativeModule ? new NativeEventEmitter(nativeModule) : null;
|
|
28
|
+
|
|
29
|
+
export const routeIcons: Readonly<Record<AudioRouteKind, IconName>> = { earpiece: "earpiece", speaker: "vol", bluetooth: "buds", wired: "buds" };
|
|
30
|
+
|
|
31
|
+
/** The mockup's `ROUTEN`: the phone's own speaker is "iPhone" on iOS and "Phone" on Android. */
|
|
32
|
+
export function routeName(route: AudioRoute): string {
|
|
33
|
+
if (route.kind === "speaker") return "Speaker";
|
|
34
|
+
if (route.kind === "earpiece") return Platform.OS === "ios" ? "iPhone" : "Phone";
|
|
35
|
+
return route.name;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The audio output button's state (R1), from the SDK's native route module. Null when the app's
|
|
40
|
+
* native build doesn't include the module yet, so the dock leaves the button out.
|
|
41
|
+
*/
|
|
42
|
+
export function useAudioOutput(): AudioOutput | null {
|
|
43
|
+
const scenario = useDevScenario().audioRoutes;
|
|
44
|
+
const [state, setState] = useState<AudioRoutes | null>(null);
|
|
45
|
+
// In the harness, picking a route moves the check like a real switch would.
|
|
46
|
+
const [scenarioSelected, setScenarioSelected] = useState<string | null>(null);
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
if (!nativeModule || !emitter) return;
|
|
49
|
+
let live = true;
|
|
50
|
+
nativeModule
|
|
51
|
+
.getRoutes()
|
|
52
|
+
.then((next) => live && setState(next))
|
|
53
|
+
.catch(() => undefined);
|
|
54
|
+
const subscription = emitter.addListener(nativeModule.eventName, (next: AudioRoutes) => setState(next));
|
|
55
|
+
return () => {
|
|
56
|
+
live = false;
|
|
57
|
+
subscription.remove();
|
|
58
|
+
};
|
|
59
|
+
}, []);
|
|
60
|
+
const select = useCallback(async (id: string) => {
|
|
61
|
+
if (!nativeModule) return;
|
|
62
|
+
setState(await nativeModule.selectRoute(id));
|
|
63
|
+
}, []);
|
|
64
|
+
const routes = scenario ? { ...scenario, selected: scenarioSelected ?? scenario.selected } : state;
|
|
65
|
+
if (!routes) return null;
|
|
66
|
+
const current = routes.routes.find((route) => route.id === routes.selected) ?? routes.routes[0];
|
|
67
|
+
if (!current) return null;
|
|
68
|
+
return { ...routes, current, select: scenario ? async (id) => setScenarioSelected(id) : select };
|
|
69
|
+
}
|