mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-10-01 13:49:36 +02:00
fix(ios): local library scan fails on iOS due to missing security-scoped bookmark access
This commit is contained in:
1 parent
2c897992c5
commit
c35857bb61
10 files changed
+602
-273
No files matched your search
@@ -272,6 +272,7 @@ class LocalLibraryNotifier extends Notifier<LocalLibraryState> {
|
||||
Future<void> startScan(
|
||||
String folderPath, {
|
||||
bool forceFullScan = false,
|
||||
String? iosBookmark,
|
||||
}) async {
|
||||
if (state.isScanning) {
|
||||
_log.w('Scan already in progress');
|
||||
@@ -316,8 +317,27 @@ class LocalLibraryNotifier extends Notifier<LocalLibraryState> {
|
||||
|
||||
_startProgressPolling();
|
||||
|
||||
// On iOS, start accessing the security-scoped bookmark so the Go backend
|
||||
// can read files outside the app sandbox.
|
||||
String? resolvedPath;
|
||||
bool didStartSecurityAccess = false;
|
||||
if (Platform.isIOS && iosBookmark != null && iosBookmark.isNotEmpty) {
|
||||
resolvedPath =
|
||||
await PlatformBridge.startAccessingIosBookmark(iosBookmark);
|
||||
if (resolvedPath != null) {
|
||||
didStartSecurityAccess = true;
|
||||
_log.i('Started iOS security-scoped access: $resolvedPath');
|
||||
} else {
|
||||
_log.w(
|
||||
'Failed to start iOS security-scoped access, '
|
||||
'falling back to original path',
|
||||
);
|
||||
}
|
||||
}
|
||||
final effectiveFolderPath = resolvedPath ?? folderPath;
|
||||
|
||||
try {
|
||||
final isSaf = folderPath.startsWith('content://');
|
||||
final isSaf = effectiveFolderPath.startsWith('content://');
|
||||
|
||||
// Get all file paths from download history to exclude them.
|
||||
// Merge DB + in-memory state to avoid race when a fresh download has not
|
||||
@@ -344,8 +364,8 @@ class LocalLibraryNotifier extends Notifier<LocalLibraryState> {
|
||||
if (forceFullScan) {
|
||||
// Full scan path - ignores existing data
|
||||
final results = isSaf
|
||||
? await PlatformBridge.scanSafTree(folderPath)
|
||||
: await PlatformBridge.scanLibraryFolder(folderPath);
|
||||
? await PlatformBridge.scanSafTree(effectiveFolderPath)
|
||||
: await PlatformBridge.scanLibraryFolder(effectiveFolderPath);
|
||||
if (_scanCancelRequested) {
|
||||
state = state.copyWith(isScanning: false, scanWasCancelled: true);
|
||||
await _showScanCancelledNotification();
|
||||
@@ -424,12 +444,12 @@ class LocalLibraryNotifier extends Notifier<LocalLibraryState> {
|
||||
final Map<String, dynamic> result;
|
||||
if (isSaf) {
|
||||
result = await PlatformBridge.scanSafTreeIncremental(
|
||||
folderPath,
|
||||
effectiveFolderPath,
|
||||
existingFiles,
|
||||
);
|
||||
} else {
|
||||
result = await PlatformBridge.scanLibraryFolderIncremental(
|
||||
folderPath,
|
||||
effectiveFolderPath,
|
||||
existingFiles,
|
||||
);
|
||||
}
|
||||
@@ -553,6 +573,10 @@ class LocalLibraryNotifier extends Notifier<LocalLibraryState> {
|
||||
state = state.copyWith(isScanning: false, scanWasCancelled: false);
|
||||
await _showScanFailedNotification(e.toString());
|
||||
} finally {
|
||||
if (didStartSecurityAccess) {
|
||||
await PlatformBridge.stopAccessingIosBookmark();
|
||||
_log.i('Stopped iOS security-scoped access');
|
||||
}
|
||||
_stopProgressPolling();
|
||||
}
|
||||
}
|
||||
@@ -807,12 +831,26 @@ class LocalLibraryNotifier extends Notifier<LocalLibraryState> {
|
||||
return decoded;
|
||||
}
|
||||
|
||||
Future<int> cleanupMissingFiles() async {
|
||||
final removed = await _db.cleanupMissingFiles();
|
||||
if (removed > 0) {
|
||||
await reloadFromStorage();
|
||||
Future<int> cleanupMissingFiles({String? iosBookmark}) async {
|
||||
bool didStartSecurityAccess = false;
|
||||
if (Platform.isIOS && iosBookmark != null && iosBookmark.isNotEmpty) {
|
||||
final resolved =
|
||||
await PlatformBridge.startAccessingIosBookmark(iosBookmark);
|
||||
if (resolved != null) {
|
||||
didStartSecurityAccess = true;
|
||||
}
|
||||
}
|
||||
try {
|
||||
final removed = await _db.cleanupMissingFiles();
|
||||
if (removed > 0) {
|
||||
await reloadFromStorage();
|
||||
}
|
||||
return removed;
|
||||
} finally {
|
||||
if (didStartSecurityAccess) {
|
||||
await PlatformBridge.stopAccessingIosBookmark();
|
||||
}
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
Future<void> clearLibrary() async {
|
||||
|
||||
@@ -532,6 +532,19 @@ class SettingsNotifier extends Notifier<AppSettings> {
|
||||
_saveSettings();
|
||||
}
|
||||
|
||||
void setLocalLibraryBookmark(String bookmark) {
|
||||
state = state.copyWith(localLibraryBookmark: bookmark);
|
||||
_saveSettings();
|
||||
}
|
||||
|
||||
void setLocalLibraryPathAndBookmark(String path, String bookmark) {
|
||||
state = state.copyWith(
|
||||
localLibraryPath: path,
|
||||
localLibraryBookmark: bookmark,
|
||||
);
|
||||
_saveSettings();
|
||||
}
|
||||
|
||||
void setLocalLibraryShowDuplicates(bool show) {
|
||||
state = state.copyWith(localLibraryShowDuplicates: show);
|
||||
_saveSettings();
|
||||
|
||||
Reference in new issue
Block a user