Post

Replies

Boosts

Views

Activity

SwiftUI Audio File Export via draggable
Hey everyone, TL;DR How do I enable a draggable TableView to drop Audio Files into Apple Music / Rekordbox / Finder? Intro / skip me I've been dabbling into Swift / SwiftUI for a few weeks now, after roughly a decade of web development. So far I've been able to piece together many things, but this time I'm stuck for hours with no success using Forums / ChatGPT / Perplexity / Trial and Error. The struggle Sometimes the target doesn't accept the dropping at all sometimes the file data is failed to be read when the drop succeeds, then only as a stream in apple music My lack of understanding / where exactly I'm stuck I think the right way is to use UTType.fileUrl but this is not accepted by other applications. I don't understand low-level aspects well enough to do things right. The code I'm just going to dump everything here, it includes failed / commented out attempts and might give you an Idea of what I'm trying to achieve. // // Tracks.swift // Tuna Family // // Created by Jan Wirth on 12/12/24. // import SwiftySandboxFileAccess import Files import SwiftUI import TunaApi struct LegacyTracks: View { @State var tracks: TunaApi.LoadTracksQuery.Data? func fetchData() { print("fetching data") Network.shared.apollo.fetch(query: TunaApi.LoadTracksQuery()) { result in switch result { case .success(let graphQLResult): self.tracks = graphQLResult.data case .failure(let error): print("Failure! Error: \(error)") } } } @State private var selection = Set<String>() var body: some View { Text("Tracks").onAppear{ fetchData() } if let tracks = tracks?.track { Table(of: LoadTracksQuery.Data.Track.self, selection: $selection) { TableColumn("Title", value: \.title) } rows : { ForEach(tracks) { track in TableRow(track) .draggable(track) // .draggable((try? File(path: track.dropped_source?.path ?? "").url) ?? test_audio.url) // This causes a compile-time error // .draggable(test_audio.url) // .draggable(DraggableTrack(url: test_audio.url)) // .itemProvider { // let provider = NSItemProvider() // if let path = self.dropped_source?.path { // if let f = try? File(path: path) { // print("Transferring", f.url) // // // } // } // // provider.register(track) // return provider // } // This does not } } .contextMenu(forSelectionType: String.self) { items in // ... Button("yoooo") {} } primaryAction: { items in print(items) // This is executed when the row is double clicked } } else { Text("Loading") } // } } } //extension Files.File: Transferable { // public static var transferRepresentation: some TransferRepresentation { // FileRepresentation(exportedContentType: .audio) { url in // SentTransferredFile( self.) // } // } //} struct DraggableTrack: Transferable { var url: URL public static var transferRepresentation: some TransferRepresentation { FileRepresentation (exportedContentType: .fileURL) { item in SentTransferredFile(test_audio.url, allowAccessingOriginalFile: true) } // FileRepresentation(contentType: .init(filenameExtension: "m4a")) { // print("file", $0) // print("Transferring fallback", test_audio.url) // return SentTransferredFile(test_audio.url, allowAccessingOriginalFile: true) // } // importing: { received in // // let copy = try Self.(source: received.file) // return Self.init(url: received.file) // } // ProxyRepresentation(exporting: \.url.absoluteString) } } extension LoadTracksQuery.Data.Track: @retroactive Identifiable { } import UniformTypeIdentifiers extension LoadTracksQuery.Data.Track: @retroactive Transferable { // static func getKind() -> UTType { // var kind: UTType = UTType.item // if let path = self.dropped_source?.path { // if let f = try? File(path: path) { // print("Transferring", f.url) // if (f.extension == "m4a") { // kind = UTType.mpeg4Audio // } // if (f.extension == "mp3") { // kind = UTType.mp3 // } // if (f.extension == "flac") { // kind = UTType.flac // } // if (f.extension == "wav") { // kind = UTType.wav // } // // } // } // return kind // } public static var transferRepresentation: some TransferRepresentation { ProxyRepresentation { $0.dropped_source?.path ?? "" } FileRepresentation(exportedContentType: .fileURL) { <#Transferable#> in SentTransferredFile(<#T##file: URL##URL#>, allowAccessingOriginalFile: <#T##Bool#>) } // FileRepresentation(contentType: .fileURL) { // print("file", $0) // if let path = $0.dropped_source?.path { // if let f = try? File(path: path) { // print("Transferring", f.url) // return SentTransferredFile(f.url, allowAccessingOriginalFile: true) // } // } // print("Transferring fallback", test_audio.url) // return SentTransferredFile(test_audio.url, allowAccessingOriginalFile: true) // } // importing: { received in // // let copy = try Self.(source: received.file) // return Self.init(_fieldData: received.file) // } // ProxyRepresentation(exporting: \.title) } }
0
0
127
1w