diff --git a/assets/translations/strings_en.i18n.json b/assets/translations/strings_en.i18n.json index 67830b27..2f35b4f4 100644 --- a/assets/translations/strings_en.i18n.json +++ b/assets/translations/strings_en.i18n.json @@ -242,6 +242,8 @@ }, "geoAssets": { "pageTitle": "Routing Assets", + "geoip": "Geoip", + "geosite": "Geosite", "version": "Version ${version}", "fileMissing": "File Missing", "update": "Update", diff --git a/assets/translations/strings_es.i18n.json b/assets/translations/strings_es.i18n.json index e98c82ef..45782c81 100644 --- a/assets/translations/strings_es.i18n.json +++ b/assets/translations/strings_es.i18n.json @@ -243,7 +243,9 @@ "update": "Actualizar", "download": "Descargar", "failureMsg": "No se pudo actualizar el activo", - "addRecommended": "Agregar activos recomendados" + "addRecommended": "Agregar activos recomendados", + "geoip": "Geoip", + "geosite": "Geosite" }, "pageTitle": "Ajustes", "experimental": "Experimental" diff --git a/assets/translations/strings_fa.i18n.json b/assets/translations/strings_fa.i18n.json index 1b630a5d..2316349f 100644 --- a/assets/translations/strings_fa.i18n.json +++ b/assets/translations/strings_fa.i18n.json @@ -242,6 +242,8 @@ }, "geoAssets": { "pageTitle": "فایل‌های مسیریابی", + "geoip": "Geoip", + "geosite": "Geosite", "version": "نسخه ${version}", "fileMissing": "فایل موجود نیست", "update": "به روز رسانی", diff --git a/assets/translations/strings_ru.i18n.json b/assets/translations/strings_ru.i18n.json index ccfedde7..4a7a533e 100644 --- a/assets/translations/strings_ru.i18n.json +++ b/assets/translations/strings_ru.i18n.json @@ -242,6 +242,8 @@ }, "geoAssets": { "pageTitle": "Активы маршрутизации", + "geoip": "Geoip", + "geosite": "Geosite", "version": "Версия ${version}", "fileMissing": "Файл отсутствует", "update": "Обновить", diff --git a/assets/translations/strings_tr.i18n.json b/assets/translations/strings_tr.i18n.json index 20f06aed..88cc4261 100644 --- a/assets/translations/strings_tr.i18n.json +++ b/assets/translations/strings_tr.i18n.json @@ -242,6 +242,8 @@ }, "geoAssets": { "pageTitle": "Varlıkları Yönlendirme", + "geoip": "Geoip", + "geosite": "Geosite", "version": "Sürüm ${version}", "fileMissing": "Eksik dosya", "update": "Güncelleme", diff --git a/assets/translations/strings_zh-CN.i18n.json b/assets/translations/strings_zh-CN.i18n.json index 0fc56fe2..064bc4c5 100644 --- a/assets/translations/strings_zh-CN.i18n.json +++ b/assets/translations/strings_zh-CN.i18n.json @@ -242,6 +242,8 @@ }, "geoAssets": { "pageTitle": "路由资源文件", + "geoip": "Geoip", + "geosite": "Geosite", "version": "版本 ${version}", "fileMissing": "文件丢失", "update": "更新", diff --git a/lib/features/geo_asset/overview/geo_assets_overview_notifier.dart b/lib/features/geo_asset/overview/geo_assets_overview_notifier.dart index d3ead5b9..be063f77 100644 --- a/lib/features/geo_asset/overview/geo_assets_overview_notifier.dart +++ b/lib/features/geo_asset/overview/geo_assets_overview_notifier.dart @@ -1,3 +1,4 @@ +import 'package:dartx/dartx.dart'; import 'package:hiddify/features/geo_asset/data/geo_asset_data_providers.dart'; import 'package:hiddify/features/geo_asset/data/geo_asset_repository.dart'; import 'package:hiddify/features/geo_asset/model/geo_asset_entity.dart'; @@ -7,17 +8,28 @@ import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'geo_assets_overview_notifier.g.dart'; +typedef GroupedRoutingAssets = ({ + List geoip, + List geosite, +}); + @riverpod class GeoAssetsOverviewNotifier extends _$GeoAssetsOverviewNotifier with AppLogger { @override - Stream> build() { + Stream build() { ref.disposeDelay(const Duration(seconds: 5)); - return ref - .watch(geoAssetRepositoryProvider) - .requireValue - .watchAll() - .map((event) => event.getOrElse((l) => throw l)); + return ref.watch(geoAssetRepositoryProvider).requireValue.watchAll().map( + (event) { + final grouped = event + .getOrElse((l) => throw l) + .groupBy((element) => element.$1.type); + return ( + geoip: grouped.getOrElse(GeoAssetType.geoip, () => []), + geosite: grouped.getOrElse(GeoAssetType.geosite, () => []), + ); + }, + ); } GeoAssetRepository get _geoAssetRepo => diff --git a/lib/features/geo_asset/overview/geo_assets_overview_page.dart b/lib/features/geo_asset/overview/geo_assets_overview_page.dart index 64b5f452..57f9667a 100644 --- a/lib/features/geo_asset/overview/geo_assets_overview_page.dart +++ b/lib/features/geo_asset/overview/geo_assets_overview_page.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:gap/gap.dart'; import 'package:hiddify/core/localization/translations.dart'; import 'package:hiddify/features/geo_asset/overview/geo_assets_overview_notifier.dart'; import 'package:hiddify/features/geo_asset/widget/geo_asset_tile.dart'; @@ -36,11 +37,11 @@ class GeoAssetsOverviewPage extends HookConsumerWidget { ), ], ), - if (state case AsyncData(value: final geoAssets)) + if (state case AsyncData(value: (:final geoip, :final geosite))) SliverPinnedHeader( child: AnimatedSwitcher( duration: const Duration(milliseconds: 200), - child: geoAssets + child: (geoip + geosite) .where((e) => e.$1.active && e.$2 == null) .isNotEmpty ? const MissingRoutingAssetsCard() @@ -48,17 +49,45 @@ class GeoAssetsOverviewPage extends HookConsumerWidget { ), ), switch (state) { - AsyncData(value: final geoAssets) => SliverList.builder( - itemBuilder: (context, index) { - final geoAsset = geoAssets[index]; - return GeoAssetTile( - geoAsset, - onMarkAsActive: () => ref - .read(geoAssetsOverviewNotifierProvider.notifier) - .markAsActive(geoAsset.$1), - ); - }, - itemCount: geoAssets.length, + AsyncData(value: (:final geoip, :final geosite)) => MultiSliver( + children: [ + ListTile( + title: Text("${t.settings.geoAssets.geoip} ›"), + titleTextStyle: Theme.of(context).textTheme.headlineSmall, + dense: true, + ), + SliverList.builder( + itemBuilder: (context, index) { + final geoAsset = geoip[index]; + return GeoAssetTile( + geoAsset, + onMarkAsActive: () => ref + .read(geoAssetsOverviewNotifierProvider.notifier) + .markAsActive(geoAsset.$1), + ); + }, + itemCount: geoip.length, + ), + const Divider(indent: 16, endIndent: 16), + ListTile( + title: Text("${t.settings.geoAssets.geosite} ›"), + titleTextStyle: Theme.of(context).textTheme.headlineSmall, + dense: true, + ), + SliverList.builder( + itemBuilder: (context, index) { + final geoAsset = geosite[index]; + return GeoAssetTile( + geoAsset, + onMarkAsActive: () => ref + .read(geoAssetsOverviewNotifierProvider.notifier) + .markAsActive(geoAsset.$1), + ); + }, + itemCount: geosite.length, + ), + const Gap(16), + ], ), _ => const SliverToBoxAdapter(), },