Files
Zakaria 1563409cb1
Build / Build for Android (push) Has been cancelled
Build / Build for iOS (push) Has been cancelled
first commit
2026-05-18 14:15:38 -04:00

165 lines
6.7 KiB
Dart

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<ArtistDownloadButton> createState() => _ArtistDownloadButtonState();
}
class _ArtistDownloadButtonState extends State<ArtistDownloadButton> {
static const _disabledButton = IconButton(
icon: Icon(Icons.download),
onPressed: null,
);
Future<List<BaseItemDto>?>? _artistDownloadButtonFuture;
final _jellyfinApiHelper = GetIt.instance<JellyfinApiHelper>();
final _downloadsHelper = GetIt.instance<DownloadsHelper>();
final _finampUserHelper = GetIt.instance<FinampUserHelper>();
List<BaseItemDto> _getUndownloadedAlbums(List<BaseItemDto> albums) {
return albums
.where((element) => !_downloadsHelper.isAlbumDownloaded(element.id))
.toList();
}
@override
Widget build(BuildContext context) {
return ValueListenableBuilder<Box<FinampSettings>>(
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<List<BaseItemDto>?>(
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<Future<List<BaseItemDto>?>> albumInfoFutures = [];
for (var element in undownloadedAlbums) {
albumInfoFutures.add(_jellyfinApiHelper.getItems(
parentItem: element,
sortBy: "SortName",
includeItemTypes: "Audio",
isGenres: false,
));
}
List<List<BaseItemDto>?> 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;
}
},
);
}
},
);
}
}