1+ import 'dart:async' ;
2+
13import 'package:firebase_analytics/firebase_analytics.dart' ;
24import 'package:flutter/material.dart' ;
35import 'package:flutter_localizations/flutter_localizations.dart' ;
46import 'package:internet_connection_checker_plus/internet_connection_checker_plus.dart' ;
7+ import 'package:mosquito_alert/mosquito_alert.dart' ;
8+ import 'package:mosquito_alert_app/core/outbox/outbox_sync_manager.dart' ;
59import 'package:mosquito_alert_app/core/widgets/offline_banner.dart' ;
610import 'package:mosquito_alert_app/features/auth/presentation/state/auth_provider.dart' ;
711import 'package:mosquito_alert_app/features/onboarding/data/onboarding_repository.dart' ;
@@ -19,26 +23,107 @@ import 'features/user/presentation/state/user_provider.dart';
1923final GlobalKey <NavigatorState > navigatorKey = GlobalKey <NavigatorState >();
2024
2125class AppShell extends StatelessWidget {
22- const AppShell ({super .key, required this .apiConnection, required this .child});
26+ const AppShell ({
27+ super .key,
28+ required this .internetStatus,
29+ required this .child,
30+ });
2331
24- final InternetConnection apiConnection ;
32+ final InternetStatus internetStatus ;
2533 final Widget child;
2634
2735 @override
2836 Widget build (BuildContext context) {
2937 return Column (
3038 children: [
31- OfflineBanner (connection : apiConnection ),
39+ OfflineBanner (internetStatus : internetStatus ),
3240 Expanded (child: child),
3341 ],
3442 );
3543 }
3644}
3745
38- class MyApp extends StatelessWidget {
39- const MyApp ({super .key, required this .apiConnection});
46+ class MyApp extends StatefulWidget {
47+ const MyApp ({super .key, required this .syncManager});
48+
49+ final OutboxSyncManager syncManager;
50+
51+ @override
52+ State <MyApp > createState () => _MyAppState ();
53+ }
54+
55+ class _MyAppState extends State <MyApp > {
56+ late final InternetConnection apiConnection;
57+ InternetStatus _internetStatus = InternetStatus .connected;
58+
59+ late StreamSubscription <InternetStatus > _apiConnectionSubscription;
60+ late final AppLifecycleListener _apiConnectionSListener;
61+
62+ StreamSubscription <InternetStatus > _createApiConnectionSubscription () {
63+ final apiClient = context.read <MosquitoAlert >();
64+ final authProvider = context.read <AuthProvider >();
65+
66+ return InternetConnection .createInstance (
67+ useDefaultOptions: false ,
68+ enableStrictCheck: true ,
69+ customCheckOptions: [
70+ // NOTE: this is dummy, all the logic is in customConnectivityCheck
71+ InternetCheckOption (uri: Uri .parse (apiClient.dio.options.baseUrl)),
72+ ],
73+ customConnectivityCheck: (option) async {
74+ try {
75+ final pingApi = apiClient.getPingApi ();
76+ final response = await pingApi.retrieve ();
77+
78+ return InternetCheckResult (
79+ option: option,
80+ isSuccess: response.statusCode == 204 ,
81+ );
82+ } catch (e) {
83+ return InternetCheckResult (option: option, isSuccess: false );
84+ }
85+ },
86+ ).onStatusChange.listen ((status) async {
87+ setState (() {
88+ _internetStatus = status;
89+ });
90+ if (status == InternetStatus .connected) {
91+ if (! authProvider.isAuthenticated) {
92+ try {
93+ await authProvider.restoreSession ();
94+ } catch (e) {
95+ print ('Error auto logging in: $e ' );
96+ return ;
97+ }
98+ }
99+ unawaited (widget.syncManager.syncAll ());
100+ }
101+ });
102+ }
40103
41- final InternetConnection apiConnection;
104+ @override
105+ void initState () {
106+ super .initState ();
107+ _apiConnectionSubscription = _createApiConnectionSubscription ();
108+ _apiConnectionSListener = AppLifecycleListener (
109+ onResume: () {
110+ _apiConnectionSubscription = _createApiConnectionSubscription ();
111+ },
112+ onPause: () {
113+ _apiConnectionSubscription.cancel ();
114+ setState (() {
115+ _internetStatus = InternetStatus .connected;
116+ });
117+ },
118+ );
119+ }
120+
121+ @override
122+ void dispose () {
123+ _apiConnectionSubscription.cancel ();
124+ _apiConnectionSListener.dispose ();
125+ super .dispose ();
126+ }
42127
43128 @override
44129 Widget build (BuildContext context) {
@@ -125,7 +210,7 @@ class MyApp extends StatelessWidget {
125210 ),
126211 ],
127212 builder: (context, child) {
128- return AppShell (apiConnection : apiConnection , child: child! );
213+ return AppShell (internetStatus : _internetStatus , child: child! );
129214 },
130215 home: Consumer <OnboardingProvider >(
131216 builder: (context, onboardingProvider, child) {
0 commit comments