mirror of
https://github.com/pawelorzech/MacTorn.git
synced 2026-01-30 04:04:27 +00:00
feat: Add notification types to enable opening specific URLs upon interaction.
This commit is contained in:
parent
1ce929bffa
commit
4f8772f986
2 changed files with 88 additions and 20 deletions
|
|
@ -1,10 +1,46 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import UserNotifications
|
import UserNotifications
|
||||||
|
import AppKit
|
||||||
|
|
||||||
class NotificationManager {
|
enum NotificationType: String {
|
||||||
|
case drugReady
|
||||||
|
case medicalReady
|
||||||
|
case boosterReady
|
||||||
|
case landed
|
||||||
|
case chainExpiring
|
||||||
|
case released
|
||||||
|
case energy
|
||||||
|
case nerve
|
||||||
|
case happy
|
||||||
|
case life
|
||||||
|
|
||||||
|
var url: URL {
|
||||||
|
switch self {
|
||||||
|
case .drugReady, .medicalReady, .boosterReady:
|
||||||
|
return URL(string: "https://www.torn.com/item.php")!
|
||||||
|
case .landed:
|
||||||
|
return URL(string: "https://www.torn.com/page.php?sid=ItemMarket")!
|
||||||
|
case .chainExpiring:
|
||||||
|
return URL(string: "https://www.torn.com/factions.php?step=your#/tab=wars")!
|
||||||
|
case .released:
|
||||||
|
return URL(string: "https://www.torn.com/")!
|
||||||
|
case .energy, .happy:
|
||||||
|
return URL(string: "https://www.torn.com/gym.php")!
|
||||||
|
case .nerve:
|
||||||
|
return URL(string: "https://www.torn.com/crimes.php")!
|
||||||
|
case .life:
|
||||||
|
return URL(string: "https://www.torn.com/hospitalview.php")!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotificationManager: NSObject, UNUserNotificationCenterDelegate {
|
||||||
static let shared = NotificationManager()
|
static let shared = NotificationManager()
|
||||||
|
|
||||||
private init() {}
|
private override init() {
|
||||||
|
super.init()
|
||||||
|
UNUserNotificationCenter.current().delegate = self
|
||||||
|
}
|
||||||
|
|
||||||
func requestPermission() async {
|
func requestPermission() async {
|
||||||
do {
|
do {
|
||||||
|
|
@ -18,22 +54,45 @@ class NotificationManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func send(title: String, body: String) {
|
func send(title: String, body: String, type: NotificationType) {
|
||||||
let content = UNMutableNotificationContent()
|
let content = UNMutableNotificationContent()
|
||||||
content.title = title
|
content.title = title
|
||||||
content.body = body
|
content.body = body
|
||||||
content.sound = .default
|
content.sound = .default
|
||||||
|
content.categoryIdentifier = type.rawValue
|
||||||
|
|
||||||
let request = UNNotificationRequest(
|
let request = UNNotificationRequest(
|
||||||
identifier: UUID().uuidString,
|
identifier: UUID().uuidString,
|
||||||
content: content,
|
content: content,
|
||||||
trigger: nil // Immediate
|
trigger: nil // Immediate
|
||||||
)
|
)
|
||||||
|
|
||||||
UNUserNotificationCenter.current().add(request) { error in
|
UNUserNotificationCenter.current().add(request) { error in
|
||||||
if let error = error {
|
if let error = error {
|
||||||
print("Notification error: \(error)")
|
print("Notification error: \(error)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - UNUserNotificationCenterDelegate
|
||||||
|
|
||||||
|
func userNotificationCenter(
|
||||||
|
_ center: UNUserNotificationCenter,
|
||||||
|
didReceive response: UNNotificationResponse,
|
||||||
|
withCompletionHandler completionHandler: @escaping () -> Void
|
||||||
|
) {
|
||||||
|
let categoryIdentifier = response.notification.request.content.categoryIdentifier
|
||||||
|
if let type = NotificationType(rawValue: categoryIdentifier) {
|
||||||
|
NSWorkspace.shared.open(type.url)
|
||||||
|
}
|
||||||
|
completionHandler()
|
||||||
|
}
|
||||||
|
|
||||||
|
func userNotificationCenter(
|
||||||
|
_ center: UNUserNotificationCenter,
|
||||||
|
willPresent notification: UNNotification,
|
||||||
|
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
|
||||||
|
) {
|
||||||
|
completionHandler([.banner, .sound])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -501,31 +501,31 @@ class AppState: ObservableObject {
|
||||||
|
|
||||||
if let prevCD = previousCooldowns, let currentCD = newData.cooldowns {
|
if let prevCD = previousCooldowns, let currentCD = newData.cooldowns {
|
||||||
if prevCD.drug > 0 && currentCD.drug == 0 {
|
if prevCD.drug > 0 && currentCD.drug == 0 {
|
||||||
NotificationManager.shared.send(title: "Drug Ready! 💊", body: "Drug cooldown has ended")
|
NotificationManager.shared.send(title: "Drug Ready! 💊", body: "Drug cooldown has ended", type: .drugReady)
|
||||||
}
|
}
|
||||||
if prevCD.medical > 0 && currentCD.medical == 0 {
|
if prevCD.medical > 0 && currentCD.medical == 0 {
|
||||||
NotificationManager.shared.send(title: "Medical Ready! 🏥", body: "Medical cooldown has ended")
|
NotificationManager.shared.send(title: "Medical Ready! 🏥", body: "Medical cooldown has ended", type: .medicalReady)
|
||||||
}
|
}
|
||||||
if prevCD.booster > 0 && currentCD.booster == 0 {
|
if prevCD.booster > 0 && currentCD.booster == 0 {
|
||||||
NotificationManager.shared.send(title: "Booster Ready! 🚀", body: "Booster cooldown has ended")
|
NotificationManager.shared.send(title: "Booster Ready! 🚀", body: "Booster cooldown has ended", type: .boosterReady)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let prevTravel = previousTravel, let currentTravel = newData.travel {
|
if let prevTravel = previousTravel, let currentTravel = newData.travel {
|
||||||
if prevTravel.isTraveling && !currentTravel.isTraveling {
|
if prevTravel.isTraveling && !currentTravel.isTraveling {
|
||||||
NotificationManager.shared.send(title: "Landed! ✈️", body: "You have arrived in \(currentTravel.destination ?? "destination")")
|
NotificationManager.shared.send(title: "Landed! ✈️", body: "You have arrived in \(currentTravel.destination ?? "destination")", type: .landed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let chain = newData.chain, chain.isActive {
|
if let chain = newData.chain, chain.isActive {
|
||||||
if chain.timeoutRemaining < 60 && chain.timeoutRemaining > 0 {
|
if chain.timeoutRemaining < 60 && chain.timeoutRemaining > 0 {
|
||||||
NotificationManager.shared.send(title: "Chain Expiring! ⚠️", body: "Chain timeout in \(chain.timeoutRemaining) seconds!")
|
NotificationManager.shared.send(title: "Chain Expiring! ⚠️", body: "Chain timeout in \(chain.timeoutRemaining) seconds!", type: .chainExpiring)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let prevStatus = previousStatus, let currentStatus = newData.status {
|
if let prevStatus = previousStatus, let currentStatus = newData.status {
|
||||||
if !prevStatus.isOkay && currentStatus.isOkay {
|
if !prevStatus.isOkay && currentStatus.isOkay {
|
||||||
NotificationManager.shared.send(title: "Released! 🎉", body: "You are now free")
|
NotificationManager.shared.send(title: "Released! 🎉", body: "You are now free", type: .released)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -533,20 +533,29 @@ class AppState: ObservableObject {
|
||||||
private func checkBarNotification(prevBar: Bar, currentBar: Bar, barType: NotificationRule.BarType) {
|
private func checkBarNotification(prevBar: Bar, currentBar: Bar, barType: NotificationRule.BarType) {
|
||||||
let prevPct = prevBar.percentage
|
let prevPct = prevBar.percentage
|
||||||
let currentPct = currentBar.percentage
|
let currentPct = currentBar.percentage
|
||||||
|
|
||||||
for rule in notificationRules where rule.enabled && rule.barType == barType {
|
for rule in notificationRules where rule.enabled && rule.barType == barType {
|
||||||
let threshold = Double(rule.threshold)
|
let threshold = Double(rule.threshold)
|
||||||
|
|
||||||
if prevPct < threshold && currentPct >= threshold {
|
if prevPct < threshold && currentPct >= threshold {
|
||||||
let title: String
|
let title: String
|
||||||
|
let notificationType: NotificationType
|
||||||
switch barType {
|
switch barType {
|
||||||
case .energy: title = "Energy \(rule.threshold)%! ⚡️"
|
case .energy:
|
||||||
case .nerve: title = "Nerve \(rule.threshold)%! 💪"
|
title = "Energy \(rule.threshold)%! ⚡️"
|
||||||
case .happy: title = "Happy \(rule.threshold)%! 😊"
|
notificationType = .energy
|
||||||
case .life: title = "Life \(rule.threshold)%! ❤️"
|
case .nerve:
|
||||||
|
title = "Nerve \(rule.threshold)%! 💪"
|
||||||
|
notificationType = .nerve
|
||||||
|
case .happy:
|
||||||
|
title = "Happy \(rule.threshold)%! 😊"
|
||||||
|
notificationType = .happy
|
||||||
|
case .life:
|
||||||
|
title = "Life \(rule.threshold)%! ❤️"
|
||||||
|
notificationType = .life
|
||||||
}
|
}
|
||||||
NotificationManager.shared.send(title: title, body: "\(barType.rawValue) is now at \(currentBar.current)/\(currentBar.maximum)")
|
NotificationManager.shared.send(title: title, body: "\(barType.rawValue) is now at \(currentBar.current)/\(currentBar.maximum)", type: notificationType)
|
||||||
|
|
||||||
if let sound = NotificationSound(rawValue: rule.soundName) {
|
if let sound = NotificationSound(rawValue: rule.soundName) {
|
||||||
SoundManager.shared.play(sound)
|
SoundManager.shared.play(sound)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue