mirror of
https://github.com/utmapp/UTM.git
synced 2026-10-12 02:24:01 +00:00
Adding drag and drop feature for VMRemovableDrivesView
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user