diff --git a/lib/screens/settings/backup_restore_page.dart b/lib/screens/settings/backup_restore_page.dart index bc917e2d..2e8d163a 100644 --- a/lib/screens/settings/backup_restore_page.dart +++ b/lib/screens/settings/backup_restore_page.dart @@ -74,10 +74,10 @@ class _BackupRestorePageState extends ConsumerState { BackupBundle? bundle; try { - final picked = await FilePicker.pickFile( - type: FileType.custom, - allowedExtensions: ['json', BackupService.fileExtension], - ); + // Android resolves custom extensions to MIME types. It recognizes JSON + // but not SFLB, so mixing them hides our own backups. Validate contents + // with BackupService after selection instead of filtering by extension. + final picked = await FilePicker.pickFile(type: FileType.any); if (picked == null) return; final path = picked.path; bundle = path != null diff --git a/test/backup_restore_picker_test.dart b/test/backup_restore_picker_test.dart new file mode 100644 index 00000000..63cb7160 --- /dev/null +++ b/test/backup_restore_picker_test.dart @@ -0,0 +1,59 @@ +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:spotiflac_android/l10n/app_localizations.dart'; +import 'package:spotiflac_android/screens/settings/backup_restore_page.dart'; + +class _BackupFilePicker extends FilePickerPlatform { + bool opened = false; + + @override + Future pickFile({ + String? dialogTitle, + String? initialDirectory, + FileType type = FileType.any, + List? allowedExtensions, + dynamic Function(FilePickerStatus)? onFileLoading, + int compressionQuality = 0, + AndroidOptions androidOptions = const AndroidOptions(), + DarwinOptions darwinOptions = const DarwinOptions(), + WindowsOptions windowsOptions = const WindowsOptions(), + LinuxOptions linuxOptions = const LinuxOptions(), + WebOptions webOptions = const WebOptions(), + }) async { + opened = true; + // A custom JSON/SFLB filter becomes JSON-only on Android because SFLB + // has no system MIME mapping. + expect(type, FileType.any); + expect(allowedExtensions, isNull); + return null; + } +} + +void main() { + testWidgets('restore does not exclude backups with an unknown MIME type', ( + tester, + ) async { + final original = FilePickerPlatform.instance; + final picker = _BackupFilePicker(); + FilePickerPlatform.instance = picker; + addTearDown(() => FilePickerPlatform.instance = original); + await tester.pumpWidget( + const ProviderScope( + child: MaterialApp( + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, + home: BackupRestorePage(), + ), + ), + ); + final restore = find.text('Choose backup file'); + await tester.ensureVisible(restore); + await tester.tap(restore); + await tester.pumpAndSettle(); + expect(picker.opened, isTrue); + expect(find.byType(AlertDialog), findsNothing); + expect(tester.takeException(), isNull); + }); +}