import 'package:dartx/dartx.dart'; import 'package:flutter/material.dart'; import 'package:hiddify/core/localization/translations.dart'; import 'package:hiddify/core/model/failures.dart'; import 'package:hiddify/core/widget/adaptive_icon.dart'; import 'package:hiddify/features/geo_asset/model/geo_asset_entity.dart'; import 'package:hiddify/features/geo_asset/model/geo_asset_failure.dart'; import 'package:hiddify/features/geo_asset/notifier/geo_asset_notifier.dart'; import 'package:hiddify/utils/utils.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:humanizer/humanizer.dart'; class GeoAssetTile extends HookConsumerWidget { GeoAssetTile( GeoAssetWithFileSize geoAssetWithFileSize, { super.key, required this.onMarkAsActive, }) : geoAsset = geoAssetWithFileSize.$1, size = geoAssetWithFileSize.$2; final GeoAssetEntity geoAsset; final int? size; final VoidCallback onMarkAsActive; @override Widget build(BuildContext context, WidgetRef ref) { final t = ref.watch(translationsProvider); final fetchState = ref.watch(fetchGeoAssetProvider(geoAsset.id)); final fileMissing = size == null; ref.listen( fetchGeoAssetProvider(geoAsset.id), (_, next) { switch (next) { case AsyncError(:final error): if (error case GeoAssetNoUpdateAvailable()) { return CustomToast(t.failure.geoAssets.notUpdate).show(context); } CustomAlertDialog.fromErr(t.presentError(error)).show(context); case AsyncData(value: final _?): CustomToast.success(t.settings.geoAssets.successMsg).show(context); } }, ); return ListTile( title: Text.rich( TextSpan( children: [ TextSpan(text: geoAsset.name), if (geoAsset.providerName.isNotBlank) TextSpan(text: " (${geoAsset.providerName})"), ], ), ), isThreeLine: true, subtitle: fetchState.isLoading ? const LinearProgressIndicator() : Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (geoAsset.version.isNotNullOrBlank) Padding( padding: const EdgeInsetsDirectional.only(end: 8), child: Text( t.settings.geoAssets.version(version: geoAsset.version!), overflow: TextOverflow.ellipsis, ), ) else const SizedBox(), Flexible( child: Text.rich( TextSpan( children: [ if (fileMissing) TextSpan( text: t.settings.geoAssets.fileMissing, style: TextStyle( color: Theme.of(context).colorScheme.error, ), ) else TextSpan(text: size?.bytes().toString()), if (geoAsset.lastCheck != null) ...[ const TextSpan(text: " • "), TextSpan(text: geoAsset.lastCheck!.format()), ], ], ), overflow: TextOverflow.ellipsis, ), ), ], ), selected: geoAsset.active, onTap: onMarkAsActive, trailing: PopupMenuButton( icon: Icon(AdaptiveIcon(context).more), itemBuilder: (context) { return [ PopupMenuItem( enabled: !fetchState.isLoading, onTap: () => ref .read(FetchGeoAssetProvider(geoAsset.id).notifier) .fetch(geoAsset), child: fileMissing ? Text(t.settings.geoAssets.download) : Text(t.settings.geoAssets.update), ), ]; }, ), ); } }