diff --git a/MiniSim.xcodeproj/project.pbxproj b/MiniSim.xcodeproj/project.pbxproj index ea7a113..89d643a 100644 --- a/MiniSim.xcodeproj/project.pbxproj +++ b/MiniSim.xcodeproj/project.pbxproj @@ -75,6 +75,7 @@ 76AC9AF62A0EA82C00864A8B /* CustomCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76AC9AF52A0EA82C00864A8B /* CustomCommands.swift */; }; 76AC9AF92A0EB50800864A8B /* SymbolPicker in Frameworks */ = {isa = PBXBuildFile; productRef = 76AC9AF82A0EB50800864A8B /* SymbolPicker */; }; 76B70F7E2B0D361A009D87A4 /* UserDefaultsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76B70F7D2B0D361A009D87A4 /* UserDefaultsTests.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 */; }; 76F04A11298A5AE000BF9CA3 /* ADB.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76F04A10298A5AE000BF9CA3 /* ADB.swift */; }; @@ -165,6 +166,7 @@ 76AC9AF52A0EA82C00864A8B /* CustomCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomCommands.swift; sourceTree = ""; }; 76B70F742B0D359D009D87A4 /* MiniSimTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MiniSimTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 76B70F7D2B0D361A009D87A4 /* UserDefaultsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsTests.swift; sourceTree = ""; }; + 76C139692C849A3F006CD80C /* MenuIcons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenuIcons.swift; sourceTree = ""; }; 76E4451129D4391000039025 /* Onboarding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Onboarding.swift; sourceTree = ""; }; 76E4451329D4403F00039025 /* NSNotificationName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSNotificationName.swift; sourceTree = ""; }; 76F04A10298A5AE000BF9CA3 /* ADB.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ADB.swift; sourceTree = ""; }; @@ -225,6 +227,7 @@ 762CF1E12981DDD400099999 /* Extensions */ = { isa = PBXGroup; children = ( + 76C139692C849A3F006CD80C /* MenuIcons.swift */, 762CF1DF2981968F00099999 /* String+match.swift */, 7645D5022983186100019227 /* NSMenuItem+ImageInit.swift */, 7630B26C2986B4FD00D8B57D /* KeyboardShortcuts.swift */, @@ -629,6 +632,7 @@ 7630B26D2986B4FD00D8B57D /* KeyboardShortcuts.swift in Sources */, 76059BF52AD4361C0008D38B /* SetupPreferences.swift in Sources */, 7684FAAF29D202F500230BB0 /* AndroidHomeError.swift in Sources */, + 76C1396A2C849A3F006CD80C /* MenuIcons.swift in Sources */, 55CDB0782B1B6D24002418D7 /* TerminalApps.swift in Sources */, 7645D4BE2982A1B100019227 /* DeviceService.swift in Sources */, 765ABF382A8BECD900A063CB /* ExecuteCommand.swift in Sources */, diff --git a/MiniSim.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/MiniSim.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 22f72c7..69666ae 100644 --- a/MiniSim.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/MiniSim.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,12 +1,13 @@ { + "originHash" : "0f54c1839af540375e74773a085736f629e4bd164fe1acab202e049e59f9fc7b", "pins" : [ { "identity" : "codeeditor", "kind" : "remoteSourceControl", "location" : "https://github.com/ZeeZide/CodeEditor.git", "state" : { - "revision" : "180bde07b44dea839b32873bd8586ba146fa9106", - "version" : "1.2.2" + "revision" : "f5c076b94f4ceb05abff88ba91d75a8d57143f0c", + "version" : "1.2.6" } }, { @@ -23,17 +24,17 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/krzyzanowskim/CryptoSwift.git", "state" : { - "revision" : "db51c407d3be4a051484a141bf0bff36c43d3b1e", - "version" : "1.8.0" + "revision" : "678d442c6f7828def400a70ae15968aef67ef52d", + "version" : "1.8.3" } }, { "identity" : "highlightr", "kind" : "remoteSourceControl", - "location" : "https://github.com/raspu/Highlightr", + "location" : "https://github.com/helje5/Highlightr", "state" : { - "revision" : "93199b9e434f04bda956a613af8f571933f9f037", - "version" : "2.1.2" + "revision" : "bd0358056ff1f12ea83833a9fc1b3b5a396a9da0", + "version" : "3.0.2" } }, { @@ -42,7 +43,7 @@ "location" : "https://github.com/sindresorhus/KeyboardShortcuts", "state" : { "branch" : "main", - "revision" : "d7b349f6822e24228141e560aa48a32dca23b22c" + "revision" : "e6b60117ec266e1e5d059f7f34815144f9762b36" } }, { @@ -51,7 +52,7 @@ "location" : "https://github.com/sindresorhus/LaunchAtLogin", "state" : { "branch" : "main", - "revision" : "7ad6331f9c38953eb1ce8737758e18f7607e984a" + "revision" : "9a894d799269cb591037f9f9cb0961510d4dca81" } }, { @@ -77,8 +78,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/jpsim/SourceKitten.git", "state" : { - "revision" : "b6dc09ee51dfb0c66e042d2328c017483a1a5d56", - "version" : "0.34.1" + "revision" : "fd4df99170f5e9d7cf9aa8312aa8506e0e7a44e7", + "version" : "0.35.0" } }, { @@ -86,8 +87,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/sparkle-project/Sparkle", "state" : { - "revision" : "9d85a02fe7916caa7531847452c4933d331503a5", - "version" : "2.3.1" + "revision" : "0ef1ee0220239b3776f433314515fd849025673f", + "version" : "2.6.4" } }, { @@ -95,17 +96,17 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-argument-parser.git", "state" : { - "revision" : "8f4d2753f0e4778c76d5f05ad16c74f707390531", - "version" : "1.2.3" + "revision" : "41982a3656a71c768319979febd796c6fd111d5c", + "version" : "1.5.0" } }, { "identity" : "swift-syntax", "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-syntax.git", + "location" : "https://github.com/swiftlang/swift-syntax.git", "state" : { - "revision" : "6ad4ea24b01559dde0773e3d091f1b9e36175036", - "version" : "509.0.2" + "revision" : "515f79b522918f83483068d99c68daeb5116342d", + "version" : "600.0.0-prerelease-2024-08-14" } }, { @@ -113,8 +114,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/realm/SwiftLint.git", "state" : { - "revision" : "f17a4f9dfb6a6afb0408426354e4180daaf49cee", - "version" : "0.54.0" + "revision" : "a24488f26e60247d8fff7bbb03d51910af3dc91c", + "version" : "0.56.2" } }, { @@ -140,8 +141,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/xnth97/SymbolPicker.git", "state" : { - "revision" : "1e81757fc81fdee86f48d101eab0d0f8e9e0ec3d", - "version" : "1.4.2" + "revision" : "f82b64bcc3d761c9e63aaa10b1912bba72cbf6d8", + "version" : "1.5.3" } }, { @@ -149,10 +150,10 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/jpsim/Yams.git", "state" : { - "revision" : "0d9ee7ea8c4ebd4a489ad7a73d5c6cad55d6fed3", - "version" : "5.0.6" + "revision" : "3036ba9d69cf1fd04d433527bc339dc0dc75433d", + "version" : "5.1.3" } } ], - "version" : 2 + "version" : 3 } diff --git a/MiniSim/.DS_Store b/MiniSim/.DS_Store deleted file mode 100644 index ac0456c..0000000 Binary files a/MiniSim/.DS_Store and /dev/null differ diff --git a/MiniSim/Assets.xcassets/.DS_Store b/MiniSim/Assets.xcassets/.DS_Store deleted file mode 100644 index ebde57b..0000000 Binary files a/MiniSim/Assets.xcassets/.DS_Store and /dev/null differ diff --git a/MiniSim/Assets.xcassets/box.imageset/Contents.json b/MiniSim/Assets.xcassets/box.imageset/Contents.json new file mode 100644 index 0000000..d0d8cc5 --- /dev/null +++ b/MiniSim/Assets.xcassets/box.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "archivebox@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MiniSim/Assets.xcassets/box.imageset/archivebox@2x.png b/MiniSim/Assets.xcassets/box.imageset/archivebox@2x.png new file mode 100644 index 0000000..90151e9 Binary files /dev/null and b/MiniSim/Assets.xcassets/box.imageset/archivebox@2x.png differ diff --git a/MiniSim/Assets.xcassets/ipad.imageset/Contents.json b/MiniSim/Assets.xcassets/ipad.imageset/Contents.json new file mode 100644 index 0000000..85e006c --- /dev/null +++ b/MiniSim/Assets.xcassets/ipad.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "ipad.landscape@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MiniSim/Assets.xcassets/ipad.imageset/ipad.landscape@2x.png b/MiniSim/Assets.xcassets/ipad.imageset/ipad.landscape@2x.png new file mode 100644 index 0000000..f1ebaf5 Binary files /dev/null and b/MiniSim/Assets.xcassets/ipad.imageset/ipad.landscape@2x.png differ diff --git a/MiniSim/Assets.xcassets/menu_icon.imageset/Contents.json b/MiniSim/Assets.xcassets/iphone.imageset/Contents.json similarity index 88% rename from MiniSim/Assets.xcassets/menu_icon.imageset/Contents.json rename to MiniSim/Assets.xcassets/iphone.imageset/Contents.json index 1ad9e47..1e89037 100644 --- a/MiniSim/Assets.xcassets/menu_icon.imageset/Contents.json +++ b/MiniSim/Assets.xcassets/iphone.imageset/Contents.json @@ -5,7 +5,7 @@ "scale" : "1x" }, { - "filename" : "menu_icon.png", + "filename" : "iphone@2x.png", "idiom" : "universal", "scale" : "2x" }, diff --git a/MiniSim/Assets.xcassets/menu_icon.imageset/menu_icon.png b/MiniSim/Assets.xcassets/iphone.imageset/iphone@2x.png similarity index 100% rename from MiniSim/Assets.xcassets/menu_icon.imageset/menu_icon.png rename to MiniSim/Assets.xcassets/iphone.imageset/iphone@2x.png diff --git a/MiniSim/Extensions/MenuIcons.swift b/MiniSim/Extensions/MenuIcons.swift new file mode 100644 index 0000000..540c6ee --- /dev/null +++ b/MiniSim/Extensions/MenuIcons.swift @@ -0,0 +1,28 @@ +import AppKit +import Foundation + +enum MenuImage: String, CaseIterable { + case iphone = "iphone" + case ipad = "ipad" + case box = "box" + + var image: NSImage? { + guard let itemImage = NSImage(named: self.rawValue) else { + return nil + } + itemImage.size = size + itemImage.isTemplate = true + return itemImage + } + + var size: NSSize { + switch self { + case .box: + return NSSize(width: 16.5, height: 15) + case .ipad: + return NSSize(width: 19, height: 14) + case .iphone: + return NSSize(width: 11, height: 19) + } + } +} diff --git a/MiniSim/Extensions/UserDefaults+Configuration.swift b/MiniSim/Extensions/UserDefaults+Configuration.swift index cdc0086..4685bd3 100644 --- a/MiniSim/Extensions/UserDefaults+Configuration.swift +++ b/MiniSim/Extensions/UserDefaults+Configuration.swift @@ -16,6 +16,7 @@ extension UserDefaults { static let enableiOSSimulators = "enableiOSSimulators" static let enableAndroidEmulators = "enableAndroidEmulators" static let preferedTerminal = "preferedTerminal" + static let menuImage = "menuImage" } @objc public dynamic var androidHome: String? { @@ -28,6 +29,11 @@ extension UserDefaults { set { set(newValue, forKey: Keys.isOnboardingFinished) } } + @objc public dynamic var menuImage: String { + get { string(forKey: Keys.menuImage) ?? "iphone" } + set { set(newValue, forKey: Keys.menuImage) } + } + public var parameters: Data? { get { object(forKey: Keys.parameters) as? Data } set { set(newValue, forKey: Keys.parameters) } diff --git a/MiniSim/MiniSim.swift b/MiniSim/MiniSim.swift index 152f145..f1f83a4 100644 --- a/MiniSim/MiniSim.swift +++ b/MiniSim/MiniSim.swift @@ -11,194 +11,187 @@ import SwiftUI import UserNotifications class MiniSim: NSObject { - private var menu: Menu! - - @objc let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) - - private var isOnboardingFinishedObserver: NSKeyValueObservation? - - private lazy var onboarding = Onboarding() - - override init() { - super.init() - - settingsController.window?.delegate = self - - setDefaultValues() - initObservers() - - setup() + private var menu: Menu! + + @objc var statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) + + private var isOnboardingFinishedObserver: NSKeyValueObservation? + private var menuImageObserver: NSKeyValueObservation? + + private lazy var onboarding = Onboarding() + + override init() { + super.init() + + settingsController.window?.delegate = self + + setDefaultValues() + initObservers() + + setup() + } + + deinit { + isOnboardingFinishedObserver?.invalidate() + menuImageObserver?.invalidate() + NotificationCenter.default.removeObserver(self, name: .commandDidSucceed, object: nil) + NotificationCenter.default.removeObserver(self, name: .deviceDeleted, object: nil) + } + + private lazy var settingsController = SettingsWindowController( + panes: [ + Settings.Pane( + identifier: .preferences, + title: "Preferences", + toolbarIcon: NSImage(systemSymbolName: "gear", accessibilityDescription: "") ?? NSImage() + ) { + Preferences() + }, + Settings.Pane( + identifier: .devices, + title: "Devices", + toolbarIcon: NSImage(systemSymbolName: "iphone", accessibilityDescription: "") ?? NSImage() + ) { + Devices() + }, + Settings.Pane( + identifier: .commands, + title: "Commands", + toolbarIcon: NSImage(systemSymbolName: "command", accessibilityDescription: "") ?? NSImage() + ) { + CustomCommands() + }, + Settings.Pane( + identifier: .about, + title: "About", + toolbarIcon: NSImage(systemSymbolName: "info.circle", accessibilityDescription: "") ?? NSImage() + ) { + About() + } + ], + style: .toolbarItems, + animated: false + ) + + func open() { + self.statusItem.button?.performClick(self) + } + + private func setup() { + if !UserDefaults.standard.isOnboardingFinished { + onboarding.show() + return } + menu = Menu() + statusItem.menu = menu + setMenuImage() - deinit { - isOnboardingFinishedObserver?.invalidate() - NotificationCenter.default.removeObserver(self, name: .commandDidSucceed, object: nil) - NotificationCenter.default.removeObserver(self, name: .deviceDeleted, object: nil) + if menu.items.isEmpty { + menu.populateDefaultMenu() + menu.items += mainMenu } - - private lazy var settingsController = SettingsWindowController( - panes: [ - Settings.Pane( - identifier: .preferences, - title: "Preferences", - toolbarIcon: NSImage(systemSymbolName: "gear", accessibilityDescription: "") ?? NSImage() - ) { - Preferences() - }, - Settings.Pane( - identifier: .devices, - title: "Devices", - toolbarIcon: NSImage(systemSymbolName: "iphone", accessibilityDescription: "") ?? NSImage() - ) { - Devices() - }, - Settings.Pane( - identifier: .commands, - title: "Commands", - toolbarIcon: NSImage(systemSymbolName: "command", accessibilityDescription: "") ?? NSImage() - ) { - CustomCommands() - }, - Settings.Pane( - identifier: .about, - title: "About", - toolbarIcon: NSImage(systemSymbolName: "info.circle", accessibilityDescription: "") ?? NSImage() - ) { - About() - } - ], - style: .toolbarItems, - animated: false - ) - - func open() { - self.statusItem.button?.performClick(self) + menu.updateDevicesList() + } + + private func initObservers() { + isOnboardingFinishedObserver = UserDefaults.standard.observe(\.isOnboardingFinished, options: .new) { _, _ in + if UserDefaults.standard.isOnboardingFinished == true { + self.setup() + self.onboarding.showPopOver(button: self.statusItem.button) + } } - - private func setup() { - if !UserDefaults.standard.isOnboardingFinished { - onboarding.show() - return - } - menu = Menu() - statusItem.menu = menu - setMenuImage() - - if menu.items.isEmpty { - menu.populateDefaultMenu() - menu.items += mainMenu - } - menu.updateDevicesList() + menuImageObserver = UserDefaults.standard.observe(\.menuImage, options: .new) { _, _ in + self.setMenuImage() } - - private func initObservers() { - isOnboardingFinishedObserver = UserDefaults.standard.observe(\.isOnboardingFinished, options: .new) { _, _ in - if UserDefaults.standard.isOnboardingFinished == true { - self.setup() - self.onboarding.showPopOver(button: self.statusItem.button) - } - } - let notificationCenter = NotificationCenter.default - notificationCenter.addObserver( - self, - selector: #selector(toggleSuccessCheckmark), - name: .commandDidSucceed, - object: nil - ) - notificationCenter.addObserver( - self, - selector: #selector(handleDeviceDeleted), - name: .deviceDeleted, - object: nil - ) + NotificationCenter.default.addObserver(self, selector: #selector(toggleSuccessCheckmark), name: .commandDidSucceed, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(handleDeviceDeleted), name: .deviceDeleted, object: nil) + } + + private func setDefaultValues() { + UserDefaults.standard.register(defaults: [ + UserDefaults.Keys.enableAndroidEmulators: true, + UserDefaults.Keys.enableiOSSimulators: true, + UserDefaults.Keys.preferedTerminal: "Terminal" + ]) + } + + private func setMenuImage() { + if let button = statusItem.button { + button.toolTip = "MiniSim" + let itemImage = MenuImage(rawValue: UserDefaults.standard.menuImage)?.image + itemImage?.isTemplate = true + button.image = itemImage } - - private func setDefaultValues() { - UserDefaults.standard.register(defaults: [ - UserDefaults.Keys.enableAndroidEmulators: true, - UserDefaults.Keys.enableiOSSimulators: true, - UserDefaults.Keys.preferedTerminal: "Terminal" - ]) + } + + @objc private func toggleSuccessCheckmark() { + DispatchQueue.main.async { + if let button = self.statusItem.button { + let itemImage = NSImage(named: "success_action") + itemImage?.size = NSSize(width: 9, height: 15) + itemImage?.isTemplate = true + button.image = itemImage + } } - private func setMenuImage() { - if let button = statusItem.button { - button.toolTip = "MiniSim" - let itemImage = NSImage(named: "menu_icon") - itemImage?.size = NSSize(width: 9, height: 16) - itemImage?.isTemplate = true - button.image = itemImage - } + DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) { + self.setMenuImage() } - - @objc private func toggleSuccessCheckmark() { - DispatchQueue.main.async { - if let button = self.statusItem.button { - let itemImage = NSImage(named: "success_action") - itemImage?.size = NSSize(width: 9, height: 15) - itemImage?.isTemplate = true - button.image = itemImage - } - } - - DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) { - self.setMenuImage() + } + + @objc private func handleDeviceDeleted() { + menu.updateDevicesList() + } + + @objc func menuItemAction(_ sender: NSMenuItem) { + if let tag = MainMenuActions(rawValue: sender.tag) { + switch tag { + case .preferences: + settingsController.show() + settingsController.window?.orderFrontRegardless() + case .quit: + NSApp.terminate(sender) + case .clearDerrivedData: + let shouldDelete = NSAlert.showQuestionDialog( + title: "Are you sure?", + message: "This action will delete derived data from your computer." + ) + if !shouldDelete { + return } - } - @objc private func handleDeviceDeleted() { - menu.updateDevicesList() - } - - @objc func menuItemAction(_ sender: NSMenuItem) { - if let tag = MainMenuActions(rawValue: sender.tag) { - switch tag { - case .preferences: - settingsController.show() - settingsController.window?.orderFrontRegardless() - case .quit: - NSApp.terminate(sender) - case .clearDerrivedData: - let shouldDelete = NSAlert.showQuestionDialog( - title: "Are you sure?", - message: "This action will delete derived data from your computer." - ) - if !shouldDelete { - return - } - - DeviceService.clearDerivedData { amountCleared, error in - guard error == nil else { - NSAlert.showError(message: error?.localizedDescription ?? "Failed to clear derived data.") - return - } - UNUserNotificationCenter.showNotification( - title: "Derived data has been cleared!", - body: "Removed \(amountCleared) of data" - ) - NotificationCenter.default.post(name: .commandDidSucceed, object: nil) - } - } + DeviceService.clearDerivedData { amountCleared, error in + guard error == nil else { + NSAlert.showError(message: error?.localizedDescription ?? "Failed to clear derived data.") + return + } + UNUserNotificationCenter.showNotification( + title: "Derived data has been cleared!", + body: "Removed \(amountCleared) of data" + ) + NotificationCenter.default.post(name: .commandDidSucceed, object: nil) } + } } - - private var mainMenu: [NSMenuItem] { - MainMenuActions.allCases.map { item in - NSMenuItem( - mainMenuItem: item, - target: self, - action: #selector(menuItemAction) - ) - } + } + + private var mainMenu: [NSMenuItem] { + MainMenuActions.allCases.map { item in + NSMenuItem( + mainMenuItem: item, + target: self, + action: #selector(menuItemAction) + ) } + } } extension MiniSim: NSWindowDelegate { - func windowDidBecomeKey(_ notification: Notification) { - NSApplication.shared.setActivationPolicy(.regular) - } + func windowDidBecomeKey(_ notification: Notification) { + NSApplication.shared.setActivationPolicy(.regular) + } - func windowWillClose(_ notification: Notification) { - NSApplication.shared.setActivationPolicy(.accessory) - } + func windowWillClose(_ notification: Notification) { + NSApplication.shared.setActivationPolicy(.accessory) + } } diff --git a/MiniSim/Views/Preferences.swift b/MiniSim/Views/Preferences.swift index 00ed966..2dfe37a 100644 --- a/MiniSim/Views/Preferences.swift +++ b/MiniSim/Views/Preferences.swift @@ -10,7 +10,9 @@ import LaunchAtLogin import Settings import ShellOut import SwiftUI + struct Preferences: View { + @State var menuImageSelected: String = "iphone" @State private var preferedTerminal: Terminal init() { @@ -24,6 +26,20 @@ struct Preferences: View { var body: some View { Settings.Container(contentWidth: 400) { + Settings.Section(title: "Icon:") { + Picker("", selection: $menuImageSelected) { + ForEach(MenuImage.allCases, id: \.self) { image in + Image(nsImage: NSImage(imageLiteralResourceName: image.rawValue)) + .tag(image.rawValue) + } + } + .fixedSize(horizontal: true, vertical: false) + .onChange(of: menuImageSelected) { _ in + UserDefaults.standard.menuImage = menuImageSelected + } + Text("The icon displayed in the Menu Bar.") + .descriptionText() + } Settings.Section(title: "Preferred Terminal:") { Picker("", selection: $preferedTerminal) { let availableTerminal = Terminal.allCases.filter { checkAppIsInstalled(appName: $0) } @@ -57,6 +73,13 @@ struct Preferences: View { } } .frame(minWidth: 650, minHeight: 450) + .onAppear { + MenuImage.allCases.forEach { image in + if UserDefaults.standard.menuImage == image.rawValue { + menuImageSelected = image.rawValue + } + } + } } func checkAppIsInstalled(appName: Terminal) -> Bool {