Fix local folder playback after app container UUID changes

After iOS reinstall/restore the app container UUID rotates, which left both
the persisted source.url and the security-scoped bookmark pointing at a
no-longer-current path. Files derived a stale absolute path that got appended
onto the resolved bookmark, producing doubled URLs that MPV could not load.

- Resolve the base URL by picking whichever of the bookmark or source.url
  actually exists on disk.
- Compute MediaFile relative paths against the resolved root so they survive
  later container changes.
- Hold the security-scoped resource access for the source's lifetime via a
  shared resolver, so MPV can open files long after the directory enumeration
  that resolved the bookmark has returned.
- Normalize legacy absolute paths embedded in old recents/history video IDs
  so they re-resolve under the current container.
This commit is contained in:
Arkadiusz Fal
2026-05-08 18:23:16 +02:00
parent 5d88ed9743
commit b7b7c5ac62
3 changed files with 161 additions and 24 deletions

View File

@@ -1394,8 +1394,20 @@ final class PlayerService {
LoggingService.shared.debug("[SubtitleDebug] Found source: \(source.name), type: \(source.type)", category: .player)
let password = mediaSourcesManager?.password(for: source)
let parentPath = (filePath as NSString).deletingLastPathComponent
let fileName = (filePath as NSString).lastPathComponent
// Legacy video IDs for `.localFolder` sources may carry an absolute container
// path (recorded before relative paths were computed correctly). Normalize
// against the source folder name so the path becomes relative and doesn't
// get appended onto the freshly resolved bookmark base, which would produce
// a doubled `/Documents/<folder>/private/var/.../Documents/<folder>/...` path.
let normalizedFilePath: String
if source.type == .localFolder {
normalizedFilePath = LocalFileClient.normalizeAbsolutePath(filePath, sourceFolderName: source.url.lastPathComponent)
} else {
normalizedFilePath = filePath
}
let parentPath = (normalizedFilePath as NSString).deletingLastPathComponent
let fileName = (normalizedFilePath as NSString).lastPathComponent
LoggingService.shared.debug("[SubtitleDebug] parentPath: \(parentPath), fileName: \(fileName)", category: .player)