Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Redesign] Downloads Size Warning + other fixes #1044

Merged
7 changes: 7 additions & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,19 @@ android {
buildTypes {
release {
signingConfig signingConfigs.release
resValue "string", "app_name", "Finamp"
// shrinkResources false
// minifyEnabled false
}
profile {
applicationIdSuffix '.profile'
minifyEnabled true // avoid dexing issues
resValue "string", "app_name", "Finamp Profile"
}
debug {
applicationIdSuffix '.debug'
minifyEnabled true // avoid dexing issues
resValue "string", "app_name", "Finamp Debug"
}
}
namespace 'com.unicornsonlsd.finamp'
Expand Down
2 changes: 1 addition & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
FlutterApplication and put your custom class here. -->
<application
android:name="${applicationName}"
android:label="Finamp"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:appCategory="audio"
android:usesCleartextTraffic="true"
Expand Down
50 changes: 38 additions & 12 deletions lib/components/AlbumScreen/download_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import '../../services/finamp_user_helper.dart';
import '../../services/jellyfin_api_helper.dart';
import '../global_snackbar.dart';

const songWarningCutoff = 150;

class DownloadDialog extends StatefulWidget {
const DownloadDialog._build({
super.key,
Expand All @@ -21,13 +23,15 @@ class DownloadDialog extends StatefulWidget {
required this.downloadLocationId,
required this.needsTranscode,
required this.children,
required this.songCount,
});

final DownloadStub item;
final String viewId;
final String? downloadLocationId;
final bool needsTranscode;
final List<BaseItemDto>? children;
final int? songCount;

@override
State<DownloadDialog> createState() => _DownloadDialogState();
Expand Down Expand Up @@ -65,7 +69,32 @@ class DownloadDialog extends StatefulWidget {
downloadLocation = locations.first.id;
}
}
if (!needTranscode && downloadLocation != null) {

// Fetch children if possible for size and songcount determinations
JellyfinApiHelper jellyfinApiHelper = GetIt.instance<JellyfinApiHelper>();
List<BaseItemDto>? children;
int? songCount;
if (item.baseItemType == BaseItemDtoType.album ||
item.baseItemType == BaseItemDtoType.playlist) {
children = await jellyfinApiHelper.getItems(
parentItem: item.baseItem!,
includeItemTypes: BaseItemDtoType.song.idString,
fields:
"${jellyfinApiHelper.defaultFields},MediaSources,MediaStreams");
songCount = children?.length;
} else if (item.baseItemType == BaseItemDtoType.artist ||
item.baseItemType == BaseItemDtoType.genre) {
children = await jellyfinApiHelper.getItems(
parentItem: item.baseItem!,
includeItemTypes: BaseItemDtoType.album.idString,
);
songCount = children?.fold<int>(
0, (count, item) => count + (item.childCount ?? 0));
}

if (!needTranscode &&
downloadLocation != null &&
(songCount ?? 0) < songWarningCutoff) {
final downloadsService = GetIt.instance<DownloadsService>();
var profile = FinampSettingsHelper
.finampSettings.shouldTranscodeDownloads ==
Expand All @@ -82,16 +111,6 @@ class DownloadDialog extends StatefulWidget {
.then((value) => GlobalSnackbar.message(
(scaffold) => AppLocalizations.of(scaffold)!.downloadsQueued)));
} else {
JellyfinApiHelper jellyfinApiHelper = GetIt.instance<JellyfinApiHelper>();
List<BaseItemDto>? children;
if (item.baseItemType == BaseItemDtoType.album ||
item.baseItemType == BaseItemDtoType.playlist) {
children = await jellyfinApiHelper.getItems(
parentItem: item.baseItem!,
includeItemTypes: "Audio",
fields:
"${jellyfinApiHelper.defaultFields},MediaSources,MediaStreams");
}
if (!context.mounted) return;
await showDialog(
context: context,
Expand All @@ -101,6 +120,7 @@ class DownloadDialog extends StatefulWidget {
downloadLocationId: downloadLocation,
needsTranscode: needTranscode,
children: children,
songCount: songCount,
),
);
}
Expand Down Expand Up @@ -146,7 +166,7 @@ class _DownloadDialogState extends State<DownloadDialog> {
.map((e) => e.mediaSources?.first.mediaStreams.first.codec)
.toSet();

if (formats.length == 1) {
if (formats.length == 1 && formats.first != null) {
originalDescription += " ${formats.first!.toUpperCase()}";
}
}
Expand All @@ -155,6 +175,7 @@ class _DownloadDialogState extends State<DownloadDialog> {
title: Text(AppLocalizations.of(context)!.addDownloads),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (widget.downloadLocationId == null)
DropdownButton<DownloadLocation>(
Expand Down Expand Up @@ -196,6 +217,11 @@ class _DownloadDialogState extends State<DownloadDialog> {
.dontTranscode(originalDescription)),
)
]),
if ((widget.songCount ?? 0) >= songWarningCutoff)
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0),
child: Text(AppLocalizations.of(context)!
.largeDownloadWarning(widget.songCount!)))
],
),
actions: [
Expand Down
10 changes: 5 additions & 5 deletions lib/components/print_duration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ String printDuration(

String twoDigits(int n) => n.toString().padLeft(2, "0");
final minutes = duration.inMinutes.remainder(60);
String twoDigitMinutes =
leadingZeroes ? twoDigits(minutes) : minutes.toString();
String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));

String durationString;
if (duration.inHours >= 1) {
String twoDigitHours = leadingZeroes
String paddedHours = leadingZeroes
? twoDigits(duration.inHours)
: duration.inHours.toString();
durationString = "$twoDigitHours:$twoDigitMinutes:$twoDigitSeconds";
durationString = "$paddedHours:${twoDigits(minutes)}:$twoDigitSeconds";
} else {
durationString = "$twoDigitMinutes:$twoDigitSeconds";
String paddedMinutes =
leadingZeroes ? twoDigits(minutes) : minutes.toString();
durationString = "$paddedMinutes:$twoDigitSeconds";
}

if (isRemaining) {
Expand Down
11 changes: 10 additions & 1 deletion lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@
"@pathReturnSlashErrorMessage": {},
"directoryMustBeEmpty": "Directory must be empty",
"@directoryMustBeEmpty": {},
"customLocationsBuggy": "Custom locations are extremely buggy due to issues with permissions. I'm thinking of ways to fix this, but for now I wouldn't recommend using them.",
"customLocationsBuggy": "Custom locations can be extremely buggy and are not recommended in most cases. Locations under the system 'Music' folder prevent saving album covers due to OS limitations.",
"@customLocationsBuggy": {},
"enterLowPriorityStateOnPause": "Enter Low-Priority State on Pause",
"@enterLowPriorityStateOnPause": {},
Expand Down Expand Up @@ -1835,5 +1835,14 @@
"genericCancel": "Cancel",
"@genericCancel": {
"description": "Used when the user stops an action from taking place inside a popup dialog window"
},
"largeDownloadWarning": "Warning: You are about to download {count} tracks.",
"@largeDownloadWarning": {
"description": "A line of warning text on the download dialog when large numbers of songs are downloaded at once.",
"placeholders": {
"count": {
"type": "int"
}
}
}
}