1
0
mirror of https://github.com/nicoverbruggen/phpmon.git synced 2025-08-07 12:00:09 +02:00

Add successful launch count, sponsor alert

Okay, so this commit adds a sponsor alert. I wanted to elaborate.

Why? At this point I've invested so much of my free time in the app that
any and all donations would be incredibly welcome. Of course, phpmon
as it exists today must always remain free and open source.

(I dislike it when an app goes open source and then becomes paid.)

Obviously, I don't want to take useful features away from users:

1) usage of the old version is the only option for those who won't pay
2) piracy is an alternative and I don't want to deal with that
3) the positive sentiment around the app disappears ("sellout!")

Instead, I will nicely ask for donations once the app has been
successfully launched 7 times or more. This alert should only
appear once.

Fun fact: PHP Monitor started  as a single menu item with only
options to switch between version numbers.

Thanks to all the support, it has now become so much more.

To those who have already contributed: thank you very much.
I hope you continue to use and enjoy the app.

Cheers!
This commit is contained in:
2022-01-29 21:29:51 +01:00
parent d0f7d2c5e9
commit bba961269c
6 changed files with 111 additions and 1 deletions

View File

@ -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 = "<group>"; };
C4D9ADBE277610E1007277F4 /* PhpSwitcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpSwitcher.swift; sourceTree = "<group>"; };
C4D9ADC7277611A0007277F4 /* InternalSwitcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternalSwitcher.swift; sourceTree = "<group>"; };
C4DEB7D327A5D60B00834718 /* Stats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stats.swift; sourceTree = "<group>"; };
C4E713562570150F00007428 /* SECURITY.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = SECURITY.md; sourceTree = "<group>"; };
C4E713572570151400007428 /* docs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = docs; sourceTree = "<group>"; };
C4EC1E65279DE0380010F296 /* ServicesView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ServicesView.xib; sourceTree = "<group>"; };
@ -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;
};

View File

@ -16,6 +16,7 @@
<p><b>Want to spread the love?</b> Leave a <a href="https://github.com/nicoverbruggen/phpmon">star on GitHub</a>!</p>
<p><b>Having issues?</b> Consult the <a href="https://github.com/nicoverbruggen/phpmon#%EF%B8%8F-faq--troubleshooting">FAQ & Troubleshooting</a> section.</p>
<p><b>Want to support me?</b> You can <a href="https://nicoverbruggen.be/sponsor">financially support</a> the continued development of this app.</p>
<p><b>Get the latest on Twitter</b> Give me a <a href="https://twitter.com/nicoverbruggen">follow on Twitter</a> to learn about the latest and greatest updates of this app.</p>
<br>
</body>
</html>

View File

@ -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()
}
/**

View File

@ -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) {

View File

@ -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)
}
}
}

View File

@ -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";