Skip to content

Commit

Permalink
Merge branch 'SagerNet:dev' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
qinyuhang authored Aug 4, 2024
2 parents a0f3371 + d60b2b5 commit cd92fb4
Show file tree
Hide file tree
Showing 42 changed files with 1,173 additions and 295 deletions.
37 changes: 16 additions & 21 deletions ApplicationLibrary/Service/UIProfileUpdateTask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,30 @@ import Library
public class UIProfileUpdateTask: BGAppRefreshTask {
private static let taskSchedulerPermittedIdentifier = "\(FilePath.packageName).update_profiles"

private actor Register {
private var registered = false
func configure() async throws {
if !registered {
let success = BGTaskScheduler.shared.register(forTaskWithIdentifier: taskSchedulerPermittedIdentifier, using: nil) { task in
NSLog("profile update task started")
Task {
await UIProfileUpdateTask.getAndUpdateProfiles(task)
}
private static var registered = false
public static func configure() throws {
if !registered {
let success = BGTaskScheduler.shared.register(forTaskWithIdentifier: taskSchedulerPermittedIdentifier, using: nil) { task in
NSLog("profile update task started")
Task {
await UIProfileUpdateTask.getAndUpdateProfiles(task)
}
if !success {
throw NSError(domain: "register failed", code: 0)
}
registered = true
}
if !success {
throw NSError(domain: "register task failed", code: 0)
}
registered = true
}
Task {
BGTaskScheduler.shared.cancelAllTaskRequests()
let profiles = try await ProfileManager.listAutoUpdateEnabled()
if profiles.isEmpty {
return
}
try scheduleUpdate(ProfileUpdateTask.calculateEarliestBeginDate(profiles))
}
}

private static let register = Register()
public static func configure() async throws {
try await register.configure()
if await UIApplication.shared.backgroundRefreshStatus != .available {
Task {
Task {
if await UIApplication.shared.backgroundRefreshStatus != .available {
await updateOnce()
}
}
Expand All @@ -54,7 +49,7 @@ import Library
if profiles.isEmpty {
return
}
await ProfileUpdateTask.updateProfiles(profiles)
_ = await ProfileUpdateTask.updateProfiles(profiles)
}

private nonisolated static func getAndUpdateProfiles(_ task: BGTask) async {
Expand Down
2 changes: 1 addition & 1 deletion ApplicationLibrary/Views/Abstract/Binding+Unwrap.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public extension Binding {

public extension Binding where Value == Int32 {
func stringBinding(defaultValue: Int32) -> Binding<String> {
return Binding<String> {
Binding<String> {
var intValue = wrappedValue
if intValue == 0 {
intValue = defaultValue
Expand Down
4 changes: 3 additions & 1 deletion ApplicationLibrary/Views/Abstract/ShareButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ public struct ProfileShareButton<Label>: View where Label: View {

public var body: some View {
#if os(iOS)
if #available(iOS 16.0, *) {
if #available(iOS 17.4, *) {
bodyCompat
} else if #available(iOS 16.0, *) {
ShareLink(item: profile, subject: Text(profile.name), preview: SharePreview("Share profile"), label: label)
} else if UIDevice.current.userInterfaceIdiom != .pad {
bodyCompat
Expand Down
74 changes: 74 additions & 0 deletions ApplicationLibrary/Views/Connections/Connection.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import Foundation

public struct Connection: Codable {
public let id: String
public let inbound: String
public let inboundType: String
public let ipVersion: Int32
public let network: String
public let source: String
public let destination: String
public let domain: String
public let displayDestination: String
public let protocolName: String
public let user: String
public let fromOutbound: String
public let createdAt: Date
public let closedAt: Date?
public var upload: Int64
public var download: Int64
public var uploadTotal: Int64
public var downloadTotal: Int64
public let rule: String
public let outbound: String
public let outboundType: String
public let chain: [String]

var hashValue: Int {
var value = id.hashValue
(value, _) = value.addingReportingOverflow(upload.hashValue)
(value, _) = value.addingReportingOverflow(download.hashValue)
(value, _) = value.addingReportingOverflow(uploadTotal.hashValue)
(value, _) = value.addingReportingOverflow(downloadTotal.hashValue)
return value
}

func performSearch(_ content: String) -> Bool {
for item in content.components(separatedBy: " ") {
let itemSep = item.components(separatedBy: ":")
if itemSep.count == 2 {
if !performSearchType(type: itemSep[0], value: itemSep[1]) {
return false
}
continue
}
if !performSearchPlain(item) {
return false
}
}
return true
}

private func performSearchPlain(_ content: String) -> Bool {
destination.contains(content) ||
domain.contains(content)
}

private func performSearchType(type: String, value: String) -> Bool {
switch type {
// TODO: impl more
case "network":
return network == value
case "inbound":
return inbound.contains(value)
case "inbound.type":
return inboundType == value
case "source":
return source.contains(value)
case "destination":
return destination.contains(value)
default:
return false
}
}
}
56 changes: 56 additions & 0 deletions ApplicationLibrary/Views/Connections/ConnectionDetailsView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import Foundation
import Libbox
import SwiftUI

public struct ConnectionDetailsView: View {
private let connection: Connection
public init(_ connection: Connection) {
self.connection = connection
}

public var body: some View {
FormView {
if connection.closedAt != nil {
FormTextItem("State", "Closed")
FormTextItem("Created At", connection.createdAt.myFormat)
} else {
FormTextItem("State", "Active")
FormTextItem("Created At", connection.createdAt.myFormat)
}
if let closedAt = connection.closedAt {
FormTextItem("Closed At", closedAt.myFormat)
}
FormTextItem("Upload", LibboxFormatBytes(connection.uploadTotal))
FormTextItem("Download", LibboxFormatBytes(connection.downloadTotal))
Section("Metadata") {
FormTextItem("Inbound", connection.inbound)
FormTextItem("Inbound Type", connection.inboundType)
FormTextItem("IP Version", "\(connection.ipVersion)")
FormTextItem("Network", connection.network.uppercased())
FormTextItem("Source", connection.source)
FormTextItem("Destination", connection.destination)
if !connection.domain.isEmpty {
FormTextItem("Domain", connection.domain)
}
if !connection.protocolName.isEmpty {
FormTextItem("Protocol", connection.protocolName)
}
if !connection.user.isEmpty {
FormTextItem("User", connection.user)
}
if !connection.fromOutbound.isEmpty {
FormTextItem("From Outbound", connection.fromOutbound)
}
if !connection.rule.isEmpty {
FormTextItem("Match Rule", connection.rule)
}
FormTextItem("Outbound", connection.outbound)
FormTextItem("Outbound Type", connection.outboundType)
if connection.chain.count > 1 {
FormTextItem("Chain", connection.chain.reversed().joined(separator: "/"))
}
}
}
.navigationTitle("Connection")
}
}
31 changes: 31 additions & 0 deletions ApplicationLibrary/Views/Connections/ConnectionListPage.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Foundation
import SwiftUI

public enum ConnectionListPage: Int, CaseIterable, Identifiable {
public var id: Self {
self
}

case active
case closed
}

public extension ConnectionListPage {
var title: String {
switch self {
case .active:
return NSLocalizedString("Active", comment: "")
case .closed:
return NSLocalizedString("Closed", comment: "")
}
}

var label: some View {
switch self {
case .active:
return Label(title, systemImage: "play.fill")
case .closed:
return Label(title, systemImage: "stop.fill")
}
}
}
Loading

0 comments on commit cd92fb4

Please sign in to comment.