Update UI + Agora Call

This commit is contained in:
2026-05-27 19:36:01 +07:00
parent a629357e8c
commit 3cb32a4d69
42 changed files with 6516 additions and 1285 deletions
@@ -7,6 +7,7 @@ import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:geolocator/geolocator.dart';
import 'package:go_router/go_router.dart';
import '../../app/injection_container.dart';
import '../../core/errors/friendly_error.dart';
@@ -139,6 +140,8 @@ class _SosScreenState extends State<SosScreen>
Future<void> _confirmAndSend() async {
if (_sosCubit.state.phase == SosPhase.sending) return;
final paired = await _ensurePaired();
if (!paired) return;
// Confirmation dialog — prevents accidental tap
final confirm = await showDialog<bool>(
@@ -181,6 +184,35 @@ class _SosScreenState extends State<SosScreen>
await _sendSos();
}
Future<bool> _ensurePaired() async {
bool paired = false;
await runFriendlyAction(
() async {
final res = await _api
.get('/shared/pairing/status')
.timeout(const Duration(seconds: 6));
final data = res.data['data'];
paired = data is Map && data['status'] == 'ACTIVE';
},
onError: (_) {},
fallback: 'Status pairing belum bisa dicek.',
);
if (paired) return true;
if (!mounted) return false;
sl<TtsService>().speak('SOS belum bisa dikirim. Hubungkan Guardian dulu.');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text(
'SOS hanya bisa dikirim setelah akun terhubung dengan Guardian.'),
action: SnackBarAction(
label: 'Pairing',
onPressed: () => context.go('/user/pairing'),
),
),
);
return false;
}
Future<void> _sendSos() async {
await runFriendlyAction(
() async {
@@ -217,96 +249,98 @@ class _SosScreenState extends State<SosScreen>
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Header
Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'SOS',
style: Theme.of(context)
.textTheme
.headlineSmall
?.copyWith(fontWeight: FontWeight.w800),
),
const Text(
'Emergency alert ke Guardian',
style: TextStyle(color: Color(0xFF64748B)),
),
],
),
),
IconButton(
onPressed: _loadHistory,
icon: const Icon(Icons.refresh),
tooltip: 'Refresh riwayat',
),
],
),
const SizedBox(height: 24),
// Active SOS banner
if (_hasActiveSos)
_ActiveSosBanner(event: _events.first, onRefresh: _loadHistory),
const SizedBox(height: 24),
// SOS Button
Center(
child: sending
? const _SendingIndicator()
: AnimatedBuilder(
animation: _pulseAnim,
builder: (_, child) => Transform.scale(
scale: _hasActiveSos ? _pulseAnim.value : 1.0,
child: child,
),
child: _SosButton(
active: _hasActiveSos,
onPressed: _confirmAndSend,
// Header
Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'SOS',
style: Theme.of(context)
.textTheme
.headlineSmall
?.copyWith(fontWeight: FontWeight.w800),
),
const Text(
'Emergency alert ke Guardian',
style: TextStyle(color: Color(0xFF64748B)),
),
],
),
),
IconButton(
onPressed: _loadHistory,
icon: const Icon(Icons.refresh),
tooltip: 'Refresh riwayat',
),
],
),
const SizedBox(height: 24),
// Active SOS banner
if (_hasActiveSos)
_ActiveSosBanner(
event: _events.first, onRefresh: _loadHistory),
const SizedBox(height: 24),
// SOS Button
Center(
child: sending
? const _SendingIndicator()
: AnimatedBuilder(
animation: _pulseAnim,
builder: (_, child) => Transform.scale(
scale: _hasActiveSos ? _pulseAnim.value : 1.0,
child: child,
),
child: _SosButton(
active: _hasActiveSos,
onPressed: _confirmAndSend,
),
),
),
const SizedBox(height: 8),
// Hint text
Text(
_hasActiveSos
? 'SOS aktif — Guardian sudah mendapat notifikasi'
: 'Tekan tombol untuk kirim SOS darurat ke Guardian',
textAlign: TextAlign.center,
style: TextStyle(
color: _hasActiveSos
? const Color(0xFFDC2626)
: const Color(0xFF64748B),
fontWeight:
_hasActiveSos ? FontWeight.w700 : FontWeight.normal,
),
),
const SizedBox(height: 28),
// History section
const Text(
'Riwayat SOS',
style: TextStyle(fontWeight: FontWeight.w800, fontSize: 16),
),
const SizedBox(height: 10),
Expanded(
child: _SosHistory(
loading: _historyLoading,
error: _historyError,
events: _events,
onRefresh: _loadHistory,
)),
],
),
const SizedBox(height: 8),
// Hint text
Text(
_hasActiveSos
? 'SOS aktif — Guardian sudah mendapat notifikasi'
: 'Tekan tombol untuk kirim SOS darurat ke Guardian',
textAlign: TextAlign.center,
style: TextStyle(
color: _hasActiveSos
? const Color(0xFFDC2626)
: const Color(0xFF64748B),
fontWeight: _hasActiveSos ? FontWeight.w700 : FontWeight.normal,
),
),
const SizedBox(height: 28),
// History section
const Text(
'Riwayat SOS',
style: TextStyle(fontWeight: FontWeight.w800, fontSize: 16),
),
const SizedBox(height: 10),
Expanded(
child: _SosHistory(
loading: _historyLoading,
error: _historyError,
events: _events,
onRefresh: _loadHistory,
)),
],
),
),
);
);
},
);
}