Files
sing-box-for-apple/SFI/ApplicationDelegate.swift
2026-04-23 08:12:53 +08:00

138 lines
5.1 KiB
Swift

import ApplicationLibrary
import FileProvider
import Foundation
import Libbox
import Library
import Network
import UIKit
import UserNotifications
class ApplicationDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
private var profileServer: ProfileServer?
private var reportTransferServer: ReportTransferServer?
func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
LibboxPrepareCrashSignalHandlers()
NativeCrashReporter.installForCurrentProcess()
LibboxReinstallCrashSignalHandlers()
NSLog("Here I stand")
let options = LibboxSetupOptions()
options.basePath = FilePath.sharedDirectory.relativePath
options.workingPath = FilePath.workingDirectory.relativePath
options.tempPath = FilePath.cacheDirectory.relativePath
options.crashReportSource = "Application"
var setupError: NSError?
LibboxSetup(options, &setupError)
if let setupError {
NSLog("setup service error: \(setupError.localizedDescription)")
}
var localeError: NSError?
LibboxSetLocale(Locale.current.identifier, &localeError)
if let localeError {
NSLog("failed to set locale: \(localeError)")
}
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()
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
default:
await UIApplication.shared.open(URL(string: url)!)
}
}
}
private func setup() {
do {
try UIProfileUpdateTask.configure()
NSLog("setup background task success")
} catch {
NSLog("setup background task error: \(error.localizedDescription)")
}
Task {
if UIDevice.current.userInterfaceIdiom == .phone {
await requestNetworkPermission()
}
await setupBackground()
}
}
private nonisolated func setupBackground() async {
if #available(iOS 16.0, *) {
do {
let profileServer = try ProfileServer()
profileServer.start()
await MainActor.run {
self.profileServer = profileServer
}
NSLog("started profile server")
} catch {
NSLog("setup profile server error: \(error.localizedDescription)")
}
do {
let reportTransferServer = try ReportTransferServer()
reportTransferServer.start()
await MainActor.run {
self.reportTransferServer = reportTransferServer
}
NSLog("started report transfer server")
} catch {
NSLog("setup report transfer server error: \(error.localizedDescription)")
}
registerFileProviderDomain()
}
}
@available(iOS 16.0, *)
private nonisolated func registerFileProviderDomain() {
let domain = NSFileProviderDomain(
identifier: NSFileProviderDomainIdentifier(AppConfiguration.fileProviderDomainID),
displayName: "sing-box"
)
NSFileProviderManager.add(domain) { error in
if let error {
NSLog("Failed to add file provider domain: \(error)")
}
}
}
private nonisolated func requestNetworkPermission() async {
if await SharedPreferences.networkPermissionRequested.get() {
return
}
if !DeviceCensorship.isChinaDevice() {
await SharedPreferences.networkPermissionRequested.set(true)
return
}
URLSession.shared.dataTask(with: URL(string: "http://captive.apple.com")!) { _, response, _ in
if let response = response as? HTTPURLResponse {
if response.statusCode == 200 {
Task {
await SharedPreferences.networkPermissionRequested.set(true)
}
}
}
}.resume()
}
}