mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-27 03:41:47 +02:00
fix(ios): create security-scoped bookmark inside native folder picker session
The download/library folder picker on iOS previously took the bare path string returned by file_picker and rebuilt a URL from it to create a security-scoped bookmark. By then the picker's access grant is gone, so bookmark creation either failed (folder selection silently rejected) or produced a bookmark that could not be re-opened, after which the first download run overwrote the user's chosen folder back to app Documents. - Add a native pickIosDirectory method channel that presents UIDocumentPickerViewController itself and creates the bookmark inside the delegate callback, while the security-scoped grant is active - Use it for the download directory (settings + first-run setup) and the local library folder pickers - Stop overwriting the saved download directory when the bookmark fails at queue start; fail queued items with a clear message instead - Skip the launch-time iOS path normalizer when a bookmark exists, so it no longer rewrites external folder paths and drops their bookmark Fixes #454
This commit is contained in:
@@ -22,6 +22,15 @@ class ExtensionSessionGrantEvent {
|
||||
});
|
||||
}
|
||||
|
||||
/// Folder picked via the native iOS document picker: the filesystem path plus
|
||||
/// the security-scoped bookmark that re-grants access across app launches.
|
||||
class IosPickedDirectory {
|
||||
final String path;
|
||||
final String bookmark;
|
||||
|
||||
const IosPickedDirectory({required this.path, required this.bookmark});
|
||||
}
|
||||
|
||||
class _BridgeCacheEntry {
|
||||
final Map<String, dynamic> value;
|
||||
final DateTime expiresAt;
|
||||
@@ -2041,6 +2050,20 @@ class PlatformBridge {
|
||||
return const <String, dynamic>{};
|
||||
}
|
||||
|
||||
/// Present the native iOS folder picker. The security-scoped bookmark is
|
||||
/// created inside the picker callback while its access grant is still
|
||||
/// active — creating it later from a bare path loses the grant.
|
||||
/// Returns null when the user cancels; throws on picker/bookmark failure.
|
||||
static Future<IosPickedDirectory?> pickIosDirectory() async {
|
||||
final result = await _channel.invokeMethod('pickIosDirectory');
|
||||
final map = _decodeNullableMapResult(result, 'pickIosDirectory');
|
||||
if (map == null) return null;
|
||||
final path = map['path'] as String? ?? '';
|
||||
final bookmark = map['bookmark'] as String? ?? '';
|
||||
if (path.isEmpty || bookmark.isEmpty) return null;
|
||||
return IosPickedDirectory(path: path, bookmark: bookmark);
|
||||
}
|
||||
|
||||
/// Create a security-scoped bookmark from a filesystem path picked by
|
||||
/// FilePicker on iOS. Must be called while the picker session is still active.
|
||||
/// Returns base64-encoded bookmark data, or null on failure.
|
||||
|
||||
Reference in New Issue
Block a user