import 'package:auto_route/auto_route.dart'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/models/chat.dart'; import 'package:island/pods/call.dart'; import 'package:island/pods/network.dart'; import 'package:island/route.gr.dart'; import 'package:island/widgets/alert.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'call_button.g.dart'; @riverpod Future ongoingCall(Ref ref, String roomId) async { if (roomId.isEmpty) return null; try { final apiClient = ref.watch(apiClientProvider); final resp = await apiClient.get('/chat/realtime/$roomId'); return SnRealtimeCall.fromJson(resp.data); } catch (e) { if (e is DioException && e.response?.statusCode == 404) { return null; } showErrorAlert(e); return null; } } class AudioCallButton extends HookConsumerWidget { final String roomId; const AudioCallButton({super.key, required this.roomId}); @override Widget build(BuildContext context, WidgetRef ref) { final ongoingCall = ref.watch(ongoingCallProvider(roomId)); final callState = ref.watch(callNotifierProvider); final callNotifier = ref.read(callNotifierProvider.notifier); final isLoading = useState(false); final apiClient = ref.watch(apiClientProvider); Future handleJoin() async { isLoading.value = true; try { await apiClient.post('/chat/realtime/$roomId'); if (context.mounted) { context.router.push(CallRoute(roomId: roomId)); } } catch (e) { showErrorAlert(e); } finally { isLoading.value = false; } } Future handleEnd() async { isLoading.value = true; try { await apiClient.delete('/chat/realtime/$roomId'); callNotifier.dispose(); // Clean up call resources } catch (e) { showErrorAlert(e); } finally { isLoading.value = false; } } if (isLoading.value) { return IconButton( icon: SizedBox( width: 24, height: 24, child: CircularProgressIndicator( strokeWidth: 2, color: Theme.of(context).appBarTheme.foregroundColor!, padding: EdgeInsets.all(4), ), ), onPressed: null, ); } if (callState.isConnected) { // Show end call button if in call return IconButton( icon: const Icon(Icons.call_end), tooltip: 'End Call', onPressed: handleEnd, ); } if (ongoingCall.value != null) { // There is an ongoing call, offer to join it directly return IconButton( icon: const Icon(Icons.call), tooltip: 'Join Ongoing Call', onPressed: () { if (context.mounted) { context.router.push(CallRoute(roomId: roomId)); } }, ); } // Show join/start call button return IconButton( icon: const Icon(Icons.call), tooltip: 'Start/Join Call', onPressed: handleJoin, ); } }