fix(notifications): show indeterminate scans without false zero percent

This commit is contained in:
zarzet committed 2026-10-11 15:38:20 +07:00
1 parent 3ff143f4be
commit 2e170ca298
22 files changed
+121 -88

No files matched your search

+1 -4
View File
@@ -5355,15 +5355,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} files scanned • {percentage}%",
"notifLibraryScanProgressNoTotal": "{scanned} files scanned",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+1 -4
View File
@@ -5355,15 +5355,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} gescannte Dateien • {percentage}%",
"notifLibraryScanProgressNoTotal": "{scanned} gescannte Dateien",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+1 -4
View File
@@ -5400,15 +5400,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} files scanned • {percentage}%",
"notifLibraryScanProgressNoTotal": "{scanned} files scanned",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+1 -4
View File
@@ -4096,15 +4096,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} files scanned • {percentage}%",
"notifLibraryScanProgressNoTotal": "{scanned} files scanned",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+1 -4
View File
@@ -5355,15 +5355,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} archivos escaneados • {percentage} %",
"notifLibraryScanProgressNoTotal": "{scanned} archivos escaneados",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+1 -4
View File
@@ -5355,15 +5355,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} fichiers analysés • {percentage} %",
"notifLibraryScanProgressNoTotal": "{scanned} fichiers analysés",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+1 -4
View File
@@ -5355,15 +5355,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} files scanned • {percentage}%",
"notifLibraryScanProgressNoTotal": "{scanned} files scanned",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+1 -4
View File
@@ -5484,15 +5484,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} file terpindai • {percentage}%",
"notifLibraryScanProgressNoTotal": "{scanned} file terpindai",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+1 -4
View File
@@ -5355,15 +5355,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} files scanned • {percentage}%",
"notifLibraryScanProgressNoTotal": "{scanned} files scanned",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+1 -4
View File
@@ -5355,15 +5355,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} files scanned • {percentage}%",
"notifLibraryScanProgressNoTotal": "{scanned} files scanned",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+1 -4
View File
@@ -5355,15 +5355,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} 게의 파일이 스캔됨 • {percentage}%",
"notifLibraryScanProgressNoTotal": "{scanned} 게의 파일이 스캔됨",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+1 -4
View File
@@ -5355,15 +5355,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} files scanned • {percentage}%",
"notifLibraryScanProgressNoTotal": "{scanned} files scanned",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+1 -4
View File
@@ -4096,15 +4096,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} files scanned • {percentage}%",
"notifLibraryScanProgressNoTotal": "{scanned} files scanned",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+1 -4
View File
@@ -5355,15 +5355,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} files scanned • {percentage}%",
"notifLibraryScanProgressNoTotal": "{scanned} files scanned",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+1 -4
View File
@@ -5354,15 +5354,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} файлов отсканировано • {percentage}%",
"notifLibraryScanProgressNoTotal": "{scanned} файлов отсканировано",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+1 -4
View File
@@ -5355,15 +5355,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} files scanned • {percentage}%",
"notifLibraryScanProgressNoTotal": "{scanned} files scanned",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+1 -4
View File
@@ -5342,15 +5342,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} Файлів скановано • {percentage}%",
"notifLibraryScanProgressNoTotal": "{scanned} Файлів скановано",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+1 -4
View File
@@ -4946,15 +4946,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} files scanned • {percentage}%",
"notifLibraryScanProgressNoTotal": "{scanned} files scanned",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+1 -4
View File
@@ -5355,15 +5355,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} files scanned • {percentage}%",
"notifLibraryScanProgressNoTotal": "{scanned} files scanned",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+1 -4
View File
@@ -5355,15 +5355,12 @@
}
}
},
"notifLibraryScanProgressNoTotal": "{scanned} files scanned • {percentage}%",
"notifLibraryScanProgressNoTotal": "{scanned} files scanned",
"@notifLibraryScanProgressNoTotal": {
"description": "Notification body for library scan progress when total is unknown",
"placeholders": {
"scanned": {
"type": "int"
},
"percentage": {
"type": "int"
}
}
},
+12 -7
View File
@@ -240,7 +240,8 @@ class NotificationService {
}
/// Builds [NotificationDetails]. A non-null [progress] switches to the
/// low-importance ongoing progress style; otherwise a dismissible alert.
/// low-importance ongoing progress style; a negative value is indeterminate.
/// Otherwise builds a dismissible alert.
NotificationDetails _details({
bool library = false,
int? progress,
@@ -276,7 +277,8 @@ class NotificationService {
priority: inProgress ? Priority.low : Priority.defaultPriority,
showProgress: inProgress,
maxProgress: inProgress ? 100 : 0,
progress: progress ?? 0,
progress: progress?.clamp(0, 100) ?? 0,
indeterminate: (progress ?? 0) < 0,
ongoing: inProgress,
autoCancel: !inProgress,
playSound: playSound,
@@ -455,17 +457,20 @@ class NotificationService {
}) async {
if (!_isInitialized) await initialize();
final clampedProgress = progress.clamp(0.0, 100.0);
final percentage = clampedProgress.round();
final progressBody = totalFiles > 0
// Network scans read tags while discovering folders, so their total is
// unknown. Zero percent would falsely imply that no files were processed.
// Use the same indeterminate value for the foreground service and plugin.
final hasTotal = totalFiles > 0;
final percentage = hasTotal ? progress.clamp(0.0, 100.0).round() : -1;
final progressBody = hasTotal
? (_l10n?.notifLibraryScanProgressWithTotal(
scannedFiles,
totalFiles,
percentage,
) ??
'$scannedFiles/$totalFiles files • $percentage%')
: (_l10n?.notifLibraryScanProgressNoTotal(scannedFiles, percentage) ??
'$scannedFiles files scanned • $percentage%');
: (_l10n?.notifLibraryScanProgressNoTotal(scannedFiles) ??
'$scannedFiles files scanned');
final body = (currentFile != null && currentFile.isNotEmpty)
? '$progressBody\n$currentFile'
: progressBody;
+89 -1
View File
@@ -1,7 +1,9 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:spotiflac_android/l10n/app_localizations.dart';
import 'package:spotiflac_android/services/notification_service.dart';
import 'package:spotiflac_android/services/verification_notification.dart';
@@ -17,8 +19,11 @@ void main() {
tapId: 'dart:cold-tap',
);
setUp(() {
setUp(() async {
debugDefaultTargetPlatformOverride = TargetPlatform.android;
NotificationService().updateStrings(
await AppLocalizations.delegate.load(const Locale('en')),
);
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(channel, (call) async {
methodCalls.add(call);
@@ -117,4 +122,87 @@ void main() {
),
);
});
test(
'scan with unknown total shows count and indeterminate progress',
() async {
final service = NotificationService();
for (final count in [0, 1566]) {
await service.showLibraryScanProgress(
progress: 0,
scannedFiles: count,
totalFiles: 0,
currentFile: 'track.flac',
);
final arguments =
methodCalls.lastWhere((call) => call.method == 'show').arguments
as Map<Object?, Object?>;
final details = arguments['platformSpecifics'] as Map<Object?, Object?>;
expect(arguments['id'], NotificationService.libraryScanId);
expect(arguments['body'], '$count files scanned\ntrack.flac');
expect(details['showProgress'], isTrue);
expect(details['indeterminate'], isTrue);
expect(details['progress'], 0);
expect(details['ongoing'], isTrue);
expect(details['autoCancel'], isFalse);
expect(details['playSound'], isFalse);
}
},
);
test('scan switches to percentage when total becomes known', () async {
final service = NotificationService();
await service.showLibraryScanProgress(
progress: 0,
scannedFiles: 1566,
totalFiles: 0,
);
await service.showLibraryScanProgress(
progress: 78.3,
scannedFiles: 1566,
totalFiles: 2000,
currentFile: 'track.flac',
);
final progressArguments =
methodCalls.lastWhere((call) => call.method == 'show').arguments
as Map<Object?, Object?>;
final progressDetails =
progressArguments['platformSpecifics'] as Map<Object?, Object?>;
expect(progressArguments['body'], '1566/2000 files • 78%\ntrack.flac');
expect(progressDetails['showProgress'], isTrue);
expect(progressDetails['indeterminate'], isFalse);
expect(progressDetails['progress'], 78);
await service.showLibraryScanComplete(totalTracks: 2000);
final completeArguments =
methodCalls.lastWhere((call) => call.method == 'show').arguments
as Map<Object?, Object?>;
final completeDetails =
completeArguments['platformSpecifics'] as Map<Object?, Object?>;
expect(completeArguments['body'], '2000 tracks indexed');
expect(completeDetails['showProgress'], isFalse);
expect(completeDetails['ongoing'], isFalse);
expect(completeDetails['autoCancel'], isTrue);
});
test('unknown-total scan never displays percentage in any locale', () async {
final service = NotificationService();
for (final locale in AppLocalizations.supportedLocales) {
service.updateStrings(await AppLocalizations.delegate.load(locale));
await service.showLibraryScanProgress(
progress: 0,
scannedFiles: 1566,
totalFiles: 0,
);
final arguments =
methodCalls.lastWhere((call) => call.method == 'show').arguments
as Map<Object?, Object?>;
final body = arguments['body'] as String;
expect(body, contains('1566'), reason: '$locale');
expect(body, isNot(contains('%')), reason: '$locale');
}
});
}