Prepare airdrop support

This commit is contained in:
世界
2023-07-26 20:38:51 +08:00
parent 486a685bb5
commit 2bd462c789
52 changed files with 488 additions and 455 deletions
@@ -0,0 +1,47 @@
import Foundation
import SwiftUI
public extension Alert {
init(_ error: Error, _ dismissAction: (() -> Void)? = nil) {
self.init(
errorMessage: error.localizedDescription,
dismissAction
)
}
init(errorMessage: String, _ dismissAction: (() -> Void)? = nil) {
self.init(
title: Text("Error"),
message: Text(errorMessage),
dismissButton: .default(Text("Ok")) {
dismissAction?()
}
)
}
}
public extension View {
func alertBinding(_ binding: Binding<Alert?>) -> some View {
alert(isPresented: Binding(get: {
binding.wrappedValue != nil
}, set: { newValue, _ in
if !newValue {
binding.wrappedValue = nil
}
})) {
binding.wrappedValue!
}
}
func alertBinding(_ binding: Binding<Alert?>, _ isLoading: Binding<Bool>) -> some View {
alert(isPresented: Binding(get: {
binding.wrappedValue != nil
}, set: { newValue, _ in
if !newValue, !isLoading.wrappedValue {
binding.wrappedValue = nil
}
})) {
binding.wrappedValue!
}
}
}
@@ -16,9 +16,7 @@ public struct ActiveDashboardView: View {
@State private var selectedProfileID: Int64! @State private var selectedProfileID: Int64!
@State private var reasserting = false @State private var reasserting = false
@State private var observer: Any? @State private var observer: Any?
@State private var alert: Alert?
@State private var errorPresented = false
@State private var errorMessage = ""
public init() {} public init() {}
@@ -78,43 +76,37 @@ public struct ActiveDashboardView: View {
} }
} }
} }
.alert(isPresented: $errorPresented) { .alertBinding($alert)
Alert(
title: Text("Error"),
message: Text(errorMessage),
dismissButton: .default(Text("Ok"))
)
}
#if os(iOS) #if os(iOS)
.onChange(of: scenePhase, perform: { newValue in .onChange(of: scenePhase, perform: { newValue in
if newValue == .active { if newValue == .active {
Task.detached {
await doReload()
}
}
})
.onChange(of: selection.wrappedValue, perform: { newValue in
if newValue == .dashboard {
Task.detached {
await doReload()
}
}
})
#elseif os(macOS)
.onAppear {
if observer == nil {
observer = NotificationCenter.default.addObserver(forName: ActiveDashboardView.NotificationUpdateSelectedProfile, object: nil, queue: nil, using: { _ in
Task.detached { Task.detached {
await doReload() await doReload()
} }
}) }
})
.onChange(of: selection.wrappedValue, perform: { newValue in
if newValue == .dashboard {
Task.detached {
await doReload()
}
}
})
#elseif os(macOS)
.onAppear {
if observer == nil {
observer = NotificationCenter.default.addObserver(forName: ActiveDashboardView.NotificationUpdateSelectedProfile, object: nil, queue: nil, using: { _ in
Task.detached {
await doReload()
}
})
}
} }
} .onDisappear {
.onDisappear { if let observer {
if let observer { NotificationCenter.default.removeObserver(observer)
NotificationCenter.default.removeObserver(observer) }
} }
}
#endif #endif
} }
@@ -132,8 +124,7 @@ public struct ActiveDashboardView: View {
do { do {
profileList = try ProfileManager.list() profileList = try ProfileManager.list()
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
return return
} }
if profileList.isEmpty { if profileList.isEmpty {
@@ -158,8 +149,7 @@ public struct ActiveDashboardView: View {
do { do {
try LibboxNewStandaloneCommandClient(FilePath.sharedDirectory.relativePath)?.serviceReload() try LibboxNewStandaloneCommandClient(FilePath.sharedDirectory.relativePath)?.serviceReload()
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
} }
} }
reasserting = false reasserting = false
@@ -7,8 +7,7 @@ public struct ExtensionStatusView: View {
@State private var message: LibboxStatusMessage? @State private var message: LibboxStatusMessage?
@State private var connectTask: Task<Void, Error>? @State private var connectTask: Task<Void, Error>?
@State private var columnCount: Int = 4 @State private var columnCount: Int = 4
@State private var errorPresented = false @State private var alert: Alert?
@State private var errorMessage = ""
private let infoFont = Font.system(.caption, design: .monospaced) private let infoFont = Font.system(.caption, design: .monospaced)
@@ -67,13 +66,7 @@ public struct ExtensionStatusView: View {
} }
commandClient = nil commandClient = nil
} }
.alert(isPresented: $errorPresented) { .alertBinding($alert)
Alert(
title: Text("Error"),
message: Text(errorMessage),
dismissButton: .default(Text("Ok"))
)
}
} }
private func doReload() { private func doReload() {
@@ -125,8 +118,7 @@ public struct ExtensionStatusView: View {
do { do {
try LibboxNewStandaloneCommandClient(FilePath.sharedDirectory.relativePath)?.closeConnections() try LibboxNewStandaloneCommandClient(FilePath.sharedDirectory.relativePath)?.closeConnections()
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
} }
} }
@@ -4,8 +4,7 @@ import SwiftUI
public struct InstallProfileButton: View { public struct InstallProfileButton: View {
@Environment(\.extensionProfile) private var extensionProfile @Environment(\.extensionProfile) private var extensionProfile
@State private var errorPresented = false @State private var alert: Alert?
@State private var errorMessage = ""
public init() {} public init() {}
@@ -15,21 +14,14 @@ public struct InstallProfileButton: View {
await installProfile() await installProfile()
} }
} }
.alert(isPresented: $errorPresented) { .alertBinding($alert)
Alert(
title: Text("Error"),
message: Text(errorMessage),
dismissButton: .default(Text("Ok"))
)
}
} }
private func installProfile() async { private func installProfile() async {
do { do {
try await ExtensionProfile.install() try await ExtensionProfile.install()
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
} }
} }
} }
@@ -4,8 +4,7 @@
import SwiftUI import SwiftUI
public struct InstallSystemExtensionButton: View { public struct InstallSystemExtensionButton: View {
@State private var errorPresented = false @State private var alert: Alert?
@State private var errorMessage = ""
private let callback: () -> Void private let callback: () -> Void
public init(_ callback: @escaping () -> Void) { public init(_ callback: @escaping () -> Void) {
self.callback = callback self.callback = callback
@@ -17,27 +16,19 @@
await installSystemExtension() await installSystemExtension()
} }
} }
.alert(isPresented: $errorPresented) { .alertBinding($alert)
Alert(
title: Text("Error"),
message: Text(errorMessage),
dismissButton: .default(Text("Ok"))
)
}
} }
private func installSystemExtension() async { private func installSystemExtension() async {
do { do {
if let result = try await SystemExtension.install() { if let result = try await SystemExtension.install() {
if result == .willCompleteAfterReboot { if result == .willCompleteAfterReboot {
errorMessage = "Need reboot" alert = Alert(errorMessage: "Need Reboot")
errorPresented = true
} }
} }
callback() callback()
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
} }
} }
} }
@@ -41,8 +41,7 @@ public struct StartStopButton: View {
private struct Button0: View { private struct Button0: View {
@Environment(\.logClient) private var logClient @Environment(\.logClient) private var logClient
@ObservedObject private var profile: ExtensionProfile @ObservedObject private var profile: ExtensionProfile
@State private var errorPresented = false @State private var alert: Alert?
@State private var errorMessage = ""
init(_ profile: ExtensionProfile) { init(_ profile: ExtensionProfile) {
self.profile = profile self.profile = profile
@@ -75,13 +74,7 @@ public struct StartStopButton: View {
#endif #endif
} }
.disabled(!profile.status.isEnabled) .disabled(!profile.status.isEnabled)
.alert(isPresented: $errorPresented) { .alertBinding($alert)
Alert(
title: Text("Error"),
message: Text(errorMessage),
dismissButton: .default(Text("Ok"))
)
}
} }
private func switchProfile(_ isEnabled: Bool) async { private func switchProfile(_ isEnabled: Bool) async {
@@ -93,8 +86,7 @@ public struct StartStopButton: View {
profile.stop() profile.stop()
} }
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
return return
} }
} }
@@ -1,4 +1,5 @@
import Foundation import Foundation
import Libbox
import Library import Library
import SwiftUI import SwiftUI
@@ -54,4 +55,17 @@ public extension EnvironmentValues {
self[logClientKey.self] = newValue self[logClientKey.self] = newValue
} }
} }
private struct importRemoteProfileKey: EnvironmentKey {
static var defaultValue: Binding<LibboxImportRemoteProfile?> = .constant(nil)
}
var importRemoteProfile: Binding<LibboxImportRemoteProfile?> {
get {
self[importRemoteProfileKey.self]
}
set {
self[importRemoteProfileKey.self] = newValue
}
}
} }
@@ -3,16 +3,13 @@ import Library
import SwiftUI import SwiftUI
public struct GroupView: View { public struct GroupView: View {
private var expland: Binding<Bool> @Binding private var expland: Bool
@State private var group: OutboundGroup @State private var group: OutboundGroup
@State private var geometryWidth: CGFloat = 300 @State private var geometryWidth: CGFloat = 300
@State private var errorPresented = false
@State private var errorMessage = ""
public init(_ group: OutboundGroup, _ expland: Binding<Bool>) { public init(_ group: OutboundGroup, _ expland: Binding<Bool>) {
self.group = group self.group = group
self.expland = expland _expland = expland
} }
private var title: some View { private var title: some View {
@@ -28,9 +25,9 @@ public struct GroupView: View {
.background(Color.gray.opacity(0.5)) .background(Color.gray.opacity(0.5))
.cornerRadius(4) .cornerRadius(4)
Button { Button {
expland.wrappedValue = !expland.wrappedValue expland = !expland
} label: { } label: {
if expland.wrappedValue { if expland {
Image(systemName: "arrow.down.to.line") Image(systemName: "arrow.down.to.line")
} else { } else {
Image(systemName: "arrow.up.to.line") Image(systemName: "arrow.up.to.line")
@@ -51,18 +48,11 @@ public struct GroupView: View {
#endif #endif
Spacer(minLength: 6) Spacer(minLength: 6)
} }
.alert(isPresented: $errorPresented) {
Alert(
title: Text("Error"),
message: Text(errorMessage),
dismissButton: .default(Text("Ok"))
)
}
} }
public var body: some View { public var body: some View {
Section { Section {
if expland.wrappedValue { if expland {
LazyVGrid(columns: Array(repeating: GridItem(.flexible()), LazyVGrid(columns: Array(repeating: GridItem(.flexible()),
count: explandColumnCount())) count: explandColumnCount()))
{ {
@@ -123,12 +113,7 @@ public struct GroupView: View {
} }
private func doURLTest() { private func doURLTest() {
do { try? LibboxNewStandaloneCommandClient(FilePath.sharedDirectory.relativePath)!.urlTest(group.tag)
try LibboxNewStandaloneCommandClient(FilePath.sharedDirectory.relativePath)!.urlTest(group.tag)
} catch {
errorMessage = error.localizedDescription
errorPresented = true
}
} }
} }
@@ -26,10 +26,7 @@ public struct EditProfileContentView: View {
@State private var profile: Profile! @State private var profile: Profile!
@State private var profileContent: String = "" @State private var profileContent: String = ""
@State private var isChanged = false @State private var isChanged = false
@State private var alert: Alert?
@State private var errorPresented = false
@State private var errorMessage = ""
@State private var fatalError = false
public var body: some View { public var body: some View {
viewBuilder { viewBuilder {
@@ -60,17 +57,7 @@ public struct EditProfileContentView: View {
} }
} }
} }
.alert(isPresented: $errorPresented) { .alertBinding($alert)
Alert(
title: Text("Error"),
message: Text(errorMessage),
dismissButton: .default(Text("Ok"), action: {
if fatalError {
dismiss()
}
})
)
}
.navigationTitle(navigationTitle) .navigationTitle(navigationTitle)
#if os(macOS) #if os(macOS)
.toolbar { .toolbar {
@@ -115,9 +102,7 @@ public struct EditProfileContentView: View {
do { do {
try loadContent0() try loadContent0()
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error, dismiss.callAsFunction)
fatalError = true
errorPresented = true
} }
} }
@@ -140,8 +125,7 @@ public struct EditProfileContentView: View {
do { do {
try profile.write(profileContent) try profile.write(profileContent)
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
return return
} }
isChanged = false isChanged = false
@@ -10,8 +10,7 @@ public struct EditProfileView: View {
@State private var isLoading = false @State private var isLoading = false
@State private var isChanged = false @State private var isChanged = false
@State private var errorPresented = false @State private var alert: Alert?
@State private var errorMessage = ""
public init() {} public init() {}
@@ -69,6 +68,17 @@ public struct EditProfileView: View {
} }
.disabled(isLoading) .disabled(isLoading)
} }
if #available(iOS 16.0, *) {
ShareLink(item: profile.shareLink) {
Text("Share")
}
} else {
Button("Share") {
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
windowScene.keyWindow?.rootViewController?.present(UIActivityViewController(activityItems: [profile.shareLink], applicationActivities: nil), animated: true, completion: nil)
}
}
}
} }
#endif #endif
} }
@@ -132,13 +142,7 @@ public struct EditProfileView: View {
} }
} }
#endif #endif
.alert(isPresented: $errorPresented) { .alertBinding($alert)
Alert(
title: Text("Error"),
message: Text(errorMessage),
dismissButton: .default(Text("Ok"))
)
}
.navigationTitle("Edit Profile") .navigationTitle("Edit Profile")
} }
@@ -150,8 +154,7 @@ public struct EditProfileView: View {
try await Task.sleep(nanoseconds: UInt64(100 * Double(NSEC_PER_MSEC))) try await Task.sleep(nanoseconds: UInt64(100 * Double(NSEC_PER_MSEC)))
try profile.updateRemoteProfile() try profile.updateRemoteProfile()
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
} }
} }
@@ -159,8 +162,7 @@ public struct EditProfileView: View {
do { do {
_ = try ProfileManager.update(profile) _ = try ProfileManager.update(profile)
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
return return
} }
isChanged = false isChanged = false
@@ -1,4 +1,3 @@
import Library import Library
import SwiftUI import SwiftUI
@@ -16,8 +15,7 @@ import SwiftUI
@State private var isLoading = true @State private var isLoading = true
@State private var profile: Profile! @State private var profile: Profile!
@State private var errorPresented = false @State private var alert: Alert?
@State private var errorMessage = ""
public var body: some View { public var body: some View {
viewBuilder { viewBuilder {
@@ -27,19 +25,11 @@ import SwiftUI
await doReload() await doReload()
} }
} }
.alert(isPresented: $errorPresented) {
Alert(
title: Text("Error"),
message: Text(errorMessage),
dismissButton: .default(Text("Ok"), action: {
dismiss()
})
)
}
} else { } else {
EditProfileView().environmentObject(profile!) EditProfileView().environmentObject(profile!)
} }
} }
.alertBinding($alert)
.onExitCommand { .onExitCommand {
dismiss() dismiss()
} }
@@ -47,20 +37,17 @@ import SwiftUI
private func doReload() async { private func doReload() async {
guard let profileID else { guard let profileID else {
errorMessage = "Context destroyed" alert = Alert(errorMessage: "Context destroyed")
errorPresented = true
return return
} }
do { do {
profile = try ProfileManager.get(profileID) profile = try ProfileManager.get(profileID)
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
return return
} }
if profile == nil { if profile == nil {
errorMessage = "Profile deleted" alert = Alert(errorMessage: "Profile deleted")
errorPresented = true
return return
} }
isLoading = false isLoading = false
@@ -17,12 +17,21 @@ public struct NewProfileView: View {
@State private var fileURL: URL! @State private var fileURL: URL!
@State private var remotePath = "" @State private var remotePath = ""
@State private var pickerPresented = false @State private var pickerPresented = false
@State private var errorPresented = false @State private var alert: Alert?
@State private var errorMessage = ""
public struct ImportRequest: Codable, Hashable {
public let name: String
public let url: String
}
private let callback: (() -> Void)? private let callback: (() -> Void)?
public init(_ callback: (() -> Void)? = nil) { public init(_ importRequest: ImportRequest? = nil, _ callback: (() -> Void)? = nil) {
self.callback = callback self.callback = callback
if let importRequest {
_profileName = .init(initialValue: importRequest.name)
_profileType = .init(initialValue: .remote)
_remotePath = .init(initialValue: importRequest.url)
}
} }
public var body: some View { public var body: some View {
@@ -88,13 +97,7 @@ public struct NewProfileView: View {
} }
} }
.navigationTitle("New Profile") .navigationTitle("New Profile")
.alert(isPresented: $errorPresented) { .alertBinding($alert)
Alert(
title: Text("Error"),
message: Text(errorMessage),
dismissButton: .default(Text("Ok"))
)
}
.fileImporter( .fileImporter(
isPresented: $pickerPresented, isPresented: $pickerPresented,
allowedContentTypes: [.json], allowedContentTypes: [.json],
@@ -106,8 +109,7 @@ public struct NewProfileView: View {
fileURL = urls[0] fileURL = urls[0]
} }
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
return return
} }
} }
@@ -118,26 +120,22 @@ public struct NewProfileView: View {
isSaving = false isSaving = false
} }
if profileName.isEmpty { if profileName.isEmpty {
errorMessage = "Missing profile name" alert = Alert(errorMessage: "Missing profile name")
errorPresented = true
return return
} }
if remotePath.isEmpty { if remotePath.isEmpty {
if profileType == .icloud { if profileType == .icloud {
errorMessage = "Missing path" alert = Alert(errorMessage: "Missing path")
errorPresented = true
return return
} else if profileType == .remote { } else if profileType == .remote {
errorMessage = "Missing URL" alert = Alert(errorMessage: "Missing URL")
errorPresented = true
return return
} }
} }
do { do {
try createProfile0() try createProfile0()
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
return return
} }
await MainActor.run { await MainActor.run {
@@ -173,13 +171,11 @@ public struct NewProfileView: View {
let profileConfig = profileConfigDirectory.appendingPathComponent("config_\(nextProfileID).json") let profileConfig = profileConfigDirectory.appendingPathComponent("config_\(nextProfileID).json")
if fileImport { if fileImport {
guard let fileURL else { guard let fileURL else {
errorMessage = "Missing file" alert = Alert(errorMessage: "Missing file")
errorPresented = true
return return
} }
if !fileURL.startAccessingSecurityScopedResource() { if !fileURL.startAccessingSecurityScopedResource() {
errorMessage = "Missing access to selected file" alert = Alert(errorMessage: "Missing access to selected file")
errorPresented = true
return return
} }
defer { defer {
@@ -1,16 +1,19 @@
import Foundation import Foundation
import Libbox
import Library import Library
import SwiftUI import SwiftUI
public struct ProfileView: View { public struct ProfileView: View {
public static let notificationName = Notification.Name("\(FilePath.packageName).update-profile") public static let notificationName = Notification.Name("\(FilePath.packageName).update-profile")
@Environment(\.importRemoteProfile) private var importRemoteProfile
@State private var importRemoteProfileRequest: NewProfileView.ImportRequest?
@State private var importRemoteProfilePresented = false
@State private var isLoading = true @State private var isLoading = true
@State private var isUpdating = false @State private var isUpdating = false
@State private var errorPresented = false @State private var alert: Alert?
@State private var errorMessage = ""
@State private var profileList: [Profile] = [] @State private var profileList: [Profile] = []
#if os(iOS) #if os(iOS)
@@ -33,36 +36,51 @@ public struct ProfileView: View {
} }
} else { } else {
#if os(iOS) #if os(iOS)
FormView { ZStack {
NavigationLink { if let importRemoteProfileRequest {
NewProfileView { NavigationLink(
Task.detached { destination: NewProfileView(importRemoteProfileRequest) {
doReload() Task.detached {
doReload()
}
},
isActive: $importRemoteProfilePresented,
label: {
EmptyView()
} }
} )
} label: {
Text("New Profile").foregroundColor(.accentColor)
} }
.disabled(editMode.isEditing) FormView {
if profileList.isEmpty { NavigationLink {
Text("Empty Profiles") NewProfileView {
} else { Task.detached {
List { doReload()
ForEach(profileList, id: \.mustID) { profile in }
viewBuilder { }
if editMode.isEditing == true { } label: {
Text(profile.name) Text("New Profile").foregroundColor(.accentColor)
} else { }
NavigationLink { .disabled(editMode.isEditing)
EditProfileView().environmentObject(profile) if profileList.isEmpty {
} label: { Text("Empty Profiles")
} else {
List {
ForEach(profileList, id: \.mustID) { profile in
viewBuilder {
if editMode.isEditing == true {
Text(profile.name) Text(profile.name)
} else {
NavigationLink {
EditProfileView().environmentObject(profile)
} label: {
Text(profile.name)
}
} }
} }
} }
.onMove(perform: moveProfile)
.onDelete(perform: deleteProfile)
} }
.onMove(perform: moveProfile)
.onDelete(perform: deleteProfile)
} }
} }
} }
@@ -92,6 +110,9 @@ public struct ProfileView: View {
}, label: { }, label: {
Image(systemName: "arrow.clockwise") Image(systemName: "arrow.clockwise")
}) })
ShareLink(item: profile.shareLink) {
Image(systemName: "square.and.arrow.up.fill")
}
} }
Button(action: { Button(action: {
openWindow(id: EditProfileWindowView.windowID, value: profile.mustID) openWindow(id: EditProfileWindowView.windowID, value: profile.mustID)
@@ -119,8 +140,13 @@ public struct ProfileView: View {
} }
.disabled(isUpdating) .disabled(isUpdating)
.navigationTitle("Profiles") .navigationTitle("Profiles")
#if os(macOS) .alertBinding($alert, $isLoading)
.onAppear { .onAppear {
if let remoteProfile = importRemoteProfile.wrappedValue {
importRemoteProfile.wrappedValue = nil
createImportRemoteProfileDialog(remoteProfile)
}
#if os(macOS)
if observer == nil { if observer == nil {
observer = NotificationCenter.default.addObserver(forName: ProfileView.notificationName, object: nil, queue: .main) { _ in observer = NotificationCenter.default.addObserver(forName: ProfileView.notificationName, object: nil, queue: .main) { _ in
Task.detached { Task.detached {
@@ -128,40 +154,63 @@ public struct ProfileView: View {
} }
} }
} }
#endif
}
.onChange(of: importRemoteProfile.wrappedValue) { newValue in
if let newValue {
importRemoteProfile.wrappedValue = nil
createImportRemoteProfileDialog(newValue)
} }
.onDisappear { }
if let observer { #if os(macOS)
NotificationCenter.default.removeObserver(observer) .onDisappear {
} if let observer {
observer = nil NotificationCenter.default.removeObserver(observer)
} }
.toolbar { observer = nil
ToolbarItem { }
Button(action: { .toolbar {
openWindow(id: NewProfileView.windowID) ToolbarItem {
}, label: { Button(action: {
Label("New Profile", systemImage: "plus.square.fill") openWindow(id: NewProfileView.windowID)
}) }, label: {
} Label("New Profile", systemImage: "plus.square.fill")
})
} }
}
#elseif os(iOS) #elseif os(iOS)
.toolbar { .toolbar {
ToolbarItem(placement: .navigationBarTrailing) { ToolbarItem(placement: .navigationBarTrailing) {
EditButton().disabled(profileList.isEmpty) EditButton().disabled(profileList.isEmpty)
}
} }
.environment(\.editMode, $editMode) }
.environment(\.editMode, $editMode)
#endif #endif
} }
private func createImportRemoteProfileDialog(_ newValue: LibboxImportRemoteProfile) {
importRemoteProfileRequest = .init(name: newValue.name, url: newValue.url)
alert = Alert(
title: Text("Import Remote Profile"),
message: Text("Are you sure to import remote configuration \(newValue.name)? You will connect to \(newValue.host) to download the configuration."),
primaryButton: .default(Text("Import")) {
#if os(iOS)
importRemoteProfilePresented = true
#elseif os(macOS)
openWindow(id: NewProfileView.windowID, value: importRemoteProfileRequest!)
#endif
},
secondaryButton: .cancel()
)
}
private func deleteSelectedProfiles(_ profileID: [Int64]) { private func deleteSelectedProfiles(_ profileID: [Int64]) {
do { do {
if try ProfileManager.delete(by: profileID) > 0 { if try ProfileManager.delete(by: profileID) > 0 {
isLoading = true isLoading = true
} }
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
} }
} }
@@ -178,8 +227,7 @@ public struct ProfileView: View {
do { do {
profileList = try ProfileManager.list() profileList = try ProfileManager.list()
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
return return
} }
} }
@@ -189,8 +237,7 @@ public struct ProfileView: View {
do { do {
_ = try profile.updateRemoteProfile() _ = try profile.updateRemoteProfile()
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
} }
isUpdating = false isUpdating = false
} }
@@ -200,8 +247,7 @@ public struct ProfileView: View {
do { do {
_ = try ProfileManager.delete(profile) _ = try ProfileManager.delete(profile)
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
return return
} }
isLoading = true isLoading = true
@@ -216,8 +262,7 @@ public struct ProfileView: View {
do { do {
try ProfileManager.update(profileList) try ProfileManager.update(profileList)
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
return return
} }
} }
@@ -231,8 +276,7 @@ public struct ProfileView: View {
do { do {
_ = try ProfileManager.delete(profileToDelete) _ = try ProfileManager.delete(profileToDelete)
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
} }
} }
} }
@@ -24,9 +24,7 @@ public struct SettingView: View {
@State private var version = "" @State private var version = ""
@State private var dataSize = "" @State private var dataSize = ""
@State private var taiwanFlagAvailable = false @State private var taiwanFlagAvailable = false
@State private var alert: Alert?
@State private var errorPresented = false
@State private var errorMessage = ""
public init() {} public init() {}
@@ -82,13 +80,11 @@ public struct SettingView: View {
do { do {
if let result = try await SystemExtension.install(forceUpdate: true) { if let result = try await SystemExtension.install(forceUpdate: true) {
if result == .willCompleteAfterReboot { if result == .willCompleteAfterReboot {
errorMessage = "Need reboot" alert = Alert(errorMessage: "Need reboot")
errorPresented = true
} }
} }
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
} }
} }
} }
@@ -134,13 +130,7 @@ public struct SettingView: View {
} }
} }
.navigationTitle("Settings") .navigationTitle("Settings")
.alert(isPresented: $errorPresented) { .alertBinding($alert)
Alert(
title: Text("Error"),
message: Text(errorMessage),
dismissButton: .default(Text("Ok"))
)
}
} }
#if os(macOS) #if os(macOS)
@@ -156,8 +146,7 @@ public struct SettingView: View {
try SMAppService.mainApp.unregister() try SMAppService.mainApp.unregister()
} }
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
} }
} }
#endif #endif
+8
View File
@@ -0,0 +1,8 @@
import Foundation
import Libbox
public extension Profile {
var shareLink: URL {
URL(string: LibboxGenerateRemoteProfileImportLink(name, remoteURL!))!
}
}

