143 lines
4.5 KiB
Dart
143 lines
4.5 KiB
Dart
import 'dart:async';
|
|
import 'dart:io';
|
|
|
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:internet_connection_checker/internet_connection_checker.dart';
|
|
import 'package:mc_gallery/features/core/services/logging_service.dart';
|
|
|
|
import '/locator.dart';
|
|
|
|
/// Used to observe the current connection type.
|
|
class ConnectionService with LoggingService {
|
|
ConnectionService({
|
|
required Connectivity connectivity,
|
|
required InternetConnectionChecker internetConnectionChecker,
|
|
bool shouldInitialize = true,
|
|
}) : _connectivity = connectivity,
|
|
_internetConnectionChecker = internetConnectionChecker {
|
|
if (shouldInitialize) initialize();
|
|
}
|
|
|
|
ConnectivityResult? _connectivityResult;
|
|
ConnectivityResult? get connectivityResult => _connectivityResult;
|
|
|
|
final Connectivity _connectivity;
|
|
final Map<String, StreamSubscription> _connectivitySubscriptions = {};
|
|
|
|
final InternetConnectionChecker _internetConnectionChecker;
|
|
|
|
final Completer _isInitialized = Completer();
|
|
|
|
Completer<bool>? _hasInternetConnection;
|
|
|
|
final ValueNotifier<bool> _hasInternetConnectionListenable = ValueNotifier(false);
|
|
ValueListenable<bool> get hasInternetConnectionListenable => _hasInternetConnectionListenable;
|
|
|
|
Future<bool> get hasInternetConnection async {
|
|
try {
|
|
if (_hasInternetConnection == null) {
|
|
_hasInternetConnection = Completer<bool>();
|
|
try {
|
|
final hasInternetConnection = await _internetConnectionChecker.hasConnection;
|
|
_hasInternetConnection!.complete(hasInternetConnection);
|
|
return hasInternetConnection;
|
|
} catch (error) {
|
|
_hasInternetConnection!.complete(false);
|
|
return false;
|
|
} finally {
|
|
_hasInternetConnection = null;
|
|
}
|
|
} else {
|
|
final awaitedHasInternet = await _hasInternetConnection!.future;
|
|
|
|
return awaitedHasInternet;
|
|
}
|
|
} on SocketException catch (_, __) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Future<void> initialize() async {
|
|
try {
|
|
final tag = runtimeType.toString();
|
|
if (_connectivitySubscriptions[tag] != null) {
|
|
await dispose();
|
|
}
|
|
_connectivitySubscriptions[tag] = _connectivity.onConnectivityChanged.listen(
|
|
_onConnectivityChanged,
|
|
cancelOnError: false,
|
|
onError: (error, stack) {},
|
|
);
|
|
await _onConnectivityChanged(await _connectivity.checkConnectivity());
|
|
_internetConnectionChecker.onStatusChange.listen((final event) {
|
|
switch (event) {
|
|
case InternetConnectionStatus.connected:
|
|
_hasInternetConnectionListenable.value = true;
|
|
break;
|
|
case InternetConnectionStatus.disconnected:
|
|
_hasInternetConnectionListenable.value = false;
|
|
break;
|
|
}
|
|
});
|
|
_isInitialized.complete();
|
|
} catch (error, stackTrace) {
|
|
handle(error, stackTrace);
|
|
}
|
|
}
|
|
|
|
Future<void> dispose() async {
|
|
for (final subscription in _connectivitySubscriptions.values) {
|
|
await subscription.cancel();
|
|
}
|
|
_connectivitySubscriptions.clear();
|
|
_connectivityResult = null;
|
|
}
|
|
|
|
Future<void> addListener({
|
|
required String tag,
|
|
required Future<void> Function({
|
|
required ConnectivityResult connectivityResult,
|
|
required bool hasInternet,
|
|
})
|
|
listener,
|
|
bool tryCallListenerOnAdd = true,
|
|
}) async {
|
|
try {
|
|
if (_connectivityResult != null && tryCallListenerOnAdd)
|
|
await listener(
|
|
connectivityResult: _connectivityResult!, hasInternet: await hasInternetConnection);
|
|
_connectivitySubscriptions[tag] =
|
|
_connectivity.onConnectivityChanged.listen((connectivityResult) async {
|
|
await listener(
|
|
connectivityResult: connectivityResult, hasInternet: await hasInternetConnection);
|
|
});
|
|
} catch (error, stackTrace) {
|
|
handle(error, stackTrace);
|
|
}
|
|
}
|
|
|
|
Future<void> removeListener({required String tag}) async {
|
|
try {
|
|
final subscription = _connectivitySubscriptions[tag];
|
|
if (subscription != null) {
|
|
await subscription.cancel();
|
|
} else {}
|
|
} catch (error, stackTrace) {
|
|
handle(error, stackTrace);
|
|
}
|
|
}
|
|
|
|
Future<void> _onConnectivityChanged(ConnectivityResult connectivityResult) async {
|
|
try {
|
|
_connectivityResult = connectivityResult;
|
|
} catch (error, stackTrace) {
|
|
handle(error, stackTrace);
|
|
}
|
|
}
|
|
|
|
static ConnectionService get locate => Locator.locate();
|
|
}
|
|
|
|
class NoInternetException implements Exception {}
|