Skip to content

Commit

Permalink
feat: manual offline detection
Browse files Browse the repository at this point in the history
  • Loading branch information
KRTirtho committed Oct 14, 2023
1 parent d0df1d2 commit 854ab89
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 53 deletions.
74 changes: 36 additions & 38 deletions lib/pages/root/root_app.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import 'dart:async';

import 'package:collection/collection.dart';
import 'package:fl_query/fl_query.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:internet_connection_checker/internet_connection_checker.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/shared/dialogs/replace_downloaded_dialog.dart';
Expand Down Expand Up @@ -52,44 +51,43 @@ class RootApp extends HookConsumerWidget {
});

final subscription =
InternetConnectionChecker().onStatusChange.listen((status) {
switch (status) {
case InternetConnectionStatus.connected:
scaffoldMessenger.showSnackBar(
SnackBar(
content: Row(
children: [
Icon(
SpotubeIcons.wifi,
color: theme.colorScheme.onPrimary,
),
const SizedBox(width: 10),
Text(context.l10n.connection_restored),
],
),
backgroundColor: theme.colorScheme.primary,
showCloseIcon: true,
width: 350,
QueryClient.connectivity.onConnectivityChanged.listen((status) {
if (status) {
scaffoldMessenger.showSnackBar(
SnackBar(
content: Row(
children: [
Icon(
SpotubeIcons.wifi,
color: theme.colorScheme.onPrimary,
),
const SizedBox(width: 10),
Text(context.l10n.connection_restored),
],
),
);
case InternetConnectionStatus.disconnected:
scaffoldMessenger.showSnackBar(
SnackBar(
content: Row(
children: [
Icon(
SpotubeIcons.noWifi,
color: theme.colorScheme.onError,
),
const SizedBox(width: 10),
Text(context.l10n.you_are_offline),
],
),
backgroundColor: theme.colorScheme.error,
showCloseIcon: true,
width: 300,
backgroundColor: theme.colorScheme.primary,
showCloseIcon: true,
width: 350,
),
);
} else {
scaffoldMessenger.showSnackBar(
SnackBar(
content: Row(
children: [
Icon(
SpotubeIcons.noWifi,
color: theme.colorScheme.onError,
),
const SizedBox(width: 10),
Text(context.l10n.you_are_offline),
],
),
);
backgroundColor: theme.colorScheme.error,
showCloseIcon: true,
width: 300,
),
);
}
});

Expand Down
95 changes: 89 additions & 6 deletions lib/services/connectivity_adapter.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,95 @@
import 'dart:async';
import 'dart:io';

import 'package:fl_query/fl_query.dart';
import 'package:internet_connection_checker/internet_connection_checker.dart';
import 'package:flutter/widgets.dart';

class FlQueryInternetConnectionCheckerAdapter extends ConnectivityAdapter
with WidgetsBindingObserver {
final _connectionStreamController = StreamController<bool>.broadcast();

FlQueryInternetConnectionCheckerAdapter() : super() {
Timer.periodic(const Duration(minutes: 3), (timer) async {
if (WidgetsBinding.instance.lifecycleState == AppLifecycleState.paused) {
return;
}
await isConnected;
});
}

@override
didChangeAppLifecycleState(AppLifecycleState state) async {
if (state == AppLifecycleState.resumed) {
await isConnected;
}
}

final vpnNames = [
'tun',
'tap',
'ppp',
'pptp',
'l2tp',
'ipsec',
'vpn',
'wireguard',
'openvpn',
'softether',
'proton',
'strongswan',
'cisco',
'forticlient',
'fortinet',
'hideme',
'hidemy',
'hideman',
'hidester',
'lightway',
];

Future<bool> isVpnActive() async {
final interfaces = await NetworkInterface.list(
includeLoopback: false,
type: InternetAddressType.any,
);

if (interfaces.isEmpty) {
return false;
}

return interfaces.any(
(interface) =>
vpnNames.any((name) => interface.name.toLowerCase().contains(name)),
);
}

Future<bool> doesConnectTo(String address) async {
try {
final result = await InternetAddress.lookup(address);
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
return true;
}
return false;
} on SocketException catch (_) {
return false;
}
}

Future<bool> _isConnected() async {
return await doesConnectTo('google.com') ||
await doesConnectTo('www.baidu.com') || // for China
await isVpnActive(); // when VPN is active that means we are connected
}

class FlQueryInternetConnectionCheckerAdapter extends ConnectivityAdapter {
@override
Future<bool> get isConnected => InternetConnectionChecker().hasConnection;
Future<bool> get isConnected async {
final connected = await _isConnected();
if (connected != isConnectedSync /*previous value*/) {
_connectionStreamController.add(connected);
}
return connected;
}

@override
Stream<bool> get onConnectivityChanged => InternetConnectionChecker()
.onStatusChange
.map((status) => status == InternetConnectionStatus.connected);
Stream<bool> get onConnectivityChanged => _connectionStreamController.stream;
}
8 changes: 0 additions & 8 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1125,14 +1125,6 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
internet_connection_checker:
dependency: "direct main"
description:
name: internet_connection_checker
sha256: "1c683e63e89c9ac66a40748b1b20889fd9804980da732bf2b58d6d5456c8e876"
url: "https://pub.dev"
source: hosted
version: "1.0.0+1"
intl:
dependency: "direct main"
description:
Expand Down
1 change: 0 additions & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ dependencies:
html: ^0.15.1
http: ^1.1.0
image_picker: ^1.0.4
internet_connection_checker: ^1.0.0+1
intl: ^0.18.0
introduction_screen: ^3.0.2
json_annotation: ^4.8.1
Expand Down

0 comments on commit 854ab89

Please sign in to comment.