Add network auto control feature for mobile platforms

Co-authored-by: monkeyWie <[email protected]>
This commit is contained in:
copilot-swe-agent[bot]andmonkeyWie committed 2025-08-11 08:04:35 +00:00
1 parent 25bf3ca65b
commit 431fdd0d54
7 files changed
+148 -1

No files matched your search

@@ -1,5 +1,6 @@
import 'package:get/get.dart';
import '../../../../util/network_monitor.dart';
import '../controllers/app_controller.dart';
class AppBinding extends Bindings {
@@ -8,5 +9,6 @@ class AppBinding extends Bindings {
Get.lazyPut<AppController>(
() => AppController(),
);
Get.put<NetworkMonitor>(NetworkMonitor(), permanent: true);
}
}
@@ -11,6 +11,7 @@ import 'package:launch_at_startup/launch_at_startup.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../../../api/model/downloader_config.dart';
import '../../../../database/database.dart';
import '../../../../i18n/message.dart';
import '../../../../util/input_formatter.dart';
import '../../../../util/locale_manager.dart';
@@ -543,6 +544,26 @@ class SettingView extends GetView<SettingController> {
);
}
// Network auto control setting (mobile only)
buildNetworkAutoControl() {
if (!Platform.isAndroid && !Platform.isIOS) {
return null;
}
return ListTile(
title: Text('networkAutoControl'.tr),
subtitle: Text('networkAutoControlTip'.tr),
trailing: Switch(
value: Database.instance.getNetworkAutoControl(),
onChanged: (bool value) {
Database.instance.saveNetworkAutoControl(value);
// Trigger rebuild to update the display value
controller.update();
},
),
);
}
// advanced config proxy items start
final proxy = downloaderCfg.value.proxy;
final buildProxy = _buildConfigItem(
@@ -985,7 +1006,10 @@ class SettingView extends GetView<SettingController> {
Text('network'.tr),
Card(
child: Column(
children: _addDivider([buildProxy()]),
children: _addDivider([
buildNetworkAutoControl(),
buildProxy(),
].where((e) => e != null).cast<Widget>().toList()),
)),
const Text('API'),
Card(
+9
View File
@@ -10,6 +10,7 @@ const String _windowState = 'windowState';
const String _bookmark = 'bookmark';
const String _createHistory = 'createHistory';
const String _webToken = 'webToken';
const String _networkAutoControl = 'networkAutoControl';
class Database {
static final Database _instance = Database._internal();
@@ -109,4 +110,12 @@ class Database {
void clearCreateHistory() {
clear(_createHistory);
}
void saveNetworkAutoControl(bool enabled) {
save<bool>(_networkAutoControl, enabled);
}
bool getNetworkAutoControl() {
return get<bool>(_networkAutoControl, (json) => json as bool) ?? false;
}
}
+2
View File
@@ -125,5 +125,7 @@ const enUS = {
'login_failed': 'Login failed, please check your username and password',
'login_failed_network':
'Login failed, please check your network connection',
'networkAutoControl': 'Network Auto Control',
'networkAutoControlTip': 'Automatically pause downloads when switching from WiFi to mobile data, and resume when switching back to WiFi',
},
};
+2
View File
@@ -122,5 +122,7 @@ const zhCN = {
'login_success': '登录成功',
'login_failed': '登录失败,请检查用户名和密码',
'login_failed_network': '登录失败,请检查网络连接',
'networkAutoControl': '网络状态自动控制',
'networkAutoControlTip': '当网络从WiFi切换到移动数据时自动暂停下载,切换回WiFi时自动恢复下载',
}
};
+107
View File
@@ -0,0 +1,107 @@
import 'dart:async';
import 'dart:io';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:get/get.dart';
import '../api/api.dart';
import '../database/database.dart';
import '../util/log_util.dart';
class NetworkMonitor extends GetxService {
static NetworkMonitor get to => Get.find();
late final Connectivity _connectivity;
late StreamSubscription<List<ConnectivityResult>> _connectivitySubscription;
final _isWiFiConnected = false.obs;
bool get isWiFiConnected => _isWiFiConnected.value;
bool _wasWiFiConnected = false;
bool _isInitialized = false;
@override
Future<void> onInit() async {
super.onInit();
// Only monitor network on mobile platforms
if (!Platform.isAndroid && !Platform.isIOS) {
return;
}
_connectivity = Connectivity();
// Check initial connectivity state
final initialResult = await _connectivity.checkConnectivity();
_updateWiFiStatus(initialResult);
_wasWiFiConnected = _isWiFiConnected.value;
_isInitialized = true;
// Listen to connectivity changes
_connectivitySubscription = _connectivity.onConnectivityChanged.listen(
_onConnectivityChanged,
onError: (error) {
logError('Network monitoring error: $error');
},
);
logInfo('Network monitor initialized');
}
@override
void onClose() {
_connectivitySubscription.cancel();
super.onClose();
}
void _updateWiFiStatus(List<ConnectivityResult> result) {
final hasWiFi = result.contains(ConnectivityResult.wifi);
_isWiFiConnected.value = hasWiFi;
}
void _onConnectivityChanged(List<ConnectivityResult> result) {
if (!_isInitialized) return;
// Check if network auto control is enabled
final isNetworkAutoControlEnabled = Database.instance.getNetworkAutoControl();
if (!isNetworkAutoControlEnabled) {
return;
}
_updateWiFiStatus(result);
final currentlyWiFi = _isWiFiConnected.value;
logInfo('Network changed: wasWiFi=$_wasWiFiConnected, currentlyWiFi=$currentlyWiFi');
// WiFi to Mobile Data: pause all tasks
if (_wasWiFiConnected && !currentlyWiFi) {
_pauseAllDownloads();
logInfo('Switched from WiFi to mobile data - pausing all downloads');
}
// Mobile Data to WiFi: resume all tasks
else if (!_wasWiFiConnected && currentlyWiFi) {
_resumeAllDownloads();
logInfo('Switched from mobile data to WiFi - resuming all downloads');
}
_wasWiFiConnected = currentlyWiFi;
}
Future<void> _pauseAllDownloads() async {
try {
await pauseAllTasks(null);
logInfo('Successfully paused all downloads due to network change');
} catch (e) {
logError('Failed to pause all downloads: $e');
}
}
Future<void> _resumeAllDownloads() async {
try {
await continueAllTasks(null);
logInfo('Successfully resumed all downloads due to network change');
} catch (e) {
logError('Failed to resume all downloads: $e');
}
}
}
+1
View File
@@ -66,6 +66,7 @@ dependencies:
toggle_switch: ^2.3.0
permission_handler: ^11.3.1
device_info_plus: ^11.1.0
connectivity_plus: ^6.1.0
checkable_treeview: ^1.3.1
contextmenu_plus: ^1.0.1
contentsize_tabbarview: ^0.0.2