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.
131 lines
4.5 KiB
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');
|
|
}
|
|
}
|
|
|
|
|