Fladder/lib/screens/syncing/widgets/sync_options_button.dart
2025-07-27 10:54:29 +02:00

139 lines
4.8 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:background_downloader/background_downloader.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:iconsax_plus/iconsax_plus.dart';
import 'package:fladder/models/syncing/sync_item.dart';
import 'package:fladder/providers/sync/sync_provider_helpers.dart';
import 'package:fladder/providers/sync_provider.dart';
import 'package:fladder/util/localization_helper.dart';
import 'package:fladder/util/refresh_state.dart';
import 'package:fladder/widgets/shared/filled_button_await.dart';
class SyncOptionsButton extends ConsumerWidget {
final SyncedItem syncedItem;
final List<SyncedItem> children;
const SyncOptionsButton({
required this.syncedItem,
required this.children,
super.key,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
return PopupMenuButton(
itemBuilder: (context) {
final unSyncedChildren = children.where((element) {
final hasDownload = ref.read(syncDownloadStatusProvider(element, []));
return element.hasVideoFile && !element.videoFile.existsSync() && hasDownload?.status == TaskStatus.notFound;
}).toList();
final syncedChildren =
children.where((element) => element.hasVideoFile && element.videoFile.existsSync()).toList();
return [
PopupMenuItem(
child: Row(
spacing: 12,
children: [
const Icon(IconsaxPlusLinear.refresh_2),
Text(context.localized.refreshMetadata),
],
),
onTap: () => context.refreshData(),
),
if (children.isNotEmpty) ...[
PopupMenuItem(
enabled: unSyncedChildren.isNotEmpty,
child: Row(
spacing: 12,
children: [
const Icon(IconsaxPlusLinear.cloud_add),
Text(context.localized.sync),
],
),
onTap: () async => _syncRemainingItems(context, syncedItem, unSyncedChildren, ref),
),
PopupMenuItem(
enabled: syncedChildren.isNotEmpty,
child: Row(
spacing: 12,
children: [
const Icon(IconsaxPlusLinear.trash),
Text(context.localized.delete),
],
),
onTap: () async => _deleteSyncedItems(context, syncedItem, syncedChildren, ref),
)
]
];
},
);
}
}
Future<dynamic> _deleteSyncedItems(
BuildContext context, SyncedItem syncedItem, List<SyncedItem> syncedChildren, WidgetRef ref) {
return showDialog(
context: context,
barrierDismissible: false,
builder: (context) => AlertDialog(
title: Text(context.localized.syncDeleteAllItemsTitle(syncedItem.itemModel?.name ?? "")),
content: Text(
context.localized.syncDeleteAllItemsDesc(syncedItem.itemModel?.name ?? "", syncedChildren.length),
),
scrollable: true,
actions: [
ElevatedButton(onPressed: () => Navigator.of(context).pop(), child: Text(context.localized.cancel)),
FilledButtonAwait(
style: FilledButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.errorContainer,
foregroundColor: Theme.of(context).colorScheme.onErrorContainer,
iconColor: Theme.of(context).colorScheme.onErrorContainer,
),
onPressed: () async {
final deleteList = syncedChildren.map((e) => ref.read(syncProvider.notifier).deleteFullSyncFiles(e, null));
await Future.wait(deleteList);
Navigator.of(context).pop();
},
child: Text(
context.localized.delete,
),
)
],
),
);
}
Future<dynamic> _syncRemainingItems(
BuildContext context, SyncedItem syncedItem, List<SyncedItem> unSyncedChildren, WidgetRef ref) {
return showDialog(
context: context,
barrierDismissible: false,
builder: (context) => AlertDialog(
title: Text(context.localized.syncAllItemsTitle(syncedItem.itemModel?.name ?? "")),
content: Text(
context.localized.syncAllItemsDesc(
syncedItem.itemModel?.name ?? "",
unSyncedChildren.length,
),
),
scrollable: true,
actions: [
ElevatedButton(onPressed: () => Navigator.of(context).pop(), child: Text(context.localized.cancel)),
FilledButtonAwait(
onPressed: () async {
final syncList = unSyncedChildren.map((e) => ref.read(syncProvider.notifier).syncFile(e, false));
await Future.wait(syncList);
Navigator.of(context).pop();
},
child: Text(
context.localized.sync,
),
)
],
),
);
}