-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add connectivity management with connectivity_plus package #2325
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import 'dart:async'; | ||
import 'package:bloc/bloc.dart'; | ||
import 'package:equatable/equatable.dart'; | ||
import 'package:connectivity_plus/connectivity_plus.dart'; | ||
import 'package:flutter/foundation.dart'; | ||
import 'dart:io' show InternetAddress; | ||
|
||
part 'connectivity_event.dart'; | ||
part 'connectivity_state.dart'; | ||
|
||
class ConnectivityBloc extends Bloc<ConnectivityEvent, ConnectivityState> { | ||
final Connectivity _connectivity; | ||
StreamSubscription? _connectivitySubscription; | ||
bool _bannerDismissed = false; | ||
bool get isBannerDismissed => _bannerDismissed; | ||
|
||
ConnectivityBloc(this._connectivity) : super(ConnectivityInitial()) { | ||
_checkInitialConnectivity(); | ||
|
||
_connectivitySubscription = | ||
_connectivity.onConnectivityChanged.listen((result) { | ||
debugPrint('Connectivity changed: $result'); | ||
add(ConnectivityChanged(result != ConnectivityResult.none)); | ||
}); | ||
|
||
on<ConnectivityChanged>((event, emit) { | ||
if (event.isConnected) { | ||
emit(ConnectivityOnline()); | ||
} else { | ||
emit(ConnectivityOffline()); | ||
} | ||
}); | ||
} | ||
|
||
Future<bool> _hasInternetConnection() async { | ||
try { | ||
final result = await InternetAddress.lookup('google.com'); | ||
return result.isNotEmpty && result[0].rawAddress.isNotEmpty; | ||
} catch (e) { | ||
return false; | ||
} | ||
} | ||
|
||
Future<void> _checkInitialConnectivity() async { | ||
try { | ||
var connectivityResult = await _connectivity.checkConnectivity(); | ||
debugPrint('Initial connectivity check result: $connectivityResult'); | ||
|
||
bool isConnected = connectivityResult != ConnectivityResult.none && | ||
await _hasInternetConnection(); | ||
add(ConnectivityChanged(isConnected)); | ||
} catch (e) { | ||
add(ConnectivityChanged(false)); | ||
} | ||
} | ||
|
||
@override | ||
Future<void> close() { | ||
_connectivitySubscription?.cancel(); | ||
return super.close(); | ||
} | ||
|
||
@override | ||
void onEvent(ConnectivityEvent event) { | ||
if (event is ConnectivityBannerDismissed) { | ||
_bannerDismissed = true; | ||
} | ||
super.onEvent(event); | ||
} | ||
|
||
Stream<ConnectivityState> mapEventToState(ConnectivityEvent event) async* { | ||
if (event is ConnectivityChanged) { | ||
yield event.isConnected ? ConnectivityOnline() : ConnectivityOffline(); | ||
} else if (event is ConnectivityBannerDismissed) { | ||
_bannerDismissed = true; | ||
yield state; | ||
} | ||
} | ||
Comment on lines
+71
to
+78
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Avoid mixing Using both Apply this diff to remove the ...
- Stream<ConnectivityState> mapEventToState(ConnectivityEvent event) async* {
- if (event is ConnectivityChanged) {
- yield event.isConnected ? ConnectivityOnline() : ConnectivityOffline();
- } else if (event is ConnectivityBannerDismissed) {
- _bannerDismissed = true;
- yield state;
- }
- }
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
part of 'connectivity_bloc.dart'; | ||
|
||
abstract class ConnectivityEvent extends Equatable { | ||
const ConnectivityEvent(); | ||
|
||
@override | ||
List<Object?> get props => []; | ||
} | ||
|
||
class ConnectivityChanged extends ConnectivityEvent { | ||
final bool isConnected; | ||
|
||
const ConnectivityChanged(this.isConnected); | ||
|
||
@override | ||
List<Object?> get props => [isConnected]; | ||
} | ||
|
||
class ConnectivityBannerDismissed extends ConnectivityEvent {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
part of 'connectivity_bloc.dart'; | ||
|
||
abstract class ConnectivityState extends Equatable { | ||
const ConnectivityState(); | ||
|
||
@override | ||
List<Object?> get props => []; | ||
} | ||
|
||
class ConnectivityInitial extends ConnectivityState {} | ||
|
||
class ConnectivityOnline extends ConnectivityState {} | ||
|
||
class ConnectivityOffline extends ConnectivityState { | ||
final bool isDismissed; | ||
|
||
ConnectivityOffline([this.isDismissed = false]); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,51 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_bloc/flutter_bloc.dart'; | ||
import 'package:airqo/src/app/shared/bloc/connectivity_bloc.dart'; | ||
|
||
class NoInternetBanner extends StatelessWidget { | ||
final VoidCallback onClose; | ||
final VoidCallback? onClose; | ||
|
||
const NoInternetBanner({Key? key, required this.onClose}) : super(key: key); | ||
const NoInternetBanner({Key? key, this.onClose}) : super(key: key); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Container( | ||
color: Colors.red, | ||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), | ||
child: Row( | ||
mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||
children: [ | ||
Text( | ||
'Internet Connection Lost', | ||
style: TextStyle( | ||
color: Colors.white, | ||
fontWeight: FontWeight.bold, | ||
fontSize: 16.0, | ||
return BlocBuilder<ConnectivityBloc, ConnectivityState>( | ||
builder: (context, state) { | ||
if (state is! ConnectivityOffline || | ||
(state).isDismissed) { | ||
return SizedBox.shrink(); | ||
} | ||
|
||
return Container( | ||
color: Colors.red, | ||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), | ||
child: SafeArea( | ||
child: Row( | ||
mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||
children: [ | ||
Expanded( | ||
child: Text( | ||
'Internet Connection Lost', | ||
style: TextStyle( | ||
color: Colors.white, | ||
fontWeight: FontWeight.bold, | ||
fontSize: 16.0, | ||
), | ||
overflow: TextOverflow.ellipsis, | ||
), | ||
), | ||
IconButton( | ||
icon: Icon(Icons.close, color: Colors.white), | ||
onPressed: () { | ||
context.read<ConnectivityBloc>().add(ConnectivityBannerDismissed()); | ||
onClose?.call(); | ||
}, | ||
), | ||
Comment on lines
+37
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Banner dismiss state does not persist across app restarts The
🔗 Analysis chainVerify dismiss behavior persistence. The banner dismissal triggers both local and bloc state updates. We should verify if this state persists across app restarts. The previous pattern didn't yield results, so I'm broadening the search to understand the connectivity-related state management and persistence mechanisms. This will help us verify if the dismiss state is actually persisted. I noticed a 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Search for persistence-related code in the ConnectivityBloc
ast-grep --pattern 'class ConnectivityBloc extends Bloc<ConnectivityEvent, ConnectivityState> {
$$$
isDismissed
$$$
}'
Length of output: 126 Script: #!/bin/bash
# Let's search for the ConnectivityBloc implementation and state handling
rg -l "ConnectivityBloc" --type dart
# Then look for persistence or storage related code in connectivity
rg "ConnectivityBannerDismissed|isDismissed" --type dart -C 3
# Search for any shared preferences or storage related to connectivity
rg "SharedPreferences.*connect" --type dart -C 2
Length of output: 4254 Script: #!/bin/bash
# Let's check the ConnectivityBloc class implementation for any persistence variables
rg "_bannerDismissed" --type dart -C 5
# Also check if there's any initialization code that might restore state
cat mobile-v3/lib/src/app/shared/bloc/connectivity_bloc.dart
Length of output: 5104 |
||
], | ||
), | ||
), | ||
IconButton( | ||
icon: Icon(Icons.close, color: Colors.white), | ||
onPressed: onClose, | ||
), | ||
], | ||
), | ||
); | ||
}, | ||
); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid manual modifications to generated files
GeneratedPluginRegistrant.m
is an auto-generated file. Manual edits might be overwritten. Ensure that theconnectivity_plus
plugin is correctly added to yourpubspec.yaml
, and let the Flutter tooling handle the plugin registration.To include the plugin properly, verify that you've added it to
pubspec.yaml
:Then, run
flutter pub get
and rebuild the project to auto-generate the correct registrant files.Also applies to: 30-30