diff --git a/Sources/NetworkFileBrowser.swift b/Sources/NetworkFileBrowser.swift index c25c1bb..24ad0be 100644 --- a/Sources/NetworkFileBrowser.swift +++ b/Sources/NetworkFileBrowser.swift @@ -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 {