Implement send notification
This commit is contained in:
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user