@@ -11,14 +11,11 @@ import AppKit
11
11
import UserNotifications
12
12
13
13
protocol DeviceServiceProtocol {
14
- static func launchDevice( uuid: String ) throws
15
14
static func getIOSDevices( ) throws -> [ Device ]
16
15
static func checkXcodeSetup( ) -> Bool
17
16
static func deleteSimulator( uuid: String ) throws
18
- static func clearDerivedData( ) throws -> String
19
17
static func handleiOSAction( device: Device , commandTag: IOSSubMenuItem , itemName: String )
20
18
21
- static func launchDevice( name: String , additionalArguments: [ String ] ) throws
22
19
static func toggleA11y( device: Device ) throws
23
20
static func getAndroidDevices( ) throws -> [ Device ]
24
21
static func sendText( device: Device , text: String ) throws
@@ -34,6 +31,7 @@ protocol DeviceServiceProtocol {
34
31
35
32
class DeviceService : DeviceServiceProtocol {
36
33
34
+ private static let queue = DispatchQueue ( label: " com.MiniSim.DeviceService " , qos: . userInteractive)
37
35
private static let deviceBootedError = " Unable to boot device in current state: Booted "
38
36
39
37
private static let derivedDataLocation = " ~/Library/Developer/Xcode/DerivedData "
@@ -93,7 +91,7 @@ class DeviceService: DeviceServiceProtocol {
93
91
}
94
92
95
93
static func focusDevice( _ device: Device ) {
96
- DispatchQueue . global ( qos : . userInitiated ) . async {
94
+ queue . async {
97
95
98
96
let runningApps = NSWorkspace . shared. runningApplications. filter ( { $0. activationPolicy == . regular} )
99
97
@@ -155,6 +153,63 @@ class DeviceService: DeviceServiceProtocol {
155
153
UNUserNotificationCenter . showNotification ( title: title, body: message)
156
154
NotificationCenter . default. post ( name: . commandDidSucceed, object: nil )
157
155
}
156
+
157
+ static func getAllDevices(
158
+ android: Bool ,
159
+ iOS: Bool ,
160
+ completionQueue: DispatchQueue = . main,
161
+ completion: @escaping ( [ Device ] , Error ? ) -> ( )
162
+ ) {
163
+ queue. async {
164
+ do {
165
+ var devicesArray : [ Device ] = [ ]
166
+
167
+ if android {
168
+ try devicesArray. append ( contentsOf: getAndroidDevices ( ) )
169
+ }
170
+
171
+ if iOS {
172
+ try devicesArray. append ( contentsOf: getIOSDevices ( ) )
173
+ }
174
+
175
+ completionQueue. async {
176
+ completion ( devicesArray, nil )
177
+ }
178
+ } catch {
179
+ completionQueue. async {
180
+ completion ( [ ] , error)
181
+ }
182
+ }
183
+ }
184
+ }
185
+
186
+ private static func launch( device: Device ) throws {
187
+ switch device. platform {
188
+ case . ios:
189
+ try launchDevice ( uuid: device. ID ?? " " )
190
+ case . android:
191
+ try launchDevice ( name: device. name)
192
+ }
193
+ }
194
+
195
+ static func launch( device: Device , completionQueue: DispatchQueue = . main, completion: @escaping ( Error ? ) -> Void ) {
196
+ self . queue. async {
197
+ do {
198
+ try self . launch ( device: device)
199
+ completionQueue. async {
200
+ completion ( nil )
201
+ }
202
+ }
203
+ catch {
204
+ guard error. localizedDescription. contains ( deviceBootedError) else {
205
+ return
206
+ }
207
+ completionQueue. async {
208
+ completion ( error)
209
+ }
210
+ }
211
+ }
212
+ }
158
213
}
159
214
160
215
// MARK: iOS Methods
@@ -182,10 +237,21 @@ extension DeviceService {
182
237
return devices
183
238
}
184
239
185
- static func clearDerivedData( ) throws -> String {
186
- let amountCleared = try ? shellOut ( to: " du -sh \( derivedDataLocation) " ) . match ( ###"\d+\.?\d+\w+"### ) . first? . first
187
- try shellOut ( to: " rm -rf \( derivedDataLocation) " )
188
- return amountCleared ?? " "
240
+ static func clearDerivedData( completionQueue: DispatchQueue = . main, completion: @escaping ( String , Error ? ) -> Void ) {
241
+ self . queue. async {
242
+ do {
243
+ let amountCleared = try ? shellOut ( to: " du -sh \( derivedDataLocation) " ) . match ( ###"\d+\.?\d+\w+"### ) . first? . first
244
+ try shellOut ( to: " rm -rf \( derivedDataLocation) " )
245
+ completionQueue. async {
246
+ completion ( amountCleared ?? " " , nil )
247
+ }
248
+ }
249
+ catch {
250
+ completionQueue. async {
251
+ completion ( " " , error)
252
+ }
253
+ }
254
+ }
189
255
}
190
256
191
257
static func getIOSDevices( ) throws -> [ Device ] {
@@ -206,7 +272,7 @@ extension DeviceService {
206
272
}
207
273
}
208
274
209
- static func launchDevice( uuid: String ) throws {
275
+ private static func launchDevice( uuid: String ) throws {
210
276
do {
211
277
try self . launchSimulatorApp ( uuid: uuid)
212
278
try shellOut ( to: ProcessPaths . xcrun. rawValue, arguments: [ " simctl " , " boot " , uuid] )
@@ -237,7 +303,7 @@ extension DeviceService {
237
303
if !NSAlert. showQuestionDialog ( title: " Are you sure? " , message: " Are you sure you want to delete this Simulator? " ) {
238
304
return
239
305
}
240
- DispatchQueue . global ( qos : . userInitiated ) . async {
306
+ queue . async {
241
307
do {
242
308
try DeviceService . deleteSimulator ( uuid: deviceID)
243
309
DeviceService . showSuccessMessage ( title: " Simulator deleted! " , message: deviceID)
@@ -250,7 +316,7 @@ extension DeviceService {
250
316
guard let command = DeviceService . getCustomCommand ( platform: . ios, commandName: itemName) else {
251
317
return
252
318
}
253
- DispatchQueue . global ( qos : . userInitiated ) . async {
319
+ queue . async {
254
320
do {
255
321
try DeviceService . runCustomCommand ( device, command: command)
256
322
} catch {
@@ -267,7 +333,7 @@ extension DeviceService {
267
333
268
334
// MARK: Android Methods
269
335
extension DeviceService {
270
- static func launchDevice( name: String , additionalArguments: [ String ] = [ ] ) throws {
336
+ private static func launchDevice( name: String , additionalArguments: [ String ] = [ ] ) throws {
271
337
let emulatorPath = try ADB . getEmulatorPath ( )
272
338
var arguments = [ " @ \( name) " ]
273
339
let formattedArguments = additionalArguments. filter ( { !$0. isEmpty } ) . map {
0 commit comments