diff --git a/apps/mobile_app/lib/navigation/app_router.dart b/apps/mobile_app/lib/navigation/app_router.dart index 0aa96c87..11aecf6b 100644 --- a/apps/mobile_app/lib/navigation/app_router.dart +++ b/apps/mobile_app/lib/navigation/app_router.dart @@ -26,7 +26,7 @@ late final GoRouter appRouter; void configureAppRouter() { appRouter = GoRouter( navigatorKey: rootNavigatorKey, - initialLocation: AppRoutes.onboarding, + initialLocation: AppRoutes.splash, debugLogDiagnostics: true, routes: [ GoRoute( diff --git a/apps/mobile_app/lib/providers/legacy_heartbeat_service.dart b/apps/mobile_app/lib/providers/legacy_heartbeat_service.dart new file mode 100644 index 00000000..411bcba3 --- /dev/null +++ b/apps/mobile_app/lib/providers/legacy_heartbeat_service.dart @@ -0,0 +1,42 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; + +class LegacyHeartbeatService { + LegacyHeartbeatService({ + required QuestiaRepository repository, + required void Function() onUnauthorized, + }) : _repository = repository, + _onUnauthorized = onUnauthorized; + + final QuestiaRepository _repository; + final void Function() _onUnauthorized; + Timer? _timer; + + static const _interval = Duration(minutes: 3); + + void start() { + if (_timer != null) return; + _beat(); + _timer = Timer.periodic(_interval, (_) => _beat()); + debugPrint('[LegacyHeartbeat] started'); + } + + void stop() { + _timer?.cancel(); + _timer = null; + debugPrint('[LegacyHeartbeat] stopped'); + } + + Future _beat() async { + try { + await _repository.get('/auth/me'); + debugPrint('[LegacyHeartbeat] /auth/me => OK'); + } catch (e) { + debugPrint('[LegacyHeartbeat] error: $e'); + stop(); + _onUnauthorized(); + } + } +} diff --git a/apps/mobile_app/lib/save_family_app.dart b/apps/mobile_app/lib/save_family_app.dart index 2de0f80c..7a02cffd 100644 --- a/apps/mobile_app/lib/save_family_app.dart +++ b/apps/mobile_app/lib/save_family_app.dart @@ -6,7 +6,9 @@ import 'package:sf_app_platform/navigation/app_router.dart'; import 'package:navigation/navigation.dart'; import 'package:sf_app_platform/providers/app_state_provider.dart'; import 'package:sf_app_platform/providers/permissions/permissions_provider.dart'; +import 'package:sf_app_platform/providers/legacy_heartbeat_service.dart'; import 'package:sf_app_platform/providers/wallet_heartbeat_service.dart'; +import 'package:get_it/get_it.dart'; import 'package:sf_infrastructure/sf_infrastructure.dart'; import 'package:sf_shared/sf_shared.dart'; import 'package:sf_localizations/sf_localizations.dart'; @@ -23,6 +25,7 @@ class SaveFamilyApp extends ConsumerStatefulWidget { class SaveFamilyAppState extends ConsumerState with WidgetsBindingObserver { late final WalletHeartbeatService walletHeartbeat; + late final LegacyHeartbeatService legacyHeartbeat; @override void initState() { @@ -33,13 +36,25 @@ class SaveFamilyAppState extends ConsumerState sessionLocal: SessionLocalDatasourceImpl(), onError: () => appRouter.go(AppRoutes.scaTreezor), ); - onBeforeSessionCleared = walletHeartbeat.stop; + legacyHeartbeat = LegacyHeartbeatService( + repository: GetIt.I(), + onUnauthorized: () { + clearSessionData(); + appRouter.go(AppRoutes.legacyLogin); + }, + ); + onBeforeSessionCleared = () { + walletHeartbeat.stop(); + legacyHeartbeat.stop(); + }; // walletHeartbeat.start(); + legacyHeartbeat.start(); } @override void dispose() { walletHeartbeat.stop(); + legacyHeartbeat.stop(); WidgetsBinding.instance.removeObserver(this); super.dispose(); } @@ -50,9 +65,11 @@ class SaveFamilyAppState extends ConsumerState ref.read(appLifecycleStateProvider.notifier).setState(state); if (state == AppLifecycleState.resumed) { // walletHeartbeat.start(); + legacyHeartbeat.start(); ref.read(permissionsProvider.notifier).checkPermissions(); } else if (state == AppLifecycleState.paused) { // walletHeartbeat.stop(); + legacyHeartbeat.stop(); } super.didChangeAppLifecycleState(state); } diff --git a/modules/legacy/modules/account/lib/src/features/account_settings/presentation/account_settings_screen.dart b/modules/legacy/modules/account/lib/src/features/account_settings/presentation/account_settings_screen.dart index ac092bf6..247f19f5 100644 --- a/modules/legacy/modules/account/lib/src/features/account_settings/presentation/account_settings_screen.dart +++ b/modules/legacy/modules/account/lib/src/features/account_settings/presentation/account_settings_screen.dart @@ -26,14 +26,14 @@ class AccountSettingsScreen extends ConsumerWidget { accountSettingsViewModelProvider.select((s) => s.isLoggingOut), ); - ref.listen( - accountSettingsViewModelProvider.select((s) => s.isLoggingOut), - (prev, isLoggingOut) { - if (prev == true && !isLoggingOut) { - navigationContract.goTo(AppRoutes.legacyLogin); - } - }, - ); + ref.listen(accountSettingsViewModelProvider.select((s) => s.isLoggingOut), ( + prev, + isLoggingOut, + ) { + if (prev == true && !isLoggingOut) { + navigationContract.goTo(AppRoutes.legacyLogin); + } + }); return LegacyPageLayout( theme: theme, @@ -46,11 +46,39 @@ class AccountSettingsScreen extends ConsumerWidget { ), child: Column( children: [ - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.personalData), icon: SFIcons.account, text: I18n.personalData, color: color), - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.changePassword), icon: Icons.lock, text: I18n.changePassword, color: color), - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.legacyDeviceSetup), icon: Icons.add_circle_outline, text: I18n.addNewSF, color: color), - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.linkedDevices), icon: Icons.account_circle_outlined, text: I18n.linkedDevices, color: color), - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.appUsers), icon: Icons.groups_outlined, text: I18n.appUsers, color: color), + _item( + context, + onPressed: () => + navigationContract.pushTo(AppRoutes.personalData), + icon: SFIcons.account, + text: I18n.personalData, + color: color, + ), + _item( + context, + onPressed: () => + navigationContract.pushTo(AppRoutes.changePassword), + icon: Icons.lock, + text: I18n.changePassword, + color: color, + ), + _item( + context, + onPressed: () => + navigationContract.pushTo(AppRoutes.legacyDeviceSetup), + icon: Icons.add_circle_outline, + text: I18n.addNewSF, + color: color, + ), + _item( + context, + onPressed: () => + navigationContract.pushTo(AppRoutes.linkedDevices), + icon: Icons.account_circle_outlined, + text: I18n.linkedDevices, + color: color, + ), + // _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.appUsers), icon: Icons.groups_outlined, text: I18n.appUsers, color: color), _item( context, onPressed: () async { @@ -82,7 +110,14 @@ class AccountSettingsScreen extends ConsumerWidget { text: I18n.regCode, color: color, ), - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.deleteAccount), icon: Icons.no_accounts, text: I18n.deleteAccount, color: color), + _item( + context, + onPressed: () => + navigationContract.pushTo(AppRoutes.deleteAccount), + icon: Icons.no_accounts, + text: I18n.deleteAccount, + color: color, + ), ], ), ), @@ -121,7 +156,9 @@ class AccountSettingsScreen extends ConsumerWidget { required Color color, }) { return Padding( - padding: EdgeInsets.only(bottom: SizeUtils.getByScreen(small: 16, big: 15)), + padding: EdgeInsets.only( + bottom: SizeUtils.getByScreen(small: 16, big: 15), + ), child: SectionButton( onPressed: onPressed, icon: Icon( diff --git a/modules/legacy/modules/device_management/lib/src/features/device_management/device_management_screen.dart b/modules/legacy/modules/device_management/lib/src/features/device_management/device_management_screen.dart index fe0130b2..8b68f252 100644 --- a/modules/legacy/modules/device_management/lib/src/features/device_management/device_management_screen.dart +++ b/modules/legacy/modules/device_management/lib/src/features/device_management/device_management_screen.dart @@ -27,14 +27,14 @@ class DeviceManagementScreen extends ConsumerWidget { ), child: Column( children: [ - AppMenuButton( - color: theme.getColorFor(ThemeCode.legacyPrimary), - onPressed: () => - navigationContract.pushTo(AppRoutes.remoteConnection), - icon: SFIcons.connection, - text: context.translate(I18n.remoteConnection), - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + // AppMenuButton( + // color: theme.getColorFor(ThemeCode.legacyPrimary), + // onPressed: () => + // navigationContract.pushTo(AppRoutes.remoteConnection), + // icon: SFIcons.connection, + // text: context.translate(I18n.remoteConnection), + // ), + // SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), AppMenuButton( color: theme.getColorFor(ThemeCode.legacyPrimary), onPressed: () => @@ -106,8 +106,7 @@ class DeviceManagementScreen extends ConsumerWidget { SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), AppMenuButton( color: theme.getColorFor(ThemeCode.legacyPrimary), - onPressed: () => - navigationContract.pushTo(AppRoutes.appsUse), + onPressed: () => navigationContract.pushTo(AppRoutes.appsUse), icon: SFIcons.screenTime, text: context.translate(I18n.appsUse), ), diff --git a/modules/legacy/modules/settings/lib/src/features/settings/presentation/settings_screen.dart b/modules/legacy/modules/settings/lib/src/features/settings/presentation/settings_screen.dart index d24b6df8..797a69aa 100644 --- a/modules/legacy/modules/settings/lib/src/features/settings/presentation/settings_screen.dart +++ b/modules/legacy/modules/settings/lib/src/features/settings/presentation/settings_screen.dart @@ -27,21 +27,111 @@ class SettingsScreen extends ConsumerWidget { ), child: Column( children: [ - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.alarm), icon: Icons.notifications_outlined, text: I18n.alarm, color: color), - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.appStore), icon: Icons.apps_rounded, text: I18n.appStore, color: color), - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.blockPhone), icon: Icons.phone_outlined, text: I18n.blockPhone, color: color), - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.timezone), icon: Icons.check, text: I18n.timezone, color: color), - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.language), icon: Icons.translate_outlined, text: I18n.language, color: color), - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.battery), icon: Icons.nightlight_outlined, text: I18n.battery, color: color), - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.remoteManagement), icon: Icons.settings_remote_outlined, text: I18n.remoteManagement, color: color), - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.legacyNotifications), icon: Icons.message_outlined, text: I18n.legacyNotifications, color: color), - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.smsAlert), icon: Icons.sms_outlined, text: I18n.smsAlert, color: color), - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.sosContacts), icon: Icons.perm_contact_calendar_outlined, text: I18n.sosContacts, color: color), - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.sound), icon: Icons.volume_up_outlined, text: I18n.sound, color: color), - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.wifiSettings), icon: Icons.wifi_find_outlined, text: I18n.wifiSettings, color: color), - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.remoteOnOff), icon: Icons.settings_power_outlined, text: I18n.remoteOnOff, color: color), - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.disableFunctions), icon: Icons.dashboard_customize_outlined, text: I18n.disableFunctions, color: color), - _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.syncClock), icon: Icons.share_arrival_time_outlined, text: I18n.syncClock, color: color), + _item( + context, + onPressed: () => navigationContract.pushTo(AppRoutes.alarm), + icon: Icons.notifications_outlined, + text: I18n.alarm, + color: color, + ), + _item( + context, + onPressed: () => navigationContract.pushTo(AppRoutes.appStore), + icon: Icons.apps_rounded, + text: I18n.appStore, + color: color, + ), + _item( + context, + onPressed: () => + navigationContract.pushTo(AppRoutes.blockPhone), + icon: Icons.phone_outlined, + text: I18n.blockPhone, + color: color, + ), + _item( + context, + onPressed: () => navigationContract.pushTo(AppRoutes.timezone), + icon: Icons.check, + text: I18n.timezone, + color: color, + ), + _item( + context, + onPressed: () => navigationContract.pushTo(AppRoutes.language), + icon: Icons.translate_outlined, + text: I18n.language, + color: color, + ), + _item( + context, + onPressed: () => navigationContract.pushTo(AppRoutes.battery), + icon: Icons.nightlight_outlined, + text: I18n.battery, + color: color, + ), + // _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.remoteManagement), icon: Icons.settings_remote_outlined, text: I18n.remoteManagement, color: color), + _item( + context, + onPressed: () => + navigationContract.pushTo(AppRoutes.legacyNotifications), + icon: Icons.message_outlined, + text: I18n.legacyNotifications, + color: color, + ), + _item( + context, + onPressed: () => navigationContract.pushTo(AppRoutes.smsAlert), + icon: Icons.sms_outlined, + text: I18n.smsAlert, + color: color, + ), + _item( + context, + onPressed: () => + navigationContract.pushTo(AppRoutes.sosContacts), + icon: Icons.perm_contact_calendar_outlined, + text: I18n.sosContacts, + color: color, + ), + // _item( + // context, + // onPressed: () => navigationContract.pushTo(AppRoutes.sound), + // icon: Icons.volume_up_outlined, + // text: I18n.sound, + // color: color, + // ), + // _item( + // context, + // onPressed: () => + // navigationContract.pushTo(AppRoutes.wifiSettings), + // icon: Icons.wifi_find_outlined, + // text: I18n.wifiSettings, + // color: color, + // ), + _item( + context, + onPressed: () => + navigationContract.pushTo(AppRoutes.remoteOnOff), + icon: Icons.settings_power_outlined, + text: I18n.remoteOnOff, + color: color, + ), + _item( + context, + onPressed: () => + navigationContract.pushTo(AppRoutes.disableFunctions), + icon: Icons.dashboard_customize_outlined, + text: I18n.disableFunctions, + color: color, + ), + _item( + context, + onPressed: () => navigationContract.pushTo(AppRoutes.syncClock), + icon: Icons.share_arrival_time_outlined, + text: I18n.syncClock, + color: color, + ), ], ), ), diff --git a/modules/splash/lib/src/domain/check_session_use_case_impl.dart b/modules/splash/lib/src/domain/check_session_use_case_impl.dart index f77c3693..0de10da3 100644 --- a/modules/splash/lib/src/domain/check_session_use_case_impl.dart +++ b/modules/splash/lib/src/domain/check_session_use_case_impl.dart @@ -12,7 +12,7 @@ class CheckSessionUseCaseImpl implements CheckSessionUseCase { @override Future execute() async { try { - await _userRepository.getChildProfiles(); + await _userRepository.getUserInfo(); return InitialRoute.home; } catch (e) { debugPrint('[CheckSessionUseCase] error: $e'); diff --git a/modules/splash/lib/src/presentation/splash_screen.dart b/modules/splash/lib/src/presentation/splash_screen.dart index 9e2ce5f0..06d125ae 100644 --- a/modules/splash/lib/src/presentation/splash_screen.dart +++ b/modules/splash/lib/src/presentation/splash_screen.dart @@ -53,8 +53,8 @@ class _SplashScreenState extends State if (!_animationDone || _route == null || !mounted) return; final destination = switch (_route!) { - InitialRoute.login => AppRoutes.login, - InitialRoute.home => AppRoutes.dashboardHome, + InitialRoute.login => AppRoutes.legacyLogin, + InitialRoute.home => AppRoutes.controlPanel, }; widget.navigationContract.goTo(destination); }