diff --git a/PHP Monitor.xcodeproj/project.pbxproj b/PHP Monitor.xcodeproj/project.pbxproj index c935ef7..2c421f0 100644 --- a/PHP Monitor.xcodeproj/project.pbxproj +++ b/PHP Monitor.xcodeproj/project.pbxproj @@ -150,6 +150,7 @@ C4D9ADC8277611A0007277F4 /* InternalSwitcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D9ADC7277611A0007277F4 /* InternalSwitcher.swift */; }; C4D9ADC9277611A0007277F4 /* InternalSwitcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D9ADC7277611A0007277F4 /* InternalSwitcher.swift */; }; C4D9ADCA277611A0007277F4 /* InternalSwitcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D9ADC7277611A0007277F4 /* InternalSwitcher.swift */; }; + C4DEB7D427A5D60B00834718 /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4DEB7D327A5D60B00834718 /* Stats.swift */; }; C4EC1E66279DE0380010F296 /* ServicesView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C4EC1E65279DE0380010F296 /* ServicesView.xib */; }; C4EC1E68279DE0540010F296 /* ServicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EC1E67279DE0540010F296 /* ServicesView.swift */; }; C4EC1E6D279DF87A0010F296 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EC1E6C279DF87A0010F296 /* Async.swift */; }; @@ -304,6 +305,7 @@ C4D89BC52783C99400A02B68 /* ComposerJson.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerJson.swift; sourceTree = ""; }; C4D9ADBE277610E1007277F4 /* PhpSwitcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpSwitcher.swift; sourceTree = ""; }; C4D9ADC7277611A0007277F4 /* InternalSwitcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternalSwitcher.swift; sourceTree = ""; }; + C4DEB7D327A5D60B00834718 /* Stats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stats.swift; sourceTree = ""; }; C4E713562570150F00007428 /* SECURITY.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = SECURITY.md; sourceTree = ""; }; C4E713572570151400007428 /* docs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = docs; sourceTree = ""; }; C4EC1E65279DE0380010F296 /* ServicesView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ServicesView.xib; sourceTree = ""; }; @@ -363,6 +365,7 @@ 5420395826135DC100FB00FA /* PrefsVC.swift */, 5420395E2613607600FB00FA /* Preferences.swift */, C4C3ED4227834C5200AB15D8 /* CustomPrefs.swift */, + C4DEB7D327A5D60B00834718 /* Stats.swift */, C41CD0272628D8E20065BBED /* Keybinds */, 54FCFD28276C88C0004CE748 /* Views */, ); @@ -952,6 +955,7 @@ C464ADB2275A87CA003FCD53 /* SiteListCell.swift in Sources */, C4EE188422D3386B00E126E5 /* Constants.swift in Sources */, C493084A279F331F009C240B /* AddSiteVC.swift in Sources */, + C4DEB7D427A5D60B00834718 /* Stats.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/phpmon/Credits.html b/phpmon/Credits.html index 4549bd7..40bcc83 100644 --- a/phpmon/Credits.html +++ b/phpmon/Credits.html @@ -16,6 +16,7 @@

Want to spread the love? Leave a star on GitHub!

Having issues? Consult the FAQ & Troubleshooting section.

Want to support me? You can financially support the continued development of this app.

+

Get the latest on Twitter Give me a follow on Twitter to learn about the latest and greatest updates of this app.


diff --git a/phpmon/Domain/Menu/MainMenu+Startup.swift b/phpmon/Domain/Menu/MainMenu+Startup.swift index bea4da2..66ab435 100644 --- a/phpmon/Domain/Menu/MainMenu+Startup.swift +++ b/phpmon/Domain/Menu/MainMenu+Startup.swift @@ -69,7 +69,9 @@ extension MainMenu { App.shared.loadGlobalHotkey() // Attempt to find out more info about Valet - Log.info("PHP Monitor has extracted the version number of Valet: \(Valet.shared.version)") + if Valet.shared.version != nil { + Log.info("PHP Monitor has extracted the version number of Valet: \(Valet.shared.version!)") + } Valet.shared.loadConfiguration() Valet.shared.validateVersion() @@ -89,6 +91,9 @@ extension MainMenu { repeats: true ) } + + Stats.incrementSuccessfulLaunchCount() + Stats.evaluateSponsorMessageShouldBeDisplayed() } /** diff --git a/phpmon/Domain/Preferences/Preferences.swift b/phpmon/Domain/Preferences/Preferences.swift index 93ee9ab..b670699 100644 --- a/phpmon/Domain/Preferences/Preferences.swift +++ b/phpmon/Domain/Preferences/Preferences.swift @@ -8,6 +8,9 @@ import Foundation +/** + These are the keys used for every preference in the app. + */ enum PreferenceName: String { case wasLaunchedBefore = "launched_before" case shouldDisplayDynamicIcon = "use_dynamic_icon" @@ -19,6 +22,14 @@ enum PreferenceName: String { case globalHotkey = "global_hotkey" } +/** + These are internal stats. They NEVER get shared. + */ +enum InternalStats: String { + case launchCount = "times_launched" + case didSeeSponsorEncouragement = "did_see_sponsor_encouragement" +} + class Preferences { // MARK: - Singleton @@ -56,6 +67,9 @@ class Preferences { PreferenceName.autoServiceRestartAfterExtensionToggle.rawValue: true, PreferenceName.autoComposerGlobalUpdateAfterSwitch.rawValue: false, PreferenceName.allowProtocolForIntegrations.rawValue: true, + /// + InternalStats.launchCount.rawValue: 0, + InternalStats.didSeeSponsorEncouragement.rawValue: false ]) if UserDefaults.standard.bool(forKey: PreferenceName.wasLaunchedBefore.rawValue) { diff --git a/phpmon/Domain/Preferences/Stats.swift b/phpmon/Domain/Preferences/Stats.swift new file mode 100644 index 0000000..a3cbc63 --- /dev/null +++ b/phpmon/Domain/Preferences/Stats.swift @@ -0,0 +1,79 @@ +// +// Stats.swift +// PHP Monitor +// +// Created by Nico Verbruggen on 29/01/2022. +// Copyright © 2022 Nico Verbruggen. All rights reserved. +// + +import Foundation +import Cocoa + +class Stats { + + /** + Keep track of how many times the app has been successfully launched. + This is used to determine whether it is time to show the sponsor + encouragement alert, but I'd like to include this stat in the + preferences window as well. "PHP Monitor has been started X + times." If the count is over 99, it should say "Think about + all of the time the app has saved you!" + */ + public static var successfulLaunchCount: Int { + UserDefaults.standard.integer( + forKey: InternalStats.launchCount.rawValue + ) + } + + /** + Did the user see the sponsor encouragement / thank you message? + Annoying the user is the worst, so let's not show the message twice. + */ + public static var didSeeSponsorEncouragement: Bool { + UserDefaults.standard.bool( + forKey: InternalStats.didSeeSponsorEncouragement.rawValue + ) + } + + /** + Increment the successful launch count. This should only be + called when the user has not encountered ANY issues starting + up the application. + */ + public static func incrementSuccessfulLaunchCount() { + let count = Stats.successfulLaunchCount + UserDefaults.standard.set( + count + 1, + forKey: InternalStats.launchCount.rawValue + ) + } + + public static func evaluateSponsorMessageShouldBeDisplayed() { + if Stats.didSeeSponsorEncouragement { + Log.info("Awesome, the user has already seen the sponsor message.") + return + } + + if Stats.successfulLaunchCount < 7 { + Log.info("It is too soon to see the sponsor message.") + Log.info("The application has been launched successfully \(Stats.successfulLaunchCount) times.") + return + } + + DispatchQueue.main.async { + let donate = Alert.present( + messageText: "startup.sponsor_encouragement.title".localized, + informativeText: "startup.sponsor_encouragement.desc".localized, + buttonTitle: "startup.sponsor_encouragement.accept".localized, + secondButtonTitle: "startup.sponsor_encouragement.skip".localized, + style: .informational) + if donate { + Log.info("The user is an absolute badass for choosing this option. Thank you.") + guard let url = URL(string: "https://nicoverbruggen.be/sponsor#pay-now") else { return } + NSWorkspace.shared.open(url) + } + UserDefaults.standard.set(true, forKey: InternalStats.didSeeSponsorEncouragement.rawValue) + } + } + +} diff --git a/phpmon/Localizable.strings b/phpmon/Localizable.strings index 153da0f..4a64530 100644 --- a/phpmon/Localizable.strings +++ b/phpmon/Localizable.strings @@ -257,3 +257,10 @@ You can do this by running `composer global update` in your terminal. After that /// 7. Multiple services active "startup.errors.services.title" = "Multiple PHP services are active"; "startup.errors.services.desc" = "This can cause php-fpm to serve a more recent version of PHP than the one you'd like to see active. Please terminate all extra PHP processes.\n\nThe easiest solution is to choose the option 'Force load latest PHP version' in the menu bar.\n\nAlternatively, you can fix this manually. You can do this by running `brew services list` and running `sudo brew services stop php@7.3` (and use the version that applies).\n\nPHP Monitor usually handles the starting and stopping of these services, so once the correct version is the only PHP version running you should not have any issues. It is recommended to restart PHP Monitor once you have resolved this issue.\n\nFor more information about this issue, please see the README.md file in the repository on GitHub."; + +// SPONSOR ENCOURAGEMENT + +"startup.sponsor_encouragement.title" = "If PHP Monitor has been useful to you or your company, please consider leaving a tip."; +"startup.sponsor_encouragement.desc" = "If you have already donated, then YOU are the reason why the app was able to get all these new features. In that case, this is a THANK YOU message to you.\n\nTo be 100% transparent: I plan to keep PHP Monitor open source and free. Your support makes this decision very easy.\n\n(You will only see this prompt once.)"; +"startup.sponsor_encouragement.accept" = "Yes, I would like to sponsor"; +"startup.sponsor_encouragement.skip" = "Nevermind";