feat(mobile): phone-icon header button + navigate to /call on connect

This commit is contained in:
byGalax
2026-05-14 06:14:17 +02:00
parent 4d787b68b4
commit 04da0f211d
+31 -1
View File
@@ -4,7 +4,7 @@ import type {
DecryptedMessage, DecryptedMessage,
MessageReaction, MessageReaction,
} from '@chat-app/shared/chat'; } from '@chat-app/shared/chat';
import { Stack, useLocalSearchParams } from 'expo-router'; import { Stack, useLocalSearchParams, useRouter } from 'expo-router';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { import {
ActionSheetIOS, ActionSheetIOS,
@@ -23,6 +23,7 @@ import {
import { MessageActionsSheet } from '../../../components/MessageActionsSheet'; import { MessageActionsSheet } from '../../../components/MessageActionsSheet';
import { MessageBubble } from '../../../components/MessageBubble'; import { MessageBubble } from '../../../components/MessageBubble';
import { useAuth } from '../../../lib/authContext'; import { useAuth } from '../../../lib/authContext';
import { useCall } from '../../../lib/callContext';
import { captureFromCamera, pickFromLibrary, type PickedImage } from '../../../lib/imagePicker'; import { captureFromCamera, pickFromLibrary, type PickedImage } from '../../../lib/imagePicker';
import { supabase } from '../../../lib/supabase'; import { supabase } from '../../../lib/supabase';
import { colors } from '../../../theme/colors'; import { colors } from '../../../theme/colors';
@@ -30,6 +31,18 @@ import { colors } from '../../../theme/colors';
export default function ConversationDetail() { export default function ConversationDetail() {
const { id } = useLocalSearchParams<{ id: string }>(); const { id } = useLocalSearchParams<{ id: string }>();
const { user, device, ownPrivateKey } = useAuth(); const { user, device, ownPrivateKey } = useAuth();
const { state: callState, startCall } = useCall();
const router = useRouter();
// When a call moves into `connected`, jump to the in-call screen so
// the user can see participants + controls. The /call screen pops
// itself when callState returns to `idle`.
useEffect(() => {
if (callState.kind === 'connected') {
router.push('/(app)/call');
}
}, [callState.kind, router]);
const [conversation, setConversation] = useState<ConversationSummary | null>(null); const [conversation, setConversation] = useState<ConversationSummary | null>(null);
const [messages, setMessages] = useState<DecryptedMessage[] | null>(null); const [messages, setMessages] = useState<DecryptedMessage[] | null>(null);
const [reactions, setReactions] = useState<Map<string, MessageReaction[]>>(new Map()); const [reactions, setReactions] = useState<Map<string, MessageReaction[]>>(new Map());
@@ -243,6 +256,18 @@ export default function ConversationDetail() {
headerStyle: { backgroundColor: colors.bg }, headerStyle: { backgroundColor: colors.bg },
headerTitleStyle: { color: colors.text }, headerTitleStyle: { color: colors.text },
headerBackTitle: 'Chats', headerBackTitle: 'Chats',
headerRight: () => (
<Pressable
onPress={() => {
if (!id) return;
void startCall(id);
}}
hitSlop={10}
style={styles.callBtn}
>
<Text style={styles.callBtnText}>📞</Text>
</Pressable>
),
}} }}
/> />
@@ -415,4 +440,9 @@ const styles = StyleSheet.create({
}, },
sendBtnDisabled: { opacity: 0.5 }, sendBtnDisabled: { opacity: 0.5 },
sendBtnText: { color: colors.text, fontWeight: '600' }, sendBtnText: { color: colors.text, fontWeight: '600' },
callBtn: {
paddingHorizontal: 10,
paddingVertical: 4,
},
callBtnText: { fontSize: 18 },
}); });