@adminide-stack/yantra-mobile 12.0.69-alpha.2 → 12.0.69-alpha.21
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/lib/components/GatewayConnector/GatewayConnector.js +2 -2
- package/lib/components/GatewayConnector/GatewayConnector.js.map +1 -1
- package/lib/components/KeyboardComposerDock.js +8 -1
- package/lib/components/KeyboardComposerDock.js.map +1 -1
- package/lib/components/NavigationHeader/NavigationHeader.js +2 -2
- package/lib/components/NavigationHeader/NavigationHeader.js.map +1 -1
- package/lib/contexts/ChatLiveStreamContext.js +4 -1
- package/lib/contexts/ChatLiveStreamContext.js.map +1 -1
- package/lib/features/agent-chat/NativeAgentChat.js +2 -0
- package/lib/features/agent-chat/NativeAgentChat.js.map +1 -1
- package/lib/features/apps/AppsCatalog.js +2 -2
- package/lib/features/apps/AppsCatalog.js.map +1 -1
- package/lib/features/audio-input/MicErrorBoundary.js +2 -2
- package/lib/features/audio-input/MicErrorBoundary.js.map +1 -1
- package/lib/features/canvas/AudioEditorExperience.js +308 -0
- package/lib/features/canvas/AudioEditorExperience.js.map +1 -0
- package/lib/features/canvas/CanvasAgentChatPane.js +310 -0
- package/lib/features/canvas/CanvasAgentChatPane.js.map +1 -0
- package/lib/features/canvas/CanvasBoardsGrid.js +414 -0
- package/lib/features/canvas/CanvasBoardsGrid.js.map +1 -0
- package/lib/features/canvas/CanvasChatResultCard.js +113 -0
- package/lib/features/canvas/CanvasChatResultCard.js.map +1 -0
- package/lib/features/canvas/CanvasEditToolsPanel.js +179 -0
- package/lib/features/canvas/CanvasEditToolsPanel.js.map +1 -0
- package/lib/features/canvas/CanvasExperience.js +859 -0
- package/lib/features/canvas/CanvasExperience.js.map +1 -0
- package/lib/features/canvas/CanvasGeneratePanel.js +514 -0
- package/lib/features/canvas/CanvasGeneratePanel.js.map +1 -0
- package/lib/features/canvas/CanvasLibrarySheet.js +355 -0
- package/lib/features/canvas/CanvasLibrarySheet.js.map +1 -0
- package/lib/features/canvas/CanvasLooksPanel.js +184 -0
- package/lib/features/canvas/CanvasLooksPanel.js.map +1 -0
- package/lib/features/canvas/CanvasTasksPanel.js +138 -0
- package/lib/features/canvas/CanvasTasksPanel.js.map +1 -0
- package/lib/features/canvas/CanvasTemplatesPanel.js +226 -0
- package/lib/features/canvas/CanvasTemplatesPanel.js.map +1 -0
- package/lib/features/canvas/CanvasToolDock.js +423 -0
- package/lib/features/canvas/CanvasToolDock.js.map +1 -0
- package/lib/features/canvas/FrameExtractorExperience.js +242 -0
- package/lib/features/canvas/FrameExtractorExperience.js.map +1 -0
- package/lib/features/canvas/ImageEditorExperience.js +491 -0
- package/lib/features/canvas/ImageEditorExperience.js.map +1 -0
- package/lib/features/canvas/InfluencerStudioExperience.js +288 -0
- package/lib/features/canvas/InfluencerStudioExperience.js.map +1 -0
- package/lib/features/canvas/MoodboardExperience.js +205 -0
- package/lib/features/canvas/MoodboardExperience.js.map +1 -0
- package/lib/features/canvas/NativeCanvasViewer.js +929 -0
- package/lib/features/canvas/NativeCanvasViewer.js.map +1 -0
- package/lib/features/canvas/PromoContextFields.js +150 -0
- package/lib/features/canvas/PromoContextFields.js.map +1 -0
- package/lib/features/canvas/SetStudioExperience.js +323 -0
- package/lib/features/canvas/SetStudioExperience.js.map +1 -0
- package/lib/features/canvas/VideoClipsExperience.js +175 -0
- package/lib/features/canvas/VideoClipsExperience.js.map +1 -0
- package/lib/features/canvas/VideoEditExperience.js +824 -0
- package/lib/features/canvas/VideoEditExperience.js.map +1 -0
- package/lib/features/canvas/VideoEditorExperience.js +3050 -0
- package/lib/features/canvas/VideoEditorExperience.js.map +1 -0
- package/lib/features/canvas/VideoGeneratorExperience.js +415 -0
- package/lib/features/canvas/VideoGeneratorExperience.js.map +1 -0
- package/lib/features/canvas/aiEdit.js +53 -0
- package/lib/features/canvas/aiEdit.js.map +1 -0
- package/lib/features/canvas/canvasAgentChat.js +76 -0
- package/lib/features/canvas/canvasAgentChat.js.map +1 -0
- package/lib/features/canvas/canvasBoardsCatalog.js +59 -0
- package/lib/features/canvas/canvasBoardsCatalog.js.map +1 -0
- package/lib/features/canvas/canvasBoardsSnapshot.js +14 -1
- package/lib/features/canvas/canvasBoardsSnapshot.js.map +1 -1
- package/lib/features/canvas/canvasChatDisplay.js +38 -0
- package/lib/features/canvas/canvasChatDisplay.js.map +1 -0
- package/lib/features/canvas/canvasChatTemplates.js +219 -0
- package/lib/features/canvas/canvasChatTemplates.js.map +1 -0
- package/lib/features/canvas/canvasCore.js +138 -1
- package/lib/features/canvas/canvasCore.js.map +1 -1
- package/lib/features/canvas/canvasEditOps.js +224 -0
- package/lib/features/canvas/canvasEditOps.js.map +1 -0
- package/lib/features/canvas/canvasTasks.js +187 -0
- package/lib/features/canvas/canvasTasks.js.map +1 -0
- package/lib/features/canvas/designPromptTemplates.js +3084 -0
- package/lib/features/canvas/designPromptTemplates.js.map +1 -0
- package/lib/features/canvas/editTools.js +54 -0
- package/lib/features/canvas/editTools.js.map +1 -0
- package/lib/features/canvas/extendVideo.js +5 -0
- package/lib/features/canvas/extendVideo.js.map +1 -0
- package/lib/features/canvas/frameExtract.js +33 -0
- package/lib/features/canvas/frameExtract.js.map +1 -0
- package/lib/features/canvas/generationModels.js +201 -0
- package/lib/features/canvas/generationModels.js.map +1 -0
- package/lib/features/canvas/influencer/influencerPipeline.js +170 -0
- package/lib/features/canvas/influencer/influencerPipeline.js.map +1 -0
- package/lib/features/canvas/influencer/productReel.js +72 -0
- package/lib/features/canvas/influencer/productReel.js.map +1 -0
- package/lib/features/canvas/influencer/reelPlan.js +159 -0
- package/lib/features/canvas/influencer/reelPlan.js.map +1 -0
- package/lib/features/canvas/moodboardCore.js +13 -0
- package/lib/features/canvas/moodboardCore.js.map +1 -0
- package/lib/features/canvas/promoProjectImport.js +99 -0
- package/lib/features/canvas/promoProjectImport.js.map +1 -0
- package/lib/features/canvas/promoVideo.js +312 -0
- package/lib/features/canvas/promoVideo.js.map +1 -0
- package/lib/features/canvas/recorder/CameraRecorderExperience.js +109 -0
- package/lib/features/canvas/recorder/CameraRecorderExperience.js.map +1 -0
- package/lib/features/canvas/sessionIdentity.js +28 -1
- package/lib/features/canvas/sessionIdentity.js.map +1 -1
- package/lib/features/canvas/set/SetViewportWebView.js +133 -0
- package/lib/features/canvas/set/SetViewportWebView.js.map +1 -0
- package/lib/features/canvas/set/cameraPath.js +194 -0
- package/lib/features/canvas/set/cameraPath.js.map +1 -0
- package/lib/features/canvas/set/setProject.js +24 -0
- package/lib/features/canvas/set/setProject.js.map +1 -0
- package/lib/features/canvas/storageLibrary.js +184 -0
- package/lib/features/canvas/storageLibrary.js.map +1 -0
- package/lib/features/canvas/studioCatalog.js +129 -0
- package/lib/features/canvas/studioCatalog.js.map +1 -0
- package/lib/features/canvas/studioLooks.js +189 -0
- package/lib/features/canvas/studioLooks.js.map +1 -0
- package/lib/features/canvas/surfaceIndex.js +63 -1
- package/lib/features/canvas/surfaceIndex.js.map +1 -1
- package/lib/features/canvas/templateImport/invideoNative.js +221 -0
- package/lib/features/canvas/templateImport/invideoNative.js.map +1 -0
- package/lib/features/canvas/templateImport/loadTemplate.js +43 -0
- package/lib/features/canvas/templateImport/loadTemplate.js.map +1 -0
- package/lib/features/canvas/templateImport/renderConfig.js +93 -0
- package/lib/features/canvas/templateImport/renderConfig.js.map +1 -0
- package/lib/features/canvas/useStudioCatalogTemplates.js +134 -0
- package/lib/features/canvas/useStudioCatalogTemplates.js.map +1 -0
- package/lib/features/canvas/video3d.js +109 -0
- package/lib/features/canvas/video3d.js.map +1 -0
- package/lib/features/canvas/videoClips.js +42 -0
- package/lib/features/canvas/videoClips.js.map +1 -0
- package/lib/features/canvas/videoEditor/agent/AgentCutPane.js +120 -0
- package/lib/features/canvas/videoEditor/agent/AgentCutPane.js.map +1 -0
- package/lib/features/canvas/videoEditor/agent/agentLoop.js +69 -0
- package/lib/features/canvas/videoEditor/agent/agentLoop.js.map +1 -0
- package/lib/features/canvas/videoEditor/agent/brainClient.js +45 -0
- package/lib/features/canvas/videoEditor/agent/brainClient.js.map +1 -0
- package/lib/features/canvas/videoEditor/agent/cutTools.js +129 -0
- package/lib/features/canvas/videoEditor/agent/cutTools.js.map +1 -0
- package/lib/features/canvas/videoEditor/editorModel.js +346 -0
- package/lib/features/canvas/videoEditor/editorModel.js.map +1 -0
- package/lib/features/canvas/videoEditor/exportRenderer.js +214 -0
- package/lib/features/canvas/videoEditor/exportRenderer.js.map +1 -0
- package/lib/features/canvas/videoEditor/filters.js +41 -0
- package/lib/features/canvas/videoEditor/filters.js.map +1 -0
- package/lib/features/canvas/videoEditor/mediaActions.js +57 -0
- package/lib/features/canvas/videoEditor/mediaActions.js.map +1 -0
- package/lib/features/canvas/videoEditor/remoteMediaClient.js +129 -0
- package/lib/features/canvas/videoEditor/remoteMediaClient.js.map +1 -0
- package/lib/features/canvas/videoEditor/solidColorPng.js +115 -0
- package/lib/features/canvas/videoEditor/solidColorPng.js.map +1 -0
- package/lib/features/canvas/videoEditor/videoEditOps.js +191 -0
- package/lib/features/canvas/videoEditor/videoEditOps.js.map +1 -0
- package/lib/features/canvas/videoEditor/videoProjectsStore.js +82 -0
- package/lib/features/canvas/videoEditor/videoProjectsStore.js.map +1 -0
- package/lib/features/canvas/videoRenderer.js +8 -0
- package/lib/features/canvas/videoRenderer.js.map +1 -0
- package/lib/features/canvas/withRemoteSafeArea.js +2 -2
- package/lib/features/canvas/withRemoteSafeArea.js.map +1 -1
- package/lib/features/characters/characterStudioProps.js +14 -0
- package/lib/features/characters/characterStudioProps.js.map +1 -0
- package/lib/features/chat/ChatCodeBlock.js +7 -3
- package/lib/features/chat/ChatCodeBlock.js.map +1 -1
- package/lib/features/chat/ChatTranscript.js +7 -3
- package/lib/features/chat/ChatTranscript.js.map +1 -1
- package/lib/features/chat/ChatWidgetCard.js +13 -0
- package/lib/features/chat/ChatWidgetCard.js.map +1 -0
- package/lib/features/chat/ConnectorConnectCard.js +164 -0
- package/lib/features/chat/ConnectorConnectCard.js.map +1 -0
- package/lib/features/chat/ConnectorConnectPrompt.js +254 -0
- package/lib/features/chat/ConnectorConnectPrompt.js.map +1 -0
- package/lib/features/chat/MessageActionBar.js.map +1 -1
- package/lib/features/chat/QueuedFollowUps.js +71 -0
- package/lib/features/chat/QueuedFollowUps.js.map +1 -0
- package/lib/features/chat/chatWidgets.js +37 -0
- package/lib/features/chat/chatWidgets.js.map +1 -0
- package/lib/features/chat/connectorConnect.js +194 -0
- package/lib/features/chat/connectorConnect.js.map +1 -0
- package/lib/features/chat/connectorConnectHandbacks.js +55 -0
- package/lib/features/chat/connectorConnectHandbacks.js.map +1 -0
- package/lib/features/design/DesignEditorExperience.js +643 -0
- package/lib/features/design/DesignEditorExperience.js.map +1 -0
- package/lib/features/design/DesignExperience.js +444 -0
- package/lib/features/design/DesignExperience.js.map +1 -0
- package/lib/features/design/designCore.js +298 -0
- package/lib/features/design/designCore.js.map +1 -0
- package/lib/features/design/designIndex.js +150 -0
- package/lib/features/design/designIndex.js.map +1 -0
- package/lib/features/design/exportDesign.js +133 -0
- package/lib/features/design/exportDesign.js.map +1 -0
- package/lib/features/job-search/ApplicationsPanel.js +907 -0
- package/lib/features/job-search/ApplicationsPanel.js.map +1 -0
- package/lib/features/job-search/ContactsPanel.js +627 -0
- package/lib/features/job-search/ContactsPanel.js.map +1 -0
- package/lib/features/job-search/InsightsPanel.js +299 -0
- package/lib/features/job-search/InsightsPanel.js.map +1 -0
- package/lib/features/job-search/InterviewPanel.js +637 -0
- package/lib/features/job-search/InterviewPanel.js.map +1 -0
- package/lib/features/job-search/JdPastePrompt.js +130 -0
- package/lib/features/job-search/JdPastePrompt.js.map +1 -0
- package/lib/features/job-search/JobCard.js +199 -0
- package/lib/features/job-search/JobCard.js.map +1 -0
- package/lib/features/job-search/JobDetailSheet.js +255 -0
- package/lib/features/job-search/JobDetailSheet.js.map +1 -0
- package/lib/features/job-search/JobSearchAgentChatPane.js +377 -0
- package/lib/features/job-search/JobSearchAgentChatPane.js.map +1 -0
- package/lib/features/job-search/JobSearchExperience.js +1324 -0
- package/lib/features/job-search/JobSearchExperience.js.map +1 -0
- package/lib/features/job-search/JobSearchLocationField.js +231 -0
- package/lib/features/job-search/JobSearchLocationField.js.map +1 -0
- package/lib/features/job-search/ProfilePanel.js +679 -0
- package/lib/features/job-search/ProfilePanel.js.map +1 -0
- package/lib/features/job-search/RepliesPanel.js +344 -0
- package/lib/features/job-search/RepliesPanel.js.map +1 -0
- package/lib/features/job-search/SavedPanel.js +297 -0
- package/lib/features/job-search/SavedPanel.js.map +1 -0
- package/lib/features/job-search/chat/widgetContent.js +29 -0
- package/lib/features/job-search/chat/widgetContent.js.map +1 -0
- package/lib/features/job-search/cvText.js +91 -0
- package/lib/features/job-search/cvText.js.map +1 -0
- package/lib/features/job-search/jobAgentSwipe.js +7 -0
- package/lib/features/job-search/jobAgentSwipe.js.map +1 -0
- package/lib/features/job-search/jobSearchClient.js +184 -0
- package/lib/features/job-search/jobSearchClient.js.map +1 -0
- package/lib/features/job-search/jobSearchExec.js +14 -0
- package/lib/features/job-search/jobSearchExec.js.map +1 -0
- package/lib/features/job-search/jobSearchRuntime.js +50 -0
- package/lib/features/job-search/jobSearchRuntime.js.map +1 -0
- package/lib/features/job-search/jobSearchTheme.js +44 -0
- package/lib/features/job-search/jobSearchTheme.js.map +1 -0
- package/lib/features/job-search/savedJobs.js +85 -0
- package/lib/features/job-search/savedJobs.js.map +1 -0
- package/lib/features/job-search/searchHistory.js +117 -0
- package/lib/features/job-search/searchHistory.js.map +1 -0
- package/lib/features/job-search/types.js +36 -0
- package/lib/features/job-search/types.js.map +1 -0
- package/lib/features/job-search/useJobSearchSession.js +558 -0
- package/lib/features/job-search/useJobSearchSession.js.map +1 -0
- package/lib/features/messaging/ChatComponents.js +529 -0
- package/lib/features/messaging/ChatComponents.js.map +1 -0
- package/lib/features/messaging/ChatInviteDeepLink.js +116 -0
- package/lib/features/messaging/ChatInviteDeepLink.js.map +1 -0
- package/lib/features/messaging/ContactsScreen.js +288 -0
- package/lib/features/messaging/ContactsScreen.js.map +1 -0
- package/lib/features/messaging/ConversationListScreen.js +147 -0
- package/lib/features/messaging/ConversationListScreen.js.map +1 -0
- package/lib/features/messaging/MessageActions.js +290 -0
- package/lib/features/messaging/MessageActions.js.map +1 -0
- package/lib/features/messaging/NativeChatExperience.js +189 -0
- package/lib/features/messaging/NativeChatExperience.js.map +1 -0
- package/lib/features/messaging/RegistrationScreen.js +7 -7
- package/lib/features/messaging/RegistrationScreen.js.map +1 -1
- package/lib/features/messaging/ThreadScreen.js +215 -0
- package/lib/features/messaging/ThreadScreen.js.map +1 -0
- package/lib/features/messaging/chatInviteLink.js +52 -0
- package/lib/features/messaging/chatInviteLink.js.map +1 -0
- package/lib/features/messaging/chatModel.js +278 -0
- package/lib/features/messaging/chatModel.js.map +1 -0
- package/lib/features/messaging/chatOperations.js +116 -1
- package/lib/features/messaging/chatOperations.js.map +1 -1
- package/lib/features/messaging/chatRegistrationStorage.js +4 -1
- package/lib/features/messaging/chatRegistrationStorage.js.map +1 -1
- package/lib/features/messaging/emojiCatalog.js +60 -0
- package/lib/features/messaging/emojiCatalog.js.map +1 -0
- package/lib/features/messaging/emojiKeywords.js +1592 -0
- package/lib/features/messaging/emojiKeywords.js.map +1 -0
- package/lib/features/messaging/nativeChatChannelQuery.js +27 -0
- package/lib/features/messaging/nativeChatChannelQuery.js.map +1 -0
- package/lib/features/messaging/phoneNumbers.js +52 -1
- package/lib/features/messaging/phoneNumbers.js.map +1 -1
- package/lib/features/messaging/sha256.js +68 -0
- package/lib/features/messaging/sha256.js.map +1 -0
- package/lib/features/messaging/useChatData.js +421 -0
- package/lib/features/messaging/useChatData.js.map +1 -0
- package/lib/features/messaging/useContactMatches.js +243 -0
- package/lib/features/messaging/useContactMatches.js.map +1 -0
- package/lib/features/messaging/usePhoneVerification.js +6 -5
- package/lib/features/messaging/usePhoneVerification.js.map +1 -1
- package/lib/features/messaging/useYantraChatMembership.js +9 -6
- package/lib/features/messaging/useYantraChatMembership.js.map +1 -1
- package/lib/features/messaging/yantraChatOrg.js +8 -3
- package/lib/features/messaging/yantraChatOrg.js.map +1 -1
- package/lib/features/resume/AnnotateModal.js +100 -0
- package/lib/features/resume/AnnotateModal.js.map +1 -0
- package/lib/features/resume/AnnotationBar.js +69 -0
- package/lib/features/resume/AnnotationBar.js.map +1 -0
- package/lib/features/resume/ExportSheet.js +105 -0
- package/lib/features/resume/ExportSheet.js.map +1 -0
- package/lib/features/resume/ResumeAgentChatPane.js +95 -0
- package/lib/features/resume/ResumeAgentChatPane.js.map +1 -0
- package/lib/features/resume/ResumeEditor.js +676 -0
- package/lib/features/resume/ResumeEditor.js.map +1 -0
- package/lib/features/resume/ResumeExperience.js +235 -0
- package/lib/features/resume/ResumeExperience.js.map +1 -0
- package/lib/features/resume/ResumeListPanel.js +262 -0
- package/lib/features/resume/ResumeListPanel.js.map +1 -0
- package/lib/features/resume/ResumeToolbar.js +236 -0
- package/lib/features/resume/ResumeToolbar.js.map +1 -0
- package/lib/features/resume/annotations.js +17 -0
- package/lib/features/resume/annotations.js.map +1 -0
- package/lib/features/resume/documentCss.js +52 -0
- package/lib/features/resume/documentCss.js.map +1 -0
- package/lib/features/resume/draft.js +89 -0
- package/lib/features/resume/draft.js.map +1 -0
- package/lib/features/resume/exportResume.js +43 -0
- package/lib/features/resume/exportResume.js.map +1 -0
- package/lib/features/resume/pickResumePhoto.js +22 -0
- package/lib/features/resume/pickResumePhoto.js.map +1 -0
- package/lib/features/resume/renderResume.js +121 -0
- package/lib/features/resume/renderResume.js.map +1 -0
- package/lib/features/resume/resumeClient.js +69 -0
- package/lib/features/resume/resumeClient.js.map +1 -0
- package/lib/features/resume/resumeExec.js +14 -0
- package/lib/features/resume/resumeExec.js.map +1 -0
- package/lib/features/resume/resumeIndex.js +244 -0
- package/lib/features/resume/resumeIndex.js.map +1 -0
- package/lib/features/resume/resumeRuntime.js +50 -0
- package/lib/features/resume/resumeRuntime.js.map +1 -0
- package/lib/features/resume/resumeTheme.js +34 -0
- package/lib/features/resume/resumeTheme.js.map +1 -0
- package/lib/features/resume/resumeToolbox.js +49 -0
- package/lib/features/resume/resumeToolbox.js.map +1 -0
- package/lib/features/resume/templates.js +90 -0
- package/lib/features/resume/templates.js.map +1 -0
- package/lib/features/resume/types.js +10 -0
- package/lib/features/resume/types.js.map +1 -0
- package/lib/features/resume/useResumeSession.js +183 -0
- package/lib/features/resume/useResumeSession.js.map +1 -0
- package/lib/features/shopping/DealsPanel.js +254 -0
- package/lib/features/shopping/DealsPanel.js.map +1 -0
- package/lib/features/shopping/HistoryPanel.js +147 -0
- package/lib/features/shopping/HistoryPanel.js.map +1 -0
- package/lib/features/shopping/OrdersPanel.js +157 -0
- package/lib/features/shopping/OrdersPanel.js.map +1 -0
- package/lib/features/shopping/ProductCard.js +326 -0
- package/lib/features/shopping/ProductCard.js.map +1 -0
- package/lib/features/shopping/ProductDetailSheet.js +313 -0
- package/lib/features/shopping/ProductDetailSheet.js.map +1 -0
- package/lib/features/shopping/ProductFilterBar.js +153 -0
- package/lib/features/shopping/ProductFilterBar.js.map +1 -0
- package/lib/features/shopping/ProductPhoto.js +27 -0
- package/lib/features/shopping/ProductPhoto.js.map +1 -0
- package/lib/features/shopping/SavedPanel.js +139 -0
- package/lib/features/shopping/SavedPanel.js.map +1 -0
- package/lib/features/shopping/ShoppingAgentChatPane.js +436 -0
- package/lib/features/shopping/ShoppingAgentChatPane.js.map +1 -0
- package/lib/features/shopping/ShoppingExperience.js +888 -0
- package/lib/features/shopping/ShoppingExperience.js.map +1 -0
- package/lib/features/shopping/TrendingSections.js +199 -0
- package/lib/features/shopping/TrendingSections.js.map +1 -0
- package/lib/features/shopping/WatchlistPanel.js +148 -0
- package/lib/features/shopping/WatchlistPanel.js.map +1 -0
- package/lib/features/shopping/catalog.js +238 -0
- package/lib/features/shopping/catalog.js.map +1 -0
- package/lib/features/shopping/chat/ShoppingChatResultCard.js +175 -0
- package/lib/features/shopping/chat/ShoppingChatResultCard.js.map +1 -0
- package/lib/features/shopping/chat/streamAssistantReply.js +34 -0
- package/lib/features/shopping/chat/streamAssistantReply.js.map +1 -0
- package/lib/features/shopping/chat/widgetContent.js +233 -0
- package/lib/features/shopping/chat/widgetContent.js.map +1 -0
- package/lib/features/shopping/hooks/useTrendingProducts.js +162 -0
- package/lib/features/shopping/hooks/useTrendingProducts.js.map +1 -0
- package/lib/features/shopping/productImage.js +42 -0
- package/lib/features/shopping/productImage.js.map +1 -0
- package/lib/features/shopping/savedProducts.js +84 -0
- package/lib/features/shopping/savedProducts.js.map +1 -0
- package/lib/features/shopping/services/catalogActions.js +166 -0
- package/lib/features/shopping/services/catalogActions.js.map +1 -0
- package/lib/features/shopping/services/parsePriceCheckIntent.js +58 -0
- package/lib/features/shopping/services/parsePriceCheckIntent.js.map +1 -0
- package/lib/features/shopping/services/parseShoppingIntent.js +67 -0
- package/lib/features/shopping/services/parseShoppingIntent.js.map +1 -0
- package/lib/features/shopping/services/productAvailability.js +25 -0
- package/lib/features/shopping/services/productAvailability.js.map +1 -0
- package/lib/features/shopping/services/productFilters.js +72 -0
- package/lib/features/shopping/services/productFilters.js.map +1 -0
- package/lib/features/shopping/services/retailerUrl.js +75 -0
- package/lib/features/shopping/services/retailerUrl.js.map +1 -0
- package/lib/features/shopping/services/shoppingChatReply.js +46 -0
- package/lib/features/shopping/services/shoppingChatReply.js.map +1 -0
- package/lib/features/shopping/services/shoppingProductSearch.js +336 -0
- package/lib/features/shopping/services/shoppingProductSearch.js.map +1 -0
- package/lib/features/shopping/services/shoppingSearchConnectorClient.js +41 -0
- package/lib/features/shopping/services/shoppingSearchConnectorClient.js.map +1 -0
- package/lib/features/shopping/shopAgentSwipe.js +7 -0
- package/lib/features/shopping/shopAgentSwipe.js.map +1 -0
- package/lib/features/shopping/shoppingCart.js +116 -0
- package/lib/features/shopping/shoppingCart.js.map +1 -0
- package/lib/features/shopping/shoppingExec.js +14 -0
- package/lib/features/shopping/shoppingExec.js.map +1 -0
- package/lib/features/shopping/shoppingHistoryStore.js +176 -0
- package/lib/features/shopping/shoppingHistoryStore.js.map +1 -0
- package/lib/features/shopping/shoppingRuntime.js +63 -0
- package/lib/features/shopping/shoppingRuntime.js.map +1 -0
- package/lib/features/shopping/timeAgo.js +14 -0
- package/lib/features/shopping/timeAgo.js.map +1 -0
- package/lib/features/shopping/useShoppingSearch.js +262 -0
- package/lib/features/shopping/useShoppingSearch.js.map +1 -0
- package/lib/features/travel/BookHeaderGlow.js +48 -0
- package/lib/features/travel/BookHeaderGlow.js.map +1 -0
- package/lib/features/travel/BookingsPanel.js +29 -0
- package/lib/features/travel/BookingsPanel.js.map +1 -0
- package/lib/features/travel/DiscoverPanel.js +155 -0
- package/lib/features/travel/DiscoverPanel.js.map +1 -0
- package/lib/features/travel/FlightCompareBar.js +86 -0
- package/lib/features/travel/FlightCompareBar.js.map +1 -0
- package/lib/features/travel/FlightDealsBoard.js +100 -0
- package/lib/features/travel/FlightDealsBoard.js.map +1 -0
- package/lib/features/travel/HistoryPanel.js +82 -0
- package/lib/features/travel/HistoryPanel.js.map +1 -0
- package/lib/features/travel/PopularDestinations.js +144 -0
- package/lib/features/travel/PopularDestinations.js.map +1 -0
- package/lib/features/travel/SavedPanel.js +27 -0
- package/lib/features/travel/SavedPanel.js.map +1 -0
- package/lib/features/travel/TravelAgentChatPane.js +303 -0
- package/lib/features/travel/TravelAgentChatPane.js.map +1 -0
- package/lib/features/travel/TravelBookHero.js +425 -0
- package/lib/features/travel/TravelBookHero.js.map +1 -0
- package/lib/features/travel/TravelDatesField.js +234 -0
- package/lib/features/travel/TravelDatesField.js.map +1 -0
- package/lib/features/travel/TravelDetailSheet.js +106 -0
- package/lib/features/travel/TravelDetailSheet.js.map +1 -0
- package/lib/features/travel/TravelExperience.js +624 -0
- package/lib/features/travel/TravelExperience.js.map +1 -0
- package/lib/features/travel/TravelGuestsField.js +85 -0
- package/lib/features/travel/TravelGuestsField.js.map +1 -0
- package/lib/features/travel/TravelLanding.js +318 -0
- package/lib/features/travel/TravelLanding.js.map +1 -0
- package/lib/features/travel/TravelLocationField.js +179 -0
- package/lib/features/travel/TravelLocationField.js.map +1 -0
- package/lib/features/travel/TravelPropertyCard.js +266 -0
- package/lib/features/travel/TravelPropertyCard.js.map +1 -0
- package/lib/features/travel/TravelPropertyPhoto.js +22 -0
- package/lib/features/travel/TravelPropertyPhoto.js.map +1 -0
- package/lib/features/travel/TravelRailFlyout.js +79 -0
- package/lib/features/travel/TravelRailFlyout.js.map +1 -0
- package/lib/features/travel/TravelResultsMap.js +126 -0
- package/lib/features/travel/TravelResultsMap.js.map +1 -0
- package/lib/features/travel/WorkspacePanel.js +148 -0
- package/lib/features/travel/WorkspacePanel.js.map +1 -0
- package/lib/features/travel/appNav.js +244 -0
- package/lib/features/travel/appNav.js.map +1 -0
- package/lib/features/travel/calendarDays.js +50 -0
- package/lib/features/travel/calendarDays.js.map +1 -0
- package/lib/features/travel/catalog.js +72 -0
- package/lib/features/travel/catalog.js.map +1 -0
- package/lib/features/travel/chat/TravelChatResultCard.js +107 -0
- package/lib/features/travel/chat/TravelChatResultCard.js.map +1 -0
- package/lib/features/travel/chat/widgetContent.js +107 -0
- package/lib/features/travel/chat/widgetContent.js.map +1 -0
- package/lib/features/travel/flightDeals.js +65 -0
- package/lib/features/travel/flightDeals.js.map +1 -0
- package/lib/features/travel/mapCoordinates.js +36 -0
- package/lib/features/travel/mapCoordinates.js.map +1 -0
- package/lib/features/travel/parseTravelIntent.js +303 -0
- package/lib/features/travel/parseTravelIntent.js.map +1 -0
- package/lib/features/travel/savedStays.js +66 -0
- package/lib/features/travel/savedStays.js.map +1 -0
- package/lib/features/travel/services/flightDealsBoard.js +111 -0
- package/lib/features/travel/services/flightDealsBoard.js.map +1 -0
- package/lib/features/travel/services/flightSearchConnectorClient.js +42 -0
- package/lib/features/travel/services/flightSearchConnectorClient.js.map +1 -0
- package/lib/features/travel/services/geocodeLocation.js +79 -0
- package/lib/features/travel/services/geocodeLocation.js.map +1 -0
- package/lib/features/travel/services/placePredictions.js +113 -0
- package/lib/features/travel/services/placePredictions.js.map +1 -0
- package/lib/features/travel/services/resolveOriginCity.js +27 -0
- package/lib/features/travel/services/resolveOriginCity.js.map +1 -0
- package/lib/features/travel/services/resortifiConnectorClient.js +76 -0
- package/lib/features/travel/services/resortifiConnectorClient.js.map +1 -0
- package/lib/features/travel/services/travelFlightSearch.js +289 -0
- package/lib/features/travel/services/travelFlightSearch.js.map +1 -0
- package/lib/features/travel/services/travelPropertySearch.js +377 -0
- package/lib/features/travel/services/travelPropertySearch.js.map +1 -0
- package/lib/features/travel/travelAgentSwipe.js +7 -0
- package/lib/features/travel/travelAgentSwipe.js.map +1 -0
- package/lib/features/travel/travelExec.js +14 -0
- package/lib/features/travel/travelExec.js.map +1 -0
- package/lib/features/travel/travelHistoryStore.js +108 -0
- package/lib/features/travel/travelHistoryStore.js.map +1 -0
- package/lib/features/travel/travelRuntime.js +62 -0
- package/lib/features/travel/travelRuntime.js.map +1 -0
- package/lib/features/travel/types.js +9 -0
- package/lib/features/travel/types.js.map +1 -0
- package/lib/features/travel/useTravelSearch.js +330 -0
- package/lib/features/travel/useTravelSearch.js.map +1 -0
- package/lib/features/travel/workspaceContent.js +548 -0
- package/lib/features/travel/workspaceContent.js.map +1 -0
- package/lib/hooks/useCdecliChannel.js +128 -6
- package/lib/hooks/useCdecliChannel.js.map +1 -1
- package/lib/hooks/useChatApi.js +4 -2
- package/lib/hooks/useChatApi.js.map +1 -1
- package/lib/hooks/useChatStream.js +77 -63
- package/lib/hooks/useChatStream.js.map +1 -1
- package/lib/hooks/useHostConnectorCard.js +24 -0
- package/lib/hooks/useHostConnectorCard.js.map +1 -0
- package/lib/hooks/useObtainSystemToken.js +23 -5
- package/lib/hooks/useObtainSystemToken.js.map +1 -1
- package/lib/hooks/webViewRetentionPolicy.js +1 -0
- package/lib/hooks/webViewRetentionPolicy.js.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/screens/Chat/index.js +51 -22
- package/lib/screens/Chat/index.js.map +1 -1
- package/lib/screens/ChatNative/index.js +13 -2
- package/lib/screens/ChatNative/index.js.map +1 -1
- package/lib/screens/Home/HomeScreen.js +3 -3
- package/lib/screens/Home/HomeScreen.js.map +1 -1
- package/lib/screens/Home/components/ChatHistoryLanding.js +32 -32
- package/lib/screens/Home/components/ChatHistoryLanding.js.map +1 -1
- package/lib/screens/JobSearchNative/useJobSearchHostChat.js +12 -6
- package/lib/screens/JobSearchNative/useJobSearchHostChat.js.map +1 -1
- package/lib/screens/ResumeNative/useResumeHostChat.js +12 -6
- package/lib/screens/ResumeNative/useResumeHostChat.js.map +1 -1
- package/lib/screens/ShoppingNative/useShoppingHostChat.js +12 -6
- package/lib/screens/ShoppingNative/useShoppingHostChat.js.map +1 -1
- package/lib/screens/TravelNative/useTravelHostChat.js +12 -6
- package/lib/screens/TravelNative/useTravelHostChat.js.map +1 -1
- package/lib/screens/WebBuilder/WebViewWithNavigation.js +2 -2
- package/lib/screens/WebBuilder/WebViewWithNavigation.js.map +1 -1
- package/lib/services/brainQuickReply.js +38 -1
- package/lib/services/brainQuickReply.js.map +1 -1
- package/lib/state/chatThreadMerge.js +6 -1
- package/lib/state/chatThreadMerge.js.map +1 -1
- package/package.json +6 -4
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import*as React from'react';import {YANTRA_CHAT_MEMBERS_QUERY,CONTACT_MATCHES_QUERY}from'./chatOperations.js';import {regionFromE164,normalizeContacts,collectLookupNumbers}from'./phoneNumbers.js';import {sha256}from'./sha256.js';var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
function memberToContact(row) {
|
|
21
|
+
var _a, _b;
|
|
22
|
+
return {
|
|
23
|
+
id: `member:${row.userId}`,
|
|
24
|
+
displayName: row.displayName,
|
|
25
|
+
imageUri: (_a = row.avatarUrl) != null ? _a : null,
|
|
26
|
+
e164: row.phoneE164 ? [row.phoneE164] : [],
|
|
27
|
+
match: {
|
|
28
|
+
userId: String(row.userId),
|
|
29
|
+
displayName: row.displayName,
|
|
30
|
+
picture: (_b = row.avatarUrl) != null ? _b : null
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function mergeOnYantra(peers, fromBook, viewerUserId) {
|
|
35
|
+
var _a, _b, _c, _d, _e;
|
|
36
|
+
const byUser = /* @__PURE__ */ new Map();
|
|
37
|
+
for (const row of [...peers, ...fromBook]) {
|
|
38
|
+
const uid = (_a = row.match) == null ? void 0 : _a.userId;
|
|
39
|
+
if (!uid || uid === viewerUserId || !/^[a-f0-9]{24}$/i.test(uid)) continue;
|
|
40
|
+
const existing = byUser.get(uid);
|
|
41
|
+
if (!existing) {
|
|
42
|
+
byUser.set(uid, row);
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
byUser.set(uid, __spreadProps(__spreadValues({}, existing), {
|
|
46
|
+
displayName: existing.displayName || row.displayName,
|
|
47
|
+
imageUri: existing.imageUri || row.imageUri,
|
|
48
|
+
e164: Array.from(/* @__PURE__ */ new Set([...existing.e164, ...row.e164])),
|
|
49
|
+
match: __spreadProps(__spreadValues({}, existing.match), {
|
|
50
|
+
displayName: ((_b = existing.match) == null ? void 0 : _b.displayName) || ((_c = row.match) == null ? void 0 : _c.displayName) || existing.displayName,
|
|
51
|
+
picture: ((_d = existing.match) == null ? void 0 : _d.picture) || ((_e = row.match) == null ? void 0 : _e.picture)
|
|
52
|
+
})
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
return Array.from(byUser.values()).sort((a, b) => a.displayName.localeCompare(b.displayName));
|
|
56
|
+
}
|
|
57
|
+
function readMatches(data) {
|
|
58
|
+
const raw = data == null ? void 0 : data.chatContactMatches;
|
|
59
|
+
if (Array.isArray(raw)) return raw;
|
|
60
|
+
if (raw && typeof raw === "object" && Array.isArray(raw.matches)) {
|
|
61
|
+
return raw.matches;
|
|
62
|
+
}
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
function useContactMatches(gql, contacts, viewer, phone) {
|
|
66
|
+
const [permission, setPermission] = React.useState(contacts ? "undetermined" : "unsupported");
|
|
67
|
+
const [limited, setLimited] = React.useState(false);
|
|
68
|
+
const [loading, setLoading] = React.useState(true);
|
|
69
|
+
const [error, setError] = React.useState(null);
|
|
70
|
+
const [peers, setPeers] = React.useState([]);
|
|
71
|
+
const [fromBook, setFromBook] = React.useState([]);
|
|
72
|
+
const [invitable, setInvitable] = React.useState([]);
|
|
73
|
+
const mounted = React.useRef(true);
|
|
74
|
+
React.useEffect(() => {
|
|
75
|
+
mounted.current = true;
|
|
76
|
+
return () => {
|
|
77
|
+
mounted.current = false;
|
|
78
|
+
};
|
|
79
|
+
}, []);
|
|
80
|
+
const loadPeers = React.useCallback(async () => {
|
|
81
|
+
var _a, _b, _c;
|
|
82
|
+
try {
|
|
83
|
+
let rows = [];
|
|
84
|
+
if (phone == null ? void 0 : phone.listMembers) {
|
|
85
|
+
const matches = await phone.listMembers();
|
|
86
|
+
rows = Object.values(matches).map((m) => {
|
|
87
|
+
var _a2;
|
|
88
|
+
return {
|
|
89
|
+
phoneE164: m.phoneE164,
|
|
90
|
+
userId: m.userId,
|
|
91
|
+
displayName: m.displayName,
|
|
92
|
+
avatarUrl: (_a2 = m.avatarUrl) != null ? _a2 : null
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
} else {
|
|
96
|
+
const res = await gql.query(YANTRA_CHAT_MEMBERS_QUERY);
|
|
97
|
+
if ((_a = res.errors) == null ? void 0 : _a.length) {
|
|
98
|
+
if (!mounted.current) return;
|
|
99
|
+
setError(res.errors[0].message);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
rows = (_c = (_b = res.data) == null ? void 0 : _b.yantraChatMembers) != null ? _c : [];
|
|
103
|
+
}
|
|
104
|
+
if (!mounted.current) return;
|
|
105
|
+
const viewerId = viewer == null ? void 0 : viewer.userId;
|
|
106
|
+
setPeers(rows.filter((r) => Boolean(r.userId) && r.userId !== viewerId && /^[a-f0-9]{24}$/i.test(r.userId)).map(memberToContact));
|
|
107
|
+
} catch (e) {
|
|
108
|
+
if (!mounted.current) return;
|
|
109
|
+
setError(e instanceof Error ? e.message : "Could not load Yantra Chat members");
|
|
110
|
+
}
|
|
111
|
+
}, [gql, phone, viewer == null ? void 0 : viewer.userId]);
|
|
112
|
+
const sync = React.useCallback(async () => {
|
|
113
|
+
var _a, _b, _c, _d;
|
|
114
|
+
if (!contacts) {
|
|
115
|
+
await loadPeers();
|
|
116
|
+
if (mounted.current) setLoading(false);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
setLoading(true);
|
|
120
|
+
setError(null);
|
|
121
|
+
try {
|
|
122
|
+
await loadPeers();
|
|
123
|
+
if (contacts.isLimited) {
|
|
124
|
+
const isLimited = await contacts.isLimited().catch(() => false);
|
|
125
|
+
if (mounted.current) setLimited(isLimited);
|
|
126
|
+
}
|
|
127
|
+
const raw = await contacts.read();
|
|
128
|
+
const regions = [contacts.defaultRegion, regionFromE164(viewer == null ? void 0 : viewer.phoneE164)];
|
|
129
|
+
const normalized = normalizeContacts(raw, regions, (_a = viewer == null ? void 0 : viewer.phoneE164) != null ? _a : null);
|
|
130
|
+
const numbers = collectLookupNumbers(normalized);
|
|
131
|
+
if (!numbers.length) {
|
|
132
|
+
if (!mounted.current) return;
|
|
133
|
+
setFromBook([]);
|
|
134
|
+
setInvitable(normalized);
|
|
135
|
+
setLoading(false);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
let matchedNumbers;
|
|
139
|
+
if (phone == null ? void 0 : phone.matchContacts) {
|
|
140
|
+
try {
|
|
141
|
+
const matches = await phone.matchContacts(numbers);
|
|
142
|
+
matchedNumbers = new Map(Object.entries(matches).map(([phoneE164, match]) => [phoneE164, match]));
|
|
143
|
+
} catch (err) {
|
|
144
|
+
if (!mounted.current) return;
|
|
145
|
+
setError(err instanceof Error ? err.message : "Could not match contacts");
|
|
146
|
+
setFromBook([]);
|
|
147
|
+
setInvitable(normalized);
|
|
148
|
+
setLoading(false);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
} else {
|
|
152
|
+
const byHash = /* @__PURE__ */ new Map();
|
|
153
|
+
for (const n of numbers) byHash.set(sha256(n), n);
|
|
154
|
+
const res = await gql.query(CONTACT_MATCHES_QUERY, {
|
|
155
|
+
phoneHashes: Array.from(byHash.keys())
|
|
156
|
+
});
|
|
157
|
+
if (!mounted.current) return;
|
|
158
|
+
matchedNumbers = /* @__PURE__ */ new Map();
|
|
159
|
+
for (const m of readMatches(res.data)) {
|
|
160
|
+
const number = (m == null ? void 0 : m.phoneHash) ? byHash.get(m.phoneHash) : void 0;
|
|
161
|
+
if (number && (m == null ? void 0 : m.userId)) matchedNumbers.set(number, m);
|
|
162
|
+
}
|
|
163
|
+
if ((_b = res.errors) == null ? void 0 : _b.length) {
|
|
164
|
+
setError(res.errors[0].message);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const here = [];
|
|
168
|
+
const rest = [];
|
|
169
|
+
for (const c of normalized) {
|
|
170
|
+
const hit = c.e164.map((n) => matchedNumbers.get(n)).find(Boolean);
|
|
171
|
+
if (hit == null ? void 0 : hit.userId) {
|
|
172
|
+
here.push(__spreadProps(__spreadValues({}, c), {
|
|
173
|
+
match: {
|
|
174
|
+
userId: String(hit.userId),
|
|
175
|
+
// Prefer the name from THEIR account over the one in
|
|
176
|
+
// your address book only when yours is missing -
|
|
177
|
+
// you called them "Mum" for a reason.
|
|
178
|
+
displayName: c.displayName || hit.displayName || hit.username || "Unknown",
|
|
179
|
+
picture: (_d = (_c = hit.avatarUrl) != null ? _c : hit.picture) != null ? _d : null
|
|
180
|
+
}
|
|
181
|
+
}));
|
|
182
|
+
} else {
|
|
183
|
+
rest.push(c);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
here.sort((a, b) => a.displayName.localeCompare(b.displayName));
|
|
187
|
+
rest.sort((a, b) => a.displayName.localeCompare(b.displayName));
|
|
188
|
+
setFromBook(here);
|
|
189
|
+
setInvitable(rest);
|
|
190
|
+
} catch (e) {
|
|
191
|
+
if (!mounted.current) return;
|
|
192
|
+
setError(e instanceof Error ? e.message : "Could not read your contacts.");
|
|
193
|
+
} finally {
|
|
194
|
+
if (mounted.current) setLoading(false);
|
|
195
|
+
}
|
|
196
|
+
}, [contacts, gql, viewer, phone, loadPeers]);
|
|
197
|
+
React.useEffect(() => {
|
|
198
|
+
void loadPeers().finally(() => {
|
|
199
|
+
if (mounted.current) setLoading(false);
|
|
200
|
+
});
|
|
201
|
+
}, [loadPeers]);
|
|
202
|
+
React.useEffect(() => {
|
|
203
|
+
let cancelled = false;
|
|
204
|
+
if (!contacts) {
|
|
205
|
+
setPermission("unsupported");
|
|
206
|
+
return () => void 0;
|
|
207
|
+
}
|
|
208
|
+
void (async () => {
|
|
209
|
+
const status = await contacts.getPermission();
|
|
210
|
+
if (cancelled || !mounted.current) return;
|
|
211
|
+
setPermission(status);
|
|
212
|
+
if (status === "granted") void sync();
|
|
213
|
+
})();
|
|
214
|
+
return () => {
|
|
215
|
+
cancelled = true;
|
|
216
|
+
};
|
|
217
|
+
}, [contacts, sync]);
|
|
218
|
+
const requestAccess = React.useCallback(async () => {
|
|
219
|
+
if (!contacts) return;
|
|
220
|
+
const status = await contacts.requestPermission();
|
|
221
|
+
if (!mounted.current) return;
|
|
222
|
+
setPermission(status);
|
|
223
|
+
if (status === "granted") await sync();
|
|
224
|
+
}, [contacts, sync]);
|
|
225
|
+
const chooseMoreContacts = React.useMemo(() => (contacts == null ? void 0 : contacts.chooseMoreContacts) ? async () => {
|
|
226
|
+
var _a;
|
|
227
|
+
await ((_a = contacts.chooseMoreContacts) == null ? void 0 : _a.call(contacts));
|
|
228
|
+
await sync();
|
|
229
|
+
} : void 0, [contacts, sync]);
|
|
230
|
+
const onYantra = React.useMemo(() => mergeOnYantra(peers, fromBook, viewer == null ? void 0 : viewer.userId), [peers, fromBook, viewer == null ? void 0 : viewer.userId]);
|
|
231
|
+
return {
|
|
232
|
+
permission,
|
|
233
|
+
limited,
|
|
234
|
+
loading,
|
|
235
|
+
error,
|
|
236
|
+
onYantra,
|
|
237
|
+
invitable,
|
|
238
|
+
requestAccess,
|
|
239
|
+
refresh: sync,
|
|
240
|
+
openSettings: async () => contacts == null ? void 0 : contacts.openSettings(),
|
|
241
|
+
chooseMoreContacts
|
|
242
|
+
};
|
|
243
|
+
}export{useContactMatches};//# sourceMappingURL=useContactMatches.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useContactMatches.js","sources":["../../../src/features/messaging/useContactMatches.ts"],"sourcesContent":["/**\n * The contact sync: read the address book, work out who is already here.\n *\n * The whole pipeline runs in the remote, so all of it is fixable by a surface\n * deploy: normalise -> hash -> ask the server -> split into \"on Yantra\" and\n * \"invite\". Only the address-book read itself is a host seam, because that is\n * the one part needing a native module.\n *\n * With phone-based membership (issue #1312), contact matching delegates to\n * the ChatPhoneSeam, which calls the `yantra-messenger` connector to match\n * E.164 phone numbers against chat members.\n *\n * NOTHING LEAVES THE DEVICE IN PLAINTEXT (legacy mode). Numbers are hashed\n * before the query. See sha256.ts and the server's chat-contact-directory.ts\n * for what that does and does not buy - it is not anonymity, but it does mean\n * we never upload or store the address book of someone who never signed up.\n *\n * If a ChatPhoneSeam is available, it takes precedence for matching.\n */\nimport * as React from 'react';\nimport { CONTACT_MATCHES_QUERY, YANTRA_CHAT_MEMBERS_QUERY } from './chatOperations';\nimport { collectLookupNumbers, normalizeContacts, regionFromE164, type NormalizedContact } from './phoneNumbers';\nimport { sha256 } from './sha256';\nimport type { ChatContactsSeam, ChatGraphQLSeam, ChatPermissionStatus, ChatViewer, ChatPhoneSeam } from './chatHost';\n\nexport interface MatchedContact extends NormalizedContact {\n /** Present when this contact already has an account. */\n match?: { userId: string; displayName: string; picture?: string | null };\n}\n\nexport interface ContactMatchesState {\n permission: ChatPermissionStatus | 'unsupported';\n /** Granted for selected contacts only (iOS 18 Limited Access). */\n limited: boolean;\n loading: boolean;\n error: string | null;\n /** Contacts already on Yantra - tap to open a DM. */\n onYantra: MatchedContact[];\n /** Everyone else - tap to invite. */\n invitable: MatchedContact[];\n /** Prompts, then syncs on success. */\n requestAccess: () => Promise<void>;\n /** Re-read the address book and re-match. */\n refresh: () => Promise<void>;\n openSettings: () => Promise<void>;\n /** Present when the host can show the iOS contact access picker. */\n chooseMoreContacts?: () => Promise<void>;\n}\n\ninterface DirectoryMember {\n phoneE164: string;\n userId: string;\n displayName: string;\n avatarUrl?: string | null;\n}\n\nfunction memberToContact(row: DirectoryMember): MatchedContact {\n return {\n id: `member:${row.userId}`,\n displayName: row.displayName,\n imageUri: row.avatarUrl ?? null,\n e164: row.phoneE164 ? [row.phoneE164] : [],\n match: {\n userId: String(row.userId),\n displayName: row.displayName,\n picture: row.avatarUrl ?? null,\n },\n };\n}\n\nfunction mergeOnYantra(\n peers: MatchedContact[],\n fromBook: MatchedContact[],\n viewerUserId?: string | null,\n): MatchedContact[] {\n const byUser = new Map<string, MatchedContact>();\n for (const row of [...peers, ...fromBook]) {\n const uid = row.match?.userId;\n if (!uid || uid === viewerUserId || !/^[a-f0-9]{24}$/i.test(uid)) continue;\n const existing = byUser.get(uid);\n if (!existing) {\n byUser.set(uid, row);\n continue;\n }\n byUser.set(uid, {\n ...existing,\n displayName: existing.displayName || row.displayName,\n imageUri: existing.imageUri || row.imageUri,\n e164: Array.from(new Set([...existing.e164, ...row.e164])),\n match: {\n ...existing.match!,\n displayName: existing.match?.displayName || row.match?.displayName || existing.displayName,\n picture: existing.match?.picture || row.match?.picture,\n },\n });\n }\n return Array.from(byUser.values()).sort((a, b) => a.displayName.localeCompare(b.displayName));\n}\n\ninterface WireMatch {\n phoneHash?: string;\n userId?: string;\n displayName?: string | null;\n username?: string | null;\n picture?: string | null;\n}\n\n/**\n * The server returns AnyObject, so the payload arrives untyped and possibly as\n * a bare array or wrapped. Normalising defensively here beats trusting a shape\n * the schema does not enforce.\n */\nfunction readMatches(data: unknown): WireMatch[] {\n const raw = (data as { chatContactMatches?: unknown })?.chatContactMatches;\n if (Array.isArray(raw)) return raw as WireMatch[];\n if (raw && typeof raw === 'object' && Array.isArray((raw as { matches?: unknown }).matches)) {\n return (raw as { matches: WireMatch[] }).matches;\n }\n return [];\n}\n\nexport function useContactMatches(\n gql: ChatGraphQLSeam,\n contacts: ChatContactsSeam | undefined,\n viewer: ChatViewer | null,\n phone?: ChatPhoneSeam,\n): ContactMatchesState {\n const [permission, setPermission] = React.useState<ChatPermissionStatus | 'unsupported'>(\n contacts ? 'undetermined' : 'unsupported',\n );\n const [limited, setLimited] = React.useState(false);\n const [loading, setLoading] = React.useState(true);\n const [error, setError] = React.useState<string | null>(null);\n const [peers, setPeers] = React.useState<MatchedContact[]>([]);\n const [fromBook, setFromBook] = React.useState<MatchedContact[]>([]);\n const [invitable, setInvitable] = React.useState<MatchedContact[]>([]);\n const mounted = React.useRef(true);\n\n React.useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n\n const loadPeers = React.useCallback(async () => {\n try {\n let rows: DirectoryMember[] = [];\n if (phone?.listMembers) {\n const matches = await phone.listMembers();\n rows = Object.values(matches).map((m) => ({\n phoneE164: m.phoneE164,\n userId: m.userId,\n displayName: m.displayName,\n avatarUrl: m.avatarUrl ?? null,\n }));\n } else {\n const res = await gql.query<{ yantraChatMembers?: DirectoryMember[] | null }>(\n YANTRA_CHAT_MEMBERS_QUERY,\n );\n if (res.errors?.length) {\n if (!mounted.current) return;\n setError(res.errors[0].message);\n return;\n }\n rows = res.data?.yantraChatMembers ?? [];\n }\n if (!mounted.current) return;\n const viewerId = viewer?.userId;\n setPeers(\n rows\n .filter((r) => Boolean(r.userId) && r.userId !== viewerId && /^[a-f0-9]{24}$/i.test(r.userId))\n .map(memberToContact),\n );\n } catch (e) {\n if (!mounted.current) return;\n setError(e instanceof Error ? e.message : 'Could not load Yantra Chat members');\n }\n }, [gql, phone, viewer?.userId]);\n\n const sync = React.useCallback(async () => {\n if (!contacts) {\n await loadPeers();\n if (mounted.current) setLoading(false);\n return;\n }\n setLoading(true);\n setError(null);\n try {\n await loadPeers();\n // Re-checked on every sync: the user can widen or narrow access in Settings at any time.\n if (contacts.isLimited) {\n const isLimited = await contacts.isLimited().catch(() => false);\n if (mounted.current) setLimited(isLimited);\n }\n const raw = await contacts.read();\n // Normalisation drops unmatchable numbers and the viewer's own\n // card, which almost everyone has saved.\n // Numbers saved without a country code are read against the device region AND the\n // viewer's verified country: the device may report US for a user whose contacts are Indian.\n const regions = [contacts.defaultRegion, regionFromE164(viewer?.phoneE164)];\n const normalized = normalizeContacts(raw, regions, viewer?.phoneE164 ?? null);\n const numbers = collectLookupNumbers(normalized);\n\n if (!numbers.length) {\n if (!mounted.current) return;\n setFromBook([]);\n setInvitable(normalized);\n setLoading(false);\n return;\n }\n\n let matchedNumbers: Map<string, any>;\n\n if (phone?.matchContacts) {\n // New phone-based membership: use connector to match by E.164 phone number\n try {\n const matches = await phone.matchContacts(numbers);\n matchedNumbers = new Map(Object.entries(matches).map(([phoneE164, match]) => [phoneE164, match]));\n } catch (err) {\n if (!mounted.current) return;\n setError(err instanceof Error ? err.message : 'Could not match contacts');\n setFromBook([]);\n setInvitable(normalized);\n setLoading(false);\n return;\n }\n } else {\n // Legacy hashed directory approach\n const byHash = new Map<string, string>();\n for (const n of numbers) byHash.set(sha256(n), n);\n\n const res = await gql.query(CONTACT_MATCHES_QUERY, { phoneHashes: Array.from(byHash.keys()) });\n if (!mounted.current) return;\n\n matchedNumbers = new Map<string, any>();\n for (const m of readMatches(res.data)) {\n const number = m?.phoneHash ? byHash.get(m.phoneHash) : undefined;\n if (number && m?.userId) matchedNumbers.set(number, m);\n }\n\n if (res.errors?.length) {\n setError(res.errors[0].message);\n }\n }\n\n const here: MatchedContact[] = [];\n const rest: MatchedContact[] = [];\n for (const c of normalized) {\n const hit = c.e164.map((n) => matchedNumbers.get(n)).find(Boolean);\n if (hit?.userId) {\n here.push({\n ...c,\n match: {\n userId: String(hit.userId),\n // Prefer the name from THEIR account over the one in\n // your address book only when yours is missing -\n // you called them \"Mum\" for a reason.\n displayName: c.displayName || hit.displayName || hit.username || 'Unknown',\n picture: hit.avatarUrl ?? hit.picture ?? null,\n },\n });\n } else {\n rest.push(c);\n }\n }\n\n here.sort((a, b) => a.displayName.localeCompare(b.displayName));\n rest.sort((a, b) => a.displayName.localeCompare(b.displayName));\n setFromBook(here);\n setInvitable(rest);\n } catch (e) {\n if (!mounted.current) return;\n setError(e instanceof Error ? e.message : 'Could not read your contacts.');\n } finally {\n if (mounted.current) setLoading(false);\n }\n }, [contacts, gql, viewer, phone, loadPeers]);\n\n React.useEffect(() => {\n void loadPeers().finally(() => {\n if (mounted.current) setLoading(false);\n });\n }, [loadPeers]);\n\n // Check the CURRENT status without prompting, so the screen can offer the\n // right action - ask, or deep-link to Settings after a previous denial.\n React.useEffect(() => {\n let cancelled = false;\n if (!contacts) {\n setPermission('unsupported');\n return () => undefined;\n }\n void (async () => {\n const status = await contacts.getPermission();\n if (cancelled || !mounted.current) return;\n setPermission(status);\n if (status === 'granted') void sync();\n })();\n return () => {\n cancelled = true;\n };\n }, [contacts, sync]);\n\n const requestAccess = React.useCallback(async () => {\n if (!contacts) return;\n const status = await contacts.requestPermission();\n if (!mounted.current) return;\n setPermission(status);\n if (status === 'granted') await sync();\n }, [contacts, sync]);\n\n // Reopens the address book afterwards: the user may have just shared more people.\n const chooseMoreContacts = React.useMemo(\n () =>\n contacts?.chooseMoreContacts\n ? async () => {\n await contacts.chooseMoreContacts?.();\n await sync();\n }\n : undefined,\n [contacts, sync],\n );\n\n const onYantra = React.useMemo(\n () => mergeOnYantra(peers, fromBook, viewer?.userId),\n [peers, fromBook, viewer?.userId],\n );\n\n return {\n permission,\n limited,\n loading,\n error,\n onYantra,\n invitable,\n requestAccess,\n refresh: sync,\n openSettings: async () => contacts?.openSettings(),\n chooseMoreContacts,\n };\n}\n"],"names":["_a"],"mappings":"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"}
|
|
@@ -19,7 +19,8 @@ function usePhoneVerification(defaultCountryCode) {
|
|
|
19
19
|
const [verifyPhoneOtpMutation] = useVerifyPhoneOtpCodeMutation();
|
|
20
20
|
const clearError = useCallback(() => setError(null), []);
|
|
21
21
|
const {
|
|
22
|
-
obtainSystemToken
|
|
22
|
+
obtainSystemToken,
|
|
23
|
+
getLastError: getLastTokenError
|
|
23
24
|
} = useObtainSystemToken();
|
|
24
25
|
const resetToInput = useCallback(() => {
|
|
25
26
|
setStage("input");
|
|
@@ -52,7 +53,7 @@ function usePhoneVerification(defaultCountryCode) {
|
|
|
52
53
|
setLoading(true);
|
|
53
54
|
try {
|
|
54
55
|
const systemToken = await obtainSystemToken();
|
|
55
|
-
if (!systemToken) throw new Error("Unable to obtain cdecli system token");
|
|
56
|
+
if (!systemToken) throw new Error(getLastTokenError() || "Unable to obtain cdecli system token");
|
|
56
57
|
const result = await sendPhoneOtpMutation({
|
|
57
58
|
variables: {
|
|
58
59
|
phoneNumber: {
|
|
@@ -74,7 +75,7 @@ function usePhoneVerification(defaultCountryCode) {
|
|
|
74
75
|
} finally {
|
|
75
76
|
setLoading(false);
|
|
76
77
|
}
|
|
77
|
-
}, [inputPhone, countryCode, sendPhoneOtpMutation, clearError, obtainSystemToken]);
|
|
78
|
+
}, [inputPhone, countryCode, sendPhoneOtpMutation, clearError, obtainSystemToken, getLastTokenError]);
|
|
78
79
|
const verifyOtp = useCallback(async () => {
|
|
79
80
|
var _a;
|
|
80
81
|
clearError();
|
|
@@ -100,7 +101,7 @@ function usePhoneVerification(defaultCountryCode) {
|
|
|
100
101
|
setLoading(true);
|
|
101
102
|
try {
|
|
102
103
|
const systemToken = await obtainSystemToken();
|
|
103
|
-
if (!systemToken) throw new Error("Unable to obtain cdecli system token");
|
|
104
|
+
if (!systemToken) throw new Error(getLastTokenError() || "Unable to obtain cdecli system token");
|
|
104
105
|
const result = await verifyPhoneOtpMutation({
|
|
105
106
|
variables: {
|
|
106
107
|
phoneNumber: {
|
|
@@ -125,7 +126,7 @@ function usePhoneVerification(defaultCountryCode) {
|
|
|
125
126
|
} finally {
|
|
126
127
|
setLoading(false);
|
|
127
128
|
}
|
|
128
|
-
}, [otp, inputPhone, countryCode, testOtpMode, verifyPhoneOtpMutation, clearError, obtainSystemToken]);
|
|
129
|
+
}, [otp, inputPhone, countryCode, testOtpMode, verifyPhoneOtpMutation, clearError, obtainSystemToken, getLastTokenError]);
|
|
129
130
|
return {
|
|
130
131
|
stage,
|
|
131
132
|
verifiedPhone,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePhoneVerification.js","sources":["../../../src/features/messaging/usePhoneVerification.ts"],"sourcesContent":["/**\n * Phone number verification flow for Yantra Chat registration.\n *\n * Manages the OTP verification process for phone-number-based membership.\n * Uses adminIde's existing `sendPhoneOTP` / `verifyPhoneOtp` mutations and Auth0's\n * `passwordlessLogin` endpoint.\n *\n * Phone numbers are normalized to E.164 format and serve as the member ID.\n */\nimport { useCallback, useState } from 'react';\nimport { useSendPhoneOtpCodeMutation, useVerifyPhoneOtpCodeMutation } from 'common/graphql';\nimport { formatPhoneNumber, isValidPhoneNumber } from './phoneNumbers';\nimport { useObtainSystemToken } from '../../hooks/useObtainSystemToken';\n\n/** Fixed code for \"Continue with test OTP\" and local dev bypass (no SMS verify). */\nexport const CHAT_REGISTRATION_TEST_OTP = '123456';\n\nfunction isChatTestOtpCode(code: string): boolean {\n return code.replace(/\\D/g, '') === CHAT_REGISTRATION_TEST_OTP;\n}\n\nfunction canBypassOtpWithTestCode(): boolean {\n if (typeof __DEV__ !== 'undefined' && __DEV__) return true;\n return process.env.EXPO_PUBLIC_CHAT_ALLOW_TEST_OTP === 'true';\n}\n\nexport interface PhoneVerificationState {\n /** Current stage of the verification flow. */\n stage: 'input' | 'otp' | 'verifying' | 'verified' | 'error';\n /** The phone number in E.164 format, if successfully verified. */\n verifiedPhone: string | null;\n /** The user-entered phone (raw input, before normalization). */\n inputPhone: string;\n /** Country code (ISO-3166 alpha-2) for phone normalization. */\n countryCode: string;\n /** OTP entered by the user. */\n otp: string;\n /** Error message if verification failed. */\n error: string | null;\n /** Busy: waiting for server response. */\n loading: boolean;\n /** User chose \"Continue with test OTP\" — skip server verify when code is 123456. */\n testOtpMode: boolean;\n}\n\nexport interface PhoneVerificationActions {\n setCountryCode: (code: string) => void;\n setInputPhone: (phone: string) => void;\n setOtp: (code: string) => void;\n sendOtp: () => Promise<void>;\n verifyOtp: () => Promise<void>;\n continueWithTestOtp: () => void;\n resetToInput: () => void;\n clearError: () => void;\n}\n\nexport interface UsePhoneVerificationResult extends PhoneVerificationState, PhoneVerificationActions {}\n\n/**\n * Manages the phone verification lifecycle.\n *\n * Starts with phone input, sends OTP, then prompts for the code.\n * On success, `verifiedPhone` contains the E.164 number ready to become\n * a member ID.\n */\nexport function usePhoneVerification(defaultCountryCode?: string): UsePhoneVerificationResult {\n const [stage, setStage] = useState<PhoneVerificationState['stage']>('input');\n const [inputPhone, setInputPhone] = useState('');\n const [countryCode, setCountryCode] = useState(defaultCountryCode || 'US');\n const [otp, setOtp] = useState('');\n const [verifiedPhone, setVerifiedPhone] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(false);\n const [testOtpMode, setTestOtpMode] = useState(false);\n\n const [sendPhoneOtpMutation] = useSendPhoneOtpCodeMutation();\n const [verifyPhoneOtpMutation] = useVerifyPhoneOtpCodeMutation();\n\n const clearError = useCallback(() => setError(null), []);\n const { obtainSystemToken } = useObtainSystemToken();\n\n const resetToInput = useCallback(() => {\n setStage('input');\n setInputPhone('');\n setOtp('');\n setError(null);\n setVerifiedPhone(null);\n setTestOtpMode(false);\n }, []);\n\n const continueWithTestOtp = useCallback(() => {\n clearError();\n const normalized = formatPhoneNumber(inputPhone, countryCode);\n if (!normalized || !isValidPhoneNumber(normalized)) {\n setError('Please enter a valid mobile number');\n return;\n }\n setTestOtpMode(true);\n setOtp(CHAT_REGISTRATION_TEST_OTP);\n setStage('otp');\n }, [inputPhone, countryCode, clearError]);\n\n const sendOtp = useCallback(async () => {\n clearError();\n setTestOtpMode(false);\n const normalized = formatPhoneNumber(inputPhone, countryCode);\n\n if (!normalized || !isValidPhoneNumber(normalized)) {\n setError('Please enter a valid mobile number');\n return;\n }\n\n setLoading(true);\n try {\n const systemToken = await obtainSystemToken();\n if (!systemToken) throw new Error('Unable to obtain cdecli system token');\n\n const result = await sendPhoneOtpMutation({\n variables: { phoneNumber: { phoneNumber: normalized } },\n context: { headers: { 'x-cdecli-system-token': systemToken } },\n });\n\n if (!result.data?.sendPhoneOTPCode) throw new Error('Failed to send OTP');\n setOtp('');\n setStage('otp');\n setError(null);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to send OTP');\n } finally {\n setLoading(false);\n }\n }, [inputPhone, countryCode, sendPhoneOtpMutation, clearError, obtainSystemToken]);\n\n const verifyOtp = useCallback(async () => {\n clearError();\n\n const code = otp.replace(/\\D/g, '');\n if (!code || code.length !== 6) {\n setError('Please enter a valid 6-digit OTP');\n return;\n }\n\n const normalized = formatPhoneNumber(inputPhone, countryCode);\n if (!normalized) {\n setError('Please enter a valid phone number');\n return;\n }\n\n // Test path: skip server verify (explicit test flow or dev code 123456).\n const useTestBypass = testOtpMode || (canBypassOtpWithTestCode() && isChatTestOtpCode(code));\n if (useTestBypass && isChatTestOtpCode(code)) {\n setVerifiedPhone(normalized);\n setStage('verified');\n setTestOtpMode(false);\n setError(null);\n return;\n }\n\n setStage('verifying');\n setLoading(true);\n try {\n const systemToken = await obtainSystemToken();\n if (!systemToken) throw new Error('Unable to obtain cdecli system token');\n\n const result = await verifyPhoneOtpMutation({\n variables: { phoneNumber: { phoneNumber: normalized }, otp: code },\n context: { headers: { 'x-cdecli-system-token': systemToken } },\n });\n\n if (!result.data?.verifyPhoneOTPCode) throw new Error('Invalid or expired OTP');\n setVerifiedPhone(normalized);\n setStage('verified');\n setTestOtpMode(false);\n setError(null);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to verify OTP');\n setStage('otp');\n } finally {\n setLoading(false);\n }\n }, [otp, inputPhone, countryCode, testOtpMode, verifyPhoneOtpMutation, clearError, obtainSystemToken]);\n\n return {\n stage,\n verifiedPhone,\n inputPhone,\n countryCode,\n otp,\n error,\n loading,\n testOtpMode,\n setCountryCode,\n setInputPhone,\n setOtp,\n sendOtp,\n verifyOtp,\n continueWithTestOtp,\n resetToInput,\n clearError,\n };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"usePhoneVerification.js","sources":["../../../src/features/messaging/usePhoneVerification.ts"],"sourcesContent":["/**\n * Phone number verification flow for Yantra Chat registration.\n *\n * Manages the OTP verification process for phone-number-based membership.\n * Uses adminIde's existing `sendPhoneOTP` / `verifyPhoneOtp` mutations and Auth0's\n * `passwordlessLogin` endpoint.\n *\n * Phone numbers are normalized to E.164 format and serve as the member ID.\n */\nimport { useCallback, useState } from 'react';\nimport { useSendPhoneOtpCodeMutation, useVerifyPhoneOtpCodeMutation } from 'common/graphql';\nimport { formatPhoneNumber, isValidPhoneNumber } from './phoneNumbers';\nimport { useObtainSystemToken } from '../../hooks/useObtainSystemToken';\n\n/** Fixed code for \"Continue with test OTP\" and local dev bypass (no SMS verify). */\nexport const CHAT_REGISTRATION_TEST_OTP = '123456';\n\nfunction isChatTestOtpCode(code: string): boolean {\n return code.replace(/\\D/g, '') === CHAT_REGISTRATION_TEST_OTP;\n}\n\nfunction canBypassOtpWithTestCode(): boolean {\n if (typeof __DEV__ !== 'undefined' && __DEV__) return true;\n return process.env.EXPO_PUBLIC_CHAT_ALLOW_TEST_OTP === 'true';\n}\n\nexport interface PhoneVerificationState {\n /** Current stage of the verification flow. */\n stage: 'input' | 'otp' | 'verifying' | 'verified' | 'error';\n /** The phone number in E.164 format, if successfully verified. */\n verifiedPhone: string | null;\n /** The user-entered phone (raw input, before normalization). */\n inputPhone: string;\n /** Country code (ISO-3166 alpha-2) for phone normalization. */\n countryCode: string;\n /** OTP entered by the user. */\n otp: string;\n /** Error message if verification failed. */\n error: string | null;\n /** Busy: waiting for server response. */\n loading: boolean;\n /** User chose \"Continue with test OTP\" — skip server verify when code is 123456. */\n testOtpMode: boolean;\n}\n\nexport interface PhoneVerificationActions {\n setCountryCode: (code: string) => void;\n setInputPhone: (phone: string) => void;\n setOtp: (code: string) => void;\n sendOtp: () => Promise<void>;\n verifyOtp: () => Promise<void>;\n continueWithTestOtp: () => void;\n resetToInput: () => void;\n clearError: () => void;\n}\n\nexport interface UsePhoneVerificationResult extends PhoneVerificationState, PhoneVerificationActions {}\n\n/**\n * Manages the phone verification lifecycle.\n *\n * Starts with phone input, sends OTP, then prompts for the code.\n * On success, `verifiedPhone` contains the E.164 number ready to become\n * a member ID.\n */\nexport function usePhoneVerification(defaultCountryCode?: string): UsePhoneVerificationResult {\n const [stage, setStage] = useState<PhoneVerificationState['stage']>('input');\n const [inputPhone, setInputPhone] = useState('');\n const [countryCode, setCountryCode] = useState(defaultCountryCode || 'US');\n const [otp, setOtp] = useState('');\n const [verifiedPhone, setVerifiedPhone] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(false);\n const [testOtpMode, setTestOtpMode] = useState(false);\n\n const [sendPhoneOtpMutation] = useSendPhoneOtpCodeMutation();\n const [verifyPhoneOtpMutation] = useVerifyPhoneOtpCodeMutation();\n\n const clearError = useCallback(() => setError(null), []);\n const { obtainSystemToken, getLastError: getLastTokenError } = useObtainSystemToken();\n\n const resetToInput = useCallback(() => {\n setStage('input');\n setInputPhone('');\n setOtp('');\n setError(null);\n setVerifiedPhone(null);\n setTestOtpMode(false);\n }, []);\n\n const continueWithTestOtp = useCallback(() => {\n clearError();\n const normalized = formatPhoneNumber(inputPhone, countryCode);\n if (!normalized || !isValidPhoneNumber(normalized)) {\n setError('Please enter a valid mobile number');\n return;\n }\n setTestOtpMode(true);\n setOtp(CHAT_REGISTRATION_TEST_OTP);\n setStage('otp');\n }, [inputPhone, countryCode, clearError]);\n\n const sendOtp = useCallback(async () => {\n clearError();\n setTestOtpMode(false);\n const normalized = formatPhoneNumber(inputPhone, countryCode);\n\n if (!normalized || !isValidPhoneNumber(normalized)) {\n setError('Please enter a valid mobile number');\n return;\n }\n\n setLoading(true);\n try {\n const systemToken = await obtainSystemToken();\n if (!systemToken) throw new Error(getLastTokenError() || 'Unable to obtain cdecli system token');\n\n const result = await sendPhoneOtpMutation({\n variables: { phoneNumber: { phoneNumber: normalized } },\n context: { headers: { 'x-cdecli-system-token': systemToken } },\n });\n\n if (!result.data?.sendPhoneOTPCode) throw new Error('Failed to send OTP');\n setOtp('');\n setStage('otp');\n setError(null);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to send OTP');\n } finally {\n setLoading(false);\n }\n }, [inputPhone, countryCode, sendPhoneOtpMutation, clearError, obtainSystemToken, getLastTokenError]);\n\n const verifyOtp = useCallback(async () => {\n clearError();\n\n const code = otp.replace(/\\D/g, '');\n if (!code || code.length !== 6) {\n setError('Please enter a valid 6-digit OTP');\n return;\n }\n\n const normalized = formatPhoneNumber(inputPhone, countryCode);\n if (!normalized) {\n setError('Please enter a valid phone number');\n return;\n }\n\n // Test path: skip server verify (explicit test flow or dev code 123456).\n const useTestBypass = testOtpMode || (canBypassOtpWithTestCode() && isChatTestOtpCode(code));\n if (useTestBypass && isChatTestOtpCode(code)) {\n setVerifiedPhone(normalized);\n setStage('verified');\n setTestOtpMode(false);\n setError(null);\n return;\n }\n\n setStage('verifying');\n setLoading(true);\n try {\n const systemToken = await obtainSystemToken();\n if (!systemToken) throw new Error(getLastTokenError() || 'Unable to obtain cdecli system token');\n\n const result = await verifyPhoneOtpMutation({\n variables: { phoneNumber: { phoneNumber: normalized }, otp: code },\n context: { headers: { 'x-cdecli-system-token': systemToken } },\n });\n\n if (!result.data?.verifyPhoneOTPCode) throw new Error('Invalid or expired OTP');\n setVerifiedPhone(normalized);\n setStage('verified');\n setTestOtpMode(false);\n setError(null);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to verify OTP');\n setStage('otp');\n } finally {\n setLoading(false);\n }\n }, [\n otp,\n inputPhone,\n countryCode,\n testOtpMode,\n verifyPhoneOtpMutation,\n clearError,\n obtainSystemToken,\n getLastTokenError,\n ]);\n\n return {\n stage,\n verifiedPhone,\n inputPhone,\n countryCode,\n otp,\n error,\n loading,\n testOtpMode,\n setCountryCode,\n setInputPhone,\n setOtp,\n sendOtp,\n verifyOtp,\n continueWithTestOtp,\n resetToInput,\n clearError,\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {useState,useCallback,useEffect,useMemo}from'react';import {useApolloClient,gql}from'@apollo/client/index.js';import AsyncStorage from'@react-native-async-storage/async-storage';import {YANTRA_CHAT_REGISTRATION_STATUS_QUERY,REGISTER_YANTRA_CHAT_MEMBER_MUTATION}from'./chatOperations.js';import {
|
|
1
|
+
import {useState,useCallback,useEffect,useMemo}from'react';import {useApolloClient,gql}from'@apollo/client/index.js';import AsyncStorage from'@react-native-async-storage/async-storage';import {YANTRA_CHAT_REGISTRATION_STATUS_QUERY,REGISTER_YANTRA_CHAT_MEMBER_MUTATION}from'./chatOperations.js';import {yantraChatPhoneStorageKey}from'./chatRegistrationStorage.js';const REGISTRATION_STATUS_DOCUMENT = gql(YANTRA_CHAT_REGISTRATION_STATUS_QUERY);
|
|
2
2
|
const REGISTER_MEMBER_DOCUMENT = gql(REGISTER_YANTRA_CHAT_MEMBER_MUTATION);
|
|
3
3
|
function useYantraChatMembership(userId, displayName) {
|
|
4
4
|
const client = useApolloClient();
|
|
@@ -14,8 +14,11 @@ function useYantraChatMembership(userId, displayName) {
|
|
|
14
14
|
}
|
|
15
15
|
setError(null);
|
|
16
16
|
try {
|
|
17
|
-
const cached = await AsyncStorage.getItem(
|
|
18
|
-
if (cached)
|
|
17
|
+
const cached = await AsyncStorage.getItem(yantraChatPhoneStorageKey(userId));
|
|
18
|
+
if (cached) {
|
|
19
|
+
setPhoneE164(cached);
|
|
20
|
+
setLoading(false);
|
|
21
|
+
}
|
|
19
22
|
const res = await client.query({
|
|
20
23
|
query: REGISTRATION_STATUS_DOCUMENT,
|
|
21
24
|
fetchPolicy: "network-only"
|
|
@@ -28,10 +31,10 @@ function useYantraChatMembership(userId, displayName) {
|
|
|
28
31
|
if ((status == null ? void 0 : status.registered) && status.phoneE164) {
|
|
29
32
|
setPhoneE164(status.phoneE164);
|
|
30
33
|
setOrganizationId(status.organizationId);
|
|
31
|
-
await AsyncStorage.setItem(
|
|
34
|
+
await AsyncStorage.setItem(yantraChatPhoneStorageKey(userId), status.phoneE164);
|
|
32
35
|
} else if (status && status.registered === false) {
|
|
33
36
|
setPhoneE164(null);
|
|
34
|
-
await AsyncStorage.removeItem(
|
|
37
|
+
await AsyncStorage.removeItem(yantraChatPhoneStorageKey(userId));
|
|
35
38
|
}
|
|
36
39
|
} catch (err) {
|
|
37
40
|
setError(err instanceof Error ? err.message : "Could not load chat registration");
|
|
@@ -59,7 +62,7 @@ function useYantraChatMembership(userId, displayName) {
|
|
|
59
62
|
}
|
|
60
63
|
setPhoneE164(payload.phoneE164);
|
|
61
64
|
setOrganizationId(payload.organizationId);
|
|
62
|
-
await AsyncStorage.setItem(
|
|
65
|
+
await AsyncStorage.setItem(yantraChatPhoneStorageKey(userId), payload.phoneE164);
|
|
63
66
|
return payload.phoneE164;
|
|
64
67
|
}, [client, userId, displayName]);
|
|
65
68
|
const needsRegistration = useMemo(() => Boolean(userId) && !loading && !phoneE164, [userId, loading, phoneE164]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useYantraChatMembership.js","sources":["../../../src/features/messaging/useYantraChatMembership.ts"],"sourcesContent":["/**\n * Yantra Chat registration status + register mutation (issue #1312).\n */\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { gql, useApolloClient } from '@apollo/client';\nimport AsyncStorage from '@react-native-async-storage/async-storage';\nimport { REGISTER_YANTRA_CHAT_MEMBER_MUTATION, YANTRA_CHAT_REGISTRATION_STATUS_QUERY } from './chatOperations';\nimport {
|
|
1
|
+
{"version":3,"file":"useYantraChatMembership.js","sources":["../../../src/features/messaging/useYantraChatMembership.ts"],"sourcesContent":["/**\n * Yantra Chat registration status + register mutation (issue #1312).\n */\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { gql, useApolloClient } from '@apollo/client';\nimport AsyncStorage from '@react-native-async-storage/async-storage';\nimport { REGISTER_YANTRA_CHAT_MEMBER_MUTATION, YANTRA_CHAT_REGISTRATION_STATUS_QUERY } from './chatOperations';\nimport { yantraChatPhoneStorageKey } from './chatRegistrationStorage';\n\nconst REGISTRATION_STATUS_DOCUMENT = gql(YANTRA_CHAT_REGISTRATION_STATUS_QUERY);\nconst REGISTER_MEMBER_DOCUMENT = gql(REGISTER_YANTRA_CHAT_MEMBER_MUTATION);\n\ninterface RegistrationPayload {\n registered: boolean;\n phoneE164: string | null;\n memberId: string | null;\n organizationId: string;\n}\n\nexport function useYantraChatMembership(userId: string | null, displayName: string) {\n const client = useApolloClient();\n const [phoneE164, setPhoneE164] = useState<string | null>(null);\n const [organizationId, setOrganizationId] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n const refresh = useCallback(async () => {\n if (!userId) {\n setLoading(false);\n return;\n }\n setError(null);\n try {\n const cached = await AsyncStorage.getItem(yantraChatPhoneStorageKey(userId));\n if (cached) {\n // Already registered on this device: open chat now and confirm with the server in the\n // background. A server \"not registered\" still clears this and shows registration.\n setPhoneE164(cached);\n setLoading(false);\n }\n\n const res = await client.query<{ yantraChatRegistrationStatus?: RegistrationPayload }>({\n query: REGISTRATION_STATUS_DOCUMENT,\n fetchPolicy: 'network-only',\n });\n\n if (res.errors?.length) {\n setError(res.errors[0]?.message ?? 'Could not load chat registration');\n // Keep AsyncStorage + in-memory phone on transient GraphQL errors (Metro reload, backend restart).\n return;\n }\n\n const status = res.data?.yantraChatRegistrationStatus;\n if (status?.registered && status.phoneE164) {\n setPhoneE164(status.phoneE164);\n setOrganizationId(status.organizationId);\n await AsyncStorage.setItem(yantraChatPhoneStorageKey(userId), status.phoneE164);\n } else if (status && status.registered === false) {\n setPhoneE164(null);\n await AsyncStorage.removeItem(yantraChatPhoneStorageKey(userId));\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Could not load chat registration');\n // Network failure: do not clear cached registration.\n } finally {\n setLoading(false);\n }\n }, [client, userId]);\n\n useEffect(() => {\n void refresh();\n }, [refresh]);\n\n const register = useCallback(\n async (phone: string) => {\n if (!userId) throw new Error('Not signed in');\n setError(null);\n const res = await client.mutate<{ registerYantraChatMember?: RegistrationPayload }>({\n mutation: REGISTER_MEMBER_DOCUMENT,\n variables: { phoneE164: phone, displayName },\n });\n const payload = res.data?.registerYantraChatMember;\n if (!payload?.registered || !payload.phoneE164) {\n throw new Error('Registration did not complete');\n }\n setPhoneE164(payload.phoneE164);\n setOrganizationId(payload.organizationId);\n await AsyncStorage.setItem(yantraChatPhoneStorageKey(userId), payload.phoneE164);\n return payload.phoneE164;\n },\n [client, userId, displayName],\n );\n\n const needsRegistration = useMemo(() => Boolean(userId) && !loading && !phoneE164, [userId, loading, phoneE164]);\n\n return {\n phoneE164,\n organizationId,\n loading,\n error,\n needsRegistration,\n register,\n refresh,\n };\n}\n"],"names":[],"mappings":"2WAQA,MAAM,4BAAA,GAA+B,IAAI,qCAAqC,CAAA;AAC9E,MAAM,wBAAA,GAA2B,IAAI,oCAAoC,CAAA;AAOzD,SAAA,uBAAA,CAAwB,QAAuB,WAAqB,EAAA;AAClF,EAAA,MAAM,SAAS,eAAgB,EAAA;AAC/B,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAwB,IAAI,CAAA;AAC9D,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAI,SAAwB,IAAI,CAAA;AACxE,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,IAAI,CAAA;AAC3C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAwB,IAAI,CAAA;AACtD,EAAM,MAAA,OAAA,GAAU,YAAY,YAAY;AAtB1C,IAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA;AAuBI,IAAA,IAAI,CAAC,MAAQ,EAAA;AACX,MAAA,UAAA,CAAW,KAAK,CAAA;AAChB,MAAA;AAAA;AAEF,IAAA,QAAA,CAAS,IAAI,CAAA;AACb,IAAI,IAAA;AACF,MAAA,MAAM,SAAS,MAAM,YAAA,CAAa,OAAQ,CAAA,yBAAA,CAA0B,MAAM,CAAC,CAAA;AAC3E,MAAA,IAAI,MAAQ,EAAA;AAGV,QAAA,YAAA,CAAa,MAAM,CAAA;AACnB,QAAA,UAAA,CAAW,KAAK,CAAA;AAAA;AAElB,MAAM,MAAA,GAAA,GAAM,MAAM,MAAA,CAAO,KAEtB,CAAA;AAAA,QACD,KAAO,EAAA,4BAAA;AAAA,QACP,WAAa,EAAA;AAAA,OACd,CAAA;AACD,MAAI,IAAA,CAAA,EAAA,GAAA,GAAA,CAAI,MAAJ,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAY,MAAQ,EAAA;AACtB,QAAA,QAAA,CAAA,CAAS,eAAI,MAAO,CAAA,CAAC,MAAZ,IAAe,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,OAAA,KAAf,YAA0B,kCAAkC,CAAA;AAErE,QAAA;AAAA;AAEF,MAAM,MAAA,MAAA,GAAA,CAAS,EAAI,GAAA,GAAA,CAAA,IAAA,KAAJ,IAAU,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,4BAAA;AACzB,MAAI,IAAA,CAAA,MAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,MAAA,CAAQ,UAAc,KAAA,MAAA,CAAO,SAAW,EAAA;AAC1C,QAAA,YAAA,CAAa,OAAO,SAAS,CAAA;AAC7B,QAAA,iBAAA,CAAkB,OAAO,cAAc,CAAA;AACvC,QAAA,MAAM,aAAa,OAAQ,CAAA,yBAAA,CAA0B,MAAM,CAAA,EAAG,OAAO,SAAS,CAAA;AAAA,OACrE,MAAA,IAAA,MAAA,IAAU,MAAO,CAAA,UAAA,KAAe,KAAO,EAAA;AAChD,QAAA,YAAA,CAAa,IAAI,CAAA;AACjB,QAAA,MAAM,YAAa,CAAA,UAAA,CAAW,yBAA0B,CAAA,MAAM,CAAC,CAAA;AAAA;AACjE,aACO,GAAK,EAAA;AACZ,MAAA,QAAA,CAAS,GAAe,YAAA,KAAA,GAAQ,GAAI,CAAA,OAAA,GAAU,kCAAkC,CAAA;AAAA,KAEhF,SAAA;AACA,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA;AAClB,GACC,EAAA,CAAC,MAAQ,EAAA,MAAM,CAAC,CAAA;AACnB,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,KAAK,OAAQ,EAAA;AAAA,GACf,EAAG,CAAC,OAAO,CAAC,CAAA;AACZ,EAAM,MAAA,QAAA,GAAW,WAAY,CAAA,OAAO,KAAkB,KAAA;AAlExD,IAAA,IAAA,EAAA;AAmEI,IAAA,IAAI,CAAC,MAAA,EAAc,MAAA,IAAI,MAAM,eAAe,CAAA;AAC5C,IAAA,QAAA,CAAS,IAAI,CAAA;AACb,IAAM,MAAA,GAAA,GAAM,MAAM,MAAA,CAAO,MAEtB,CAAA;AAAA,MACD,QAAU,EAAA,wBAAA;AAAA,MACV,SAAW,EAAA;AAAA,QACT,SAAW,EAAA,KAAA;AAAA,QACX;AAAA;AACF,KACD,CAAA;AACD,IAAM,MAAA,OAAA,GAAA,CAAU,EAAI,GAAA,GAAA,CAAA,IAAA,KAAJ,IAAU,GAAA,MAAA,GAAA,EAAA,CAAA,wBAAA;AAC1B,IAAA,IAAI,EAAC,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAS,UAAc,CAAA,IAAA,CAAC,QAAQ,SAAW,EAAA;AAC9C,MAAM,MAAA,IAAI,MAAM,+BAA+B,CAAA;AAAA;AAEjD,IAAA,YAAA,CAAa,QAAQ,SAAS,CAAA;AAC9B,IAAA,iBAAA,CAAkB,QAAQ,cAAc,CAAA;AACxC,IAAA,MAAM,aAAa,OAAQ,CAAA,yBAAA,CAA0B,MAAM,CAAA,EAAG,QAAQ,SAAS,CAAA;AAC/E,IAAA,OAAO,OAAQ,CAAA,SAAA;AAAA,GACd,EAAA,CAAC,MAAQ,EAAA,MAAA,EAAQ,WAAW,CAAC,CAAA;AAChC,EAAA,MAAM,iBAAoB,GAAA,OAAA,CAAQ,MAAM,OAAA,CAAQ,MAAM,CAAK,IAAA,CAAC,OAAW,IAAA,CAAC,SAAW,EAAA,CAAC,MAAQ,EAAA,OAAA,EAAS,SAAS,CAAC,CAAA;AAC/G,EAAO,OAAA;AAAA,IACL,SAAA;AAAA,IACA,cAAA;AAAA,IACA,OAAA;AAAA,IACA,KAAA;AAAA,IACA,iBAAA;AAAA,IACA,QAAA;AAAA,IACA;AAAA,GACF;AACF"}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import {CHAT_WORKSPACE}from'common';const YANTRA_CHAT_ORG_SLUG = "yantra-chat";
|
|
2
|
-
CHAT_WORKSPACE.CHAT_ORGANIZATION_ID;
|
|
3
|
-
CHAT_WORKSPACE.CHAT_ORGANIZATION_UUID;
|
|
2
|
+
const YANTRA_CHAT_ORG_MONGO_ID = CHAT_WORKSPACE.CHAT_ORGANIZATION_ID;
|
|
3
|
+
const YANTRA_CHAT_ORG_UUID = CHAT_WORKSPACE.CHAT_ORGANIZATION_UUID;
|
|
4
4
|
function isYantraChatOrgSlug(orgName) {
|
|
5
5
|
const trimmed = orgName == null ? void 0 : orgName.trim();
|
|
6
6
|
if (!trimmed) return false;
|
|
7
7
|
return trimmed === YANTRA_CHAT_ORG_SLUG;
|
|
8
8
|
}
|
|
9
|
+
function isYantraChatOrgKey(value) {
|
|
10
|
+
const trimmed = value == null ? void 0 : value.trim();
|
|
11
|
+
if (!trimmed) return false;
|
|
12
|
+
return trimmed === YANTRA_CHAT_ORG_SLUG || trimmed === YANTRA_CHAT_ORG_UUID || trimmed === YANTRA_CHAT_ORG_MONGO_ID;
|
|
13
|
+
}
|
|
9
14
|
function pickWorkspaceOrgSlug(orgs) {
|
|
10
15
|
var _a, _b;
|
|
11
16
|
if (!(orgs == null ? void 0 : orgs.length)) return null;
|
|
@@ -14,4 +19,4 @@ function pickWorkspaceOrgSlug(orgs) {
|
|
|
14
19
|
return name.length > 0 && !isYantraChatOrgSlug(name);
|
|
15
20
|
});
|
|
16
21
|
return (_b = (_a = first == null ? void 0 : first.name) == null ? void 0 : _a.trim()) != null ? _b : null;
|
|
17
|
-
}export{YANTRA_CHAT_ORG_SLUG,isYantraChatOrgSlug,pickWorkspaceOrgSlug};//# sourceMappingURL=yantraChatOrg.js.map
|
|
22
|
+
}export{YANTRA_CHAT_ORG_MONGO_ID,YANTRA_CHAT_ORG_SLUG,YANTRA_CHAT_ORG_UUID,isYantraChatOrgKey,isYantraChatOrgSlug,pickWorkspaceOrgSlug};//# sourceMappingURL=yantraChatOrg.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yantraChatOrg.js","sources":["../../../src/features/messaging/yantraChatOrg.ts"],"sourcesContent":["import { CHAT_WORKSPACE } from 'common';\n\n/**\n * Seeded Yantra Chat organization slug (issue #1312).\n * Used only for native person-to-person chat — not the user's default workspace org.\n */\nexport const YANTRA_CHAT_ORG_SLUG = 'yantra-chat';\n\nexport const YANTRA_CHAT_ORG_MONGO_ID = CHAT_WORKSPACE.CHAT_ORGANIZATION_ID;\n\nexport const YANTRA_CHAT_ORG_UUID = CHAT_WORKSPACE.CHAT_ORGANIZATION_UUID;\n\nexport function isYantraChatOrgSlug(orgName: string | null | undefined): boolean {\n const trimmed = orgName?.trim();\n if (!trimmed) return false;\n return trimmed === YANTRA_CHAT_ORG_SLUG;\n}\n\n/** Slug, filing UUID, or Mongo id — any key the chat org is stored under. */\nexport function isYantraChatOrgKey(value: string | null | undefined): boolean {\n const trimmed = value?.trim();\n if (!trimmed) return false;\n return trimmed === YANTRA_CHAT_ORG_SLUG || trimmed === YANTRA_CHAT_ORG_UUID || trimmed === YANTRA_CHAT_ORG_MONGO_ID;\n}\n\n/** Pick a default workspace org; never use the chat-only org for Home / AI chat / settings. */\nexport function pickWorkspaceOrgSlug(\n orgs: Array<{ name?: string | null; title?: string | null } | null | undefined> | null | undefined,\n): string | null {\n if (!orgs?.length) return null;\n const first = orgs.find((o) => {\n const name = typeof o?.name === 'string' ? o.name.trim() : '';\n return name.length > 0 && !isYantraChatOrgSlug(name);\n });\n return first?.name?.trim() ?? null;\n}\n"],"names":[],"mappings":"oCAMO,MAAM,oBAAuB,GAAA;
|
|
1
|
+
{"version":3,"file":"yantraChatOrg.js","sources":["../../../src/features/messaging/yantraChatOrg.ts"],"sourcesContent":["import { CHAT_WORKSPACE } from 'common';\n\n/**\n * Seeded Yantra Chat organization slug (issue #1312).\n * Used only for native person-to-person chat — not the user's default workspace org.\n */\nexport const YANTRA_CHAT_ORG_SLUG = 'yantra-chat';\n\nexport const YANTRA_CHAT_ORG_MONGO_ID = CHAT_WORKSPACE.CHAT_ORGANIZATION_ID;\n\nexport const YANTRA_CHAT_ORG_UUID = CHAT_WORKSPACE.CHAT_ORGANIZATION_UUID;\n\nexport function isYantraChatOrgSlug(orgName: string | null | undefined): boolean {\n const trimmed = orgName?.trim();\n if (!trimmed) return false;\n return trimmed === YANTRA_CHAT_ORG_SLUG;\n}\n\n/** Slug, filing UUID, or Mongo id — any key the chat org is stored under. */\nexport function isYantraChatOrgKey(value: string | null | undefined): boolean {\n const trimmed = value?.trim();\n if (!trimmed) return false;\n return trimmed === YANTRA_CHAT_ORG_SLUG || trimmed === YANTRA_CHAT_ORG_UUID || trimmed === YANTRA_CHAT_ORG_MONGO_ID;\n}\n\n/** Pick a default workspace org; never use the chat-only org for Home / AI chat / settings. */\nexport function pickWorkspaceOrgSlug(\n orgs: Array<{ name?: string | null; title?: string | null } | null | undefined> | null | undefined,\n): string | null {\n if (!orgs?.length) return null;\n const first = orgs.find((o) => {\n const name = typeof o?.name === 'string' ? o.name.trim() : '';\n return name.length > 0 && !isYantraChatOrgSlug(name);\n });\n return first?.name?.trim() ?? null;\n}\n"],"names":[],"mappings":"oCAMO,MAAM,oBAAuB,GAAA;AAC7B,MAAM,2BAA2B,cAAe,CAAA;AAChD,MAAM,uBAAuB,cAAe,CAAA;AAC5C,SAAS,oBAAoB,OAA6C,EAAA;AAC/E,EAAA,MAAM,UAAU,OAAS,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAA,IAAA,EAAA;AACzB,EAAI,IAAA,CAAC,SAAgB,OAAA,KAAA;AACrB,EAAA,OAAO,OAAY,KAAA,oBAAA;AACrB;AAGO,SAAS,mBAAmB,KAA2C,EAAA;AAC5E,EAAA,MAAM,UAAU,KAAO,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAA,IAAA,EAAA;AACvB,EAAI,IAAA,CAAC,SAAgB,OAAA,KAAA;AACrB,EAAA,OAAO,OAAY,KAAA,oBAAA,IAAwB,OAAY,KAAA,oBAAA,IAAwB,OAAY,KAAA,wBAAA;AAC7F;AAGO,SAAS,qBAAqB,IAGoB,EAAA;AA1BzD,EAAA,IAAA,EAAA,EAAA,EAAA;AA2BE,EAAI,IAAA,EAAC,IAAM,IAAA,IAAA,GAAA,MAAA,GAAA,IAAA,CAAA,MAAA,CAAA,EAAe,OAAA,IAAA;AAC1B,EAAM,MAAA,KAAA,GAAQ,IAAK,CAAA,IAAA,CAAK,CAAK,CAAA,KAAA;AAC3B,IAAM,MAAA,IAAA,GAAO,QAAO,CAAG,IAAA,IAAA,GAAA,MAAA,GAAA,CAAA,CAAA,IAAA,CAAA,KAAS,WAAW,CAAE,CAAA,IAAA,CAAK,MAAS,GAAA,EAAA;AAC3D,IAAA,OAAO,IAAK,CAAA,MAAA,GAAS,CAAK,IAAA,CAAC,oBAAoB,IAAI,CAAA;AAAA,GACpD,CAAA;AACD,EAAA,OAAA,CAAO,EAAO,GAAA,CAAA,EAAA,GAAA,KAAA,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAA,IAAA,KAAP,IAAa,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,EAAA,KAAb,IAAuB,GAAA,EAAA,GAAA,IAAA;AAChC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import {jsx,jsxs}from'react/jsx-runtime';import {useState}from'react';import {StyleSheet,Modal,Pressable,Text,TextInput,View}from'react-native';function AnnotateModal({
|
|
2
|
+
field,
|
|
3
|
+
text,
|
|
4
|
+
onAdd,
|
|
5
|
+
onCancel,
|
|
6
|
+
theme
|
|
7
|
+
}) {
|
|
8
|
+
const [comment, setComment] = useState("");
|
|
9
|
+
return /* @__PURE__ */ jsx(Modal, { transparent: true, animationType: "fade", onRequestClose: onCancel, children: /* @__PURE__ */ jsx(Pressable, { style: styles.backdrop, onPress: onCancel, children: /* @__PURE__ */ jsxs(Pressable, { style: [styles.sheet, {
|
|
10
|
+
backgroundColor: theme.card,
|
|
11
|
+
borderColor: theme.border
|
|
12
|
+
}], onPress: (e) => e.stopPropagation(), children: [
|
|
13
|
+
/* @__PURE__ */ jsxs(Text, { style: [styles.title, {
|
|
14
|
+
color: theme.ink
|
|
15
|
+
}], children: [
|
|
16
|
+
"Annotate \xB7 ",
|
|
17
|
+
field
|
|
18
|
+
] }),
|
|
19
|
+
text ? /* @__PURE__ */ jsxs(Text, { style: [styles.quote, {
|
|
20
|
+
color: theme.muted
|
|
21
|
+
}], numberOfLines: 2, children: [
|
|
22
|
+
"\u201C",
|
|
23
|
+
text,
|
|
24
|
+
"\u201D"
|
|
25
|
+
] }) : null,
|
|
26
|
+
/* @__PURE__ */ jsx(TextInput, { value: comment, onChangeText: setComment, placeholder: "What should change?", placeholderTextColor: theme.muted, multiline: true, autoFocus: true, style: [styles.input, {
|
|
27
|
+
color: theme.ink,
|
|
28
|
+
borderColor: theme.border,
|
|
29
|
+
backgroundColor: theme.screen
|
|
30
|
+
}] }),
|
|
31
|
+
/* @__PURE__ */ jsxs(View, { style: styles.row, children: [
|
|
32
|
+
/* @__PURE__ */ jsx(Pressable, { onPress: onCancel, style: [styles.btn, {
|
|
33
|
+
borderColor: theme.border
|
|
34
|
+
}], children: /* @__PURE__ */ jsx(Text, { style: {
|
|
35
|
+
color: theme.muted,
|
|
36
|
+
fontWeight: "600"
|
|
37
|
+
}, children: "Cancel" }) }),
|
|
38
|
+
/* @__PURE__ */ jsx(Pressable, { onPress: () => onAdd(comment.trim(), false), disabled: !comment.trim(), style: [styles.btn, {
|
|
39
|
+
borderColor: theme.border,
|
|
40
|
+
opacity: comment.trim() ? 1 : 0.5
|
|
41
|
+
}], children: /* @__PURE__ */ jsx(Text, { style: {
|
|
42
|
+
color: theme.ink,
|
|
43
|
+
fontWeight: "600"
|
|
44
|
+
}, children: "Add" }) }),
|
|
45
|
+
/* @__PURE__ */ jsx(Pressable, { onPress: () => onAdd(comment.trim(), true), disabled: !comment.trim(), style: [styles.btn, styles.primary, {
|
|
46
|
+
backgroundColor: theme.accent,
|
|
47
|
+
opacity: comment.trim() ? 1 : 0.5
|
|
48
|
+
}], children: /* @__PURE__ */ jsx(Text, { style: {
|
|
49
|
+
color: theme.accentInk,
|
|
50
|
+
fontWeight: "700"
|
|
51
|
+
}, children: "Send" }) })
|
|
52
|
+
] })
|
|
53
|
+
] }) }) });
|
|
54
|
+
}
|
|
55
|
+
const styles = StyleSheet.create({
|
|
56
|
+
backdrop: {
|
|
57
|
+
flex: 1,
|
|
58
|
+
backgroundColor: "rgba(15,23,42,0.45)",
|
|
59
|
+
justifyContent: "center",
|
|
60
|
+
padding: 24
|
|
61
|
+
},
|
|
62
|
+
sheet: {
|
|
63
|
+
borderRadius: 16,
|
|
64
|
+
borderWidth: StyleSheet.hairlineWidth,
|
|
65
|
+
padding: 16
|
|
66
|
+
},
|
|
67
|
+
title: {
|
|
68
|
+
fontSize: 16,
|
|
69
|
+
fontWeight: "700",
|
|
70
|
+
marginBottom: 6
|
|
71
|
+
},
|
|
72
|
+
quote: {
|
|
73
|
+
fontSize: 12,
|
|
74
|
+
fontStyle: "italic",
|
|
75
|
+
marginBottom: 10
|
|
76
|
+
},
|
|
77
|
+
input: {
|
|
78
|
+
minHeight: 88,
|
|
79
|
+
borderWidth: StyleSheet.hairlineWidth,
|
|
80
|
+
borderRadius: 10,
|
|
81
|
+
padding: 12,
|
|
82
|
+
fontSize: 14,
|
|
83
|
+
textAlignVertical: "top"
|
|
84
|
+
},
|
|
85
|
+
row: {
|
|
86
|
+
flexDirection: "row",
|
|
87
|
+
gap: 8,
|
|
88
|
+
marginTop: 14,
|
|
89
|
+
justifyContent: "flex-end"
|
|
90
|
+
},
|
|
91
|
+
btn: {
|
|
92
|
+
borderWidth: StyleSheet.hairlineWidth,
|
|
93
|
+
borderRadius: 10,
|
|
94
|
+
paddingHorizontal: 14,
|
|
95
|
+
paddingVertical: 10
|
|
96
|
+
},
|
|
97
|
+
primary: {
|
|
98
|
+
borderWidth: 0
|
|
99
|
+
}
|
|
100
|
+
});export{AnnotateModal};//# sourceMappingURL=AnnotateModal.js.map
|