fix(backup): allow selecting SFLB archives for restore

This commit is contained in:
zarzet
2026-09-07 19:38:14 +07:00
parent c0f6a60706
commit 259fb5b6c0
2 changed files with 63 additions and 4 deletions
@@ -74,10 +74,10 @@ class _BackupRestorePageState extends ConsumerState<BackupRestorePage> {
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
+59
View File
@@ -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<PlatformFile?> pickFile({
String? dialogTitle,
String? initialDirectory,
FileType type = FileType.any,
List<String>? 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);
});
}