Implement send notification

This commit is contained in:
世界
2024-11-07 16:52:14 +08:00
parent c72167b0dc
commit 348f2809a1
6 changed files with 102 additions and 25 deletions
@@ -138,16 +138,21 @@ public struct DashboardView: View {
private func loopShowDeprecateNotes(_ reports: any LibboxDeprecatedNoteIteratorProtocol) { private func loopShowDeprecateNotes(_ reports: any LibboxDeprecatedNoteIteratorProtocol) {
if reports.hasNext() { if reports.hasNext() {
let report = reports.next()! let report = reports.next()!
NSLog("show next")
alert = Alert( alert = Alert(
title: Text("Deprecated Warning"), title: Text("Deprecated Warning"),
message: Text(report.message()), message: Text(report.message()),
primaryButton: .cancel(Text("Ok")) { primaryButton: .default(Text("Documentation")) {
loopShowDeprecateNotes(reports)
},
secondaryButton: .default(Text("Documentation")) {
openURL(URL(string: report.migrationLink)!) openURL(URL(string: report.migrationLink)!)
loopShowDeprecateNotes(reports) Task.detached {
try await Task.sleep(nanoseconds: 300 * MSEC_PER_SEC)
await loopShowDeprecateNotes(reports)
}
},
secondaryButton: .cancel(Text("Ok")) {
Task.detached {
try await Task.sleep(nanoseconds: 300 * MSEC_PER_SEC)
await loopShowDeprecateNotes(reports)
}
} }
) )
} }
@@ -4,7 +4,6 @@ import SwiftUI
public struct ExtensionStatusView: View { public struct ExtensionStatusView: View {
@Environment(\.scenePhase) private var scenePhase @Environment(\.scenePhase) private var scenePhase
@Environment(\.openURL) private var openURL
@StateObject private var commandClient = CommandClient(.status) @StateObject private var commandClient = CommandClient(.status)
@State private var columnCount: Int = 4 @State private var columnCount: Int = 4
@@ -91,9 +90,7 @@ public struct ExtensionStatusView: View {
.padding([.top, .leading, .trailing]) .padding([.top, .leading, .trailing])
} }
.onAppear { .onAppear {
commandClient.connect { urlString in commandClient.connect()
openURL(URL(string: urlString)!)
}
} }
.onDisappear { .onDisappear {
commandClient.disconnect() commandClient.disconnect()
+1 -13
View File
@@ -14,8 +14,6 @@ public class CommandClient: ObservableObject {
private let logMaxLines: Int private let logMaxLines: Int
private var commandClient: LibboxCommandClient? private var commandClient: LibboxCommandClient?
private var connectTask: Task<Void, Error>? private var connectTask: Task<Void, Error>?
private var openURLFunc: ((String) -> Void)?
@Published public var isConnected: Bool @Published public var isConnected: Bool
@Published public var status: LibboxStatusMessage? @Published public var status: LibboxStatusMessage?
@Published public var groups: [LibboxOutboundGroup]? @Published public var groups: [LibboxOutboundGroup]?
@@ -31,15 +29,13 @@ public class CommandClient: ObservableObject {
public init(_ connectionType: ConnectionType, logMaxLines: Int = 300) { public init(_ connectionType: ConnectionType, logMaxLines: Int = 300) {
self.connectionType = connectionType self.connectionType = connectionType
self.logMaxLines = logMaxLines self.logMaxLines = logMaxLines
openURLFunc = nil
logList = [] logList = []
clashModeList = [] clashModeList = []
clashMode = "" clashMode = ""
isConnected = false isConnected = false
} }
public func connect(_ openURLFunc: ((String) -> Void)? = nil) { public func connect() {
self.openURLFunc = openURLFunc
if isConnected { if isConnected {
return return
} }
@@ -52,7 +48,6 @@ public class CommandClient: ObservableObject {
} }
public func disconnect() { public func disconnect() {
openURLFunc = nil
if let connectTask { if let connectTask {
connectTask.cancel() connectTask.cancel()
self.connectTask = nil self.connectTask = nil
@@ -227,13 +222,6 @@ public class CommandClient: ObservableObject {
commandClient.connections = connections commandClient.connections = connections
} }
} }
func openURL(_ url: String?) {
guard let url else {
return
}
commandClient.openURLFunc?(url)
}
} }
} }
@@ -1,6 +1,7 @@
import Foundation import Foundation
import Libbox import Libbox
import NetworkExtension import NetworkExtension
import UserNotifications
#if canImport(CoreWLAN) #if canImport(CoreWLAN)
import CoreWLAN import CoreWLAN
#endif #endif
@@ -338,4 +339,28 @@ public class ExtensionPlatformInterface: NSObject, LibboxPlatformInterfaceProtoc
func reset() { func reset() {
networkSettings = nil networkSettings = nil
} }
public func send(_ notification: LibboxNotification?) throws {
#if !os(tvOS)
guard let notification else {
return
}
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
content.title = notification.title
content.subtitle = notification.subtitle
content.body = notification.body
if !notification.openURL.isEmpty {
content.userInfo["OPEN_URL"] = notification.openURL
content.categoryIdentifier = "OPEN_URL"
}
content.interruptionLevel = .active
let request = UNNotificationRequest(identifier: notification.identifier, content: content, trigger: nil)
try runBlocking {
try await center.requestAuthorization(options: [.alert])
try await center.add(request)
}
#endif
}
} }
+32 -1
View File
@@ -3,11 +3,25 @@ import ApplicationLibrary
import Foundation import Foundation
import Libbox import Libbox
import Library import Library
import UserNotifications
open class ApplicationDelegate: NSObject, NSApplicationDelegate { open class ApplicationDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDelegate {
public func applicationDidFinishLaunching(_: Notification) { public func applicationDidFinishLaunching(_: Notification) {
NSLog("Here I stand") NSLog("Here I stand")
LibboxSetup(FilePath.sharedDirectory.relativePath, FilePath.workingDirectory.relativePath, FilePath.cacheDirectory.relativePath, false) LibboxSetup(FilePath.sharedDirectory.relativePath, FilePath.workingDirectory.relativePath, FilePath.cacheDirectory.relativePath, false)
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.setNotificationCategories([
UNNotificationCategory(
identifier: "OPEN_URL",
actions: [
UNNotificationAction(identifier: "COPY_URL", title: "Copy URL", options: .foreground, icon: UNNotificationActionIcon(systemImageName: "clipboard.fill")),
UNNotificationAction(identifier: "OPEN_URL", title: "Open", options: .foreground, icon: UNNotificationActionIcon(systemImageName: "safari.fill")),
],
intentIdentifiers: []
),
]
)
notificationCenter.delegate = self
let event = NSAppleEventManager.shared().currentAppleEvent let event = NSAppleEventManager.shared().currentAppleEvent
let launchedAsLogInItem = let launchedAsLogInItem =
event?.eventID == kAEOpenApplication && event?.eventID == kAEOpenApplication &&
@@ -34,6 +48,23 @@ open class ApplicationDelegate: NSObject, NSApplicationDelegate {
} }
} }
public func userNotificationCenter(_: UNUserNotificationCenter, willPresent _: UNNotification) async -> UNNotificationPresentationOptions {
.banner
}
public func userNotificationCenter(_: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async {
if let url = response.notification.request.content.userInfo["OPEN_URL"] as? String {
switch response.actionIdentifier {
case "COPY_URL":
NSPasteboard.general.setString(url, forType: .URL)
case "OPEN_URL":
fallthrough
default:
NSWorkspace.shared.open(URL(string: url)!)
}
}
}
public func applicationShouldTerminateAfterLastWindowClosed(_: NSApplication) -> Bool { public func applicationShouldTerminateAfterLastWindowClosed(_: NSApplication) -> Bool {
SharedPreferences.inDebug || !SharedPreferences.menuBarExtraInBackground.getBlocking() SharedPreferences.inDebug || !SharedPreferences.menuBarExtraInBackground.getBlocking()
} }
+32 -1
View File
@@ -4,17 +4,48 @@ import Libbox
import Library import Library
import Network import Network
import UIKit import UIKit
import UserNotifications
class ApplicationDelegate: NSObject, UIApplicationDelegate { class ApplicationDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
private var profileServer: ProfileServer? private var profileServer: ProfileServer?
func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool { func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
NSLog("Here I stand") NSLog("Here I stand")
LibboxSetup(FilePath.sharedDirectory.relativePath, FilePath.workingDirectory.relativePath, FilePath.cacheDirectory.relativePath, false) LibboxSetup(FilePath.sharedDirectory.relativePath, FilePath.workingDirectory.relativePath, FilePath.cacheDirectory.relativePath, false)
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.setNotificationCategories([
UNNotificationCategory(
identifier: "OPEN_URL",
actions: [
UNNotificationAction(identifier: "COPY_URL", title: "Copy URL", options: .foreground, icon: UNNotificationActionIcon(systemImageName: "clipboard.fill")),
UNNotificationAction(identifier: "OPEN_URL", title: "Open", options: .foreground, icon: UNNotificationActionIcon(systemImageName: "safari.fill")),
],
intentIdentifiers: []
),
]
)
notificationCenter.delegate = self
setup() setup()
return true return true
} }
func userNotificationCenter(_: UNUserNotificationCenter, willPresent _: UNNotification) async -> UNNotificationPresentationOptions {
.banner
}
func userNotificationCenter(_: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async {
if let url = response.notification.request.content.userInfo["OPEN_URL"] as? String {
switch response.actionIdentifier {
case "COPY_URL":
UIPasteboard.general.string = url
case "OPEN_URL":
fallthrough
default:
await UIApplication.shared.open(URL(string: url)!)
}
}
}
private func setup() { private func setup() {
do { do {
try UIProfileUpdateTask.configure() try UIProfileUpdateTask.configure()