Skip to content

Commit

Permalink
feat: rewrite of Device Service (#129)
Browse files Browse the repository at this point in the history
* feat: move custom commands to separate class

* refactor: rewrite of Device Service

* feat: add AppleUtilsTest

* feat: add action factory tests and Device discovery tests

* fix: skip failing test, move to action executor
  • Loading branch information
okwasniewski authored Sep 12, 2024
1 parent 0121c91 commit d8b552e
Show file tree
Hide file tree
Showing 32 changed files with 1,417 additions and 685 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ jobs:
key: ${{ runner.os }}-deriveddata-${{ hashFiles('**/*.xcodeproj/project.pbxproj') }}
- name: Test
run: |
xcodebuild -scheme MiniSim -destination 'platform=macOS' \
set -o pipefail && xcodebuild -scheme MiniSim -destination 'platform=macOS' \
-skipPackagePluginValidation -skipMacroValidation \
-derivedDataPath ${{ env.DERIVED_DATA_PATH }} \
test-without-building \
Expand Down
56 changes: 56 additions & 0 deletions MiniSim.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,20 @@
76BF0AD92C8CB3E6003BE568 /* AcknowList in Frameworks */ = {isa = PBXBuildFile; productRef = 76BF0AD82C8CB3E6003BE568 /* AcknowList */; };
76BF0ADB2C8CB4CD003BE568 /* Package.resolved in Resources */ = {isa = PBXBuildFile; fileRef = 76BF0ADA2C8CB4CD003BE568 /* Package.resolved */; };
76BF0ADD2C8DF660003BE568 /* AccessibilityElementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76BF0ADC2C8DF660003BE568 /* AccessibilityElementTests.swift */; };
76BF0ADF2C8E01B3003BE568 /* CustomCommandService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76BF0ADE2C8E01B3003BE568 /* CustomCommandService.swift */; };
76BF0AE12C8E027D003BE568 /* DeviceConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76BF0AE02C8E027D003BE568 /* DeviceConstants.swift */; };
76BF0AE32C8E041C003BE568 /* CustomCommandServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76BF0AE22C8E041C003BE568 /* CustomCommandServiceTests.swift */; };
76BF0AE62C8E0F83003BE568 /* Actions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76BF0AE52C8E0F83003BE568 /* Actions.swift */; };
76BF0AE82C8E1077003BE568 /* ActionFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76BF0AE72C8E1077003BE568 /* ActionFactory.swift */; };
76BF0AEA2C905A94003BE568 /* AppleUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76BF0AE92C905A94003BE568 /* AppleUtils.swift */; };
76BF0AEC2C905C37003BE568 /* AndroidDeviceService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76BF0AEB2C905C37003BE568 /* AndroidDeviceService.swift */; };
76BF0AEE2C905C43003BE568 /* IOSDeviceService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76BF0AED2C905C43003BE568 /* IOSDeviceService.swift */; };
76BF0AF02C9061E8003BE568 /* DeviceDiscoveryService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76BF0AEF2C9061E8003BE568 /* DeviceDiscoveryService.swift */; };
76BF0AF22C907033003BE568 /* DeviceServiceFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76BF0AF12C907032003BE568 /* DeviceServiceFactory.swift */; };
76BF0AF42C90A74E003BE568 /* AppleUtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76BF0AF32C90A74E003BE568 /* AppleUtilsTests.swift */; };
76BF0AF62C90AB03003BE568 /* DeviceDiscoveryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76BF0AF52C90AB03003BE568 /* DeviceDiscoveryTests.swift */; };
76BF0AF82C90ACF2003BE568 /* ActionFactoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76BF0AF72C90ACF2003BE568 /* ActionFactoryTests.swift */; };
76BF0AFA2C9367DE003BE568 /* ActionExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76BF0AF92C9367DE003BE568 /* ActionExecutor.swift */; };
76C1396A2C849A3F006CD80C /* MenuIcons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76C139692C849A3F006CD80C /* MenuIcons.swift */; };
76E4451229D4391000039025 /* Onboarding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76E4451129D4391000039025 /* Onboarding.swift */; };
76E4451429D4403F00039025 /* NSNotificationName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76E4451329D4403F00039025 /* NSNotificationName.swift */; };
Expand Down Expand Up @@ -178,6 +192,20 @@
76B70F832B0D5AB4009D87A4 /* Shell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shell.swift; sourceTree = "<group>"; };
76BF0ADA2C8CB4CD003BE568 /* Package.resolved */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Package.resolved; path = MiniSim.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved; sourceTree = SOURCE_ROOT; };
76BF0ADC2C8DF660003BE568 /* AccessibilityElementTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityElementTests.swift; sourceTree = "<group>"; };
76BF0ADE2C8E01B3003BE568 /* CustomCommandService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomCommandService.swift; sourceTree = "<group>"; };
76BF0AE02C8E027D003BE568 /* DeviceConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceConstants.swift; sourceTree = "<group>"; };
76BF0AE22C8E041C003BE568 /* CustomCommandServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomCommandServiceTests.swift; sourceTree = "<group>"; };
76BF0AE52C8E0F83003BE568 /* Actions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Actions.swift; sourceTree = "<group>"; };
76BF0AE72C8E1077003BE568 /* ActionFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionFactory.swift; sourceTree = "<group>"; };
76BF0AE92C905A94003BE568 /* AppleUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppleUtils.swift; sourceTree = "<group>"; };
76BF0AEB2C905C37003BE568 /* AndroidDeviceService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AndroidDeviceService.swift; sourceTree = "<group>"; };
76BF0AED2C905C43003BE568 /* IOSDeviceService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IOSDeviceService.swift; sourceTree = "<group>"; };
76BF0AEF2C9061E8003BE568 /* DeviceDiscoveryService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceDiscoveryService.swift; sourceTree = "<group>"; };
76BF0AF12C907032003BE568 /* DeviceServiceFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceServiceFactory.swift; sourceTree = "<group>"; };
76BF0AF32C90A74E003BE568 /* AppleUtilsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleUtilsTests.swift; sourceTree = "<group>"; };
76BF0AF52C90AB03003BE568 /* DeviceDiscoveryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceDiscoveryTests.swift; sourceTree = "<group>"; };
76BF0AF72C90ACF2003BE568 /* ActionFactoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionFactoryTests.swift; sourceTree = "<group>"; };
76BF0AF92C9367DE003BE568 /* ActionExecutor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionExecutor.swift; sourceTree = "<group>"; };
76C139692C849A3F006CD80C /* MenuIcons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenuIcons.swift; sourceTree = "<group>"; };
76E4451129D4391000039025 /* Onboarding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Onboarding.swift; sourceTree = "<group>"; };
76E4451329D4403F00039025 /* NSNotificationName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSNotificationName.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -311,9 +339,19 @@
55CDB0762B1B6D06002418D7 /* Terminal */,
76F269832A2A375900424BDA /* CustomErrors */,
7645D4BD2982A1B100019227 /* DeviceService.swift */,
76BF0AEB2C905C37003BE568 /* AndroidDeviceService.swift */,
76BF0AED2C905C43003BE568 /* IOSDeviceService.swift */,
76BF0AE92C905A94003BE568 /* AppleUtils.swift */,
7699511C2C845B1900462287 /* DeviceParser.swift */,
76F04A10298A5AE000BF9CA3 /* ADB.swift */,
76B70F832B0D5AB4009D87A4 /* Shell.swift */,
76BF0ADE2C8E01B3003BE568 /* CustomCommandService.swift */,
76BF0AE02C8E027D003BE568 /* DeviceConstants.swift */,
76BF0AE52C8E0F83003BE568 /* Actions.swift */,
76BF0AE72C8E1077003BE568 /* ActionFactory.swift */,
76BF0AEF2C9061E8003BE568 /* DeviceDiscoveryService.swift */,
76BF0AF12C907032003BE568 /* DeviceServiceFactory.swift */,
76BF0AF92C9367DE003BE568 /* ActionExecutor.swift */,
);
path = Service;
sourceTree = "<group>";
Expand Down Expand Up @@ -418,6 +456,10 @@
7699511E2C845CBA00462287 /* DeviceParserTests.swift */,
76B70F812B0D50FE009D87A4 /* ADBTests.swift */,
76BF0ADC2C8DF660003BE568 /* AccessibilityElementTests.swift */,
76BF0AE22C8E041C003BE568 /* CustomCommandServiceTests.swift */,
76BF0AF32C90A74E003BE568 /* AppleUtilsTests.swift */,
76BF0AF52C90AB03003BE568 /* DeviceDiscoveryTests.swift */,
76BF0AF72C90ACF2003BE568 /* ActionFactoryTests.swift */,
);
path = MiniSimTests;
sourceTree = "<group>";
Expand Down Expand Up @@ -612,7 +654,9 @@
76F269852A2A376A00424BDA /* CustomCommandError.swift in Sources */,
767799A029C30BF5009030F8 /* BlurredView.swift in Sources */,
7645D4C42982CB2B00019227 /* MiniSim.swift in Sources */,
76BF0ADF2C8E01B3003BE568 /* CustomCommandService.swift in Sources */,
76F2A912299033EA002D4EF6 /* DeviceError.swift in Sources */,
76BF0AE12C8E027D003BE568 /* DeviceConstants.swift in Sources */,
7631218E2A12B3BA00EE7F48 /* CustomCommandsViewModel.swift in Sources */,
4AFACC782AD74E9000EC369F /* DeviceListSection.swift in Sources */,
760554A32C085BEA001607FE /* Thread+Asserts.swift in Sources */,
Expand All @@ -623,14 +667,18 @@
76630F0E29BDE7EB00FB64F9 /* ParametersTable.swift in Sources */,
7677999829C25894009030F8 /* OnboardingPager.swift in Sources */,
52B363EC2AEC10A3006F515C /* ParametersTableForm.swift in Sources */,
76BF0AEC2C905C37003BE568 /* AndroidDeviceService.swift in Sources */,
7630B2682985C4CF00D8B57D /* About.swift in Sources */,
76BF0AF02C9061E8003BE568 /* DeviceDiscoveryService.swift in Sources */,
7699511D2C845B1900462287 /* DeviceParser.swift in Sources */,
76630F0C29BDD0C000FB64F9 /* Devices.swift in Sources */,
767C761F29B26ED3009B9AEC /* AccessibilityElement.swift in Sources */,
7610992F2A3F95D90067885A /* NSScriptCommand+utils.swift in Sources */,
4AFACC762AD73D7900EC369F /* NSMenuItem+ConvenienceInit.swift in Sources */,
76F269872A2A39D100424BDA /* Variables.swift in Sources */,
76BF0AF22C907033003BE568 /* DeviceServiceFactory.swift in Sources */,
764BA3EB2A5AD43F003A78AF /* LaunchDeviceCommand.swift in Sources */,
76BF0AE62C8E0F83003BE568 /* Actions.swift in Sources */,
7630B2732986C68000D8B57D /* PaneIdentifier.swift in Sources */,
7630B2662985C44A00D8B57D /* Preferences.swift in Sources */,
7625140B2992B46D0060A225 /* Pasteboard+utils.swift in Sources */,
Expand All @@ -643,11 +691,13 @@
76AC9AF62A0EA82C00864A8B /* CustomCommands.swift in Sources */,
76489D5C29BFCA330070EF03 /* OnboardingItem.swift in Sources */,
7645D5012982E6FA00019227 /* main.swift in Sources */,
76BF0AEA2C905A94003BE568 /* AppleUtils.swift in Sources */,
76F2A914299050F9002D4EF6 /* UserDefaults+Configuration.swift in Sources */,
76059BF72AD449DC0008D38B /* OnboardingHeader.swift in Sources */,
763121902A12B45000EE7F48 /* CustomCommandFormViewModel.swift in Sources */,
52B363EE2AEC10B3006F515C /* ParametersTableFormViewModel.swift in Sources */,
7630B2772986D65800D8B57D /* Bundle+appName.swift in Sources */,
76BF0AFA2C9367DE003BE568 /* ActionExecutor.swift in Sources */,
763121892A12AF9C00EE7F48 /* Command.swift in Sources */,
767DDF6829D32ABC005E6F32 /* ReadyPopOver.swift in Sources */,
764BA3E92A5AD418003A78AF /* GetDevicesCommand.swift in Sources */,
Expand All @@ -664,9 +714,11 @@
7630B26D2986B4FD00D8B57D /* KeyboardShortcuts.swift in Sources */,
76059BF52AD4361C0008D38B /* SetupPreferences.swift in Sources */,
7684FAAF29D202F500230BB0 /* AndroidHomeError.swift in Sources */,
76BF0AE82C8E1077003BE568 /* ActionFactory.swift in Sources */,
76C1396A2C849A3F006CD80C /* MenuIcons.swift in Sources */,
55CDB0782B1B6D24002418D7 /* TerminalApps.swift in Sources */,
9B225A9C2C7E360D002620BA /* DeviceType.swift in Sources */,
76BF0AEE2C905C43003BE568 /* IOSDeviceService.swift in Sources */,
7645D4BE2982A1B100019227 /* DeviceService.swift in Sources */,
765ABF382A8BECD900A063CB /* ExecuteCommand.swift in Sources */,
);
Expand All @@ -676,8 +728,12 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
76BF0AF62C90AB03003BE568 /* DeviceDiscoveryTests.swift in Sources */,
7699511F2C845CBA00462287 /* DeviceParserTests.swift in Sources */,
76BF0ADD2C8DF660003BE568 /* AccessibilityElementTests.swift in Sources */,
76BF0AE32C8E041C003BE568 /* CustomCommandServiceTests.swift in Sources */,
76BF0AF42C90A74E003BE568 /* AppleUtilsTests.swift in Sources */,
76BF0AF82C90ACF2003BE568 /* ActionFactoryTests.swift in Sources */,
76B70F7E2B0D361A009D87A4 /* UserDefaultsTests.swift in Sources */,
760DEACE2B0DFB6600253576 /* ShellStub.swift in Sources */,
76B70F822B0D50FE009D87A4 /* ADBTests.swift in Sources */,
Expand Down
20 changes: 6 additions & 14 deletions MiniSim/AppleScript Commands/ExecuteCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,13 @@ class ExecuteCommand: NSScriptCommand {
guard let menuItem = SubMenuItems.Tags(rawValue: rawTag) else {
return nil
}
let actionExecutor = ActionExecutor()
actionExecutor.execute(
device: device,
commandTag: menuItem,
itemName: commandName
)

switch platform {
case .android:
DeviceService.handleAndroidAction(
device: device,
commandTag: menuItem,
itemName: commandName
)
case .ios:
DeviceService.handleiOSAction(
device: device,
commandTag: menuItem,
itemName: commandName
)
}
return nil
}
}
2 changes: 1 addition & 1 deletion MiniSim/AppleScript Commands/GetCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class GetCommands: NSScriptCommand {
let commands = SubMenuItems.items(platform: platform, deviceType: deviceType)
.compactMap { $0 as? SubMenuActionItem }
.map { $0.commandItem }
let customCommands = DeviceService.getCustomCommands(platform: platform)
let customCommands = CustomCommandService.getCustomCommands(platform: platform)
.map { command in
Command(
id: command.id,
Expand Down
11 changes: 1 addition & 10 deletions MiniSim/AppleScript Commands/GetDevicesCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,7 @@ class GetDevicesCommand: NSScriptCommand {
}

do {
switch (platform, deviceType) {
case (.android, .physical):
return try self.encode(DeviceService.getAndroidPhysicalDevices())
case (.android, .virtual):
return try self.encode(DeviceService.getAndroidEmulators())
case (.ios, .physical):
return try self.encode(DeviceService.getIOSPhysicalDevices())
case (.ios, .virtual):
return try self.encode(DeviceService.getIOSSimulators())
}
return try self.encode(DeviceServiceFactory.getDeviceDiscoveryService(platform: platform).getDevices(type: deviceType))

Check warning on line 24 in MiniSim/AppleScript Commands/GetDevicesCommand.swift

View workflow job for this annotation

GitHub Actions / lint

Line Length Violation: Line should be 120 characters or less; currently it has 131 characters (line_length)
} catch {
scriptErrorNumber = NSInternalScriptError
return nil
Expand Down
8 changes: 4 additions & 4 deletions MiniSim/AppleScript Commands/LaunchDeviceCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,20 @@ class LaunchDeviceCommand: NSScriptCommand {

do {
var devices: [Device] = []
try devices.append(contentsOf: DeviceService.getIOSDevices())
try devices.append(contentsOf: DeviceService.getAndroidDevices())
try devices.append(contentsOf: DeviceServiceFactory.getDeviceDiscoveryService(platform: .ios).getDevices())
try devices.append(contentsOf: DeviceServiceFactory.getDeviceDiscoveryService(platform: .android).getDevices())

Check warning on line 21 in MiniSim/AppleScript Commands/LaunchDeviceCommand.swift

View workflow job for this annotation

GitHub Actions / lint

Line Length Violation: Line should be 120 characters or less; currently it has 123 characters (line_length)

guard let device = devices.first(where: { $0.name == deviceName }) else {
scriptErrorNumber = NSInternalScriptError
return nil
}

if device.booted {
DeviceService.focusDevice(device)
device.focus()
return nil
}

DeviceService.launch(device: device) { _ in }
try? device.launch()
return nil
} catch {
scriptErrorNumber = NSInternalScriptError
Expand Down
41 changes: 20 additions & 21 deletions MiniSim/Menu.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import UserNotifications

class Menu: NSMenu {

Check warning on line 12 in MiniSim/Menu.swift

View workflow job for this annotation

GitHub Actions / lint

Type Body Length Violation: Type body should span 250 lines or less excluding comments and whitespace: currently spans 254 lines (type_body_length)
public let maxKeyEquivalent = 9
let actionExecutor = ActionExecutor()

var devices: [Device] = [] {
didSet {
Expand Down Expand Up @@ -71,7 +72,7 @@ class Menu: NSMenu {

func updateDevicesList() {
let userDefaults = UserDefaults.standard
DeviceService.getAllDevices(
DeviceServiceFactory.getAllDevices(
android: userDefaults.enableAndroidEmulators && userDefaults.androidHome != nil,
iOS: userDefaults.enableiOSSimulators
) { devices, error in
Expand All @@ -93,30 +94,28 @@ class Menu: NSMenu {
.forEach(safeRemoveItem)
}

@objc private func androidSubMenuClick(_ sender: NSMenuItem) {
guard let tag = SubMenuItems.Tags(rawValue: sender.tag) else { return }
guard let device = getDeviceByName(name: sender.parent?.title ?? "") else { return }
@objc private func subMenuClick(_ sender: NSMenuItem) {
guard let tag = SubMenuItems.Tags(rawValue: sender.tag) else { return }
guard let device = getDeviceByName(name: sender.parent?.title ?? "") else { return }

DeviceService.handleAndroidAction(device: device, commandTag: tag, itemName: sender.title)
}

@objc private func IOSSubMenuClick(_ sender: NSMenuItem) {
guard let tag = SubMenuItems.Tags(rawValue: sender.tag) else { return }
guard let device = getDeviceByName(name: sender.parent?.title ?? "") else { return }

DeviceService.handleiOSAction(device: device, commandTag: tag, itemName: sender.title)
actionExecutor.execute(
device: device,
commandTag: tag,
itemName: sender.title
)
}

@objc private func deviceItemClick(_ sender: NSMenuItem) {
guard let device = getDeviceByName(name: sender.title), device.type == .virtual else { return }

if device.booted {
DeviceService.focusDevice(device)
return
}

DeviceService.launch(device: device) { error in
if let error {
DispatchQueue.global().async {
if device.booted {
device.focus()
return
}
do {
try device.launch()
} catch {
NSAlert.showError(message: error.localizedDescription)
}
}
Expand Down Expand Up @@ -242,7 +241,7 @@ class Menu: NSMenu {
let subMenu = NSMenu()
let platform = device.platform
let deviceType = device.type
let callback = platform == .android ? #selector(androidSubMenuClick) : #selector(IOSSubMenuClick)
let callback = #selector(subMenuClick)
let actionsSubMenu = createActionsSubMenu(
for: SubMenuItems.items(platform: platform, deviceType: deviceType),
isDeviceBooted: device.booted,
Expand Down Expand Up @@ -284,7 +283,7 @@ class Menu: NSMenu {
}

func createCustomCommandsMenu(for platform: Platform, isDeviceBooted: Bool, callback: Selector) -> [NSMenuItem] {
DeviceService.getCustomCommands(platform: platform)
CustomCommandService.getCustomCommands(platform: platform)
.filter { item in
if item.needBootedDevice && !isDeviceBooted {
return false
Expand Down
2 changes: 1 addition & 1 deletion MiniSim/MenuItems/SubMenuItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ protocol SubMenuActionItem: SubMenuItem {
}

enum SubMenuItems {
enum Tags: Int {
enum Tags: Int, CaseIterable {
case copyName = 100
case copyID
case coldBoot
Expand Down
Loading

0 comments on commit d8b552e

Please sign in to comment.