You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
HMG_Patient_App_New/lib/services/app_lifecycle_service.dart

131 lines
4.5 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/cache_consts.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/presentation/tele_consultation/zoom/call_screen.dart';
import 'package:hmg_patient_app_new/routes/app_routes.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
/// Service to monitor and track app lifecycle state changes
/// This helps detect when app goes to background/foreground
class AppLifecycleService with WidgetsBindingObserver {
final _stateController = StreamController<AppLifecycleState>.broadcast();
/// Stream of app lifecycle state changes
Stream<AppLifecycleState> get appStateStream => _stateController.stream;
AppLifecycleState _currentState = AppLifecycleState.resumed;
/// Current app lifecycle state
AppLifecycleState get currentState => _currentState;
/// Check if app is currently active/visible
bool get isAppActive => _currentState == AppLifecycleState.resumed;
/// Check if app is in background or inactive
bool get isAppInBackground =>
_currentState == AppLifecycleState.paused ||
_currentState == AppLifecycleState.inactive ||
_currentState == AppLifecycleState.detached;
/// Last time app was resumed
DateTime? _lastResumedTime;
DateTime? get lastResumedTime => _lastResumedTime;
/// Last time app went to background
DateTime? _lastPausedTime;
DateTime? get lastPausedTime => _lastPausedTime;
/// Duration app has been in current state
Duration get timeInCurrentState {
final referenceTime = _currentState == AppLifecycleState.resumed
? _lastResumedTime
: _lastPausedTime;
if (referenceTime == null) return Duration.zero;
return DateTime.now().difference(referenceTime);
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
_currentState = state;
// Track timing
if (state == AppLifecycleState.resumed) {
_lastResumedTime = DateTime.now();
debugPrint('📱 App RESUMED');
} else if (state == AppLifecycleState.paused) {
_lastPausedTime = DateTime.now();
debugPrint('📱 App PAUSED/BACKGROUNDED');
} else if (state == AppLifecycleState.inactive) {
debugPrint('📱 App INACTIVE');
} else if (state == AppLifecycleState.detached) {
debugPrint('📱 App DETACHED');
}
_stateController.add(state);
}
String? _extractJoinSessionId(String? routeName) {
if (routeName == null || routeName.isEmpty) return null;
final match = RegExp(r'/join/([^?#]+)').firstMatch(routeName);
if (match != null && match.group(1)!.isNotEmpty) {
return Uri.decodeComponent(match.group(1)!);
}
return null;
}
Future<bool> _handleIncomingDeepLink(String? route) async {
debugPrint('🔗 DeepLink received in AppLifecycleService: $route');
final sessionId = _extractJoinSessionId(route);
if (sessionId != null) {
final appState = getIt.get<AppState>();
await Utils.saveStringFromPrefs(CacheConst.zoomRoomID, sessionId);
debugPrint('🔗 DeepLink Join Session ID parsed: $sessionId (splashDone=${appState.isSplashInitializationDone})');
if (!appState.isSplashInitializationDone) {
appState.deepLinkJoinSessionId = sessionId;
return true;
}
final navState = getIt.get<NavigationService>().navigatorKey.currentState;
if (navState != null) {
String callTypeID = await Utils.getStringFromPrefs(CacheConst.callTypeID);
navState.pushNamed(
AppRoutes.zoomCallPage,
arguments: CallArguments(sessionId, "123", "Patient", "40", "0", true, int.tryParse(callTypeID) ?? 1),
);
return true;
}
}
return false;
}
@override
Future<bool> didPushRouteInformation(RouteInformation routeInformation) {
return _handleIncomingDeepLink(routeInformation.uri.toString());
}
@override
Future<bool> didPushRoute(String route) {
return _handleIncomingDeepLink(route);
}
/// Initialize the lifecycle observer
void initialize() {
WidgetsBinding.instance.addObserver(this);
debugPrint('📱 AppLifecycleService initialized');
}
/// Clean up resources
void dispose() {
WidgetsBinding.instance.removeObserver(this);
_stateController.close();
debugPrint('📱 AppLifecycleService disposed');
}
}