Adding drag and drop feature for VMRemovableDrivesView

This commit is contained in:
Tigran Hambardzumyan
2024-04-24 23:41:09 +04:00
parent 6025783960
commit 00a1bb55aa
2 changed files with 37 additions and 7 deletions
+34 -4
View File
@@ -15,6 +15,7 @@
//
import SwiftUI
import UniformTypeIdentifiers
struct VMRemovableDrivesView: View {
@ObservedObject var vm: VMData
@@ -25,7 +26,10 @@ struct VMRemovableDrivesView: View {
/// Explanation see "SwiftUI FileImporter modal bug" in the `body`
@State private var workaroundFileImporterBug: Bool = false
@State private var currentDrive: UTMQemuConfigurationDrive?
private static let shareDirectoryUTType = UTType.folder
private static let diskImageUTType = UTType.data
private var qemuVM: (any UTMSpiceVirtualMachine)! {
vm.wrapped as? any UTMSpiceVirtualMachine
}
@@ -73,8 +77,21 @@ struct VMRemovableDrivesView: View {
} else {
Button("Browse…", action: { shareDirectoryFileImportPresented.toggle() })
}
}.fileImporter(isPresented: $shareDirectoryFileImportPresented, allowedContentTypes: [.folder], onCompletion: selectShareDirectory)
.disabled(mode == .virtfs && vm.state != .stopped)
}.fileImporter(isPresented: $shareDirectoryFileImportPresented, allowedContentTypes: [Self.shareDirectoryUTType], onCompletion: selectShareDirectory)
.disabled(mode == .virtfs && vm.state != .stopped)
.onDrop(of: [Self.shareDirectoryUTType], isTargeted: nil) { providers in
guard let item = providers.first, item.hasItemConformingToTypeIdentifier(Self.shareDirectoryUTType.identifier) else { return false }
item.loadItem(forTypeIdentifier: Self.shareDirectoryUTType.identifier) { url, error in
if let url = url as? URL {
selectShareDirectory(result: .success(url))
}
if let error = error {
selectShareDirectory(result: .failure(error))
}
}
return true
}
}
ForEach(config.drives.filter { $0.isExternal }) { drive in
HStack {
@@ -128,12 +145,25 @@ struct VMRemovableDrivesView: View {
.lineLimit(1)
.truncationMode(.tail)
.foregroundColor(.secondary)
}.fileImporter(isPresented: $diskImageFileImportPresented, allowedContentTypes: [.data]) { result in
}.fileImporter(isPresented: $diskImageFileImportPresented, allowedContentTypes: [Self.diskImageUTType]) { result in
if let currentDrive = self.currentDrive {
selectRemovableImage(forDrive: currentDrive, result: result)
self.currentDrive = nil
}
}
.onDrop(of: [Self.diskImageUTType], isTargeted: nil) { providers in
guard let item = providers.first, item.hasItemConformingToTypeIdentifier(Self.diskImageUTType.identifier) else { return false }
item.loadItem(forTypeIdentifier: Self.diskImageUTType.identifier) { url, error in
if let url = url as? URL{
selectRemovableImage(forDrive: drive, result: .success(url))
}
if let error {
selectRemovableImage(forDrive: drive, result: .failure(error))
}
}
return true
}
}
}
}
+3 -3
View File
@@ -792,10 +792,10 @@ extension UTMQemuVirtualMachine {
try await eject(drive, isForced: true)
let file = try UTMRegistryEntry.File(url: url, isReadOnly: drive.isReadOnly)
await registryEntry.setExternalDrive(file, forId: drive.id)
try await changeMedium(drive, with: tempBookmark, url: url, isSecurityScoped: false, isAccessOnly: isAccessOnly)
try await changeMedium(drive, with: tempBookmark, isSecurityScoped: false, isAccessOnly: isAccessOnly)
}
private func changeMedium(_ drive: UTMQemuConfigurationDrive, with bookmark: Data, url: URL?, isSecurityScoped: Bool, isAccessOnly: Bool) async throws {
private func changeMedium(_ drive: UTMQemuConfigurationDrive, with bookmark: Data, isSecurityScoped: Bool, isAccessOnly: Bool) async throws {
let system = await system ?? UTMProcess()
let (success, bookmark, path) = await system.accessData(withBookmark: bookmark, securityScoped: isSecurityScoped)
guard let bookmark = bookmark, let path = path, success else {
@@ -818,7 +818,7 @@ extension UTMQemuVirtualMachine {
let id = drive.id
if let bookmark = await registryEntry.externalDrives[id]?.remoteBookmark {
// an image bookmark was saved while QEMU was running
try await changeMedium(drive, with: bookmark, url: nil, isSecurityScoped: true, isAccessOnly: !isMounting)
try await changeMedium(drive, with: bookmark, isSecurityScoped: true, isAccessOnly: !isMounting)
} else if let localBookmark = await registryEntry.externalDrives[id]?.bookmark {
// an image bookmark was saved while QEMU was NOT running
let url = try URL(resolvingPersistentBookmarkData: localBookmark)