Initial commit
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
import 'android_scan.dart';
|
||||
import 'database.dart';
|
||||
import 'permissions.dart';
|
||||
import 'scan_service.dart';
|
||||
|
||||
/// Beschriftung des Hinzufügen-/Scan-Buttons je Plattform.
|
||||
String get addMusicLabel =>
|
||||
Platform.isAndroid ? 'Musik scannen' : 'Musikordner hinzufügen';
|
||||
|
||||
/// Koordiniert Ordnerwahl und Scans; hält den Scan-Fortschritt für die UI.
|
||||
/// Android scannt automatisch über MediaStore (Scoped Storage lässt keinen
|
||||
/// direkten Dateizugriff zu); Desktop scannt vom Nutzer gewählte Ordner.
|
||||
class LibraryService extends ChangeNotifier {
|
||||
LibraryService(this.db);
|
||||
final MeloDb db;
|
||||
static const _uuid = Uuid();
|
||||
|
||||
bool scanning = false;
|
||||
int scanDone = 0;
|
||||
int scanTotal = 0;
|
||||
bool permissionDenied = false;
|
||||
|
||||
/// Auf Android: automatischer Geräte-Scan. Auf Desktop: Ordner wählen + scannen.
|
||||
Future<void> pickFolderAndScan() async {
|
||||
if (!await _ensurePermission()) return;
|
||||
if (Platform.isAndroid) {
|
||||
await _scan();
|
||||
return;
|
||||
}
|
||||
final path = await FilePicker.getDirectoryPath();
|
||||
if (path == null) return;
|
||||
await db.addFolder(FoldersCompanion.insert(
|
||||
id: _uuid.v4(),
|
||||
path: path,
|
||||
updatedAtMs: DateTime.now().millisecondsSinceEpoch,
|
||||
));
|
||||
await _scan();
|
||||
}
|
||||
|
||||
/// Scannt erneut (Android: ganzes Gerät; Desktop: alle gemerkten Ordner).
|
||||
Future<void> rescan() async {
|
||||
if (!await _ensurePermission()) return;
|
||||
await _scan();
|
||||
}
|
||||
|
||||
Future<bool> _ensurePermission() async {
|
||||
final granted = await ensureAudioPermission();
|
||||
permissionDenied = !granted;
|
||||
notifyListeners();
|
||||
return granted;
|
||||
}
|
||||
|
||||
Future<void> _scan() async {
|
||||
if (scanning) return;
|
||||
scanning = true;
|
||||
scanDone = 0;
|
||||
scanTotal = 0;
|
||||
notifyListeners();
|
||||
try {
|
||||
if (Platform.isAndroid) {
|
||||
await scanAndroidMediaStore(db, onProgress: _onProgress);
|
||||
} else {
|
||||
final folders = (await db.activeFolders()).map((f) => f.path).toList();
|
||||
await scanFolders(db, folders, onProgress: _onProgress);
|
||||
}
|
||||
} finally {
|
||||
scanning = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
void _onProgress(int done, int total) {
|
||||
scanDone = done;
|
||||
scanTotal = total;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user