fix(iOS): copy SMB files to local Documents before playing — AVPlayer can't handle smb:// URLs

This commit is contained in:
yumoqing 2026-07-04 18:10:31 +08:00
parent bf734454f8
commit b9e65f306a

View File

@ -264,6 +264,8 @@ struct NetworkFileBrowserIOS: View {
@State private var isLoading = false
@State private var streamURL = ""
@State private var showFileImporter = false
@State private var copyingFile = false
@State private var copyProgress = ""
var body: some View {
NavigationView {
@ -272,6 +274,15 @@ struct NetworkFileBrowserIOS: View {
}
.navigationTitle(browseURL != nil ? "Browsing" : "Network Files")
.navigationBarTitleDisplayMode(.inline)
.overlay {
if copyingFile {
Color.black.opacity(0.6).ignoresSafeArea()
VStack(spacing: 12) {
ProgressView()
Text(copyProgress).foregroundColor(.white)
}
}
}
.toolbar {
if browseURL != nil {
ToolbarItem(placement: .navigationBarLeading) {
@ -418,7 +429,59 @@ struct NetworkFileBrowserIOS: View {
private func handleSelect(_ item: NetworkFileItem) {
if item.isDirectory { if let cur = browseURL { pathStack.append(cur) }; navigateTo(item.url) }
else if item.isMediaFile { bridge.addItem(url: item.url, name: item.name, type: "network"); if item.hasMatchingASS { bridge.loadExternalSubtitle(url: item.url.deletingPathExtension().appendingPathExtension("ass")) }; isPresented = false }
else if item.isMediaFile {
// SMB AVPlayer smb://
if item.url.scheme == "smb" {
copyFromSMBAndPlay(item)
} else {
playMedia(item)
}
}
}
private func playMedia(_ item: NetworkFileItem) {
bridge.addItem(url: item.url, name: item.name, type: "network")
if item.hasMatchingASS { bridge.loadExternalSubtitle(url: item.url.deletingPathExtension().appendingPathExtension("ass")) }
isPresented = false
}
private func copyFromSMBAndPlay(_ item: NetworkFileItem) {
copyingFile = true
copyProgress = "Copying \(item.name)..."
DispatchQueue.global(qos: .userInitiated).async {
let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let localURL = docs.appendingPathComponent(item.name)
//
try? FileManager.default.removeItem(at: localURL)
do {
try FileManager.default.copyItem(at: item.url, to: localURL)
// ASS
var assLocal: URL?
if item.hasMatchingASS {
let assURL = item.url.deletingPathExtension().appendingPathExtension("ass")
let assDest = docs.appendingPathComponent(assURL.lastPathComponent)
if (try? FileManager.default.copyItem(at: assURL, to: assDest)) != nil {
assLocal = assDest
}
}
DispatchQueue.main.async {
self.copyingFile = false
bridge.addItem(url: localURL, name: item.name, type: "network")
if let al = assLocal { bridge.loadExternalSubtitle(url: al) }
isPresented = false
}
} catch {
DispatchQueue.main.async {
self.copyingFile = false
self.connectError = "Copy failed: \(error.localizedDescription)"
}
}
}
}
private func fmtSize(_ s: Int64) -> String {