Before

Width:  |  Height:  |  Size: 278 KiB

After

Width:  |  Height:  |  Size: 278 KiB

Before

Width:  |  Height:  |  Size: 286 KiB

After

Width:  |  Height:  |  Size: 286 KiB

Before

Width:  |  Height:  |  Size: 273 KiB

After

Width:  |  Height:  |  Size: 273 KiB

Before

Width:  |  Height:  |  Size: 273 KiB

After

Width:  |  Height:  |  Size: 273 KiB

Before

Width:  |  Height:  |  Size: 286 KiB

After

Width:  |  Height:  |  Size: 286 KiB

Before

Width:  |  Height:  |  Size: 306 KiB

After

Width:  |  Height:  |  Size: 306 KiB

Before

Width:  |  Height:  |  Size: 272 KiB

After

Width:  |  Height:  |  Size: 272 KiB

Before

Width:  |  Height:  |  Size: 274 KiB

After

Width:  |  Height:  |  Size: 274 KiB

Before

Width:  |  Height:  |  Size: 306 KiB

After

Width:  |  Height:  |  Size: 306 KiB

Before

Width:  |  Height:  |  Size: 340 KiB

After

Width:  |  Height:  |  Size: 340 KiB

Binary file not shown.
+4 -4
View File
@@ -12,7 +12,7 @@ public struct MacApplication: Scene {
MainView() MainView()
.onAppear { .onAppear {
Task.detached { Task.detached {
await initialize() initialize()
} }
} }
.environment(\.showMenuBarExtra, $showMenuBarExtra) .environment(\.showMenuBarExtra, $showMenuBarExtra)
@@ -35,9 +35,9 @@ public struct MacApplication: Scene {
SidebarCommands() SidebarCommands()
} }
Window("New Profile", id: NewProfileView.windowID) { WindowGroup("New Profile", id: NewProfileView.windowID, for: NewProfileView.ImportRequest.self) { importRequest in
NewProfileView() NewProfileView(importRequest.wrappedValue)
} }.commandsRemoved()
WindowGroup("Edit Profile", id: EditProfileWindowView.windowID, for: Int64.self) { profileID in WindowGroup("Edit Profile", id: EditProfileWindowView.windowID, for: Int64.self) { profileID in
EditProfileWindowView(profileID.wrappedValue) EditProfileWindowView(profileID.wrappedValue)
+29 -23
View File
@@ -1,4 +1,5 @@
import ApplicationLibrary import ApplicationLibrary
import Libbox
import Library import Library
import SwiftUI import SwiftUI
@@ -9,11 +10,8 @@ public struct MainView: View {
@State private var extensionProfile: ExtensionProfile? @State private var extensionProfile: ExtensionProfile?
@State private var profileLoading = true @State private var profileLoading = true
@State private var logClient: LogClient! @State private var logClient: LogClient!
@State private var alert: Alert?
@State private var dialogTitle = "" @State private var importRemoteProfile: LibboxImportRemoteProfile?
@State private var dialogContent = ""
@State private var dialogAction: (() -> Void)?
@State private var dialogPresented = false
public init() {} public init() {}
public var body: some View { public var body: some View {
@@ -44,19 +42,10 @@ public struct MainView: View {
} }
} }
#endif #endif
.alert(isPresented: $dialogPresented, content: { .alertBinding($alert)
Alert(
title: Text(dialogTitle),
message: Text(dialogContent),
dismissButton: .default(Text("Ok"), action: dialogAction)
)
})
.onAppear { .onAppear {
ServiceNotification.setServiceNotificationListener { notification in ServiceNotification.setServiceNotificationListener { notification in
dialogTitle = notification.title alert = Alert(title: Text(notification.title), message: Text(notification.body))
dialogContent = notification.body
dialogAction = nil
dialogPresented = true
} }
} }
.onDisappear { .onDisappear {
@@ -84,6 +73,22 @@ public struct MainView: View {
.environment(\.selection, $selection) .environment(\.selection, $selection)
.environment(\.extensionProfile, $extensionProfile) .environment(\.extensionProfile, $extensionProfile)
.environment(\.logClient, $logClient) .environment(\.logClient, $logClient)
.environment(\.importRemoteProfile, $importRemoteProfile)
.handlesExternalEvents(preferring: [], allowing: ["*"])
.onOpenURL(perform: openURL)
}
private func openURL(url: URL) {
if url.host == "import-remote-profile" {
var error: NSError?
importRemoteProfile = LibboxParseRemoteProfileImportLink(url.absoluteString, &error)
if error != nil {
return
}
if selection != .profiles {
selection = .profiles
}
}
} }
private func loadProfile() async { private func loadProfile() async {
@@ -115,13 +120,14 @@ public struct MainView: View {
private func checkApplicationPath() { private func checkApplicationPath() {
let directoryName = URL(filePath: Bundle.main.bundlePath).deletingLastPathComponent().pathComponents.last let directoryName = URL(filePath: Bundle.main.bundlePath).deletingLastPathComponent().pathComponents.last
if directoryName != "Applications" { if directoryName != "Applications" {
dialogTitle = "Wrong application location" alert = Alert(
dialogContent = "This app needs to be placed under ~/Applications to work." title: Text("Wrong application location"),
dialogAction = { message: Text("This app needs to be placed under ~/Applications to work."),
NSWorkspace.shared.selectFile(Bundle.main.bundlePath, inFileViewerRootedAtPath: "") dismissButton: .default(Text("Ok")) {
NSApp.terminate(nil) NSWorkspace.shared.selectFile(Bundle.main.bundlePath, inFileViewerRootedAtPath: "")
} NSApp.terminate(nil)
dialogPresented = true }
)
} }
} }
} }
+7 -25
View File
@@ -71,8 +71,7 @@ public struct MenuView: View {
private struct StatusSwitch: View { private struct StatusSwitch: View {
@ObservedObject private var profile: ExtensionProfile @ObservedObject private var profile: ExtensionProfile
@State private var errorPresented = false @State private var alert: Alert?
@State private var errorMessage = ""
init(_ profile: ExtensionProfile) { init(_ profile: ExtensionProfile) {
self.profile = profile self.profile = profile
@@ -88,13 +87,7 @@ public struct MenuView: View {
})) {} })) {}
.toggleStyle(.switch) .toggleStyle(.switch)
.disabled(!profile.status.isEnabled) .disabled(!profile.status.isEnabled)
.alert(isPresented: $errorPresented) { .alertBinding($alert)
Alert(
title: Text("Error"),
message: Text(errorMessage),
dismissButton: .default(Text("Ok"))
)
}
} }
private func switchProfile(_ isEnabled: Bool) async { private func switchProfile(_ isEnabled: Bool) async {
@@ -105,8 +98,7 @@ public struct MenuView: View {
profile.stop() profile.stop()
} }
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
return return
} }
} }
@@ -123,10 +115,8 @@ public struct MenuView: View {
@State private var profileList: [Profile] = [] @State private var profileList: [Profile] = []
@State private var selectedProfileID: Int64! @State private var selectedProfileID: Int64!
@State private var reasserting = false @State private var reasserting = false
@State private var errorPresented = false
@State private var errorMessage = ""
@State private var observer: Any? @State private var observer: Any?
@State private var alert: Alert?
var body: some View { var body: some View {
viewBuilder { viewBuilder {
@@ -169,13 +159,7 @@ public struct MenuView: View {
NotificationCenter.default.removeObserver(observer) NotificationCenter.default.removeObserver(observer)
} }
} }
.alert(isPresented: $errorPresented) { .alertBinding($alert)
Alert(
title: Text("Error"),
message: Text(errorMessage),
dismissButton: .default(Text("Ok"))
)
}
} }
private func doReload() { private func doReload() {
@@ -185,8 +169,7 @@ public struct MenuView: View {
do { do {
profileList = try ProfileManager.list() profileList = try ProfileManager.list()
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
return return
} }
if profileList.isEmpty { if profileList.isEmpty {
@@ -210,8 +193,7 @@ public struct MenuView: View {
do { do {
try LibboxNewStandaloneCommandClient(FilePath.sharedDirectory.relativePath)?.serviceReload() try LibboxNewStandaloneCommandClient(FilePath.sharedDirectory.relativePath)?.serviceReload()
} catch { } catch {
errorMessage = error.localizedDescription alert = Alert(error)
errorPresented = true
} }
} }
reasserting = false reasserting = false
+15
View File
@@ -6,6 +6,21 @@
<array> <array>
<string>io.nekohasekai.sfa.update_profiles</string> <string>io.nekohasekai.sfa.update_profiles</string>
</array> </array>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLIconFile</key>
<string>AppIcon.icns</string>
<key>CFBundleURLName</key>
<string>sing-box</string>
<key>CFBundleURLSchemes</key>
<array>
<string>sing-box</string>
</array>
</dict>
</array>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>
<false/> <false/>
<key>NSUbiquitousContainers</key> <key>NSUbiquitousContainers</key>
+19 -1
View File
@@ -1,4 +1,5 @@
import ApplicationLibrary import ApplicationLibrary
import Libbox
import Library import Library
import SwiftUI import SwiftUI
@@ -14,6 +15,8 @@ struct MainView: View {
@State private var serviceNotificationContent = "" @State private var serviceNotificationContent = ""
@State private var serviceNotificationPresented = false @State private var serviceNotificationPresented = false
@State private var importRemoteProfile: LibboxImportRemoteProfile?
var body: some View { var body: some View {
viewBuilder { viewBuilder {
if profileLoading { if profileLoading {
@@ -54,7 +57,22 @@ struct MainView: View {
.environment(\.selection, $selection) .environment(\.selection, $selection)
.environment(\.extensionProfile, $extensionProfile) .environment(\.extensionProfile, $extensionProfile)
.environment(\.logClient, $logClient) .environment(\.logClient, $logClient)
.preferredColorScheme(.dark) .environment(\.importRemoteProfile, $importRemoteProfile)
.handlesExternalEvents(preferring: [], allowing: ["*"])
.onOpenURL(perform: openURL)
}
private func openURL(url: URL) {
if url.host == "import-remote-profile" {
var error: NSError?
importRemoteProfile = LibboxParseRemoteProfileImportLink(url.absoluteString, &error)
if error != nil {
return
}
if selection != .profiles {
selection = .profiles
}
}
} }
private func loadProfile() async { private func loadProfile() async {
+17 -2
View File
@@ -2,6 +2,23 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLIconFile</key>
<string>AppIcon.icns</string>
<key>CFBundleURLName</key>
<string>sing-box</string>
<key>CFBundleURLSchemes</key>
<array>
<string>sing-box</string>
</array>
</dict>
</array>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>NSUbiquitousContainers</key> <key>NSUbiquitousContainers</key>
<dict> <dict>
<key>iCloud.io.nekohasekai.sfa</key> <key>iCloud.io.nekohasekai.sfa</key>
@@ -14,7 +31,5 @@
<string>Any</string> <string>Any</string>
</dict> </dict>
</dict> </dict>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
</dict> </dict>
</plist> </plist>
@@ -1,11 +0,0 @@
{
"colors": [
{
"idiom": "universal"
}
],
"info": {
"author": "xcode",
"version": 1
}
}
@@ -1,68 +0,0 @@
{
"images" : [
{
"filename" : "apple-16 1x.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "16x16"
},
{
"filename" : "apple-16 2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"filename" : "apple-32 1x.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "32x32"
},
{
"filename" : "apple-32 2x 1.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"filename" : "apple-128 1x.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "128x128"
},
{
"filename" : "apple-128 2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"filename" : "apple-256 1x.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "256x256"
},
{
"filename" : "apple-256 2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"filename" : "apple-512 1x.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"filename" : "apple-512 2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 286 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 286 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 306 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 306 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 340 KiB

-6
View File
@@ -1,6 +0,0 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
+15
View File
@@ -2,6 +2,21 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLIconFile</key>
<string>AppIcon</string>
<key>CFBundleURLName</key>
<string>sing-box</string>
<key>CFBundleURLSchemes</key>
<array>
<string>sing-box</string>
</array>
</dict>
</array>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>
<false/> <false/>
<key>NSUbiquitousContainers</key> <key>NSUbiquitousContainers</key>
+66 -21
View File
@@ -14,7 +14,6 @@
3A1CF2F62A50EE9C000A8289 /* GroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A1CF2F52A50EE9C000A8289 /* GroupView.swift */; }; 3A1CF2F62A50EE9C000A8289 /* GroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A1CF2F52A50EE9C000A8289 /* GroupView.swift */; };
3A1CF2F82A50F0A5000A8289 /* GroupItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A1CF2F72A50F0A5000A8289 /* GroupItemView.swift */; }; 3A1CF2F82A50F0A5000A8289 /* GroupItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A1CF2F72A50F0A5000A8289 /* GroupItemView.swift */; };
3A1CF2FA2A50F0BD000A8289 /* OutboundGroupItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A1CF2F92A50F0BD000A8289 /* OutboundGroupItem.swift */; }; 3A1CF2FA2A50F0BD000A8289 /* OutboundGroupItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A1CF2F92A50F0BD000A8289 /* OutboundGroupItem.swift */; };
3A2223542A6E1B6700C50B23 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3A2223532A6E1B6700C50B23 /* Info.plist */; };
3A2223562A6E1BDE00C50B23 /* Variant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A2223552A6E1BDE00C50B23 /* Variant.swift */; }; 3A2223562A6E1BDE00C50B23 /* Variant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A2223552A6E1BDE00C50B23 /* Variant.swift */; };
3A2223582A6E1CC700C50B23 /* MacApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A2223572A6E1CC700C50B23 /* MacApplication.swift */; }; 3A2223582A6E1CC700C50B23 /* MacApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A2223572A6E1CC700C50B23 /* MacApplication.swift */; };
3A22235A2A6E212A00C50B23 /* SystemExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A2223592A6E212A00C50B23 /* SystemExtension.swift */; }; 3A22235A2A6E212A00C50B23 /* SystemExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A2223592A6E212A00C50B23 /* SystemExtension.swift */; };
@@ -55,6 +54,12 @@
3A5F26C92A503D4A00C27EDF /* Library.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3AEC211D2A459B4700A63465 /* Library.framework */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 3A5F26C92A503D4A00C27EDF /* Library.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3AEC211D2A459B4700A63465 /* Library.framework */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
3A648D2D2A4EEAA600D95A12 /* Library.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A648D2C2A4EEAA600D95A12 /* Library.swift */; }; 3A648D2D2A4EEAA600D95A12 /* Library.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A648D2C2A4EEAA600D95A12 /* Library.swift */; };
3A648D542A4EF4C700D95A12 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AF342B12A4AA520002B34AC /* NetworkExtension.framework */; }; 3A648D542A4EF4C700D95A12 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AF342B12A4AA520002B34AC /* NetworkExtension.framework */; };
3A6CA5A02A71317A0027933B /* MarkdownUI in Frameworks */ = {isa = PBXBuildFile; productRef = 3A6CA59F2A71317A0027933B /* MarkdownUI */; };
3A6CA5A32A713A580027933B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3AEECC0A2A6DF9CA006A0E0C /* Assets.xcassets */; };
3A6CA5A62A713AA10027933B /* AppIcon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 3A6CA5A52A713AA10027933B /* AppIcon.icns */; };
3A6CA5A72A713ABA0027933B /* AppIcon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 3A6CA5A52A713AA10027933B /* AppIcon.icns */; };
3A6CA5A82A713B340027933B /* AppIcon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 3A6CA5A52A713AA10027933B /* AppIcon.icns */; };
3A6CA5A92A713C420027933B /* AppIcon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 3A6CA5A52A713AA10027933B /* AppIcon.icns */; };
3A76504C2A4F08BA003945C5 /* Libbox.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AEC20DB2A4599D000A63465 /* Libbox.xcframework */; }; 3A76504C2A4F08BA003945C5 /* Libbox.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AEC20DB2A4599D000A63465 /* Libbox.xcframework */; };
3A7701702A4E6B34008F031F /* IntentsExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A77016F2A4E6B34008F031F /* IntentsExtension.swift */; }; 3A7701702A4E6B34008F031F /* IntentsExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A77016F2A4E6B34008F031F /* IntentsExtension.swift */; };
3A7701722A4E6B34008F031F /* Intents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7701712A4E6B34008F031F /* Intents.swift */; }; 3A7701722A4E6B34008F031F /* Intents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7701712A4E6B34008F031F /* Intents.swift */; };
@@ -65,10 +70,12 @@
3A9144D92A46AE370036E9AD /* ShadredPreferences+Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A9144D82A46AE370036E9AD /* ShadredPreferences+Database.swift */; }; 3A9144D92A46AE370036E9AD /* ShadredPreferences+Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A9144D82A46AE370036E9AD /* ShadredPreferences+Database.swift */; };
3A9759202A4EB69C00E4404B /* Library.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AEC211D2A459B4700A63465 /* Library.framework */; }; 3A9759202A4EB69C00E4404B /* Library.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AEC211D2A459B4700A63465 /* Library.framework */; };
3A9759212A4EB69C00E4404B /* Library.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3AEC211D2A459B4700A63465 /* Library.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3A9759212A4EB69C00E4404B /* Library.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3AEC211D2A459B4700A63465 /* Library.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
3AB1220B2A70FD500087CD55 /* Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AB1220A2A70FD500087CD55 /* Alert.swift */; };
3AC194492A50013F00BD8CB9 /* IntentsExtension.appex in Embed ExtensionKit Extensions */ = {isa = PBXBuildFile; fileRef = 3A77016D2A4E6B34008F031F /* IntentsExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 3AC194492A50013F00BD8CB9 /* IntentsExtension.appex in Embed ExtensionKit Extensions */ = {isa = PBXBuildFile; fileRef = 3A77016D2A4E6B34008F031F /* IntentsExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
3AC1944F2A50247300BD8CB9 /* ApplicationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AC1944E2A50247300BD8CB9 /* ApplicationDelegate.swift */; }; 3AC1944F2A50247300BD8CB9 /* ApplicationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AC1944E2A50247300BD8CB9 /* ApplicationDelegate.swift */; };
3AC194502A502DFE00BD8CB9 /* ServiceNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AC1944C2A50206C00BD8CB9 /* ServiceNotification.swift */; }; 3AC194502A502DFE00BD8CB9 /* ServiceNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AC1944C2A50206C00BD8CB9 /* ServiceNotification.swift */; };
3AC5EC082A6417470077AF34 /* DeviceCensorship.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AC5EC072A6417470077AF34 /* DeviceCensorship.swift */; }; 3AC5EC082A6417470077AF34 /* DeviceCensorship.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AC5EC072A6417470077AF34 /* DeviceCensorship.swift */; };
3AD0953D2A70EB310052764E /* Profile+Share.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AD0953C2A70EB310052764E /* Profile+Share.swift */; };
3AE4D0B22A6E2B6A009FEA9E /* ExtensionPlatformInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AF342A62A4AA0FF002B34AC /* ExtensionPlatformInterface.swift */; }; 3AE4D0B22A6E2B6A009FEA9E /* ExtensionPlatformInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AF342A62A4AA0FF002B34AC /* ExtensionPlatformInterface.swift */; };
3AE4D0B32A6E2B94009FEA9E /* Extension+RunBlocking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AF342A82A4AA155002B34AC /* Extension+RunBlocking.swift */; }; 3AE4D0B32A6E2B94009FEA9E /* Extension+RunBlocking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AF342A82A4AA155002B34AC /* Extension+RunBlocking.swift */; };
3AE4D0B42A6E2BA3009FEA9E /* Extension+Iterator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AF342AA2A4AA173002B34AC /* Extension+Iterator.swift */; }; 3AE4D0B42A6E2BA3009FEA9E /* Extension+Iterator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AF342AA2A4AA173002B34AC /* Extension+Iterator.swift */; };
@@ -80,7 +87,6 @@
3AEAEE992A4F16430059612D /* Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 3A096F862A4ED3DE00D4A2ED /* Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 3AEAEE992A4F16430059612D /* Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 3A096F862A4ED3DE00D4A2ED /* Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
3AEC20F62A459AB400A63465 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AEC20F52A459AB400A63465 /* Application.swift */; }; 3AEC20F62A459AB400A63465 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AEC20F52A459AB400A63465 /* Application.swift */; };
3AEC20FA2A459AB500A63465 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3AEC20F92A459AB500A63465 /* Assets.xcassets */; }; 3AEC20FA2A459AB500A63465 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3AEC20F92A459AB500A63465 /* Assets.xcassets */; };
3AEC21102A459B1A00A63465 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3AEC210F2A459B1A00A63465 /* Assets.xcassets */; };
3AEC212F2A459D5600A63465 /* Profile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AEC212E2A459D5600A63465 /* Profile.swift */; }; 3AEC212F2A459D5600A63465 /* Profile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AEC212E2A459D5600A63465 /* Profile.swift */; };
3AEC213C2A459FDF00A63465 /* Databse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AEC213B2A459FDF00A63465 /* Databse.swift */; }; 3AEC213C2A459FDF00A63465 /* Databse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AEC213B2A459FDF00A63465 /* Databse.swift */; };
3AEC21402A45A28F00A63465 /* ProfileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AEC213F2A45A28F00A63465 /* ProfileManager.swift */; }; 3AEC21402A45A28F00A63465 /* ProfileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AEC213F2A45A28F00A63465 /* ProfileManager.swift */; };
@@ -373,6 +379,7 @@
3A57DF3F2A4D70B600690BC5 /* MenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuView.swift; sourceTree = "<group>"; }; 3A57DF3F2A4D70B600690BC5 /* MenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuView.swift; sourceTree = "<group>"; };
3A57DF412A4D927A00690BC5 /* Profile+Hashable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Profile+Hashable.swift"; sourceTree = "<group>"; }; 3A57DF412A4D927A00690BC5 /* Profile+Hashable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Profile+Hashable.swift"; sourceTree = "<group>"; };
3A648D2C2A4EEAA600D95A12 /* Library.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Library.swift; sourceTree = "<group>"; }; 3A648D2C2A4EEAA600D95A12 /* Library.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Library.swift; sourceTree = "<group>"; };
3A6CA5A52A713AA10027933B /* AppIcon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon.icns; sourceTree = "<group>"; };
3A77016D2A4E6B34008F031F /* IntentsExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.extensionkit-extension"; includeInIndex = 0; path = IntentsExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 3A77016D2A4E6B34008F031F /* IntentsExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.extensionkit-extension"; includeInIndex = 0; path = IntentsExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
3A77016F2A4E6B34008F031F /* IntentsExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentsExtension.swift; sourceTree = "<group>"; }; 3A77016F2A4E6B34008F031F /* IntentsExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentsExtension.swift; sourceTree = "<group>"; };
3A7701712A4E6B34008F031F /* Intents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Intents.swift; sourceTree = "<group>"; }; 3A7701712A4E6B34008F031F /* Intents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Intents.swift; sourceTree = "<group>"; };
@@ -388,11 +395,13 @@
3AAB5E732A4BF90B009757F1 /* ServiceLogView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceLogView.swift; sourceTree = "<group>"; }; 3AAB5E732A4BF90B009757F1 /* ServiceLogView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceLogView.swift; sourceTree = "<group>"; };
3AAB5E752A4BFB0B009757F1 /* EditProfileContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditProfileContentView.swift; sourceTree = "<group>"; }; 3AAB5E752A4BFB0B009757F1 /* EditProfileContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditProfileContentView.swift; sourceTree = "<group>"; };
3AAB5E7A2A4C1446009757F1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 3AAB5E7A2A4C1446009757F1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
3AB1220A2A70FD500087CD55 /* Alert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Alert.swift; sourceTree = "<group>"; };
3ABA46D22A6A32A100D8366B /* Messages.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Messages.framework; path = Library/Frameworks/Messages.framework; sourceTree = DEVELOPER_DIR; }; 3ABA46D22A6A32A100D8366B /* Messages.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Messages.framework; path = Library/Frameworks/Messages.framework; sourceTree = DEVELOPER_DIR; };
3AC1944C2A50206C00BD8CB9 /* ServiceNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceNotification.swift; sourceTree = "<group>"; }; 3AC1944C2A50206C00BD8CB9 /* ServiceNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceNotification.swift; sourceTree = "<group>"; };
3AC1944E2A50247300BD8CB9 /* ApplicationDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationDelegate.swift; sourceTree = "<group>"; }; 3AC1944E2A50247300BD8CB9 /* ApplicationDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationDelegate.swift; sourceTree = "<group>"; };
3AC194512A50303300BD8CB9 /* ApplicationDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationDelegate.swift; sourceTree = "<group>"; }; 3AC194512A50303300BD8CB9 /* ApplicationDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationDelegate.swift; sourceTree = "<group>"; };
3AC5EC072A6417470077AF34 /* DeviceCensorship.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceCensorship.swift; sourceTree = "<group>"; }; 3AC5EC072A6417470077AF34 /* DeviceCensorship.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceCensorship.swift; sourceTree = "<group>"; };
3AD0953C2A70EB310052764E /* Profile+Share.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Profile+Share.swift"; sourceTree = "<group>"; };
3ADF8DF12A4AF59900900CC8 /* ActiveDashboardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveDashboardView.swift; sourceTree = "<group>"; }; 3ADF8DF12A4AF59900900CC8 /* ActiveDashboardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveDashboardView.swift; sourceTree = "<group>"; };
3ADF8DF32A4AF9B500900CC8 /* DashboardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardView.swift; sourceTree = "<group>"; }; 3ADF8DF32A4AF9B500900CC8 /* DashboardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardView.swift; sourceTree = "<group>"; };
3ADF8DF62A4AFB2C00900CC8 /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = "<group>"; }; 3ADF8DF62A4AFB2C00900CC8 /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = "<group>"; };
@@ -410,7 +419,6 @@
3AEC21092A459B1900A63465 /* sing-box.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "sing-box.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 3AEC21092A459B1900A63465 /* sing-box.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "sing-box.app"; sourceTree = BUILT_PRODUCTS_DIR; };
3AEC210B2A459B1900A63465 /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = "<group>"; }; 3AEC210B2A459B1900A63465 /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = "<group>"; };
3AEC210D2A459B1900A63465 /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; }; 3AEC210D2A459B1900A63465 /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
3AEC210F2A459B1A00A63465 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
3AEC21142A459B1A00A63465 /* SFM.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SFM.entitlements; sourceTree = "<group>"; }; 3AEC21142A459B1A00A63465 /* SFM.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SFM.entitlements; sourceTree = "<group>"; };
3AEC211D2A459B4700A63465 /* Library.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Library.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3AEC211D2A459B4700A63465 /* Library.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Library.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3AEC212E2A459D5600A63465 /* Profile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Profile.swift; sourceTree = "<group>"; }; 3AEC212E2A459D5600A63465 /* Profile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Profile.swift; sourceTree = "<group>"; };
@@ -460,6 +468,7 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
3A4EAD1B2A4FEB02005435B3 /* Library.framework in Frameworks */, 3A4EAD1B2A4FEB02005435B3 /* Library.framework in Frameworks */,
3A6CA5A02A71317A0027933B /* MarkdownUI in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -573,6 +582,14 @@
path = Service; path = Service;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
3A6CA5A42A713A6C0027933B /* Icons */ = {
isa = PBXGroup;
children = (
3A6CA5A52A713AA10027933B /* AppIcon.icns */,
);
path = Icons;
sourceTree = "<group>";
};
3A77016E2A4E6B34008F031F /* IntentsExtension */ = { 3A77016E2A4E6B34008F031F /* IntentsExtension */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -677,7 +694,6 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
3AEC210B2A459B1900A63465 /* Application.swift */, 3AEC210B2A459B1900A63465 /* Application.swift */,
3AEC210F2A459B1A00A63465 /* Assets.xcassets */,
3AEC21142A459B1A00A63465 /* SFM.entitlements */, 3AEC21142A459B1A00A63465 /* SFM.entitlements */,
3AEAEE9C2A4F1A9D0059612D /* Info.plist */, 3AEAEE9C2A4F1A9D0059612D /* Info.plist */,
); );
@@ -707,6 +723,7 @@
3A9144D82A46AE370036E9AD /* ShadredPreferences+Database.swift */, 3A9144D82A46AE370036E9AD /* ShadredPreferences+Database.swift */,
3A57DF362A4D5D2600690BC5 /* Profile+Date.swift */, 3A57DF362A4D5D2600690BC5 /* Profile+Date.swift */,
3A57DF412A4D927A00690BC5 /* Profile+Hashable.swift */, 3A57DF412A4D927A00690BC5 /* Profile+Hashable.swift */,
3AD0953C2A70EB310052764E /* Profile+Share.swift */,
); );
path = Database; path = Database;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -767,7 +784,6 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
3AEECC062A6DF9CA006A0E0C /* Application.swift */, 3AEECC062A6DF9CA006A0E0C /* Application.swift */,
3AEECC0A2A6DF9CA006A0E0C /* Assets.xcassets */,
3AEECC502A6E0074006A0E0C /* SFM.entitlements */, 3AEECC502A6E0074006A0E0C /* SFM.entitlements */,
3A2223532A6E1B6700C50B23 /* Info.plist */, 3A2223532A6E1B6700C50B23 /* Info.plist */,
3A2EAEEC2A6F4CBB00D00DE3 /* IndependentApplicationDelegate.swift */, 3A2EAEEC2A6F4CBB00D00DE3 /* IndependentApplicationDelegate.swift */,
@@ -778,6 +794,8 @@
3AEECC302A6DFDAD006A0E0C /* MacLibrary */ = { 3AEECC302A6DFDAD006A0E0C /* MacLibrary */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
3A6CA5A42A713A6C0027933B /* Icons */,
3AEECC0A2A6DF9CA006A0E0C /* Assets.xcassets */,
3AEC210D2A459B1900A63465 /* MainView.swift */, 3AEC210D2A459B1900A63465 /* MainView.swift */,
3A57DF3F2A4D70B600690BC5 /* MenuView.swift */, 3A57DF3F2A4D70B600690BC5 /* MenuView.swift */,
3A1CF2F32A50E937000A8289 /* SidebarView.swift */, 3A1CF2F32A50E937000A8289 /* SidebarView.swift */,
@@ -808,6 +826,7 @@
3AF342D32A4AADB2002B34AC /* Formtem.swift */, 3AF342D32A4AADB2002B34AC /* Formtem.swift */,
3ADF8E022A4B118700900CC8 /* Binding+Unwrap.swift */, 3ADF8E022A4B118700900CC8 /* Binding+Unwrap.swift */,
3AC5EC072A6417470077AF34 /* DeviceCensorship.swift */, 3AC5EC072A6417470077AF34 /* DeviceCensorship.swift */,
3AB1220A2A70FD500087CD55 /* Alert.swift */,
); );
path = Abstract; path = Abstract;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -871,6 +890,9 @@
3A4EAD1E2A4FEB02005435B3 /* PBXTargetDependency */, 3A4EAD1E2A4FEB02005435B3 /* PBXTargetDependency */,
); );
name = ApplicationLibrary; name = ApplicationLibrary;
packageProductDependencies = (
3A6CA59F2A71317A0027933B /* MarkdownUI */,
);
productName = ApplicationLibrary; productName = ApplicationLibrary;
productReference = 3A4EAD102A4FEAE6005435B3 /* ApplicationLibrary.framework */; productReference = 3A4EAD102A4FEAE6005435B3 /* ApplicationLibrary.framework */;
productType = "com.apple.product-type.framework"; productType = "com.apple.product-type.framework";
@@ -1090,6 +1112,7 @@
3A7E90362A46778E00D53052 /* XCRemoteSwiftPackageReference "BinaryCodable" */, 3A7E90362A46778E00D53052 /* XCRemoteSwiftPackageReference "BinaryCodable" */,
3A017F902A4AB2E4009149FA /* XCRemoteSwiftPackageReference "GRDB" */, 3A017F902A4AB2E4009149FA /* XCRemoteSwiftPackageReference "GRDB" */,
3A57DF3A2A4D705000690BC5 /* XCRemoteSwiftPackageReference "MacControlCenterUI" */, 3A57DF3A2A4D705000690BC5 /* XCRemoteSwiftPackageReference "MacControlCenterUI" */,
3ADB2D832A71266E00A6517D /* XCRemoteSwiftPackageReference "swift-markdown-ui" */,
); );
productRefGroup = 3AEC20C72A45991900A63465 /* Products */; productRefGroup = 3AEC20C72A45991900A63465 /* Products */;
projectDirPath = ""; projectDirPath = "";
@@ -1120,6 +1143,7 @@
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
3A6CA5A92A713C420027933B /* AppIcon.icns in Resources */,
3AEC20FA2A459AB500A63465 /* Assets.xcassets in Resources */, 3AEC20FA2A459AB500A63465 /* Assets.xcassets in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@@ -1128,8 +1152,9 @@
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
3A6CA5A72A713ABA0027933B /* AppIcon.icns in Resources */,
3A6CA5A32A713A580027933B /* Assets.xcassets in Resources */,
3A251C122A52D09700651082 /* Assets.xcassets in Resources */, 3A251C122A52D09700651082 /* Assets.xcassets in Resources */,
3AEC21102A459B1A00A63465 /* Assets.xcassets in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -1151,8 +1176,8 @@
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
3A6CA5A82A713B340027933B /* AppIcon.icns in Resources */,
3AEC8A4F2A6E5E18003702E1 /* Assets.xcassets in Resources */, 3AEC8A4F2A6E5E18003702E1 /* Assets.xcassets in Resources */,
3A2223542A6E1B6700C50B23 /* Info.plist in Resources */,
3AEECC0B2A6DF9CA006A0E0C /* Assets.xcassets in Resources */, 3AEECC0B2A6DF9CA006A0E0C /* Assets.xcassets in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@@ -1161,6 +1186,7 @@
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
3A6CA5A62A713AA10027933B /* AppIcon.icns in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -1197,6 +1223,7 @@
3A4EAD2F2A4FEB77005435B3 /* EditProfileContentView.swift in Sources */, 3A4EAD2F2A4FEB77005435B3 /* EditProfileContentView.swift in Sources */,
3A4EAD272A4FEB65005435B3 /* DashboardView.swift in Sources */, 3A4EAD272A4FEB65005435B3 /* DashboardView.swift in Sources */,
3A4EAD342A4FEB7F005435B3 /* LogView.swift in Sources */, 3A4EAD342A4FEB7F005435B3 /* LogView.swift in Sources */,
3AB1220B2A70FD500087CD55 /* Alert.swift in Sources */,
3A4EAD362A4FEB9C005435B3 /* ProfileUpdateTask.swift in Sources */, 3A4EAD362A4FEB9C005435B3 /* ProfileUpdateTask.swift in Sources */,
3A1CF2F62A50EE9C000A8289 /* GroupView.swift in Sources */, 3A1CF2F62A50EE9C000A8289 /* GroupView.swift in Sources */,
3A4EAD212A4FEB3C005435B3 /* ApplicationLibrary.swift in Sources */, 3A4EAD212A4FEB3C005435B3 /* ApplicationLibrary.swift in Sources */,
@@ -1248,6 +1275,7 @@
3AEC214A2A45AA5600A63465 /* Profile+RW.swift in Sources */, 3AEC214A2A45AA5600A63465 /* Profile+RW.swift in Sources */,
3A57DF422A4D927A00690BC5 /* Profile+Hashable.swift in Sources */, 3A57DF422A4D927A00690BC5 /* Profile+Hashable.swift in Sources */,
3A7E90352A46756300D53052 /* SharedPreferences.swift in Sources */, 3A7E90352A46756300D53052 /* SharedPreferences.swift in Sources */,
3AD0953D2A70EB310052764E /* Profile+Share.swift in Sources */,
3AE4D0B32A6E2B94009FEA9E /* Extension+RunBlocking.swift in Sources */, 3AE4D0B32A6E2B94009FEA9E /* Extension+RunBlocking.swift in Sources */,
3AEC21482A45A9DE00A63465 /* Bundle+Version.swift in Sources */, 3AEC21482A45A9DE00A63465 /* Bundle+Version.swift in Sources */,
3A57DF372A4D5D2600690BC5 /* Profile+Date.swift in Sources */, 3A57DF372A4D5D2600690BC5 /* Profile+Date.swift in Sources */,
@@ -1418,6 +1446,7 @@
MACOSX_DEPLOYMENT_TARGET = 13.0; MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
OTHER_CODE_SIGN_FLAGS = ""; OTHER_CODE_SIGN_FLAGS = "";
OTHER_LDFLAGS = "-ld64";
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.extension; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.extension;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1457,6 +1486,7 @@
MACOSX_DEPLOYMENT_TARGET = 13.0; MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
OTHER_CODE_SIGN_FLAGS = ""; OTHER_CODE_SIGN_FLAGS = "";
OTHER_LDFLAGS = "-ld64";
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.extension; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.extension;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1574,6 +1604,7 @@
MACOSX_DEPLOYMENT_TARGET = 13.0; MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
OTHER_CODE_SIGN_FLAGS = ""; OTHER_CODE_SIGN_FLAGS = "";
OTHER_LDFLAGS = "-ld64";
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.intents; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.intents;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1613,6 +1644,7 @@
MACOSX_DEPLOYMENT_TARGET = 13.0; MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
OTHER_CODE_SIGN_FLAGS = ""; OTHER_CODE_SIGN_FLAGS = "";
OTHER_LDFLAGS = "-ld64";
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.intents; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.intents;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1764,7 +1796,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CODE_SIGN_ENTITLEMENTS = SFI/SFI.entitlements; CODE_SIGN_ENTITLEMENTS = SFI/SFI.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
@@ -1786,9 +1818,9 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.3.4; MARKETING_VERSION = 1.3.5;
OTHER_CODE_SIGN_FLAGS = "--deep"; OTHER_CODE_SIGN_FLAGS = "--deep";
OTHER_LDFLAGS = ""; OTHER_LDFLAGS = "-ld64";
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa;
PRODUCT_NAME = "sing-box"; PRODUCT_NAME = "sing-box";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1805,7 +1837,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CODE_SIGN_ENTITLEMENTS = SFI/SFI.entitlements; CODE_SIGN_ENTITLEMENTS = SFI/SFI.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
@@ -1827,9 +1859,9 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.3.4; MARKETING_VERSION = 1.3.5;
OTHER_CODE_SIGN_FLAGS = "--deep"; OTHER_CODE_SIGN_FLAGS = "--deep";
OTHER_LDFLAGS = ""; OTHER_LDFLAGS = "-ld64";
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa;
PRODUCT_NAME = "sing-box"; PRODUCT_NAME = "sing-box";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1851,7 +1883,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 12; CURRENT_PROJECT_VERSION = 14;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = Z56Z6NYZN2; DEVELOPMENT_TEAM = Z56Z6NYZN2;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
@@ -1867,7 +1899,7 @@
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 13.0; MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.3.4; MARKETING_VERSION = 1.3.5;
OTHER_CODE_SIGN_FLAGS = ""; OTHER_CODE_SIGN_FLAGS = "";
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa;
PRODUCT_NAME = "sing-box"; PRODUCT_NAME = "sing-box";
@@ -1889,7 +1921,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 12; CURRENT_PROJECT_VERSION = 14;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = Z56Z6NYZN2; DEVELOPMENT_TEAM = Z56Z6NYZN2;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
@@ -1905,7 +1937,7 @@
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 13.0; MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.3.4; MARKETING_VERSION = 1.3.5;
OTHER_CODE_SIGN_FLAGS = ""; OTHER_CODE_SIGN_FLAGS = "";
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa;
PRODUCT_NAME = "sing-box"; PRODUCT_NAME = "sing-box";
@@ -1952,7 +1984,7 @@
MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++";
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20";
OTHER_CODE_SIGN_FLAGS = "--deep"; OTHER_CODE_SIGN_FLAGS = "--deep";
OTHER_LDFLAGS = ""; OTHER_LDFLAGS = "-ld64";
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.library; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.library;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2004,7 +2036,7 @@
MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++";
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20";
OTHER_CODE_SIGN_FLAGS = "--deep"; OTHER_CODE_SIGN_FLAGS = "--deep";
OTHER_LDFLAGS = ""; OTHER_LDFLAGS = "-ld64";
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.library; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.library;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2117,7 +2149,7 @@
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 13.0; MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.3.4; MARKETING_VERSION = 1.3.5;
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.independent; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.independent;
PRODUCT_NAME = SFM; PRODUCT_NAME = SFM;
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2156,7 +2188,7 @@
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 13.0; MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.3.4; MARKETING_VERSION = 1.3.5;
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.independent; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.independent;
PRODUCT_NAME = SFM; PRODUCT_NAME = SFM;
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2367,6 +2399,14 @@
minimumVersion = 2.0.0; minimumVersion = 2.0.0;
}; };
}; };
3ADB2D832A71266E00A6517D /* XCRemoteSwiftPackageReference "swift-markdown-ui" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/gonzalezreal/swift-markdown-ui";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 2.1.0;
};
};
/* End XCRemoteSwiftPackageReference section */ /* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */ /* Begin XCSwiftPackageProductDependency section */
@@ -2375,6 +2415,11 @@
package = 3A017F902A4AB2E4009149FA /* XCRemoteSwiftPackageReference "GRDB" */; package = 3A017F902A4AB2E4009149FA /* XCRemoteSwiftPackageReference "GRDB" */;
productName = GRDB; productName = GRDB;
}; };
3A6CA59F2A71317A0027933B /* MarkdownUI */ = {
isa = XCSwiftPackageProductDependency;
package = 3ADB2D832A71266E00A6517D /* XCRemoteSwiftPackageReference "swift-markdown-ui" */;
productName = MarkdownUI;
};
3A7E90372A46778E00D53052 /* BinaryCodable */ = { 3A7E90372A46778E00D53052 /* BinaryCodable */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
package = 3A7E90362A46778E00D53052 /* XCRemoteSwiftPackageReference "BinaryCodable" */; package = 3A7E90362A46778E00D53052 /* XCRemoteSwiftPackageReference "BinaryCodable" */;
@@ -35,6 +35,15 @@
"revision" : "8757eb7c2cd708320df92e6ad6572efe90e58f16", "revision" : "8757eb7c2cd708320df92e6ad6572efe90e58f16",
"version" : "1.0.4" "version" : "1.0.4"
} }
},
{
"identity" : "swift-markdown-ui",
"kind" : "remoteSourceControl",
"location" : "https://github.com/gonzalezreal/swift-markdown-ui",
"state" : {
"revision" : "12b351a75201a8124c2f2e1f9fc6ef5cd812c0b9",
"version" : "2.1.0"
}
} }
], ],
"version" : 2 "version" : 2
@@ -14,52 +14,52 @@
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>15</integer> <integer>18</integer>
</dict> </dict>
<key>Associations (Playground) 2.xcscheme</key> <key>Associations (Playground) 2.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>16</integer> <integer>19</integer>
</dict> </dict>
<key>Associations (Playground) 3.xcscheme</key> <key>Associations (Playground) 3.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>27</integer> <integer>30</integer>
</dict> </dict>
<key>Associations (Playground) 4.xcscheme</key> <key>Associations (Playground) 4.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>28</integer> <integer>31</integer>
</dict> </dict>
<key>Associations (Playground) 5.xcscheme</key> <key>Associations (Playground) 5.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>29</integer> <integer>32</integer>
</dict> </dict>
<key>Associations (Playground).xcscheme</key> <key>Associations (Playground).xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>14</integer> <integer>17</integer>
</dict> </dict>
<key>ExtensionMac.xcscheme_^#shared#^_</key> <key>ExtensionMac.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>22</integer> <integer>25</integer>
</dict> </dict>
<key>Launcher.xcscheme_^#shared#^_</key> <key>Launcher.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>18</integer> <integer>21</integer>
</dict> </dict>
<key>MacExtension.xcscheme_^#shared#^_</key> <key>MacExtension.xcscheme_^#shared#^_</key>
<dict> <dict>
@@ -69,59 +69,59 @@
<key>MacLibrary.xcscheme_^#shared#^_</key> <key>MacLibrary.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>4</integer> <integer>5</integer>
</dict> </dict>
<key>MessageExtension.xcscheme_^#shared#^_</key> <key>MessageExtension.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>16</integer> <integer>20</integer>
</dict> </dict>
<key>MyPlayground (Playground) 1.xcscheme</key> <key>MyPlayground (Playground) 1.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>9</integer> <integer>11</integer>
</dict> </dict>
<key>MyPlayground (Playground) 2.xcscheme</key> <key>MyPlayground (Playground) 2.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>10</integer> <integer>12</integer>
</dict> </dict>
<key>MyPlayground (Playground) 3.xcscheme</key> <key>MyPlayground (Playground) 3.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>23</integer> <integer>26</integer>
</dict> </dict>
<key>MyPlayground (Playground) 4.xcscheme</key> <key>MyPlayground (Playground) 4.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>24</integer> <integer>27</integer>
</dict> </dict>
<key>MyPlayground (Playground) 5.xcscheme</key> <key>MyPlayground (Playground) 5.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>26</integer> <integer>29</integer>
</dict> </dict>
<key>MyPlayground (Playground).xcscheme</key> <key>MyPlayground (Playground).xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>8</integer> <integer>10</integer>
</dict> </dict>
<key>SFA.xcscheme_^#shared#^_</key> <key>SFA.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>21</integer> <integer>24</integer>
</dict> </dict>
<key>SFI.xcscheme</key> <key>SFI.xcscheme</key>
<dict> <dict>
@@ -131,121 +131,121 @@
<key>SFM.System.xcscheme_^#shared#^_</key> <key>SFM.System.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>5</integer> <integer>4</integer>
</dict> </dict>
<key>SFM.xcscheme_^#shared#^_</key> <key>SFM.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>2</integer>
</dict>
<key>SystemExtension.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>1</integer> <integer>1</integer>
</dict> </dict>
<key>SystemExtension.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>2</integer>
</dict>
<key>Test.xcscheme_^#shared#^_</key> <key>Test.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>10</integer> <integer>13</integer>
</dict> </dict>
<key>Tour (Playground) 1.xcscheme</key> <key>Tour (Playground) 1.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>6</integer> <integer>8</integer>
</dict> </dict>
<key>Tour (Playground) 2.xcscheme</key> <key>Tour (Playground) 2.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>7</integer> <integer>9</integer>
</dict> </dict>
<key>Tour (Playground) 3.xcscheme</key> <key>Tour (Playground) 3.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>33</integer> <integer>36</integer>
</dict> </dict>
<key>Tour (Playground) 4.xcscheme</key> <key>Tour (Playground) 4.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>34</integer> <integer>37</integer>
</dict> </dict>
<key>Tour (Playground) 5.xcscheme</key> <key>Tour (Playground) 5.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>35</integer> <integer>38</integer>
</dict> </dict>
<key>Tour (Playground).xcscheme</key> <key>Tour (Playground).xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>5</integer> <integer>7</integer>
</dict> </dict>
<key>TransactionObserver (Playground) 1.xcscheme</key> <key>TransactionObserver (Playground) 1.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>12</integer> <integer>15</integer>
</dict> </dict>
<key>TransactionObserver (Playground) 2.xcscheme</key> <key>TransactionObserver (Playground) 2.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>13</integer> <integer>16</integer>
</dict> </dict>
<key>TransactionObserver (Playground) 3.xcscheme</key> <key>TransactionObserver (Playground) 3.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>30</integer> <integer>33</integer>
</dict> </dict>
<key>TransactionObserver (Playground) 4.xcscheme</key> <key>TransactionObserver (Playground) 4.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>31</integer> <integer>34</integer>
</dict> </dict>
<key>TransactionObserver (Playground) 5.xcscheme</key> <key>TransactionObserver (Playground) 5.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>32</integer> <integer>35</integer>
</dict> </dict>
<key>TransactionObserver (Playground).xcscheme</key> <key>TransactionObserver (Playground).xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>11</integer> <integer>14</integer>
</dict> </dict>
<key>mactest.xcscheme_^#shared#^_</key> <key>mactest.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>25</integer> <integer>28</integer>
</dict> </dict>
<key>sing-box.xcscheme_^#shared#^_</key> <key>sing-box.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>20</integer> <integer>23</integer>
</dict> </dict>
<key>test.xcscheme_^#shared#^_</key> <key>test.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>19</integer> <integer>22</integer>
</dict> </dict>
</dict> </dict>
<key>SuppressBuildableAutocreation</key> <key>SuppressBuildableAutocreation</key>