1
0
mirror of https://github.com/nicoverbruggen/phpmon.git synced 2025-08-07 20:10:08 +02:00
Files
app/phpmon/Domain/Preferences/Preferences.swift
Nico Verbruggen bba961269c 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!
2022-01-29 21:29:51 +01:00

160 lines
5.9 KiB
Swift

//
// Preferences.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 30/03/2021.
// Copyright © 2021 Nico Verbruggen. All rights reserved.
//
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"
case shouldDisplayPhpHintInIcon = "add_php_to_icon"
case fullPhpVersionDynamicIcon = "full_php_in_menu_bar"
case autoServiceRestartAfterExtensionToggle = "auto_restart_after_extension_toggle"
case autoComposerGlobalUpdateAfterSwitch = "auto_composer_global_update_after_switch"
case allowProtocolForIntegrations = "allow_protocol_for_integrations"
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
static var shared = Preferences()
var customPreferences: CustomPrefs
var cachedPreferences: [PreferenceName: Any?]
public init() {
Preferences.handleFirstTimeLaunch()
cachedPreferences = Self.cache()
customPreferences = CustomPrefs(scanApps: [])
loadCustomPreferences()
}
// MARK: - First Time Run
/**
Note: macOS seems to cache plist values in memory as well as in files.
You can find the persisted configuration file in: ~/Library/Preferences/com.nicoverbruggen.phpmon.plist
To clear the cache, and get a first-run experience you may need to run:
```
defaults delete com.nicoverbruggen.phpmon
killall cfprefsd
```
*/
static func handleFirstTimeLaunch() {
UserDefaults.standard.register(defaults: [
PreferenceName.shouldDisplayDynamicIcon.rawValue: true,
PreferenceName.shouldDisplayPhpHintInIcon.rawValue: true,
PreferenceName.fullPhpVersionDynamicIcon.rawValue: false,
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) {
return
}
Log.info("Saving first-time preferences!")
UserDefaults.standard.setValue(true, forKey: PreferenceName.wasLaunchedBefore.rawValue)
UserDefaults.standard.synchronize()
}
// MARK: - API
static var preferences: [PreferenceName: Any?] {
return Self.shared.cachedPreferences
}
static var custom: CustomPrefs {
return Self.shared.customPreferences
}
/**
Determine whether a particular preference is enabled.
- Important: Requires the preference to have a corresponding boolean value, or a fatal error will be thrown.
*/
static func isEnabled(_ preference: PreferenceName) -> Bool {
if let bool = Preferences.preferences[preference] as? Bool {
return bool == true
} else {
fatalError("\(preference) is not a valid boolean preference!")
}
}
// MARK: - Internal Functionality
private static func cache() -> [PreferenceName: Any] {
return [
// Part 1: Always Booleans
.shouldDisplayDynamicIcon: UserDefaults.standard.bool(forKey: PreferenceName.shouldDisplayDynamicIcon.rawValue) as Any,
.shouldDisplayPhpHintInIcon: UserDefaults.standard.bool(forKey: PreferenceName.shouldDisplayPhpHintInIcon.rawValue) as Any,
.fullPhpVersionDynamicIcon: UserDefaults.standard.bool(forKey: PreferenceName.fullPhpVersionDynamicIcon.rawValue) as Any,
.autoServiceRestartAfterExtensionToggle: UserDefaults.standard.bool(forKey: PreferenceName.autoServiceRestartAfterExtensionToggle.rawValue) as Any,
.autoComposerGlobalUpdateAfterSwitch: UserDefaults.standard.bool(forKey: PreferenceName.autoComposerGlobalUpdateAfterSwitch.rawValue) as Any,
.allowProtocolForIntegrations: UserDefaults.standard.bool(forKey: PreferenceName.allowProtocolForIntegrations.rawValue) as Any,
// Part 2: Always Strings
.globalHotkey: UserDefaults.standard.string(forKey: PreferenceName.globalHotkey.rawValue) as Any,
]
}
static func update(_ preference: PreferenceName, value: Any?) {
if (value == nil) {
UserDefaults.standard.removeObject(forKey: preference.rawValue)
} else {
UserDefaults.standard.setValue(value, forKey: preference.rawValue)
}
UserDefaults.standard.synchronize()
// Update the preferences cache in memory!
Preferences.shared.cachedPreferences = Preferences.cache()
}
// MARK: - Custom Preferences
private func loadCustomPreferences() {
let url = URL(fileURLWithPath: "/Users/\(Paths.whoami)/.phpmon.conf.json")
if Filesystem.fileExists(url.path) {
Log.info("A custom .phpmon.conf.json file was found. Attempting to parse...")
loadCustomPreferencesFile(url)
} else {
Log.info("There was no .phpmon.conf.json file to be loaded.")
}
}
private func loadCustomPreferencesFile(_ url: URL) {
do {
customPreferences = try JSONDecoder().decode(
CustomPrefs.self,
from: try! String(contentsOf: url, encoding: .utf8).data(using: .utf8)!
)
Log.info("The .phpmon.conf.json file was successfully parsed.")
} catch {
Log.warn("The .phpmon.conf.json file seems to be missing or malformed.")
}
}
}