From 16d2e7d06f04b0d88a05449a832388909481f0e9 Mon Sep 17 00:00:00 2001 From: Nico Verbruggen Date: Tue, 30 Mar 2021 16:31:28 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20preferences=20dialog=20to=20e?= =?UTF-8?q?nable=20static=20icon=20(#25)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PHP Monitor.xcodeproj/project.pbxproj | 24 ++++- phpmon/Assets.xcassets/Contents.json | 6 +- .../Contents.json | 22 +++++ .../StatusBarIconStatic.imageset/phpmon.png | Bin 0 -> 229 bytes .../phpmon@2x.png | Bin 0 -> 358 bytes phpmon/Domain/Core/App.swift | 8 ++ phpmon/Domain/Core/Base.lproj/Main.storyboard | 87 +++++++++++++++++- phpmon/Domain/Menu/MainMenu.swift | 21 ++++- phpmon/Domain/Preferences/Preferences.swift | 48 ++++++++++ phpmon/Domain/Preferences/PrefsVC.swift | 51 ++++++++++ phpmon/Localizable.strings | 8 ++ 11 files changed, 262 insertions(+), 13 deletions(-) create mode 100644 phpmon/Assets.xcassets/StatusBarIconStatic.imageset/Contents.json create mode 100644 phpmon/Assets.xcassets/StatusBarIconStatic.imageset/phpmon.png create mode 100644 phpmon/Assets.xcassets/StatusBarIconStatic.imageset/phpmon@2x.png create mode 100644 phpmon/Domain/Preferences/Preferences.swift create mode 100644 phpmon/Domain/Preferences/PrefsVC.swift diff --git a/PHP Monitor.xcodeproj/project.pbxproj b/PHP Monitor.xcodeproj/project.pbxproj index 23f61a3..3774f31 100644 --- a/PHP Monitor.xcodeproj/project.pbxproj +++ b/PHP Monitor.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 5420395926135DC100FB00FA /* PrefsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5420395826135DC100FB00FA /* PrefsVC.swift */; }; + 5420395F2613607600FB00FA /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5420395E2613607600FB00FA /* Preferences.swift */; }; C405A4D024B9B9140062FAFA /* InternetAccessPolicy.strings in Resources */ = {isa = PBXBuildFile; fileRef = C405A4CE24B9B9130062FAFA /* InternetAccessPolicy.strings */; }; C405A4D124B9B9140062FAFA /* InternetAccessPolicy.plist in Resources */ = {isa = PBXBuildFile; fileRef = C405A4CF24B9B9140062FAFA /* InternetAccessPolicy.plist */; }; C412E5FC25700D5300A1FB67 /* HomebrewPackage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */; }; @@ -76,6 +78,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 5420395826135DC100FB00FA /* PrefsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsVC.swift; sourceTree = ""; }; + 5420395E2613607600FB00FA /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = ""; }; C405A4CE24B9B9130062FAFA /* InternetAccessPolicy.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = InternetAccessPolicy.strings; sourceTree = ""; }; C405A4CF24B9B9140062FAFA /* InternetAccessPolicy.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = InternetAccessPolicy.plist; sourceTree = ""; }; C412E5FB25700D5300A1FB67 /* HomebrewPackage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomebrewPackage.swift; sourceTree = ""; }; @@ -140,6 +144,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 5420395726135DB800FB00FA /* Preferences */ = { + isa = PBXGroup; + children = ( + 5420395826135DC100FB00FA /* PrefsVC.swift */, + 5420395E2613607600FB00FA /* Preferences.swift */, + ); + path = Preferences; + sourceTree = ""; + }; C405A4CD24B9B9070062FAFA /* IAP */ = { isa = PBXGroup; children = ( @@ -190,6 +203,7 @@ C41E181722CB61EB0072CF09 /* Domain */ = { isa = PBXGroup; children = ( + 5420395726135DB800FB00FA /* Preferences */, C4F7808A25D7F918000DBC97 /* Terminal */, C4B13B1D25C4915000548C3A /* Core */, C47331A0247093AC009A0597 /* Menu */, @@ -381,12 +395,14 @@ C4ACA38F25C754C100060C66 /* PhpExtension.swift in Sources */, C4D8016622B1584700C6DA1B /* Startup.swift in Sources */, C4F8C0A422D4F12C002EFE61 /* DateExtension.swift in Sources */, + 5420395926135DC100FB00FA /* PrefsVC.swift in Sources */, C41C1B4722B009A400E7CF16 /* Shell.swift in Sources */, C41C1B4D22B0215A00E7CF16 /* Actions.swift in Sources */, C48D0CA325CC992000CC7490 /* StatsView.swift in Sources */, C42295DD2358D02000E263B2 /* Command.swift in Sources */, C4811D2422D70A4700B5F6B3 /* App.swift in Sources */, C41C1B4922B00A9800E7CF16 /* MenuBarImageGenerator.swift in Sources */, + 5420395F2613607600FB00FA /* Preferences.swift in Sources */, C48D0C9325CC804200CC7490 /* XibLoadable.swift in Sources */, C4811D2A22D70F9A00B5F6B3 /* MainMenu.swift in Sources */, C412E5FC25700D5300A1FB67 /* HomebrewPackage.swift in Sources */, @@ -581,7 +597,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 50; + CURRENT_PROJECT_VERSION = 52; DEVELOPMENT_TEAM = 8M54J5J787; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = phpmon/Info.plist; @@ -589,7 +605,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = "3.3-prerelease"; + MARKETING_VERSION = "3.3-prerelease2"; PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -605,7 +621,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 50; + CURRENT_PROJECT_VERSION = 52; DEVELOPMENT_TEAM = 8M54J5J787; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = phpmon/Info.plist; @@ -613,7 +629,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = "3.3-prerelease"; + MARKETING_VERSION = "3.3-prerelease2"; PRODUCT_BUNDLE_IDENTIFIER = com.nicoverbruggen.phpmon; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/phpmon/Assets.xcassets/Contents.json b/phpmon/Assets.xcassets/Contents.json index da4a164..73c0059 100644 --- a/phpmon/Assets.xcassets/Contents.json +++ b/phpmon/Assets.xcassets/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/phpmon/Assets.xcassets/StatusBarIconStatic.imageset/Contents.json b/phpmon/Assets.xcassets/StatusBarIconStatic.imageset/Contents.json new file mode 100644 index 0000000..a16dc36 --- /dev/null +++ b/phpmon/Assets.xcassets/StatusBarIconStatic.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "filename" : "phpmon.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "phpmon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/phpmon/Assets.xcassets/StatusBarIconStatic.imageset/phpmon.png b/phpmon/Assets.xcassets/StatusBarIconStatic.imageset/phpmon.png new file mode 100644 index 0000000000000000000000000000000000000000..5ca598767a36526677e7d110738a6d1e1d03971e GIT binary patch literal 229 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H0wnYHF4+L2)_A%&hE&|Tdcm5n$w8#`q5Z-w zn@X6~UKy>>iEWIK3{yKdemEE--6U>oWF|J}^4yx8Cwab@ zR_C2?_kLDZv%YcRqO2bW`;OjH_CBVU^XfJKIf-j}e_RBD6pn59`?QGb0H5NULvD#3 zJB>lS(^~)W_czVqwPd|F-8I$iSZhz_ d@k@vIF#Nu^L9*h3OES>i44$rjF6*2UngGcJTsQy# literal 0 HcmV?d00001 diff --git a/phpmon/Assets.xcassets/StatusBarIconStatic.imageset/phpmon@2x.png b/phpmon/Assets.xcassets/StatusBarIconStatic.imageset/phpmon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..76e40b33cb911c0cba3c5e08350ec910cd6dd882 GIT binary patch literal 358 zcmV-s0h#`ZP)Omn&>T$ggl)KV3px0}8s^>*a5zn3YiHG^YBWX;2W~fS{|OYT4wZ7 z9^T;tOdt%gl7~NzE68j(40g2{gJWoJ_Ob^{D{(7f@q{@&vL$-6sl-=$mRKyrUA0_-&!T`b;Mb|qC)gd#& zy%|BK?tUks0$R`%EfoCkq*p-)Z>EEa|D7m`qG*x&0k2}eA9;9Y1^@s607*qoM6N<$ Ef{tg8-~a#s literal 0 HcmV?d00001 diff --git a/phpmon/Domain/Core/App.swift b/phpmon/Domain/Core/App.swift index bf096c0..fcebe1a 100644 --- a/phpmon/Domain/Core/App.swift +++ b/phpmon/Domain/Core/App.swift @@ -18,6 +18,14 @@ class App { return App.shared.busy } + /** The list of preferences that are currently active. */ + var preferences: [PreferenceName: Bool]! + + /** + The window controller of the currently active window. + */ + var windowController: NSWindowController? = nil + /** Whether the application is busy switching versions. */ diff --git a/phpmon/Domain/Core/Base.lproj/Main.storyboard b/phpmon/Domain/Core/Base.lproj/Main.storyboard index a2f2ee0..b3d66eb 100644 --- a/phpmon/Domain/Core/Base.lproj/Main.storyboard +++ b/phpmon/Domain/Core/Base.lproj/Main.storyboard @@ -1,8 +1,9 @@ - + - + + @@ -54,5 +55,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/phpmon/Domain/Menu/MainMenu.swift b/phpmon/Domain/Menu/MainMenu.swift index 417f316..c17fc29 100644 --- a/phpmon/Domain/Menu/MainMenu.swift +++ b/phpmon/Domain/Menu/MainMenu.swift @@ -96,6 +96,7 @@ class MainMenu: NSObject, NSWindowDelegate { menu.addItem(NSMenuItem.separator()) // Add about & quit menu items + menu.addItem(NSMenuItem(title: "mi_preferences".localized, action: #selector(openPrefs), keyEquivalent: "")) menu.addItem(NSMenuItem(title: "mi_about".localized, action: #selector(openAbout), keyEquivalent: "")) menu.addItem(NSMenuItem(title: "mi_quit".localized, action: #selector(terminateApp), keyEquivalent: "q")) @@ -159,16 +160,24 @@ class MainMenu: NSObject, NSWindowDelegate { @objc func updatePhpVersionInStatusBar() { App.shared.currentInstall = PhpInstallation() - + refreshIcon() + update() + } + + func refreshIcon() { DispatchQueue.main.async { [self] in if (App.busy) { setStatusBar(image: NSImage(named: NSImage.Name("StatusBarIcon"))!) } else { - setStatusBarImage(version: App.phpInstall!.version.short) + if Preferences.preferences[.shouldDisplayDynamicIcon] == false { + // Static icon has been requested + setStatusBar(image: NSImage(named: NSImage.Name("StatusBarIconStatic"))!) + } else { + // The dynamic icon has been requested + setStatusBarImage(version: App.phpInstall!.version.short) + } } } - - update() } @objc func reloadPhpMonitorMenu() { @@ -301,6 +310,10 @@ class MainMenu: NSObject, NSWindowDelegate { NSApplication.shared.orderFrontStandardAboutPanel() } + @objc func openPrefs() { + PrefsVC.show() + } + @objc func terminateApp() { NSApplication.shared.terminate(nil) } diff --git a/phpmon/Domain/Preferences/Preferences.swift b/phpmon/Domain/Preferences/Preferences.swift new file mode 100644 index 0000000..e8b2390 --- /dev/null +++ b/phpmon/Domain/Preferences/Preferences.swift @@ -0,0 +1,48 @@ +// +// Preferences.swift +// PHP Monitor +// +// Created by Nico Verbruggen on 30/03/2021. +// Copyright © 2021 Nico Verbruggen. All rights reserved. +// + +import Foundation + +enum PreferenceName: String { + case shouldDisplayDynamicIcon = "use_dynamic_icon" +} + +class Preferences { + + static func handleFirstTimeLaunch() { + let launchedBefore = UserDefaults.standard.bool(forKey: "alreadyLaunched") + + if launchedBefore { + return + } + + UserDefaults.standard.setValue(true, forKey: PreferenceName.shouldDisplayDynamicIcon.rawValue) + UserDefaults.standard.setValue(true, forKey: "alreadyLaunched") + UserDefaults.standard.synchronize() + } + + static func retrieve() -> [PreferenceName: Bool] { + Preferences.handleFirstTimeLaunch() + + return [ + .shouldDisplayDynamicIcon: UserDefaults.standard.bool( + forKey: PreferenceName.shouldDisplayDynamicIcon.rawValue + ) + ] + } + + static var preferences: [PreferenceName: Bool] { + return Preferences.retrieve() + } + + static func update(_ preference: PreferenceName, value: Bool) { + UserDefaults.standard.setValue(value, forKey: preference.rawValue) + UserDefaults.standard.synchronize() + } + +} diff --git a/phpmon/Domain/Preferences/PrefsVC.swift b/phpmon/Domain/Preferences/PrefsVC.swift new file mode 100644 index 0000000..1ff32bf --- /dev/null +++ b/phpmon/Domain/Preferences/PrefsVC.swift @@ -0,0 +1,51 @@ +// +// PrefsVC.swift +// PHP Monitor +// +// Created by Nico Verbruggen on 30/03/2021. +// Copyright © 2021 Nico Verbruggen. All rights reserved. +// + +import Cocoa + +class PrefsVC: NSViewController { + + @IBOutlet weak var buttonDynamicIcon: NSButton! + @IBOutlet weak var labelDynamicIcon: NSTextField! + @IBOutlet weak var buttonClose: NSButton! + + public static func show(delegate: NSWindowDelegate? = nil) { + if (App.shared.windowController == nil) { + let vc = NSStoryboard(name: "Main", bundle: nil).instantiateController(withIdentifier: "preferences") as! PrefsVC + let window = NSWindow(contentViewController: vc) + window.title = "prefs.title".localized + window.delegate = delegate + window.styleMask = [.titled, .closable] + App.shared.windowController = NSWindowController(window: window) + } + App.shared.windowController!.showWindow(self) + NSApp.activate(ignoringOtherApps: true) + } + + @IBAction func toggledDynamicIcon(_ sender: Any) { + Preferences.update(.shouldDisplayDynamicIcon, value: buttonDynamicIcon.state == .on) + MainMenu.shared.refreshIcon() + } + + override func viewWillAppear() { + buttonDynamicIcon.title = "prefs.dynamic_icon_title".localized + labelDynamicIcon.stringValue = "prefs.dynamic_icon_desc".localized + buttonClose.title = "prefs.close".localized + + let prefs = Preferences.preferences + self.buttonDynamicIcon.state = (prefs[.shouldDisplayDynamicIcon] == true) ? .on : .off + } + + @IBAction func pressed(_ sender: Any) { + self.view.window?.windowController?.close() + } + + deinit { + print("VC deallocated") + } +} diff --git a/phpmon/Localizable.strings b/phpmon/Localizable.strings index 5b282d3..6943ec6 100644 --- a/phpmon/Localizable.strings +++ b/phpmon/Localizable.strings @@ -39,9 +39,17 @@ "mi_detected_extensions" = "Detected Extensions"; "mi_no_extensions_detected" = "No additional extensions detected."; +"mi_preferences" = "Preferences..."; "mi_quit" = "Quit PHP Monitor"; "mi_about" = "About PHP Monitor"; +// PREFERENCES + +"prefs.title" = "Preferences"; +"prefs.close" = "Close"; +"prefs.dynamic_icon_title" = "Show a dynamic icon in the menu bar"; +"prefs.dynamic_icon_desc" = "If you uncheck this box, the truck icon will always be visible.\nIf checked, it will display the major version number of the currently linked PHP version."; + // NOTIFICATIONS "notification.version_changed_title" = "PHP %@ now active";