mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
feat: manual offline detection
This commit is contained in:
parent
d0df1d29f5
commit
854ab8910d
@ -1,12 +1,11 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:fl_query/fl_query.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.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:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:spotube/collections/spotube_icons.dart';
|
import 'package:spotube/collections/spotube_icons.dart';
|
||||||
import 'package:spotube/components/shared/dialogs/replace_downloaded_dialog.dart';
|
import 'package:spotube/components/shared/dialogs/replace_downloaded_dialog.dart';
|
||||||
@ -52,44 +51,43 @@ class RootApp extends HookConsumerWidget {
|
|||||||
});
|
});
|
||||||
|
|
||||||
final subscription =
|
final subscription =
|
||||||
InternetConnectionChecker().onStatusChange.listen((status) {
|
QueryClient.connectivity.onConnectivityChanged.listen((status) {
|
||||||
switch (status) {
|
if (status) {
|
||||||
case InternetConnectionStatus.connected:
|
scaffoldMessenger.showSnackBar(
|
||||||
scaffoldMessenger.showSnackBar(
|
SnackBar(
|
||||||
SnackBar(
|
content: Row(
|
||||||
content: Row(
|
children: [
|
||||||
children: [
|
Icon(
|
||||||
Icon(
|
SpotubeIcons.wifi,
|
||||||
SpotubeIcons.wifi,
|
color: theme.colorScheme.onPrimary,
|
||||||
color: theme.colorScheme.onPrimary,
|
),
|
||||||
),
|
const SizedBox(width: 10),
|
||||||
const SizedBox(width: 10),
|
Text(context.l10n.connection_restored),
|
||||||
Text(context.l10n.connection_restored),
|
],
|
||||||
],
|
|
||||||
),
|
|
||||||
backgroundColor: theme.colorScheme.primary,
|
|
||||||
showCloseIcon: true,
|
|
||||||
width: 350,
|
|
||||||
),
|
),
|
||||||
);
|
backgroundColor: theme.colorScheme.primary,
|
||||||
case InternetConnectionStatus.disconnected:
|
showCloseIcon: true,
|
||||||
scaffoldMessenger.showSnackBar(
|
width: 350,
|
||||||
SnackBar(
|
),
|
||||||
content: Row(
|
);
|
||||||
children: [
|
} else {
|
||||||
Icon(
|
scaffoldMessenger.showSnackBar(
|
||||||
SpotubeIcons.noWifi,
|
SnackBar(
|
||||||
color: theme.colorScheme.onError,
|
content: Row(
|
||||||
),
|
children: [
|
||||||
const SizedBox(width: 10),
|
Icon(
|
||||||
Text(context.l10n.you_are_offline),
|
SpotubeIcons.noWifi,
|
||||||
],
|
color: theme.colorScheme.onError,
|
||||||
),
|
),
|
||||||
backgroundColor: theme.colorScheme.error,
|
const SizedBox(width: 10),
|
||||||
showCloseIcon: true,
|
Text(context.l10n.you_are_offline),
|
||||||
width: 300,
|
],
|
||||||
),
|
),
|
||||||
);
|
backgroundColor: theme.colorScheme.error,
|
||||||
|
showCloseIcon: true,
|
||||||
|
width: 300,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,12 +1,95 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:fl_query/fl_query.dart';
|
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 {
|
class FlQueryInternetConnectionCheckerAdapter extends ConnectivityAdapter
|
||||||
@override
|
with WidgetsBindingObserver {
|
||||||
Future<bool> get isConnected => InternetConnectionChecker().hasConnection;
|
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
|
@override
|
||||||
Stream<bool> get onConnectivityChanged => InternetConnectionChecker()
|
didChangeAppLifecycleState(AppLifecycleState state) async {
|
||||||
.onStatusChange
|
if (state == AppLifecycleState.resumed) {
|
||||||
.map((status) => status == InternetConnectionStatus.connected);
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<bool> get isConnected async {
|
||||||
|
final connected = await _isConnected();
|
||||||
|
if (connected != isConnectedSync /*previous value*/) {
|
||||||
|
_connectionStreamController.add(connected);
|
||||||
|
}
|
||||||
|
return connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<bool> get onConnectivityChanged => _connectionStreamController.stream;
|
||||||
}
|
}
|
||||||
|
@ -1125,14 +1125,6 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
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:
|
intl:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -63,7 +63,6 @@ dependencies:
|
|||||||
html: ^0.15.1
|
html: ^0.15.1
|
||||||
http: ^1.1.0
|
http: ^1.1.0
|
||||||
image_picker: ^1.0.4
|
image_picker: ^1.0.4
|
||||||
internet_connection_checker: ^1.0.0+1
|
|
||||||
intl: ^0.18.0
|
intl: ^0.18.0
|
||||||
introduction_screen: ^3.0.2
|
introduction_screen: ^3.0.2
|
||||||
json_annotation: ^4.8.1
|
json_annotation: ^4.8.1
|
||||||
|
Loading…
Reference in New Issue
Block a user