Add drag-out export from item list
This commit is contained in:
parent
d1c7d1de73
commit
f6ab43833c
@ -37,6 +37,7 @@ struct ItemListColumnView<MenuContent: View>: View {
|
||||
let searchPrompt: String
|
||||
let chooseFolderAction: () -> Void
|
||||
let dropAction: ([NSItemProvider]) -> Bool
|
||||
let dragProvider: (MinecraftContentItem) -> NSItemProvider
|
||||
let itemContextMenu: (MinecraftContentItem) -> MenuContent
|
||||
|
||||
var body: some View {
|
||||
@ -51,6 +52,9 @@ struct ItemListColumnView<MenuContent: View>: View {
|
||||
List(items, selection: $selectedItemID) { item in
|
||||
ContentRowView(item: item)
|
||||
.tag(item.id)
|
||||
.onDrag {
|
||||
dragProvider(item)
|
||||
}
|
||||
.contextMenu {
|
||||
itemContextMenu(item)
|
||||
}
|
||||
|
||||
@ -321,6 +321,7 @@ struct ItemListColumnPreviewContainer: View {
|
||||
searchPrompt: "Search Worlds",
|
||||
chooseFolderAction: {},
|
||||
dropAction: { _ in false },
|
||||
dragProvider: { _ in NSItemProvider() },
|
||||
itemContextMenu: { item in
|
||||
Button("Reveal \(item.displayName)") {}
|
||||
}
|
||||
|
||||
@ -74,6 +74,7 @@ struct ContentView: View {
|
||||
searchPrompt: searchPrompt,
|
||||
chooseFolderAction: pickFolder,
|
||||
dropAction: handleDroppedProviders(_:),
|
||||
dragProvider: dragProvider(for:),
|
||||
itemContextMenu: itemContextMenu(for:)
|
||||
)
|
||||
.navigationSplitViewColumnWidth(min: 340, ideal: 400, max: 460)
|
||||
@ -653,7 +654,13 @@ struct ContentView: View {
|
||||
return false
|
||||
}
|
||||
|
||||
return source.availability == .available
|
||||
return source.availability == .available && source.capabilities.canExportPortablePackages
|
||||
}
|
||||
|
||||
private func sourceForItem(_ item: MinecraftContentItem) -> MinecraftSource? {
|
||||
library.visibleSources.first(where: { source in
|
||||
source.items.contains(where: { $0.id == item.id })
|
||||
})
|
||||
}
|
||||
|
||||
private func saveItem(_ item: MinecraftContentItem) {
|
||||
@ -791,6 +798,44 @@ struct ContentView: View {
|
||||
private func archiveType(for item: MinecraftContentItem) -> UTType {
|
||||
UTType(filenameExtension: item.contentType.archiveExtension) ?? .data
|
||||
}
|
||||
|
||||
private func dragProvider(for item: MinecraftContentItem) -> NSItemProvider {
|
||||
let provider = NSItemProvider()
|
||||
let contentType = archiveType(for: item)
|
||||
provider.suggestedName = itemActionService.suggestedArchiveFilename(for: item)
|
||||
|
||||
provider.registerFileRepresentation(
|
||||
forTypeIdentifier: contentType.identifier,
|
||||
fileOptions: [],
|
||||
visibility: .all
|
||||
) { completion in
|
||||
guard let source = sourceForItem(item), areFileActionsEnabled(for: item) else {
|
||||
completion(nil, false, SourceAccessError.accessFailed(reason: "This item is not currently available for export."))
|
||||
return nil
|
||||
}
|
||||
|
||||
let task = Task {
|
||||
do {
|
||||
let representation = try await library.externalRepresentation(
|
||||
for: item,
|
||||
in: source,
|
||||
preferredKind: .portablePackage
|
||||
)
|
||||
completion(representation.url, representation.isTemporary, nil)
|
||||
} catch {
|
||||
completion(nil, false, error)
|
||||
}
|
||||
}
|
||||
|
||||
let progress = Progress(totalUnitCount: 1)
|
||||
progress.cancellationHandler = {
|
||||
task.cancel()
|
||||
}
|
||||
return progress
|
||||
}
|
||||
|
||||
return provider
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView_Previews: PreviewProvider {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user