mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-08-17 08:30:33 +02:00
fix: sync download progress notification states
This commit is contained in:
@@ -5818,9 +5818,27 @@ abstract class AppLocalizations {
|
||||
/// Notification body for queue complete - how many tracks were downloaded
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{count} tracks downloaded successfully'**
|
||||
/// **'{count, plural, =1{1 track downloaded successfully} other{{count} tracks downloaded successfully}}'**
|
||||
String notifTracksDownloadedSuccess(int count);
|
||||
|
||||
/// Notification body when queue finishes with failures
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{completed, plural, =1{1 track downloaded} other{{completed} tracks downloaded}}, {failed, plural, =1{1 failed} other{{failed} failed}}'**
|
||||
String notifDownloadsFinishedBody(int completed, int failed);
|
||||
|
||||
/// Notification title when downloads are canceled by the user
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Downloads canceled'**
|
||||
String get notifDownloadsCanceledTitle;
|
||||
|
||||
/// Notification body when downloads are canceled by the user
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{count, plural, =1{1 download canceled by user} other{{count} downloads canceled by user}}'**
|
||||
String notifDownloadsCanceledBody(int count);
|
||||
|
||||
/// Notification title while scanning local library
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
||||
@@ -3448,6 +3448,37 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifDownloadsFinishedBody(int completed, int failed) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
completed,
|
||||
locale: localeName,
|
||||
other: '$completed tracks downloaded',
|
||||
one: '1 track downloaded',
|
||||
);
|
||||
String _temp1 = intl.Intl.pluralLogic(
|
||||
failed,
|
||||
locale: localeName,
|
||||
other: '$failed failed',
|
||||
one: '1 failed',
|
||||
);
|
||||
return '$_temp0, $_temp1';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadsCanceledTitle => 'Downloads canceled';
|
||||
|
||||
@override
|
||||
String notifDownloadsCanceledBody(int count) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
count,
|
||||
locale: localeName,
|
||||
other: '$count downloads canceled by user',
|
||||
one: '1 download canceled by user',
|
||||
);
|
||||
return '$_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
|
||||
@@ -3410,7 +3410,44 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String notifTracksDownloadedSuccess(int count) {
|
||||
return '$count tracks downloaded successfully';
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
count,
|
||||
locale: localeName,
|
||||
other: '$count tracks downloaded successfully',
|
||||
one: '1 track downloaded successfully',
|
||||
);
|
||||
return '$_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifDownloadsFinishedBody(int completed, int failed) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
completed,
|
||||
locale: localeName,
|
||||
other: '$completed tracks downloaded',
|
||||
one: '1 track downloaded',
|
||||
);
|
||||
String _temp1 = intl.Intl.pluralLogic(
|
||||
failed,
|
||||
locale: localeName,
|
||||
other: '$failed failed',
|
||||
one: '1 failed',
|
||||
);
|
||||
return '$_temp0, $_temp1';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadsCanceledTitle => 'Downloads canceled';
|
||||
|
||||
@override
|
||||
String notifDownloadsCanceledBody(int count) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
count,
|
||||
locale: localeName,
|
||||
other: '$count downloads canceled by user',
|
||||
one: '1 download canceled by user',
|
||||
);
|
||||
return '$_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -3413,6 +3413,37 @@ class AppLocalizationsEs extends AppLocalizations {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifDownloadsFinishedBody(int completed, int failed) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
completed,
|
||||
locale: localeName,
|
||||
other: '$completed tracks downloaded',
|
||||
one: '1 track downloaded',
|
||||
);
|
||||
String _temp1 = intl.Intl.pluralLogic(
|
||||
failed,
|
||||
locale: localeName,
|
||||
other: '$failed failed',
|
||||
one: '1 failed',
|
||||
);
|
||||
return '$_temp0, $_temp1';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadsCanceledTitle => 'Downloads canceled';
|
||||
|
||||
@override
|
||||
String notifDownloadsCanceledBody(int count) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
count,
|
||||
locale: localeName,
|
||||
other: '$count downloads canceled by user',
|
||||
one: '1 download canceled by user',
|
||||
);
|
||||
return '$_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
|
||||
@@ -3417,6 +3417,37 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifDownloadsFinishedBody(int completed, int failed) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
completed,
|
||||
locale: localeName,
|
||||
other: '$completed tracks downloaded',
|
||||
one: '1 track downloaded',
|
||||
);
|
||||
String _temp1 = intl.Intl.pluralLogic(
|
||||
failed,
|
||||
locale: localeName,
|
||||
other: '$failed failed',
|
||||
one: '1 failed',
|
||||
);
|
||||
return '$_temp0, $_temp1';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadsCanceledTitle => 'Downloads canceled';
|
||||
|
||||
@override
|
||||
String notifDownloadsCanceledBody(int count) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
count,
|
||||
locale: localeName,
|
||||
other: '$count downloads canceled by user',
|
||||
one: '1 download canceled by user',
|
||||
);
|
||||
return '$_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
|
||||
@@ -3414,6 +3414,37 @@ class AppLocalizationsHi extends AppLocalizations {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifDownloadsFinishedBody(int completed, int failed) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
completed,
|
||||
locale: localeName,
|
||||
other: '$completed tracks downloaded',
|
||||
one: '1 track downloaded',
|
||||
);
|
||||
String _temp1 = intl.Intl.pluralLogic(
|
||||
failed,
|
||||
locale: localeName,
|
||||
other: '$failed failed',
|
||||
one: '1 failed',
|
||||
);
|
||||
return '$_temp0, $_temp1';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadsCanceledTitle => 'Downloads canceled';
|
||||
|
||||
@override
|
||||
String notifDownloadsCanceledBody(int count) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
count,
|
||||
locale: localeName,
|
||||
other: '$count downloads canceled by user',
|
||||
one: '1 download canceled by user',
|
||||
);
|
||||
return '$_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
|
||||
@@ -3412,15 +3412,28 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String notifDownloadsFinished(int completed, int failed) {
|
||||
return 'Downloads Finished ($completed done, $failed failed)';
|
||||
return 'Unduhan Selesai ($completed selesai, $failed gagal)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAllDownloadsComplete => 'All Downloads Complete';
|
||||
String get notifAllDownloadsComplete => 'Semua Unduhan Selesai';
|
||||
|
||||
@override
|
||||
String notifTracksDownloadedSuccess(int count) {
|
||||
return '$count tracks downloaded successfully';
|
||||
return '$count lagu berhasil diunduh';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifDownloadsFinishedBody(int completed, int failed) {
|
||||
return '$completed lagu diunduh, $failed gagal';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadsCanceledTitle => 'Unduhan dibatalkan';
|
||||
|
||||
@override
|
||||
String notifDownloadsCanceledBody(int count) {
|
||||
return '$count unduhan dibatalkan oleh pengguna';
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -3401,6 +3401,37 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifDownloadsFinishedBody(int completed, int failed) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
completed,
|
||||
locale: localeName,
|
||||
other: '$completed tracks downloaded',
|
||||
one: '1 track downloaded',
|
||||
);
|
||||
String _temp1 = intl.Intl.pluralLogic(
|
||||
failed,
|
||||
locale: localeName,
|
||||
other: '$failed failed',
|
||||
one: '1 failed',
|
||||
);
|
||||
return '$_temp0, $_temp1';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadsCanceledTitle => 'Downloads canceled';
|
||||
|
||||
@override
|
||||
String notifDownloadsCanceledBody(int count) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
count,
|
||||
locale: localeName,
|
||||
other: '$count downloads canceled by user',
|
||||
one: '1 download canceled by user',
|
||||
);
|
||||
return '$_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
|
||||
@@ -3394,6 +3394,37 @@ class AppLocalizationsKo extends AppLocalizations {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifDownloadsFinishedBody(int completed, int failed) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
completed,
|
||||
locale: localeName,
|
||||
other: '$completed tracks downloaded',
|
||||
one: '1 track downloaded',
|
||||
);
|
||||
String _temp1 = intl.Intl.pluralLogic(
|
||||
failed,
|
||||
locale: localeName,
|
||||
other: '$failed failed',
|
||||
one: '1 failed',
|
||||
);
|
||||
return '$_temp0, $_temp1';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadsCanceledTitle => 'Downloads canceled';
|
||||
|
||||
@override
|
||||
String notifDownloadsCanceledBody(int count) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
count,
|
||||
locale: localeName,
|
||||
other: '$count downloads canceled by user',
|
||||
one: '1 download canceled by user',
|
||||
);
|
||||
return '$_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
|
||||
@@ -3414,6 +3414,37 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifDownloadsFinishedBody(int completed, int failed) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
completed,
|
||||
locale: localeName,
|
||||
other: '$completed tracks downloaded',
|
||||
one: '1 track downloaded',
|
||||
);
|
||||
String _temp1 = intl.Intl.pluralLogic(
|
||||
failed,
|
||||
locale: localeName,
|
||||
other: '$failed failed',
|
||||
one: '1 failed',
|
||||
);
|
||||
return '$_temp0, $_temp1';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadsCanceledTitle => 'Downloads canceled';
|
||||
|
||||
@override
|
||||
String notifDownloadsCanceledBody(int count) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
count,
|
||||
locale: localeName,
|
||||
other: '$count downloads canceled by user',
|
||||
one: '1 download canceled by user',
|
||||
);
|
||||
return '$_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
|
||||
@@ -3413,6 +3413,37 @@ class AppLocalizationsPt extends AppLocalizations {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifDownloadsFinishedBody(int completed, int failed) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
completed,
|
||||
locale: localeName,
|
||||
other: '$completed tracks downloaded',
|
||||
one: '1 track downloaded',
|
||||
);
|
||||
String _temp1 = intl.Intl.pluralLogic(
|
||||
failed,
|
||||
locale: localeName,
|
||||
other: '$failed failed',
|
||||
one: '1 failed',
|
||||
);
|
||||
return '$_temp0, $_temp1';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadsCanceledTitle => 'Downloads canceled';
|
||||
|
||||
@override
|
||||
String notifDownloadsCanceledBody(int count) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
count,
|
||||
locale: localeName,
|
||||
other: '$count downloads canceled by user',
|
||||
one: '1 download canceled by user',
|
||||
);
|
||||
return '$_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
|
||||
@@ -3473,6 +3473,37 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifDownloadsFinishedBody(int completed, int failed) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
completed,
|
||||
locale: localeName,
|
||||
other: '$completed tracks downloaded',
|
||||
one: '1 track downloaded',
|
||||
);
|
||||
String _temp1 = intl.Intl.pluralLogic(
|
||||
failed,
|
||||
locale: localeName,
|
||||
other: '$failed failed',
|
||||
one: '1 failed',
|
||||
);
|
||||
return '$_temp0, $_temp1';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadsCanceledTitle => 'Downloads canceled';
|
||||
|
||||
@override
|
||||
String notifDownloadsCanceledBody(int count) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
count,
|
||||
locale: localeName,
|
||||
other: '$count downloads canceled by user',
|
||||
one: '1 download canceled by user',
|
||||
);
|
||||
return '$_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
|
||||
@@ -3440,6 +3440,37 @@ class AppLocalizationsTr extends AppLocalizations {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifDownloadsFinishedBody(int completed, int failed) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
completed,
|
||||
locale: localeName,
|
||||
other: '$completed tracks downloaded',
|
||||
one: '1 track downloaded',
|
||||
);
|
||||
String _temp1 = intl.Intl.pluralLogic(
|
||||
failed,
|
||||
locale: localeName,
|
||||
other: '$failed failed',
|
||||
one: '1 failed',
|
||||
);
|
||||
return '$_temp0, $_temp1';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadsCanceledTitle => 'Downloads canceled';
|
||||
|
||||
@override
|
||||
String notifDownloadsCanceledBody(int count) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
count,
|
||||
locale: localeName,
|
||||
other: '$count downloads canceled by user',
|
||||
one: '1 download canceled by user',
|
||||
);
|
||||
return '$_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
|
||||
@@ -3473,6 +3473,37 @@ class AppLocalizationsUk extends AppLocalizations {
|
||||
return '$count треки успішно завантажено';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifDownloadsFinishedBody(int completed, int failed) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
completed,
|
||||
locale: localeName,
|
||||
other: '$completed tracks downloaded',
|
||||
one: '1 track downloaded',
|
||||
);
|
||||
String _temp1 = intl.Intl.pluralLogic(
|
||||
failed,
|
||||
locale: localeName,
|
||||
other: '$failed failed',
|
||||
one: '1 failed',
|
||||
);
|
||||
return '$_temp0, $_temp1';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadsCanceledTitle => 'Downloads canceled';
|
||||
|
||||
@override
|
||||
String notifDownloadsCanceledBody(int count) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
count,
|
||||
locale: localeName,
|
||||
other: '$count downloads canceled by user',
|
||||
one: '1 download canceled by user',
|
||||
);
|
||||
return '$_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Сканування локальної бібліотеки';
|
||||
|
||||
|
||||
@@ -3413,6 +3413,37 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifDownloadsFinishedBody(int completed, int failed) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
completed,
|
||||
locale: localeName,
|
||||
other: '$completed tracks downloaded',
|
||||
one: '1 track downloaded',
|
||||
);
|
||||
String _temp1 = intl.Intl.pluralLogic(
|
||||
failed,
|
||||
locale: localeName,
|
||||
other: '$failed failed',
|
||||
one: '1 failed',
|
||||
);
|
||||
return '$_temp0, $_temp1';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadsCanceledTitle => 'Downloads canceled';
|
||||
|
||||
@override
|
||||
String notifDownloadsCanceledBody(int count) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
count,
|
||||
locale: localeName,
|
||||
other: '$count downloads canceled by user',
|
||||
one: '1 download canceled by user',
|
||||
);
|
||||
return '$_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
|
||||
+26
-1
@@ -4465,7 +4465,7 @@
|
||||
"@notifAllDownloadsComplete": {
|
||||
"description": "Notification title when all downloads finish successfully"
|
||||
},
|
||||
"notifTracksDownloadedSuccess": "{count} tracks downloaded successfully",
|
||||
"notifTracksDownloadedSuccess": "{count, plural, =1{1 track downloaded successfully} other{{count} tracks downloaded successfully}}",
|
||||
"@notifTracksDownloadedSuccess": {
|
||||
"description": "Notification body for queue complete - how many tracks were downloaded",
|
||||
"placeholders": {
|
||||
@@ -4474,6 +4474,31 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifDownloadsFinishedBody": "{completed, plural, =1{1 track downloaded} other{{completed} tracks downloaded}}, {failed, plural, =1{1 failed} other{{failed} failed}}",
|
||||
"@notifDownloadsFinishedBody": {
|
||||
"description": "Notification body when queue finishes with failures",
|
||||
"placeholders": {
|
||||
"completed": {
|
||||
"type": "int"
|
||||
},
|
||||
"failed": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifDownloadsCanceledTitle": "Downloads canceled",
|
||||
"@notifDownloadsCanceledTitle": {
|
||||
"description": "Notification title when downloads are canceled by the user"
|
||||
},
|
||||
"notifDownloadsCanceledBody": "{count, plural, =1{1 download canceled by user} other{{count} downloads canceled by user}}",
|
||||
"@notifDownloadsCanceledBody": {
|
||||
"description": "Notification body when downloads are canceled by the user",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifScanningLibrary": "Scanning local library",
|
||||
"@notifScanningLibrary": {
|
||||
"description": "Notification title while scanning local library"
|
||||
|
||||
+28
-3
@@ -4366,7 +4366,7 @@
|
||||
"@notifDownloadComplete": {
|
||||
"description": "Notification title when a single download is complete"
|
||||
},
|
||||
"notifDownloadsFinished": "Downloads Finished ({completed} done, {failed} failed)",
|
||||
"notifDownloadsFinished": "Unduhan Selesai ({completed} selesai, {failed} gagal)",
|
||||
"@notifDownloadsFinished": {
|
||||
"description": "Notification title when queue finishes with some failures",
|
||||
"placeholders": {
|
||||
@@ -4378,11 +4378,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifAllDownloadsComplete": "All Downloads Complete",
|
||||
"notifAllDownloadsComplete": "Semua Unduhan Selesai",
|
||||
"@notifAllDownloadsComplete": {
|
||||
"description": "Notification title when all downloads finish successfully"
|
||||
},
|
||||
"notifTracksDownloadedSuccess": "{count} tracks downloaded successfully",
|
||||
"notifTracksDownloadedSuccess": "{count} lagu berhasil diunduh",
|
||||
"@notifTracksDownloadedSuccess": {
|
||||
"description": "Notification body for queue complete - how many tracks were downloaded",
|
||||
"placeholders": {
|
||||
@@ -4391,6 +4391,31 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifDownloadsFinishedBody": "{completed} lagu diunduh, {failed} gagal",
|
||||
"@notifDownloadsFinishedBody": {
|
||||
"description": "Notification body when queue finishes with failures",
|
||||
"placeholders": {
|
||||
"completed": {
|
||||
"type": "int"
|
||||
},
|
||||
"failed": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifDownloadsCanceledTitle": "Unduhan dibatalkan",
|
||||
"@notifDownloadsCanceledTitle": {
|
||||
"description": "Notification title when downloads are canceled by the user"
|
||||
},
|
||||
"notifDownloadsCanceledBody": "{count} unduhan dibatalkan oleh pengguna",
|
||||
"@notifDownloadsCanceledBody": {
|
||||
"description": "Notification body when downloads are canceled by the user",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifScanningLibrary": "Scanning local library",
|
||||
"@notifScanningLibrary": {
|
||||
"description": "Notification title while scanning local library"
|
||||
|
||||
@@ -1354,6 +1354,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
bool _networkPausedByWifiOnly = false;
|
||||
String? _lastServiceTrackName;
|
||||
String? _lastServiceArtistName;
|
||||
String? _lastServiceStatus;
|
||||
int _lastServicePercent = -1;
|
||||
int _lastServiceQueueCount = -1;
|
||||
DateTime _lastServiceUpdateAt = DateTime.fromMillisecondsSinceEpoch(0);
|
||||
@@ -1672,6 +1673,9 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
int queuedCount = 0;
|
||||
int downloadingCount = 0;
|
||||
DownloadItem? firstDownloading;
|
||||
bool hasFinalizingItem = false;
|
||||
String? finalizingTrackName;
|
||||
String? finalizingArtistName;
|
||||
for (int i = 0; i < currentItems.length; i++) {
|
||||
final item = currentItems[i];
|
||||
if (item.status == DownloadStatus.downloading) {
|
||||
@@ -1679,16 +1683,18 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
firstDownloading ??= item;
|
||||
}
|
||||
if (item.status == DownloadStatus.queued ||
|
||||
item.status == DownloadStatus.downloading) {
|
||||
item.status == DownloadStatus.downloading ||
|
||||
item.status == DownloadStatus.finalizing) {
|
||||
queuedCount++;
|
||||
}
|
||||
if (item.status == DownloadStatus.finalizing && !hasFinalizingItem) {
|
||||
hasFinalizingItem = true;
|
||||
finalizingTrackName = item.track.name;
|
||||
finalizingArtistName = item.track.artistName;
|
||||
}
|
||||
}
|
||||
final progressUpdates = <String, _ProgressUpdate>{};
|
||||
|
||||
bool hasFinalizingItem = false;
|
||||
String? finalizingTrackName;
|
||||
String? finalizingArtistName;
|
||||
|
||||
for (final entry in items.entries) {
|
||||
final itemId = entry.key;
|
||||
final localItem = lookup.byItemId[itemId];
|
||||
@@ -1707,6 +1713,13 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
localItem.status == DownloadStatus.failed) {
|
||||
continue;
|
||||
}
|
||||
if (localItem.status == DownloadStatus.finalizing) {
|
||||
PlatformBridge.clearItemProgress(itemId).catchError((_) {});
|
||||
hasFinalizingItem = true;
|
||||
finalizingTrackName = localItem.track.name;
|
||||
finalizingArtistName = localItem.track.artistName;
|
||||
continue;
|
||||
}
|
||||
final rawItemProgress = entry.value;
|
||||
if (rawItemProgress is! Map) {
|
||||
continue;
|
||||
@@ -1718,6 +1731,10 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
final speedMBps = (itemProgress['speed_mbps'] as num?)?.toDouble() ?? 0.0;
|
||||
final isDownloading = itemProgress['is_downloading'] as bool? ?? false;
|
||||
final status = itemProgress['status'] as String? ?? 'downloading';
|
||||
final progressFromBackend =
|
||||
(itemProgress['progress'] as num?)?.toDouble() ?? 0.0;
|
||||
final hasRealProgress =
|
||||
bytesReceived > 0 || bytesTotal > 0 || progressFromBackend > 0;
|
||||
|
||||
if (status == 'finalizing') {
|
||||
progressUpdates[itemId] = const _ProgressUpdate(
|
||||
@@ -1730,7 +1747,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (status == 'preparing') {
|
||||
if (status == 'preparing' && !hasRealProgress) {
|
||||
progressUpdates[itemId] = const _ProgressUpdate(
|
||||
status: DownloadStatus.downloading,
|
||||
progress: 0.0,
|
||||
@@ -1745,10 +1762,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
continue;
|
||||
}
|
||||
|
||||
final progressFromBackend =
|
||||
(itemProgress['progress'] as num?)?.toDouble() ?? 0.0;
|
||||
|
||||
if (isDownloading) {
|
||||
if (isDownloading || hasRealProgress) {
|
||||
double percentage = 0.0;
|
||||
if (bytesTotal > 0) {
|
||||
percentage = bytesReceived / bytesTotal;
|
||||
@@ -1798,6 +1812,10 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
continue;
|
||||
}
|
||||
final update = entry.value;
|
||||
if (current.status == DownloadStatus.finalizing &&
|
||||
update.status != DownloadStatus.finalizing) {
|
||||
continue;
|
||||
}
|
||||
final next = current.copyWith(
|
||||
status: update.status,
|
||||
progress: update.progress,
|
||||
@@ -1833,7 +1851,16 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
|
||||
if (hasFinalizingItem && finalizingTrackName != null) {
|
||||
final safeArtistName = finalizingArtistName ?? '';
|
||||
if (finalizingTrackName != _lastFinalizingTrackName ||
|
||||
if (Platform.isAndroid) {
|
||||
_maybeUpdateAndroidDownloadService(
|
||||
trackName: finalizingTrackName,
|
||||
artistName: _notificationService.embeddingMetadataLabel,
|
||||
progress: 100,
|
||||
total: 100,
|
||||
queueCount: queuedCount,
|
||||
status: 'finalizing',
|
||||
);
|
||||
} else if (finalizingTrackName != _lastFinalizingTrackName ||
|
||||
safeArtistName != _lastFinalizingArtistName) {
|
||||
_notificationService.showDownloadFinalizing(
|
||||
trackName: finalizingTrackName,
|
||||
@@ -1848,18 +1875,18 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
_lastFinalizingArtistName = null;
|
||||
|
||||
if (items.isNotEmpty) {
|
||||
final firstEntry = items.entries.first;
|
||||
final rawFirstProgress = firstEntry.value;
|
||||
if (rawFirstProgress is! Map) {
|
||||
return;
|
||||
}
|
||||
final firstProgress = Map<String, dynamic>.from(rawFirstProgress);
|
||||
final bytesReceived =
|
||||
(firstProgress['bytes_received'] as num?)?.toInt() ?? 0;
|
||||
final bytesTotal = (firstProgress['bytes_total'] as num?)?.toInt() ?? 0;
|
||||
final backendStatus = firstProgress['status'] as String? ?? 'downloading';
|
||||
|
||||
if (downloadingCount > 0 && firstDownloading != null) {
|
||||
final rawProgress = items[firstDownloading.id];
|
||||
if (rawProgress is! Map) {
|
||||
return;
|
||||
}
|
||||
final selectedProgress = Map<String, dynamic>.from(rawProgress);
|
||||
final bytesReceived =
|
||||
(selectedProgress['bytes_received'] as num?)?.toInt() ?? 0;
|
||||
final bytesTotal =
|
||||
(selectedProgress['bytes_total'] as num?)?.toInt() ?? 0;
|
||||
final backendStatus =
|
||||
selectedProgress['status'] as String? ?? 'downloading';
|
||||
final trackName = downloadingCount == 1
|
||||
? firstDownloading.track.name
|
||||
: '$downloadingCount downloads';
|
||||
@@ -1870,24 +1897,29 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
int notifProgress = bytesReceived;
|
||||
int notifTotal = bytesTotal;
|
||||
|
||||
if (backendStatus == 'preparing') {
|
||||
final progressPercent =
|
||||
(selectedProgress['progress'] as num?)?.toDouble() ?? 0.0;
|
||||
final hasRealProgress =
|
||||
bytesReceived > 0 || bytesTotal > 0 || progressPercent > 0;
|
||||
|
||||
if (backendStatus == 'preparing' && !hasRealProgress) {
|
||||
notifProgress = 0;
|
||||
notifTotal = 100;
|
||||
notifTotal = 0;
|
||||
} else if (bytesTotal <= 0) {
|
||||
final progressPercent =
|
||||
(firstProgress['progress'] as num?)?.toDouble() ?? 0.0;
|
||||
notifProgress = (progressPercent * 100).toInt();
|
||||
notifTotal = 100;
|
||||
}
|
||||
final serviceStatus = notifTotal <= 0 ? 'preparing' : 'downloading';
|
||||
|
||||
final safeNotifTotal = notifTotal > 0 ? notifTotal : 1;
|
||||
if (_shouldUpdateProgressNotification(
|
||||
trackName: trackName,
|
||||
artistName: artistName,
|
||||
progress: notifProgress,
|
||||
total: safeNotifTotal,
|
||||
queueCount: queuedCount,
|
||||
)) {
|
||||
if (!Platform.isAndroid &&
|
||||
_shouldUpdateProgressNotification(
|
||||
trackName: trackName,
|
||||
artistName: artistName,
|
||||
progress: notifProgress,
|
||||
total: notifTotal,
|
||||
queueCount: queuedCount,
|
||||
)) {
|
||||
final safeNotifTotal = notifTotal > 0 ? notifTotal : 1;
|
||||
_notificationService.showDownloadProgress(
|
||||
trackName: trackName,
|
||||
artistName: artistName,
|
||||
@@ -1901,8 +1933,9 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
trackName: firstDownloading.track.name,
|
||||
artistName: firstDownloading.track.artistName,
|
||||
progress: notifProgress,
|
||||
total: safeNotifTotal,
|
||||
total: notifTotal,
|
||||
queueCount: queuedCount,
|
||||
status: serviceStatus,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1915,22 +1948,28 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
required int progress,
|
||||
required int total,
|
||||
required int queueCount,
|
||||
String status = 'downloading',
|
||||
}) {
|
||||
final now = DateTime.now();
|
||||
final safeTotal = total > 0 ? total : 1;
|
||||
final progressPercent = ((progress * 100) / safeTotal)
|
||||
.round()
|
||||
.clamp(0, 100)
|
||||
.toInt();
|
||||
final progressBucket = progressPercent == 100
|
||||
? 100
|
||||
: ((progressPercent ~/ _serviceProgressStepPercent) *
|
||||
_serviceProgressStepPercent)
|
||||
.clamp(0, 100);
|
||||
final progressBucket = total <= 0
|
||||
? -1
|
||||
: (() {
|
||||
final progressPercent = ((progress * 100) / total)
|
||||
.round()
|
||||
.clamp(0, 100)
|
||||
.toInt();
|
||||
return progressPercent == 100
|
||||
? 100
|
||||
: ((progressPercent ~/ _serviceProgressStepPercent) *
|
||||
_serviceProgressStepPercent)
|
||||
.clamp(0, 100)
|
||||
.toInt();
|
||||
})();
|
||||
|
||||
final didContentChange =
|
||||
trackName != _lastServiceTrackName ||
|
||||
artistName != _lastServiceArtistName ||
|
||||
status != _lastServiceStatus ||
|
||||
queueCount != _lastServiceQueueCount ||
|
||||
progressBucket != _lastServicePercent;
|
||||
final allowHeartbeat =
|
||||
@@ -1942,6 +1981,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
|
||||
_lastServiceTrackName = trackName;
|
||||
_lastServiceArtistName = artistName;
|
||||
_lastServiceStatus = status;
|
||||
_lastServicePercent = progressBucket;
|
||||
_lastServiceQueueCount = queueCount;
|
||||
_lastServiceUpdateAt = now;
|
||||
@@ -1950,8 +1990,9 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
trackName: trackName,
|
||||
artistName: artistName,
|
||||
progress: progress,
|
||||
total: safeTotal,
|
||||
total: total,
|
||||
queueCount: queueCount,
|
||||
status: status,
|
||||
).catchError((_) {});
|
||||
}
|
||||
|
||||
@@ -1969,6 +2010,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
_usingProgressStream = false;
|
||||
_lastServiceTrackName = null;
|
||||
_lastServiceArtistName = null;
|
||||
_lastServiceStatus = null;
|
||||
_lastServicePercent = -1;
|
||||
_lastServiceQueueCount = -1;
|
||||
_lastServiceUpdateAt = DateTime.fromMillisecondsSinceEpoch(0);
|
||||
@@ -3015,6 +3057,26 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
updatedItems[index] = next;
|
||||
state = state.copyWith(items: updatedItems);
|
||||
|
||||
if (Platform.isAndroid && status == DownloadStatus.finalizing) {
|
||||
PlatformBridge.clearItemProgress(id).catchError((_) {});
|
||||
final queueCount = updatedItems
|
||||
.where(
|
||||
(entry) =>
|
||||
entry.status == DownloadStatus.queued ||
|
||||
entry.status == DownloadStatus.downloading ||
|
||||
entry.status == DownloadStatus.finalizing,
|
||||
)
|
||||
.length;
|
||||
_maybeUpdateAndroidDownloadService(
|
||||
trackName: next.track.name,
|
||||
artistName: _notificationService.embeddingMetadataLabel,
|
||||
progress: 100,
|
||||
total: 100,
|
||||
queueCount: queueCount,
|
||||
status: 'finalizing',
|
||||
);
|
||||
}
|
||||
|
||||
if (status == DownloadStatus.completed ||
|
||||
status == DownloadStatus.failed ||
|
||||
status == DownloadStatus.skipped) {
|
||||
@@ -4327,6 +4389,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
orElse: () => state.items.first,
|
||||
);
|
||||
try {
|
||||
await _notificationService.cancelDownloadNotification();
|
||||
await PlatformBridge.startDownloadService(
|
||||
trackName: firstItem.track.name,
|
||||
artistName: firstItem.track.artistName,
|
||||
@@ -4470,7 +4533,8 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
_log.i(
|
||||
'Queue stats - completed: $_completedInSession, failed: $_failedInSession, totalAtStart: $_totalQueuedAtStart',
|
||||
);
|
||||
if (!stoppedWhilePaused && _totalQueuedAtStart > 0) {
|
||||
final hasSessionResults = _completedInSession > 0 || _failedInSession > 0;
|
||||
if (!stoppedWhilePaused && _totalQueuedAtStart > 0 && hasSessionResults) {
|
||||
await _notificationService.showQueueComplete(
|
||||
completedCount: _completedInSession,
|
||||
failedCount: _failedInSession,
|
||||
@@ -4483,6 +4547,10 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
_log.i('Auto-exported failed downloads to: $exportPath');
|
||||
}
|
||||
}
|
||||
} else if (!stoppedWhilePaused && _totalQueuedAtStart > 0) {
|
||||
await _notificationService.showQueueCanceled(
|
||||
canceledCount: _totalQueuedAtStart,
|
||||
);
|
||||
}
|
||||
|
||||
if (stoppedWhilePaused) {
|
||||
|
||||
@@ -23,6 +23,9 @@ class NotificationService {
|
||||
_l10n = l10n;
|
||||
}
|
||||
|
||||
String get embeddingMetadataLabel =>
|
||||
_l10n?.notifEmbeddingMetadata ?? 'Embedding metadata...';
|
||||
|
||||
static const int downloadProgressId = 1;
|
||||
static const int updateDownloadId = 2;
|
||||
static const int libraryScanId = 3;
|
||||
@@ -282,11 +285,17 @@ class NotificationService {
|
||||
required int failedCount,
|
||||
}) async {
|
||||
if (!_isInitialized) await initialize();
|
||||
if (completedCount <= 0 && failedCount <= 0) return;
|
||||
|
||||
final title = failedCount > 0
|
||||
? (_l10n?.notifDownloadsFinished(completedCount, failedCount) ??
|
||||
'Downloads Finished ($completedCount done, $failedCount failed)')
|
||||
: (_l10n?.notifAllDownloadsComplete ?? 'All Downloads Complete');
|
||||
final body = failedCount > 0
|
||||
? (_l10n?.notifDownloadsFinishedBody(completedCount, failedCount) ??
|
||||
'$completedCount downloaded, $failedCount failed')
|
||||
: (_l10n?.notifTracksDownloadedSuccess(completedCount) ??
|
||||
'$completedCount tracks downloaded successfully');
|
||||
|
||||
const androidDetails = AndroidNotificationDetails(
|
||||
channelId,
|
||||
@@ -313,9 +322,46 @@ class NotificationService {
|
||||
await _showSafely(
|
||||
id: downloadProgressId,
|
||||
title: title,
|
||||
body:
|
||||
_l10n?.notifTracksDownloadedSuccess(completedCount) ??
|
||||
'$completedCount tracks downloaded successfully',
|
||||
body: body,
|
||||
details: details,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> showQueueCanceled({required int canceledCount}) async {
|
||||
if (!_isInitialized) await initialize();
|
||||
if (canceledCount <= 0) return;
|
||||
|
||||
final title = _l10n?.notifDownloadsCanceledTitle ?? 'Downloads canceled';
|
||||
final body =
|
||||
_l10n?.notifDownloadsCanceledBody(canceledCount) ??
|
||||
'$canceledCount downloads canceled by user';
|
||||
|
||||
const androidDetails = AndroidNotificationDetails(
|
||||
channelId,
|
||||
channelName,
|
||||
channelDescription: channelDescription,
|
||||
importance: Importance.defaultImportance,
|
||||
priority: Priority.defaultPriority,
|
||||
autoCancel: true,
|
||||
playSound: false,
|
||||
icon: '@mipmap/ic_launcher',
|
||||
);
|
||||
|
||||
const iosDetails = DarwinNotificationDetails(
|
||||
presentAlert: true,
|
||||
presentBadge: true,
|
||||
presentSound: false,
|
||||
);
|
||||
|
||||
const details = NotificationDetails(
|
||||
android: androidDetails,
|
||||
iOS: iosDetails,
|
||||
);
|
||||
|
||||
await _showSafely(
|
||||
id: downloadProgressId,
|
||||
title: title,
|
||||
body: body,
|
||||
details: details,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -816,6 +816,7 @@ class PlatformBridge {
|
||||
required int progress,
|
||||
required int total,
|
||||
required int queueCount,
|
||||
String status = 'downloading',
|
||||
}) async {
|
||||
await _channel.invokeMethod('updateDownloadServiceProgress', {
|
||||
'track_name': trackName,
|
||||
@@ -823,6 +824,7 @@ class PlatformBridge {
|
||||
'progress': progress,
|
||||
'total': total,
|
||||
'queue_count': queueCount,
|
||||
'status': status,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user