Add reconnect alert for config options

This commit is contained in:
problematicconsumer
2024-03-03 14:03:36 +03:30
parent 45fbe76c6e
commit 60db9a2239
6 changed files with 202 additions and 1 deletions

View File

@@ -2,10 +2,12 @@ import 'package:dartx/dartx.dart';
import 'package:fpdart/fpdart.dart';
import 'package:hiddify/core/model/optional_range.dart';
import 'package:hiddify/core/model/region.dart';
import 'package:hiddify/core/preferences/general_preferences.dart';
import 'package:hiddify/core/utils/exception_handler.dart';
import 'package:hiddify/core/utils/json_converters.dart';
import 'package:hiddify/core/utils/preferences_utils.dart';
import 'package:hiddify/features/config_option/model/config_option_failure.dart';
import 'package:hiddify/features/geo_asset/data/geo_asset_data_providers.dart';
import 'package:hiddify/features/geo_asset/data/geo_asset_path_resolver.dart';
import 'package:hiddify/features/geo_asset/data/geo_asset_repository.dart';
import 'package:hiddify/features/log/model/log_level.dart';
@@ -324,6 +326,107 @@ abstract class ConfigOptions {
warpWireguardConfig,
];
static final singboxConfigOptions = FutureProvider<SingboxConfigOption>(
(ref) async {
final region = ref.watch(Preferences.region);
final rules = switch (region) {
Region.ir => [
const SingboxRule(
domains: "domain:.ir,geosite:ir",
ip: "geoip:ir",
outbound: RuleOutbound.bypass,
),
],
Region.cn => [
const SingboxRule(
domains: "domain:.cn,geosite:cn",
ip: "geoip:cn",
outbound: RuleOutbound.bypass,
),
],
Region.ru => [
const SingboxRule(
domains: "domain:.ru",
ip: "geoip:ru",
outbound: RuleOutbound.bypass,
),
],
Region.af => [
const SingboxRule(
domains: "domain:.af,geosite:af",
ip: "geoip:af",
outbound: RuleOutbound.bypass,
),
],
_ => <SingboxRule>[],
};
final geoAssetsRepo = await ref.watch(geoAssetRepositoryProvider.future);
final geoAssets =
await geoAssetsRepo.getActivePair().getOrElse((l) => throw l).run();
final mode = ref.watch(serviceMode);
return SingboxConfigOption(
executeConfigAsIs: false,
logLevel: ref.watch(logLevel),
resolveDestination: ref.watch(resolveDestination),
ipv6Mode: ref.watch(ipv6Mode),
remoteDnsAddress: ref.watch(remoteDnsAddress),
remoteDnsDomainStrategy: ref.watch(remoteDnsDomainStrategy),
directDnsAddress: ref.watch(directDnsAddress),
directDnsDomainStrategy: ref.watch(directDnsDomainStrategy),
mixedPort: ref.watch(mixedPort),
localDnsPort: ref.watch(localDnsPort),
tunImplementation: ref.watch(tunImplementation),
mtu: ref.watch(mtu),
strictRoute: ref.watch(strictRoute),
connectionTestUrl: ref.watch(connectionTestUrl),
urlTestInterval: ref.watch(urlTestInterval),
enableClashApi: ref.watch(enableClashApi),
clashApiPort: ref.watch(clashApiPort),
enableTun: mode == ServiceMode.tun,
enableTunService: mode == ServiceMode.tunService,
setSystemProxy: mode == ServiceMode.systemProxy,
bypassLan: ref.watch(bypassLan),
allowConnectionFromLan: ref.watch(allowConnectionFromLan),
enableFakeDns: ref.watch(enableFakeDns),
enableDnsRouting: ref.watch(enableDnsRouting),
independentDnsCache: ref.watch(independentDnsCache),
enableTlsFragment: ref.watch(enableTlsFragment),
tlsFragmentSize: ref.watch(tlsFragmentSize),
tlsFragmentSleep: ref.watch(tlsFragmentSleep),
enableTlsMixedSniCase: ref.watch(enableTlsMixedSniCase),
enableTlsPadding: ref.watch(enableTlsPadding),
tlsPaddingSize: ref.watch(tlsPaddingSize),
enableMux: ref.watch(enableMux),
muxPadding: ref.watch(muxPadding),
muxMaxStreams: ref.watch(muxMaxStreams),
muxProtocol: ref.watch(muxProtocol),
warp: SingboxWarpOption(
enable: ref.watch(enableWarp),
mode: ref.watch(warpDetourMode),
wireguardConfig: ref.watch(warpWireguardConfig),
licenseKey: ref.watch(warpLicenseKey),
accountId: ref.watch(warpAccountId),
accessToken: ref.watch(warpAccessToken),
cleanIp: ref.watch(warpCleanIp),
cleanPort: ref.watch(warpPort),
warpNoise: ref.watch(warpNoise),
warpNoiseDelay: ref.watch(warpNoiseDelay),
),
geoipPath: ref.watch(geoAssetPathResolverProvider).relativePath(
geoAssets.geoip.providerName,
geoAssets.geoip.fileName,
),
geositePath: ref.watch(geoAssetPathResolverProvider).relativePath(
geoAssets.geosite.providerName,
geoAssets.geosite.fileName,
),
rules: rules,
);
},
);
/// singbox options
///
/// **this is partial, don't use it directly**

View File

@@ -2,6 +2,8 @@ import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:hiddify/features/config_option/data/config_option_repository.dart';
import 'package:hiddify/features/connection/data/connection_data_providers.dart';
import 'package:hiddify/features/connection/notifier/connection_notifier.dart';
import 'package:hiddify/utils/custom_loggers.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
@@ -10,7 +12,29 @@ part 'config_option_notifier.g.dart';
@Riverpod(keepAlive: true)
class ConfigOptionNotifier extends _$ConfigOptionNotifier with AppLogger {
@override
Future<void> build() async {}
Future<bool> build() async {
final serviceRunning = await ref.watch(serviceRunningProvider.future);
final serviceSingboxOptions =
ref.read(connectionRepositoryProvider).configOptionsSnapshot;
ref.listen(
ConfigOptions.singboxConfigOptions,
(previous, next) async {
if (!serviceRunning || serviceSingboxOptions == null) return;
if (next case AsyncData(:final value) when next != previous) {
if (_lastUpdate == null ||
DateTime.now().difference(_lastUpdate!) >
const Duration(seconds: 3)) {
_lastUpdate = DateTime.now();
state = AsyncData(value != serviceSingboxOptions);
}
}
},
fireImmediately: true,
);
return false;
}
DateTime? _lastUpdate;
Future<void> exportJsonToClipboard() async {
final map = {