refactor: clean up logging and improve error handling in voice call service

- Removed unnecessary print statements from VoiceCallService to enhance code clarity and maintainability.
- Improved error handling by ensuring that exceptions are properly caught and handled without excessive logging.
- Updated the VoiceCallPage to streamline error dialog presentation, removing redundant console logs while maintaining user feedback.
- Enhanced the use of color values in UI components for better readability and consistency.
This commit is contained in:
cogwheel0
2025-10-08 13:38:56 +05:30
parent 4f6c10c857
commit 7dd41ebf60
2 changed files with 8 additions and 96 deletions

View File

@@ -68,13 +68,8 @@ class VoiceCallService {
Future<void> initialize() async {
if (_isDisposed) return;
// ignore: avoid_print
print('[VoiceCall] Starting initialization...');
// Initialize voice input
final voiceInitialized = await _voiceInput.initialize();
// ignore: avoid_print
print('[VoiceCall] Voice initialized: $voiceInitialized');
if (!voiceInitialized) {
_updateState(VoiceCallState.error);
throw Exception('Voice input initialization failed');
@@ -82,8 +77,6 @@ class VoiceCallService {
// Check if local STT is available
final hasLocalStt = _voiceInput.hasLocalStt;
// ignore: avoid_print
print('[VoiceCall] Has local STT: $hasLocalStt');
if (!hasLocalStt) {
_updateState(VoiceCallState.error);
throw Exception('Speech recognition not available on this device');
@@ -91,8 +84,6 @@ class VoiceCallService {
// Check microphone permissions
final hasMicPermission = await _voiceInput.checkPermissions();
// ignore: avoid_print
print('[VoiceCall] Has mic permission: $hasMicPermission');
if (!hasMicPermission) {
_updateState(VoiceCallState.error);
throw Exception('Microphone permission not granted');
@@ -100,40 +91,23 @@ class VoiceCallService {
// Initialize TTS
await _tts.initialize();
// ignore: avoid_print
print('[VoiceCall] TTS initialized');
}
Future<void> startCall(String? conversationId) async {
// ignore: avoid_print
print('[VoiceCall] startCall() entered. _isDisposed=$_isDisposed');
if (_isDisposed) {
// ignore: avoid_print
print('[VoiceCall] EARLY RETURN: Service is disposed');
return;
}
if (_isDisposed) return;
try {
// ignore: avoid_print
print('[VoiceCall] Starting call for conversation: $conversationId');
_updateState(VoiceCallState.connecting);
// Ensure socket connection
// ignore: avoid_print
print('[VoiceCall] Ensuring socket connection...');
await _socketService.ensureConnected();
_sessionId = _socketService.sessionId;
// ignore: avoid_print
print('[VoiceCall] Session ID: $_sessionId');
if (_sessionId == null) {
throw Exception('Failed to establish socket connection');
}
// Set up socket event listener for assistant responses
// ignore: avoid_print
print('[VoiceCall] Setting up socket event handler...');
_socketSubscription = _socketService.addChatEventHandler(
conversationId: conversationId,
sessionId: _sessionId,
@@ -142,14 +116,8 @@ class VoiceCallService {
);
// Start listening for user voice input
// ignore: avoid_print
print('[VoiceCall] Starting to listen...');
await _startListening();
// ignore: avoid_print
print('[VoiceCall] Listen started successfully');
} catch (e) {
// ignore: avoid_print
print('[VoiceCall] Error in startCall: $e');
_updateState(VoiceCallState.error);
rethrow;
}
@@ -161,44 +129,27 @@ class VoiceCallService {
try {
_accumulatedTranscript = '';
// ignore: avoid_print
print('[VoiceCall] _startListening called');
// Check if voice input is available
if (!_voiceInput.hasLocalStt) {
// ignore: avoid_print
print('[VoiceCall] ERROR: No local STT available');
_updateState(VoiceCallState.error);
throw Exception('Voice input not available on this device');
}
// ignore: avoid_print
print('[VoiceCall] Setting state to listening...');
_updateState(VoiceCallState.listening);
// ignore: avoid_print
print('[VoiceCall] Calling beginListening...');
final stream = await _voiceInput.beginListening();
// ignore: avoid_print
print('[VoiceCall] Got stream from beginListening');
_transcriptSubscription = stream.listen(
(text) {
// ignore: avoid_print
print('[VoiceCall] Transcript received: $text');
if (_isDisposed) return;
_accumulatedTranscript = text;
_transcriptController.add(text);
},
onError: (error) {
// ignore: avoid_print
print('[VoiceCall] Stream error: $error');
if (_isDisposed) return;
_updateState(VoiceCallState.error);
},
onDone: () async {
// ignore: avoid_print
print('[VoiceCall] Stream done. Transcript: $_accumulatedTranscript');
if (_isDisposed) return;
// User stopped speaking, send message to assistant
if (_accumulatedTranscript.trim().isNotEmpty) {
@@ -210,8 +161,6 @@ class VoiceCallService {
},
);
// ignore: avoid_print
print('[VoiceCall] Setting up intensity stream...');
// Forward intensity stream for waveform visualization
_intensitySubscription = _voiceInput.intensityStream.listen(
(intensity) {
@@ -219,11 +168,7 @@ class VoiceCallService {
_intensityController.add(intensity);
},
);
// ignore: avoid_print
print('[VoiceCall] _startListening completed successfully');
} catch (e) {
// ignore: avoid_print
print('[VoiceCall] ERROR in _startListening: $e');
_updateState(VoiceCallState.error);
rethrow;
}
@@ -276,9 +221,6 @@ class VoiceCallService {
final finishReason = firstChoice?['finish_reason'];
if (finishReason == 'stop') {
// ignore: avoid_print
print('[VoiceCall] Response completed! Text: $_accumulatedResponse');
if (_accumulatedResponse.isNotEmpty) {
_speakResponse(_accumulatedResponse);
_accumulatedResponse = '';
@@ -297,24 +239,15 @@ class VoiceCallService {
if (_isDisposed) return;
try {
// ignore: avoid_print
print('[VoiceCall] _speakResponse called with: $response');
// Stop listening before speaking
await _voiceInput.stopListening();
await _transcriptSubscription?.cancel();
await _intensitySubscription?.cancel();
_updateState(VoiceCallState.speaking);
// ignore: avoid_print
print('[VoiceCall] State updated to speaking, calling TTS...');
await _tts.speak(response);
// ignore: avoid_print
print('[VoiceCall] TTS.speak() returned');
// After speaking completes, _handleTtsComplete will restart listening
} catch (e) {
// ignore: avoid_print
print('[VoiceCall] Error in _speakResponse: $e');
_updateState(VoiceCallState.error);
// Restart listening even if TTS fails
await _startListening();

View File

@@ -52,12 +52,7 @@ class _VoiceCallPageState extends ConsumerState<VoiceCallPage>
Future<void> _initializeCall() async {
try {
// ignore: avoid_print
print('[VoiceCallPage] _initializeCall started');
_service = ref.read(voiceCallServiceProvider);
// ignore: avoid_print
print('[VoiceCallPage] Service instance: ${_service.hashCode}');
// Subscribe to service streams
_stateSubscription = _service!.stateStream.listen((state) {
@@ -93,29 +88,12 @@ class _VoiceCallPageState extends ConsumerState<VoiceCallPage>
});
// Initialize and start the call
// ignore: avoid_print
print('[VoiceCallPage] About to initialize service');
await _service!.initialize();
// ignore: avoid_print
print('[VoiceCallPage] Service initialized, reading activeConversation');
final activeConversation = ref.read(activeConversationProvider);
// ignore: avoid_print
print('[VoiceCallPage] Active conversation: ${activeConversation?.id}');
// ignore: avoid_print
print('[VoiceCallPage] About to call startCall');
await _service!.startCall(activeConversation?.id);
// ignore: avoid_print
print('[VoiceCallPage] startCall completed');
} catch (e) {
if (mounted) {
// Show error details in a debug-friendly way
final errorMessage = e.toString();
_showErrorDialog(errorMessage);
// Also print to console for debugging
// ignore: avoid_print
print('[VoiceCallPage] ERROR during initialization: $errorMessage');
// ignore: avoid_print
print('[VoiceCallPage] Stack trace: ${StackTrace.current}');
_showErrorDialog(e.toString());
}
}
}
@@ -143,6 +121,7 @@ class _VoiceCallPageState extends ConsumerState<VoiceCallPage>
@override
void dispose() {
// Cancel subscriptions (fire and forget)
_stateSubscription?.cancel();
_transcriptSubscription?.cancel();
_responseSubscription?.cancel();
@@ -185,7 +164,7 @@ class _VoiceCallPageState extends ConsumerState<VoiceCallPage>
Text(
selectedModel?.name ?? '',
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
color: textColor.withOpacity(0.7),
color: textColor.withValues(alpha: 0.7),
),
),
const SizedBox(height: 48),
@@ -291,7 +270,7 @@ class _VoiceCallPageState extends ConsumerState<VoiceCallPage>
height: 120,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: primaryColor.withOpacity(0.2),
color: primaryColor.withValues(alpha: 0.2),
border: Border.all(
color: primaryColor,
width: 3,
@@ -325,12 +304,12 @@ class _VoiceCallPageState extends ConsumerState<VoiceCallPage>
height: 120,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: textColor.withOpacity(0.1),
color: textColor.withValues(alpha: 0.1),
),
child: Icon(
CupertinoIcons.mic_fill,
size: 48,
color: textColor.withOpacity(0.5),
color: textColor.withValues(alpha: 0.5),
),
);
}
@@ -359,7 +338,7 @@ class _VoiceCallPageState extends ConsumerState<VoiceCallPage>
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
color: textColor.withOpacity(0.8),
color: textColor.withValues(alpha: 0.8),
height: 1.5,
),
),