15
15
//
16
16
17
17
import SwiftUI
18
+ import UniformTypeIdentifiers
18
19
19
20
struct VMRemovableDrivesView : View {
20
21
@ObservedObject var vm : VMData
@@ -25,7 +26,10 @@ struct VMRemovableDrivesView: View {
25
26
/// Explanation see "SwiftUI FileImporter modal bug" in the `body`
26
27
@State private var workaroundFileImporterBug : Bool = false
27
28
@State private var currentDrive : UTMQemuConfigurationDrive ?
28
-
29
+
30
+ private static let shareDirectoryUTType = UTType . folder
31
+ private static let diskImageUTType = UTType . data
32
+
29
33
private var qemuVM : ( any UTMSpiceVirtualMachine ) ! {
30
34
vm. wrapped as? any UTMSpiceVirtualMachine
31
35
}
@@ -73,8 +77,21 @@ struct VMRemovableDrivesView: View {
73
77
} else {
74
78
Button ( " Browse… " , action: { shareDirectoryFileImportPresented. toggle ( ) } )
75
79
}
76
- } . fileImporter ( isPresented: $shareDirectoryFileImportPresented, allowedContentTypes: [ . folder] , onCompletion: selectShareDirectory)
77
- . disabled ( mode == . virtfs && vm. state != . stopped)
80
+ } . fileImporter ( isPresented: $shareDirectoryFileImportPresented, allowedContentTypes: [ Self . shareDirectoryUTType] , onCompletion: selectShareDirectory)
81
+ . disabled ( mode == . virtfs && vm. state != . stopped)
82
+ . onDrop ( of: [ Self . shareDirectoryUTType] , isTargeted: nil ) { providers in
83
+ guard let item = providers. first, item. hasItemConformingToTypeIdentifier ( Self . shareDirectoryUTType. identifier) else { return false }
84
+
85
+ item. loadItem ( forTypeIdentifier: Self . shareDirectoryUTType. identifier) { url, error in
86
+ if let url = url as? URL {
87
+ selectShareDirectory ( result: . success( url) )
88
+ }
89
+ if let error = error {
90
+ selectShareDirectory ( result: . failure( error) )
91
+ }
92
+ }
93
+ return true
94
+ }
78
95
}
79
96
ForEach ( config. drives. filter { $0. isExternal } ) { drive in
80
97
HStack {
@@ -128,12 +145,25 @@ struct VMRemovableDrivesView: View {
128
145
. lineLimit ( 1 )
129
146
. truncationMode ( . tail)
130
147
. foregroundColor ( . secondary)
131
- } . fileImporter ( isPresented: $diskImageFileImportPresented, allowedContentTypes: [ . data ] ) { result in
148
+ } . fileImporter ( isPresented: $diskImageFileImportPresented, allowedContentTypes: [ Self . diskImageUTType ] ) { result in
132
149
if let currentDrive = self . currentDrive {
133
150
selectRemovableImage ( forDrive: currentDrive, result: result)
134
151
self . currentDrive = nil
135
152
}
136
153
}
154
+ . onDrop ( of: [ Self . diskImageUTType] , isTargeted: nil ) { providers in
155
+ guard let item = providers. first, item. hasItemConformingToTypeIdentifier ( Self . diskImageUTType. identifier) else { return false }
156
+
157
+ item. loadItem ( forTypeIdentifier: Self . diskImageUTType. identifier) { url, error in
158
+ if let url = url as? URL {
159
+ selectRemovableImage ( forDrive: drive, result: . success( url) )
160
+ }
161
+ if let error {
162
+ selectRemovableImage ( forDrive: drive, result: . failure( error) )
163
+ }
164
+ }
165
+ return true
166
+ }
137
167
}
138
168
}
139
169
}
0 commit comments