import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:get_it/get_it.dart'; import 'package:hive/hive.dart'; import '../../models/jellyfin_models.dart'; import '../../models/finamp_models.dart'; import '../../services/finamp_settings_helper.dart'; import '../../services/finamp_user_helper.dart'; import '../../services/jellyfin_api_helper.dart'; import '../../services/downloads_helper.dart'; import '../AlbumScreen/download_dialog.dart'; import '../confirmation_prompt_dialog.dart'; import '../error_snackbar.dart'; class ArtistDownloadButton extends StatefulWidget { const ArtistDownloadButton({ Key? key, required this.artist, }) : super(key: key); final BaseItemDto artist; @override State createState() => _ArtistDownloadButtonState(); } class _ArtistDownloadButtonState extends State { static const _disabledButton = IconButton( icon: Icon(Icons.download), onPressed: null, ); Future?>? _artistDownloadButtonFuture; final _jellyfinApiHelper = GetIt.instance(); final _downloadsHelper = GetIt.instance(); final _finampUserHelper = GetIt.instance(); List _getUndownloadedAlbums(List albums) { return albums .where((element) => !_downloadsHelper.isAlbumDownloaded(element.id)) .toList(); } @override Widget build(BuildContext context) { return ValueListenableBuilder>( valueListenable: FinampSettingsHelper.finampSettingsListener, builder: (context, box, _) { final isOffline = box.get("FinampSettings")?.isOffline ?? false; bool deleteAlbums = false; if (isOffline) { return _disabledButton; } else { // We only want to get album data if we're online _artistDownloadButtonFuture ??= _jellyfinApiHelper.getItems( parentItem: widget.artist, includeItemTypes: "MusicAlbum", isGenres: false, ); return FutureBuilder?>( future: _artistDownloadButtonFuture, builder: (context, snapshot) { if (snapshot.hasData) { final undownloadedAlbums = _getUndownloadedAlbums(snapshot.data!); deleteAlbums = undownloadedAlbums.isEmpty; return IconButton( tooltip: AppLocalizations.of(context)! .downloadArtist(widget.artist.name ?? "Unknown Artist"), icon: deleteAlbums ? const Icon(Icons.delete) : const Icon(Icons.download), onPressed:() async { if (deleteAlbums) { showDialog( context: context, builder: (context) => ConfirmationPromptDialog( promptText: AppLocalizations.of(context)! .deleteDownloadsPrompt( widget.artist.name ?? "", widget.artist.type == "MusicArtist" ? "artist" : "genre"), confirmButtonText: AppLocalizations.of(context)! .deleteDownloadsConfirmButtonText, abortButtonText: AppLocalizations.of(context)! .deleteDownloadsAbortButtonText, onConfirmed: () async { try { final deleteFutures = snapshot.data!.map((e) => _downloadsHelper.deleteParentAndChildDownloads( jellyfinItemIds: _downloadsHelper .getDownloadedParent(e.id)! .downloadedChildren .keys .toList(), deletedFor: e.id)); await Future.wait(deleteFutures); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text("Downloads deleted."))); final undownloadedAlbums = _getUndownloadedAlbums(snapshot.data!); setState(() { deleteAlbums = undownloadedAlbums.isEmpty; }); } catch (error) { errorSnackbar(error, context); } }, onAborted: () {}, ), ); } else { List?>> albumInfoFutures = []; for (var element in undownloadedAlbums) { albumInfoFutures.add(_jellyfinApiHelper.getItems( parentItem: element, sortBy: "SortName", includeItemTypes: "Audio", isGenres: false, )); } List?> albumInfo; try { albumInfo = await Future.wait(albumInfoFutures); } catch (e) { errorSnackbar(e, context); return; } await showDialog( context: context, builder: (context) => DownloadDialog( parents: undownloadedAlbums, // getItems returns null so we have to null check // each element items: albumInfo.map((e) => e!).toList(), viewId: _finampUserHelper.currentUser!.currentViewId!, ), ); } // We call a setState so that the downloaded albums are // checked again (so that the download icon turns into a // delete icon and vice-versa) setState(() {}); }, ); } else if (snapshot.hasError) { errorSnackbar(snapshot.error, context); return _disabledButton; } else { return _disabledButton; } }, ); } }, ); } }