Update files

This commit is contained in:
Mohamed Boudra
2026-02-07 15:37:44 +07:00
parent 8adcb0a4cd
commit 902a415911
13 changed files with 267 additions and 139 deletions
@@ -4,7 +4,6 @@ import {
Text,
ActivityIndicator,
Platform,
Alert,
} from "react-native";
import { useState, useEffect, useRef, useCallback, useMemo } from "react";
import { StyleSheet, useUnistyles } from "react-native-unistyles";
@@ -425,15 +424,10 @@ export function AgentInputArea({
return;
}
if (voice.isVoiceModeForAgent(serverId, agentId)) {
void voice.stopVoice().catch((error) => {
console.error("[AgentInputArea] Failed to stop voice mode", error);
Alert.alert("Voice failed", "Unable to stop realtime voice mode.");
});
return;
}
void voice.startVoice(serverId, agentId).catch((error) => {
console.error("[AgentInputArea] Failed to start voice mode", error);
Alert.alert("Voice failed", "Unable to start realtime voice mode.");
});
}, [agentId, isConnected, serverId, voice]);
@@ -543,29 +537,26 @@ export function AgentInputArea({
const rightContent = (
<View style={styles.rightControls}>
<Pressable
onPress={handleToggleRealtimeVoice}
disabled={!isConnected || voice?.isVoiceSwitching}
accessibilityLabel={
isVoiceModeForAgent ? "Disable realtime voice mode" : "Enable realtime voice mode"
}
accessibilityRole="button"
style={[
styles.realtimeVoiceButton as any,
isVoiceModeForAgent ? (styles.realtimeVoiceButtonActive as any) : undefined,
(!isConnected || voice?.isVoiceSwitching
? styles.buttonDisabled
: undefined) as any,
]}
>
{voice?.isVoiceSwitching ? (
<ActivityIndicator size="small" color="white" />
) : isVoiceModeForAgent ? (
<Square size={16} color="white" fill="white" />
) : (
<AudioLines size={18} color={theme.colors.foreground} />
)}
</Pressable>
{!isVoiceModeForAgent ? (
<Pressable
onPress={handleToggleRealtimeVoice}
disabled={!isConnected || voice?.isVoiceSwitching}
accessibilityLabel="Enable realtime voice mode"
accessibilityRole="button"
style={[
styles.realtimeVoiceButton as any,
(!isConnected || voice?.isVoiceSwitching
? styles.buttonDisabled
: undefined) as any,
]}
>
{voice?.isVoiceSwitching ? (
<ActivityIndicator size="small" color="white" />
) : (
<AudioLines size={18} color={theme.colors.foreground} />
)}
</Pressable>
) : null}
{cancelButton}
</View>
);
@@ -1,13 +1,21 @@
import { Pressable, View } from "react-native";
import { ActivityIndicator, Alert, Pressable, View } from "react-native";
import { StyleSheet, useUnistyles } from "react-native-unistyles";
import { Mic, MicOff } from "lucide-react-native";
import { Mic, MicOff, Square } from "lucide-react-native";
import { VolumeMeter } from "@/components/volume-meter";
import { useVoice } from "@/contexts/voice-context";
export function VoiceCompactIndicator() {
const { theme } = useUnistyles();
const { isVoiceMode, volume, isMuted, isDetecting, isSpeaking, toggleMute } =
useVoice();
const {
isVoiceMode,
isVoiceSwitching,
volume,
isMuted,
isDetecting,
isSpeaking,
toggleMute,
stopVoice,
} = useVoice();
if (!isVoiceMode) {
return null;
@@ -26,19 +34,52 @@ export function VoiceCompactIndicator() {
/>
</View>
<Pressable
onPress={toggleMute}
accessibilityRole="button"
accessibilityLabel={isMuted ? "Unmute voice" : "Mute voice"}
style={styles.muteButton}
hitSlop={8}
>
{isMuted ? (
<MicOff size={14} color={theme.colors.palette.white} />
) : (
<Mic size={14} color={theme.colors.foreground} />
)}
</Pressable>
<View style={styles.controlsRow}>
<Pressable
onPress={toggleMute}
disabled={isVoiceSwitching}
accessibilityRole="button"
accessibilityLabel={isMuted ? "Unmute voice" : "Mute voice"}
style={[
styles.muteButton,
isVoiceSwitching ? styles.buttonDisabled : undefined,
]}
hitSlop={8}
>
{isMuted ? (
<MicOff size={14} color={theme.colors.palette.white} />
) : (
<Mic size={14} color={theme.colors.foreground} />
)}
</Pressable>
<Pressable
onPress={() => {
void stopVoice().catch((error) => {
console.error("[VoiceCompactIndicator] Failed to stop voice mode", error);
Alert.alert("Voice failed", "Unable to stop realtime voice mode.");
});
}}
disabled={isVoiceSwitching}
accessibilityRole="button"
accessibilityLabel="Disable realtime voice mode"
style={[
styles.stopButton,
isVoiceSwitching ? styles.buttonDisabled : undefined,
]}
hitSlop={8}
>
{isVoiceSwitching ? (
<ActivityIndicator size="small" color={theme.colors.palette.white} />
) : (
<Square
size={14}
color={theme.colors.palette.white}
fill={theme.colors.palette.white}
/>
)}
</Pressable>
</View>
</View>
);
}
@@ -47,7 +88,7 @@ const styles = StyleSheet.create((theme) => ({
container: {
flexDirection: "row",
alignItems: "center",
gap: theme.spacing[2],
gap: theme.spacing[1],
paddingLeft: theme.spacing[3],
paddingRight: theme.spacing[1],
height: 32,
@@ -63,6 +104,11 @@ const styles = StyleSheet.create((theme) => ({
meterContainer: {
justifyContent: "center",
},
controlsRow: {
flexDirection: "row",
alignItems: "center",
gap: theme.spacing[1],
},
muteButton: {
width: 28,
height: 28,
@@ -72,4 +118,17 @@ const styles = StyleSheet.create((theme) => ({
backgroundColor: "transparent",
borderWidth: 0,
},
stopButton: {
width: 28,
height: 28,
borderRadius: theme.borderRadius.full,
alignItems: "center",
justifyContent: "center",
backgroundColor: theme.colors.palette.red[600],
borderWidth: theme.borderWidth[1],
borderColor: theme.colors.palette.red[800],
},
buttonDisabled: {
opacity: 0.5,
},
}));