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
+59 -16
View File
@@ -4,13 +4,14 @@ import 'package:google_fonts/google_fonts.dart';
import 'app_cubit.dart';
import 'router.dart';
import '../core/theme/app_colors.dart';
class WalkGuideApp extends StatelessWidget {
const WalkGuideApp({super.key});
@override
Widget build(BuildContext context) {
const seed = Color(0xFF1A56DB);
const seed = AppColors.primary;
return BlocProvider(
create: (_) => AppCubit(),
@@ -23,9 +24,15 @@ class WalkGuideApp extends StatelessWidget {
colorScheme: ColorScheme.fromSeed(
seedColor: seed,
brightness: Brightness.light,
primary: seed,
secondary: AppColors.accent,
error: AppColors.danger,
),
scaffoldBackgroundColor: AppColors.surface,
textTheme: GoogleFonts.interTextTheme().apply(
bodyColor: AppColors.text,
displayColor: AppColors.text,
),
scaffoldBackgroundColor: const Color(0xFFF4F7FB),
textTheme: GoogleFonts.interTextTheme(),
pageTransitionsTheme: const PageTransitionsTheme(
builders: {
TargetPlatform.android: ZoomPageTransitionsBuilder(),
@@ -35,16 +42,41 @@ class WalkGuideApp extends StatelessWidget {
),
appBarTheme: const AppBarTheme(
centerTitle: false,
backgroundColor: Color(0xFFF4F7FB),
foregroundColor: Color(0xFF0F172A),
backgroundColor: AppColors.surface,
foregroundColor: AppColors.text,
elevation: 0,
surfaceTintColor: Colors.transparent,
),
cardTheme: CardThemeData(
elevation: 0,
color: AppColors.surfaceRaised,
surfaceTintColor: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
side: const BorderSide(color: AppColors.border),
),
),
dividerTheme: const DividerThemeData(
color: AppColors.border,
thickness: 1,
space: 1,
),
iconButtonTheme: IconButtonThemeData(
style: IconButton.styleFrom(
foregroundColor: AppColors.text,
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
side: const BorderSide(color: AppColors.border),
),
),
),
navigationBarTheme: NavigationBarThemeData(
elevation: 0,
height: 76,
backgroundColor: Colors.white.withValues(alpha: 0.96),
indicatorColor: const Color(0xFFE0E7FF),
backgroundColor: Colors.white,
indicatorColor: const Color(0xFFDDEAFE),
surfaceTintColor: Colors.transparent,
labelTextStyle: WidgetStateProperty.resolveWith(
(states) => TextStyle(
fontSize: 12,
@@ -61,7 +93,7 @@ class WalkGuideApp extends StatelessWidget {
minimumSize: const Size(0, 50),
textStyle: const TextStyle(fontWeight: FontWeight.w800),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14),
borderRadius: BorderRadius.circular(10),
),
),
),
@@ -70,27 +102,38 @@ class WalkGuideApp extends StatelessWidget {
minimumSize: const Size(0, 50),
foregroundColor: seed,
textStyle: const TextStyle(fontWeight: FontWeight.w800),
side: const BorderSide(color: Color(0xFFCBD5E1)),
side: const BorderSide(color: AppColors.border),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14),
borderRadius: BorderRadius.circular(10),
),
),
),
snackBarTheme: SnackBarThemeData(
behavior: SnackBarBehavior.floating,
backgroundColor: AppColors.text,
contentTextStyle: GoogleFonts.inter(
color: Colors.white,
fontWeight: FontWeight.w600,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
inputDecorationTheme: InputDecorationTheme(
filled: true,
fillColor: const Color(0xFFF8FAFC),
fillColor: Colors.white,
contentPadding:
const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: const BorderSide(color: Color(0xFFE2E8F0)),
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: AppColors.border),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: const BorderSide(color: Color(0xFFE2E8F0)),
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: AppColors.border),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: seed, width: 1.5),
),
),
@@ -10,6 +10,7 @@ import '../core/services/haptic_service.dart';
import '../core/services/call_service.dart';
import '../core/services/fcm_service.dart';
import '../core/services/hardware_shortcut_listener.dart';
import '../core/services/incoming_call_polling_service.dart';
import '../core/services/location_reporter_service.dart';
import '../core/services/offline_queue_service.dart';
import '../core/services/stt_service.dart';
@@ -39,17 +40,24 @@ Future<void> initDependencies() async {
sl.registerLazySingleton<SttService>(() => SttService());
sl.registerLazySingleton<HapticService>(() => HapticService());
sl.registerLazySingleton<ObstacleAlertStrategy>(
() => TtsWithHapticObstacleAlertStrategy(sl<TtsService>(), sl<HapticService>()),
() => TtsWithHapticObstacleAlertStrategy(
sl<TtsService>(), sl<HapticService>()),
);
sl.registerLazySingleton<ObstacleAnalyzer>(() => ObstacleAnalyzer());
sl.registerLazySingleton<YoloDetector>(() => YoloDetector(sl<ObstacleAnalyzer>()));
sl.registerLazySingleton<YoloDetector>(
() => YoloDetector(sl<ObstacleAnalyzer>()));
sl.registerLazySingleton<OfflineQueueService>(
() => OfflineQueueService(sl<LocalDatabase>()),
);
sl.registerLazySingleton<FcmService>(() => FcmService(sl<ApiClient>()));
sl.registerLazySingleton<WebSocketService>(() => WebSocketService(sl<SecureStorage>()));
sl.registerLazySingleton<LocationReporterService>(() => LocationReporterService(sl<ApiClient>(), sl<OfflineQueueService>()));
sl.registerLazySingleton<WebSocketService>(
() => WebSocketService(sl<SecureStorage>()));
sl.registerLazySingleton<LocationReporterService>(() =>
LocationReporterService(sl<ApiClient>(), sl<OfflineQueueService>()));
sl.registerLazySingleton<CallService>(() => CallService(sl<ApiClient>()));
sl.registerLazySingleton<IncomingCallPollingService>(
() => IncomingCallPollingService(sl<ApiClient>()),
);
sl.registerLazySingleton<HardwareShortcutListener>(
() => HardwareShortcutListener(sl<ApiClient>()),
);
@@ -59,8 +67,10 @@ Future<void> initDependencies() async {
sl.registerLazySingleton<WalkGuideRepository>(
() => WalkGuideRepositoryImpl(sl<ApiClient>(), sl<OfflineQueueService>()),
);
sl.registerFactory<WalkGuideCubit>(() => WalkGuideCubit(sl<WalkGuideRepository>()));
sl.registerLazySingleton<SosRepository>(() => SosRepositoryImpl(sl<ApiClient>()));
sl.registerFactory<WalkGuideCubit>(
() => WalkGuideCubit(sl<WalkGuideRepository>()));
sl.registerLazySingleton<SosRepository>(
() => SosRepositoryImpl(sl<ApiClient>()));
sl.registerFactory<SosCubit>(() => SosCubit(sl<SosRepository>()));
sl.registerLazySingleton<NotificationRepository>(
() => NotificationRepositoryImpl(sl<ApiClient>(), sl<LocalDatabase>()),
@@ -29,7 +29,8 @@ import '../features/navigation_mode/presentation/screens/navigation_mode_screen.
as nav;
import '../features/notifications/presentation/screens/notification_screen.dart'
as notifications;
import '../features/pairing/presentation/screens/pairing_screens.dart' as pairing;
import '../features/pairing/presentation/screens/pairing_screens.dart'
as pairing;
import '../features/server_connect/server_connect_server.dart'
as server_connect;
import '../features/settings/presentation/screens/user_settings_screen.dart'
@@ -96,7 +97,17 @@ final GoRouter appRouter = GoRouter(
builder: (_, __) => const auth_register.RegisterScreen()),
GoRoute(
path: '/incoming-call',
builder: (_, __) => const call.IncomingCallScreen()),
builder: (_, state) {
final extra = state.extra is Map
? Map<String, dynamic>.from(state.extra as Map)
: <String, dynamic>{};
return call.IncomingCallScreen(
callerName: extra['callerName']?.toString() ?? 'Guardian',
callerId: int.tryParse(extra['callerId']?.toString() ?? ''),
channelName: extra['channelName']?.toString(),
agoraToken: extra['agoraToken']?.toString(),
);
}),
ShellRoute(
builder: (_, __, child) => UserShell(child: child),
routes: [
@@ -161,6 +172,12 @@ final GoRouter appRouter = GoRouter(
path: '/guardian/settings',
builder: (_, __) =>
const guardian_settings.GuardianSettingsScreen()),
GoRoute(
path: '/guardian/call',
builder: (_, __) => const call.CallScreen(
targetLabel: 'User',
returnRoute: '/guardian/dashboard',
)),
GoRoute(
path: '/guardian/benchmark',
builder: (_, __) => const benchmark.AiBenchmarkScreen()),