Skip to content

Commit 824f664

Browse files
committed
Do not request check api connection when on background
1 parent 98a4418 commit 824f664

File tree

3 files changed

+123
-87
lines changed

3 files changed

+123
-87
lines changed

lib/app.dart

Lines changed: 92 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
import 'dart:async';
2+
13
import 'package:firebase_analytics/firebase_analytics.dart';
24
import 'package:flutter/material.dart';
35
import 'package:flutter_localizations/flutter_localizations.dart';
46
import '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';
59
import 'package:mosquito_alert_app/core/widgets/offline_banner.dart';
610
import 'package:mosquito_alert_app/features/auth/presentation/state/auth_provider.dart';
711
import 'package:mosquito_alert_app/features/onboarding/data/onboarding_repository.dart';
@@ -19,26 +23,107 @@ import 'features/user/presentation/state/user_provider.dart';
1923
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
2024

2125
class 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) {

lib/core/widgets/offline_banner.dart

Lines changed: 30 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,59 +3,46 @@ import 'package:flutter/material.dart';
33
import 'package:internet_connection_checker_plus/internet_connection_checker_plus.dart';
44

55
class OfflineBanner extends StatefulWidget {
6-
const OfflineBanner({super.key, required this.connection});
6+
const OfflineBanner({super.key, required this.internetStatus});
77

8-
final InternetConnection connection;
8+
final InternetStatus internetStatus;
99

1010
@override
1111
State<OfflineBanner> createState() => _OfflineBannerState();
1212
}
1313

1414
class _OfflineBannerState extends State<OfflineBanner> {
15-
InternetStatus? _status;
16-
InternetStatus? _previousStatus;
15+
InternetStatus _previousStatus = InternetStatus.connected;
1716
Timer? _onlineTimer;
1817

1918
@override
20-
void initState() {
21-
super.initState();
22-
_initConnectionStatus();
23-
24-
widget.connection.onStatusChange.listen((status) {
25-
if (!mounted) return;
26-
27-
_onlineTimer?.cancel();
28-
29-
// Show "Online" only if previous status was disconnected
30-
bool showOnlineBanner =
31-
_previousStatus == InternetStatus.disconnected &&
32-
status == InternetStatus.connected;
33-
34-
setState(() {
35-
_previousStatus = _status;
36-
_status = status;
37-
});
38-
39-
// When back online, hide after 1 second
40-
if (showOnlineBanner) {
41-
_onlineTimer = Timer(const Duration(seconds: 1), () {
42-
if (!mounted) return;
43-
setState(() {
44-
_onlineTimer = null;
45-
});
46-
});
47-
}
48-
});
19+
void didUpdateWidget(covariant OfflineBanner oldWidget) {
20+
super.didUpdateWidget(oldWidget);
21+
_handleStatusChange(widget.internetStatus);
4922
}
5023

51-
Future<void> _initConnectionStatus() async {
52-
final status = await widget.connection.internetStatus;
53-
if (!mounted) return;
24+
void _handleStatusChange(InternetStatus status) {
25+
// Check if we just went online
26+
bool showOnlineBanner =
27+
_previousStatus == InternetStatus.disconnected &&
28+
status == InternetStatus.connected;
5429

5530
setState(() {
56-
_status = status;
5731
_previousStatus = status;
5832
});
33+
34+
if (showOnlineBanner) {
35+
// Clear any existing timer
36+
_onlineTimer?.cancel();
37+
38+
// Hide the online banner after 1 second
39+
_onlineTimer = Timer(const Duration(seconds: 1), () {
40+
if (!mounted) return;
41+
setState(() {
42+
_onlineTimer = null;
43+
});
44+
});
45+
}
5946
}
6047

6148
@override
@@ -67,15 +54,16 @@ class _OfflineBannerState extends State<OfflineBanner> {
6754
@override
6855
Widget build(BuildContext context) {
6956
final showBanner =
70-
_status == InternetStatus.disconnected || _onlineTimer != null;
57+
widget.internetStatus == InternetStatus.disconnected ||
58+
_onlineTimer != null;
7159

72-
final text = _status == InternetStatus.disconnected
60+
final text = widget.internetStatus == InternetStatus.disconnected
7361
? 'Offline mode'
7462
: 'Online';
75-
final color = _status == InternetStatus.disconnected
63+
final color = widget.internetStatus == InternetStatus.disconnected
7664
? Colors.blue
7765
: Colors.green;
78-
final icon = _status == InternetStatus.disconnected
66+
final icon = widget.internetStatus == InternetStatus.disconnected
7967
? Icons.wifi_off
8068
: Icons.wifi;
8169

@@ -85,7 +73,7 @@ class _OfflineBannerState extends State<OfflineBanner> {
8573
padding: EdgeInsets.symmetric(horizontal: 16),
8674
width: double.infinity,
8775
curve: Curves.easeInOut,
88-
child: showBanner && _status != null
76+
child: showBanner
8977
? SafeArea(
9078
bottom: false,
9179
child: Padding(

lib/main.dart

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import 'dart:async';
22

3-
import 'package:internet_connection_checker_plus/internet_connection_checker_plus.dart';
43
import 'package:firebase_core/firebase_core.dart';
54
import 'package:flutter/material.dart';
65
import 'package:flutter/services.dart';
@@ -104,42 +103,6 @@ Future<void> main({String env = 'prod'}) async {
104103

105104
await TrackingService.configure(repository: fixesRepository);
106105

107-
// Auto-sync when online
108-
final apiConnection = InternetConnection.createInstance(
109-
useDefaultOptions: false,
110-
enableStrictCheck: true,
111-
customCheckOptions: [
112-
// NOTE: this is dummy, all the logic is in customConnectivityCheck
113-
InternetCheckOption(uri: Uri.parse(apiClient.dio.options.baseUrl)),
114-
],
115-
customConnectivityCheck: (option) async {
116-
try {
117-
final pingApi = apiClient.getPingApi();
118-
final response = await pingApi.retrieve();
119-
120-
return InternetCheckResult(
121-
option: option,
122-
isSuccess: response.statusCode == 204,
123-
);
124-
} catch (_) {
125-
return InternetCheckResult(option: option, isSuccess: false);
126-
}
127-
},
128-
);
129-
apiConnection.onStatusChange.listen((status) async {
130-
if (status == InternetStatus.connected) {
131-
if (!authProvider.isAuthenticated) {
132-
try {
133-
await authProvider.restoreSession();
134-
} catch (e) {
135-
print('Error auto logging in: $e');
136-
return;
137-
}
138-
}
139-
await syncManager.syncAll();
140-
}
141-
});
142-
143106
InAppReviewManager.configure(
144107
observationRepository,
145108
biteRepository,
@@ -172,7 +135,7 @@ Future<void> main({String env = 'prod'}) async {
172135
),
173136
ChangeNotifierProvider<FixesProvider>(create: (_) => FixesProvider()),
174137
],
175-
child: MyApp(apiConnection: apiConnection),
138+
child: MyApp(syncManager: syncManager),
176139
),
177140
);
178141
}

0 commit comments

Comments
 (0)