add basic routing options, auto update routing assets,use ruleset, remove geo assets

This commit is contained in:
hiddify-com
2024-07-04 21:04:44 +02:00
parent 93f4bbca32
commit c6d34e7455
27 changed files with 773 additions and 835 deletions

View File

@@ -1,6 +1,6 @@
import 'package:hiddify/core/preferences/preferences_provider.dart';
import 'package:hiddify/features/config_option/data/config_option_repository.dart';
import 'package:hiddify/features/geo_asset/data/geo_asset_data_providers.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'config_option_data_providers.g.dart';
@@ -12,7 +12,5 @@ ConfigOptionRepository configOptionRepository(
return ConfigOptionRepository(
preferences: ref.watch(sharedPreferencesProvider).requireValue,
getConfigOptions: () => ref.read(ConfigOptions.singboxConfigOptions.future),
geoAssetRepository: ref.watch(geoAssetRepositoryProvider).requireValue,
geoAssetPathResolver: ref.watch(geoAssetPathResolverProvider),
);
}

View File

@@ -3,13 +3,12 @@ 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';
import 'package:hiddify/singbox/model/singbox_config_enum.dart';
import 'package:hiddify/singbox/model/singbox_config_option.dart';
@@ -26,6 +25,17 @@ abstract class ConfigOptions {
mapTo: (value) => value.key,
);
static final region = PreferencesNotifier.create<Region, String>(
"region",
Region.other,
mapFrom: Region.values.byName,
mapTo: (value) => value.name,
);
static final blockAds = PreferencesNotifier.create<bool, bool>(
"block-ads",
false,
);
static final logLevel = PreferencesNotifier.create<LogLevel, String>(
"log-level",
LogLevel.warn,
@@ -305,6 +315,8 @@ abstract class ConfigOptions {
};
static final Map<String, StateNotifierProvider<PreferencesNotifier, dynamic>> preferences = {
"region": region,
"block-ads": blockAds,
"service-mode": serviceMode,
"log-level": logLevel,
"resolve-destination": resolveDestination,
@@ -359,44 +371,46 @@ abstract class ConfigOptions {
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 region = ref.watch(Preferences.region);
final rules = <SingboxRule>[];
// 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 mode = ref.watch(serviceMode);
// final reg = ref.watch(Preferences.region.notifier).raw();
return SingboxConfigOption(
region: ref.watch(region).name,
blockAds: ref.watch(blockAds),
executeConfigAsIs: false,
logLevel: ref.watch(logLevel),
resolveDestination: ref.watch(resolveDestination),
@@ -461,14 +475,14 @@ abstract class ConfigOptions {
noise: ref.watch(warpNoise),
noiseDelay: 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,
),
// geoipPath: ref.watch(geoAssetPathResolverProvider).relativePath(
// geoAssets.geoip.providerName,
// geoAssets.geoip.fileName,
// ),
// geositePath: ref.watch(geoAssetPathResolverProvider).relativePath(
// geoAssets.geosite.providerName,
// geoAssets.geosite.fileName,
// ),
rules: rules,
);
},
@@ -479,14 +493,10 @@ class ConfigOptionRepository with ExceptionHandler, InfraLogger {
ConfigOptionRepository({
required this.preferences,
required this.getConfigOptions,
required this.geoAssetRepository,
required this.geoAssetPathResolver,
});
final SharedPreferences preferences;
final Future<SingboxConfigOption> Function() getConfigOptions;
final GeoAssetRepository geoAssetRepository;
final GeoAssetPathResolver geoAssetPathResolver;
TaskEither<ConfigOptionFailure, SingboxConfigOption> getFullSingboxConfigOption() {
return exceptionHandler(

View File

@@ -15,16 +15,13 @@ class ConfigOptionNotifier extends _$ConfigOptionNotifier with AppLogger {
@override
Future<bool> build() async {
final serviceRunning = await ref.watch(serviceRunningProvider.future);
final serviceSingboxOptions =
ref.read(connectionRepositoryProvider).configOptionsSnapshot;
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(milliseconds: 100)) {
if (_lastUpdate == null || DateTime.now().difference(_lastUpdate!) > const Duration(milliseconds: 100)) {
_lastUpdate = DateTime.now();
state = AsyncData(value != serviceSingboxOptions);
}
@@ -63,8 +60,7 @@ class ConfigOptionNotifier extends _$ConfigOptionNotifier with AppLogger {
Future<bool> importFromClipboard() async {
try {
final input =
await Clipboard.getData("text/plain").then((value) => value?.text);
final input = await Clipboard.getData("text/plain").then((value) => value?.text);
if (input == null) return false;
if (jsonDecode(input) case final Map<String, dynamic> map) {
for (final option in ConfigOptions.preferences.entries) {

View File

@@ -4,8 +4,8 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:gap/gap.dart';
import 'package:hiddify/core/localization/translations.dart';
import 'package:hiddify/core/model/optional_range.dart';
import 'package:hiddify/core/model/region.dart';
import 'package:hiddify/core/notification/in_app_notification_controller.dart';
import 'package:hiddify/core/preferences/general_preferences.dart';
import 'package:hiddify/core/widget/adaptive_icon.dart';
import 'package:hiddify/core/widget/tip_card.dart';
import 'package:hiddify/features/common/confirmation_dialogs.dart';
@@ -140,6 +140,18 @@ class ConfigOptionsPage extends HookConsumerWidget {
),
const SettingsDivider(),
SettingsSection(t.config.section.route),
ChoicePreferenceWidget(
selected: ref.watch(ConfigOptions.region),
preferences: ref.watch(ConfigOptions.region.notifier),
choices: Region.values,
title: t.settings.general.region,
presentChoice: (value) => value.present(t),
),
SwitchListTile(
title: Text(experimental(t.config.blockAds)),
value: ref.watch(ConfigOptions.blockAds),
onChanged: ref.watch(ConfigOptions.blockAds.notifier).update,
),
SwitchListTile(
title: Text(experimental(t.config.bypassLan)),
value: ref.watch(ConfigOptions.bypassLan),