├── .swift-version ├── Library ├── Library.swift ├── Database │ ├── Profile+Share.swift │ ├── Profile+Date.swift │ ├── Profile+Hashable.swift │ ├── Profile+Update.swift │ ├── Profile+RW.swift │ ├── Databse.swift │ ├── ShadredPreferences+Database.swift │ ├── ProfileManager.swift │ ├── Profile.swift │ ├── SharedPreferences.swift │ └── Profile+Transferable.swift ├── Network │ ├── Extension+Iterator.swift │ ├── NEVPNStatus+isConnected.swift │ ├── Extension+RunBlocking.swift │ ├── HTTPClient.swift │ ├── ExtensionEnvironments.swift │ └── ExtensionProfile.swift ├── Shared │ ├── Bundle+Version.swift │ ├── Variant.swift │ ├── Color+Extension.swift │ └── FilePath.swift └── Discovery │ └── NWSocket.swift ├── MacLibrary ├── MacLibrary.swift ├── Icons │ └── AppIcon.icns ├── Assets.xcassets │ ├── Contents.json │ ├── AppIcon.appiconset │ │ ├── apple-16 1x.png │ │ ├── apple-16 2x.png │ │ ├── apple-32 1x.png │ │ ├── apple-128 1x.png │ │ ├── apple-128 2x.png │ │ ├── apple-256 1x.png │ │ ├── apple-256 2x.png │ │ ├── apple-32 2x 1.png │ │ ├── apple-512 1x.png │ │ ├── apple-512 2x.png │ │ └── Contents.json │ ├── AccentColor.colorset │ │ └── Contents.json │ └── MenuIcon.symbolset │ │ └── Contents.json ├── MenuLabel.swift ├── ApplicationDelegate.swift ├── SidebarView.swift ├── MacApplication.swift └── MainView.swift ├── SFI ├── Assets.xcassets │ ├── Contents.json │ ├── AppIcon.appiconset │ │ ├── 100.png │ │ ├── 114.png │ │ ├── 120.png │ │ ├── 144.png │ │ ├── 152.png │ │ ├── 167.png │ │ ├── 180.png │ │ ├── 20.png │ │ ├── 29.png │ │ ├── 40.png │ │ ├── 50.png │ │ ├── 57.png │ │ ├── 58.png │ │ ├── 60.png │ │ ├── 72.png │ │ ├── 76.png │ │ ├── 80.png │ │ ├── 87.png │ │ └── 1024.png │ └── AccentColor.colorset │ │ └── Contents.json ├── Upload.plist ├── Application.swift ├── SFI.entitlements ├── ContentView.swift ├── ApplicationDelegate.swift ├── MainView.swift └── Info.plist ├── SFT ├── Assets.xcassets │ ├── Contents.json │ ├── App Icon & Top Shelf Image.brandassets │ │ ├── App Icon.imagestack │ │ │ ├── Back.imagestacklayer │ │ │ │ ├── Contents.json │ │ │ │ └── Content.imageset │ │ │ │ │ ├── tv- App Icon Small - Back - 400 x 240 pt.png │ │ │ │ │ ├── tv - App Icon Small - Back - 400 x 240 pt@2x.png │ │ │ │ │ └── Contents.json │ │ │ ├── Front.imagestacklayer │ │ │ │ ├── Contents.json │ │ │ │ └── Content.imageset │ │ │ │ │ └── Contents.json │ │ │ ├── Middle.imagestacklayer │ │ │ │ ├── Contents.json │ │ │ │ └── Content.imageset │ │ │ │ │ ├── tv- App Icon Small - Front - 400 x 240 pt.png │ │ │ │ │ ├── tv - App Icon Small - Front - 400 x 240 pt@2x.png │ │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── App Icon - App Store.imagestack │ │ │ ├── Back.imagestacklayer │ │ │ │ ├── Contents.json │ │ │ │ └── Content.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── tv - App Icon - AppStore - Back -1280 x 768 pt.png │ │ │ ├── Front.imagestacklayer │ │ │ │ ├── Contents.json │ │ │ │ └── Content.imageset │ │ │ │ │ └── Contents.json │ │ │ ├── Middle.imagestacklayer │ │ │ │ ├── Contents.json │ │ │ │ └── Content.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── tv - App Icon - AppStore - Front -1280 x 768 pt.png │ │ │ └── Contents.json │ │ ├── Top Shelf Image.imageset │ │ │ ├── 1920 x 720 pt.png │ │ │ ├── 1920 x 720 pt@2x.png │ │ │ └── Contents.json │ │ ├── Top Shelf Image Wide.imageset │ │ │ ├── tv - Top Shelf - Wide - 2320 x 720 pt.png │ │ │ ├── tv - Top Shelf - Wide - 2320 x 720 pt@2x.png │ │ │ └── Contents.json │ │ └── Contents.json │ └── AccentColor.colorset │ │ └── Contents.json ├── Application.swift ├── SFT.entitlements ├── ApplicationDelegate.swift ├── MainView.swift ├── Info.plist └── ContentView.swift ├── IntentsExtension ├── IntentsExtension.swift ├── Info.plist └── IntentsExtension.entitlements ├── WidgetExtension ├── Assets.xcassets │ ├── Contents.json │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── WidgetBackground.colorset │ │ └── Contents.json │ └── AppIcon.appiconset │ │ └── Contents.json ├── WidgetExtensionBundle.swift ├── WidgetExtension.entitlements ├── Info.plist ├── Intents.swift └── WidgetExtension.swift ├── ApplicationLibrary ├── Assets.xcassets │ ├── Contents.json │ └── save.symbolset │ │ └── Contents.json ├── Views │ ├── Abstract │ │ ├── ViewBuilder.swift │ │ ├── Binding+Setter.swift │ │ ├── BackButton.swift │ │ ├── NavigationDestinationCompat.swift │ │ ├── NavigationStackCompat.swift │ │ ├── ViewCompat.swift │ │ ├── Binding+Unwrap.swift │ │ ├── Alert.swift │ │ ├── DeleteButton.swift │ │ ├── RequestReviewButton.swift │ │ ├── FormItem.swift │ │ └── DeviceCensorship.swift │ ├── Groups │ │ ├── OutboundGroup.swift │ │ ├── OutboundGroupItem.swift │ │ ├── GroupItemView.swift │ │ └── GroupListView.swift │ ├── Connections │ │ ├── ConnectionListPage.swift │ │ ├── ConnectionDetailsView.swift │ │ └── Connection.swift │ ├── Dashboard │ │ ├── InstallProfileButton.swift │ │ ├── InstallSystemExtensionButton.swift │ │ ├── ClashModeView.swift │ │ ├── DashboardPage.swift │ │ ├── StartStopButton.swift │ │ └── DashboardView.swift │ ├── Setting │ │ ├── SponsorsView.swift │ │ ├── OnDemandRulesView.swift │ │ ├── CoreView.swift │ │ ├── ProfileOverrideView.swift │ │ └── ServiceLogView.swift │ ├── EnvironmentValues.swift │ ├── NavigationPage.swift │ └── Log │ │ └── LogView.swift ├── ApplicationLibrary.swift └── Service │ ├── ProfileUpdateTask.swift │ └── UIProfileUpdateTask.swift ├── Extension ├── PacketTunnelProvider.swift ├── Info.plist └── Extension.entitlements ├── TVExtension ├── PacketTunnelProvider.swift ├── Info.plist └── TVExtension.entitlements ├── .gitignore ├── sing-box.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── swiftpm │ │ └── Package.resolved └── xcshareddata │ └── xcschemes │ ├── SFI.xcscheme │ ├── SFM.xcscheme │ ├── SFT.xcscheme │ └── SFM.System.xcscheme ├── SystemExtension ├── main.swift ├── Info.plist ├── SystemExtension.entitlements └── PacketTunnelProvider.swift ├── SFM ├── Application.swift ├── SFM.entitlements └── Info.plist ├── SFM.System ├── Application.swift ├── Upload.plist ├── IndependentApplicationDelegate.swift ├── SFM.entitlements └── Info.plist ├── LICENSE ├── make_ios.sh └── README.md /.swift-version: -------------------------------------------------------------------------------- 1 | 5.7 -------------------------------------------------------------------------------- /Library/Library.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public class Library {} 4 | -------------------------------------------------------------------------------- /MacLibrary/MacLibrary.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public class MacLibrary {} 4 | -------------------------------------------------------------------------------- /MacLibrary/Icons/AppIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/MacLibrary/Icons/AppIcon.icns -------------------------------------------------------------------------------- /SFI/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "author": "xcode", 4 | "version": 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /IntentsExtension/IntentsExtension.swift: -------------------------------------------------------------------------------- 1 | import AppIntents 2 | 3 | @main 4 | struct IntentsExtension: AppIntentsExtension {} 5 | -------------------------------------------------------------------------------- /MacLibrary/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /WidgetExtension/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ApplicationLibrary/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Extension/PacketTunnelProvider.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Library 3 | 4 | class PacketTunnelProvider: ExtensionProvider {} 5 | -------------------------------------------------------------------------------- /TVExtension/PacketTunnelProvider.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Library 3 | 4 | class PacketTunnelProvider: ExtensionProvider {} 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /Libbox.xcframework/ 3 | xcuserdata/ 4 | .DS_Store/ 5 | /build/ 6 | /sing-box.xcodeproj/project.pbxproj.back 7 | /packages/ 8 | -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AppIcon.appiconset/100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFI/Assets.xcassets/AppIcon.appiconset/100.png -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AppIcon.appiconset/114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFI/Assets.xcassets/AppIcon.appiconset/114.png -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AppIcon.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFI/Assets.xcassets/AppIcon.appiconset/120.png -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AppIcon.appiconset/144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFI/Assets.xcassets/AppIcon.appiconset/144.png -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AppIcon.appiconset/152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFI/Assets.xcassets/AppIcon.appiconset/152.png -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AppIcon.appiconset/167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFI/Assets.xcassets/AppIcon.appiconset/167.png -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AppIcon.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFI/Assets.xcassets/AppIcon.appiconset/180.png -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AppIcon.appiconset/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFI/Assets.xcassets/AppIcon.appiconset/20.png -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AppIcon.appiconset/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFI/Assets.xcassets/AppIcon.appiconset/29.png -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AppIcon.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFI/Assets.xcassets/AppIcon.appiconset/40.png -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AppIcon.appiconset/50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFI/Assets.xcassets/AppIcon.appiconset/50.png -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AppIcon.appiconset/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFI/Assets.xcassets/AppIcon.appiconset/57.png -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AppIcon.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFI/Assets.xcassets/AppIcon.appiconset/58.png -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AppIcon.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFI/Assets.xcassets/AppIcon.appiconset/60.png -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AppIcon.appiconset/72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFI/Assets.xcassets/AppIcon.appiconset/72.png -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AppIcon.appiconset/76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFI/Assets.xcassets/AppIcon.appiconset/76.png -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AppIcon.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFI/Assets.xcassets/AppIcon.appiconset/80.png -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AppIcon.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFI/Assets.xcassets/AppIcon.appiconset/87.png -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFI/Assets.xcassets/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-16 1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-16 1x.png -------------------------------------------------------------------------------- /MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-16 2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-16 2x.png -------------------------------------------------------------------------------- /MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-32 1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-32 1x.png -------------------------------------------------------------------------------- /MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-128 1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-128 1x.png -------------------------------------------------------------------------------- /MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-128 2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-128 2x.png -------------------------------------------------------------------------------- /MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-256 1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-256 1x.png -------------------------------------------------------------------------------- /MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-256 2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-256 2x.png -------------------------------------------------------------------------------- /MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-32 2x 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-32 2x 1.png -------------------------------------------------------------------------------- /MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-512 1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-512 1x.png -------------------------------------------------------------------------------- /MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-512 2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/MacLibrary/Assets.xcassets/AppIcon.appiconset/apple-512 2x.png -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ApplicationLibrary/Views/Abstract/ViewBuilder.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | 4 | public func viewBuilder(@ViewBuilder _ builder: () -> some View) -> some View { 5 | builder() 6 | } 7 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SFI/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors": [ 3 | { 4 | "idiom": "universal" 5 | } 6 | ], 7 | "info": { 8 | "author": "xcode", 9 | "version": 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /sing-box.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ApplicationLibrary/ApplicationLibrary.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public class ApplicationLibrary { 4 | public static let bundle = Bundle(for: ApplicationLibrary.self) 5 | public static let inPreview = false 6 | } 7 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /WidgetExtension/WidgetExtensionBundle.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | import WidgetKit 3 | 4 | @main 5 | struct WidgetExtensionBundle: WidgetBundle { 6 | var body: some Widget { 7 | WidgetExtension() 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Library/Database/Profile+Share.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Libbox 3 | 4 | public extension Profile { 5 | var shareLink: URL { 6 | URL(string: LibboxGenerateRemoteProfileImportLink(name, remoteURL!))! 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /MacLibrary/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /WidgetExtension/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SystemExtension/main.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Library 3 | import NetworkExtension 4 | 5 | Variant.useSystemExtension = true 6 | 7 | autoreleasepool { 8 | NEProvider.startSystemExtensionMode() 9 | } 10 | 11 | dispatchMain() 12 | -------------------------------------------------------------------------------- /WidgetExtension/Assets.xcassets/WidgetBackground.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/1920 x 720 pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/1920 x 720 pt.png -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/1920 x 720 pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/1920 x 720 pt@2x.png -------------------------------------------------------------------------------- /SFM/Application.swift: -------------------------------------------------------------------------------- 1 | import MacLibrary 2 | import SwiftUI 3 | 4 | @main 5 | struct Application: App { 6 | @NSApplicationDelegateAdaptor private var appDelegate: ApplicationDelegate 7 | 8 | var body: some Scene { 9 | MacApplication() 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ApplicationLibrary/Assets.xcassets/save.symbolset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "author": "xcode", 4 | "version": 1 5 | }, 6 | "symbols": [ 7 | { 8 | "filename": "save-save_symbol.svg", 9 | "idiom": "universal" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /Library/Database/Profile+Date.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension Date { 4 | var myFormat: String { 5 | let dateFormatter = DateFormatter() 6 | dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" 7 | return dateFormatter.string(from: self) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /WidgetExtension/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SFM.System/Application.swift: -------------------------------------------------------------------------------- 1 | import Library 2 | import MacLibrary 3 | import SwiftUI 4 | 5 | @main 6 | struct Application: App { 7 | @NSApplicationDelegateAdaptor private var appDelegate: IndependentApplicationDelegate 8 | 9 | var body: some Scene { 10 | MacApplication() 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/tv - Top Shelf - Wide - 2320 x 720 pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/tv - Top Shelf - Wide - 2320 x 720 pt.png -------------------------------------------------------------------------------- /Library/Database/Profile+Hashable.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension Profile: Hashable { 4 | public static func == (lhs: Profile, rhs: Profile) -> Bool { 5 | lhs.id == rhs.id 6 | } 7 | 8 | public func hash(into hasher: inout Hasher) { 9 | hasher.combine(id) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/tv - Top Shelf - Wide - 2320 x 720 pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/tv - Top Shelf - Wide - 2320 x 720 pt@2x.png -------------------------------------------------------------------------------- /Library/Network/Extension+Iterator.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Libbox 3 | 4 | public extension LibboxStringIteratorProtocol { 5 | func toArray() -> [String] { 6 | var array: [String] = [] 7 | while hasNext() { 8 | array.append(next()) 9 | } 10 | return array 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Library/Shared/Bundle+Version.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension Bundle { 4 | var version: String { 5 | infoDictionary?["CFBundleShortVersionString"] as? String ?? "unknown" 6 | } 7 | 8 | var versionNumber: String { 9 | infoDictionary?["CFBundleVersion"] as? String ?? "unknown" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /sing-box.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /MacLibrary/Assets.xcassets/MenuIcon.symbolset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | }, 6 | "properties" : { 7 | "symbol-rendering-intent" : "template" 8 | }, 9 | "symbols" : [ 10 | { 11 | "filename" : "menu_icon.svg", 12 | "idiom" : "universal" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/tv- App Icon Small - Back - 400 x 240 pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/tv- App Icon Small - Back - 400 x 240 pt.png -------------------------------------------------------------------------------- /ApplicationLibrary/Views/Abstract/Binding+Setter.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | 4 | public extension Binding { 5 | func withSetter(_ setter: @escaping (Value) -> Void) -> Binding { 6 | Binding { 7 | wrappedValue 8 | } set: { [setter] newValue, _ in 9 | setter(newValue) 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/tv- App Icon Small - Front - 400 x 240 pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/tv- App Icon Small - Front - 400 x 240 pt.png -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "tv - App Icon - AppStore - Back -1280 x 768 pt.png", 5 | "idiom" : "tv" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/tv - App Icon Small - Back - 400 x 240 pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/tv - App Icon Small - Back - 400 x 240 pt@2x.png -------------------------------------------------------------------------------- /ApplicationLibrary/Views/Abstract/BackButton.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | 4 | public struct BackButton: View { 5 | @Environment(\.dismiss) private var dismiss 6 | 7 | public var body: some View { 8 | Button { 9 | dismiss() 10 | } label: { 11 | Image(systemName: "chevron.backward") 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "tv - App Icon - AppStore - Front -1280 x 768 pt.png", 5 | "idiom" : "tv" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/tv - App Icon Small - Front - 400 x 240 pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/tv - App Icon Small - Front - 400 x 240 pt@2x.png -------------------------------------------------------------------------------- /WidgetExtension/WidgetExtension.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.org.sagernet.sfa 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /WidgetExtension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSExtension 6 | 7 | NSExtensionPointIdentifier 8 | com.apple.widgetkit-extension 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /ApplicationLibrary/Views/Abstract/NavigationDestinationCompat.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | func NavigationDestinationCompat(isPresented: Binding, @ViewBuilder destination: () -> some View) -> some View { 4 | NavigationLink( 5 | destination: destination(), 6 | isActive: isPresented, 7 | label: { 8 | EmptyView() 9 | } 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "author" : "xcode", 14 | "version" : 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /IntentsExtension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | EXAppExtensionAttributes 6 | 7 | EXExtensionPointIdentifier 8 | com.apple.appintents-extension 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/tv - App Icon - AppStore - Back -1280 x 768 pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/tv - App Icon - AppStore - Back -1280 x 768 pt.png -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/tv - App Icon - AppStore - Front -1280 x 768 pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elziy/sing-box-for-apple/HEAD/SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/tv - App Icon - AppStore - Front -1280 x 768 pt.png -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | }, 6 | "layers" : [ 7 | { 8 | "filename" : "Front.imagestacklayer" 9 | }, 10 | { 11 | "filename" : "Middle.imagestacklayer" 12 | }, 13 | { 14 | "filename" : "Back.imagestacklayer" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | }, 6 | "layers" : [ 7 | { 8 | "filename" : "Front.imagestacklayer" 9 | }, 10 | { 11 | "filename" : "Middle.imagestacklayer" 12 | }, 13 | { 14 | "filename" : "Back.imagestacklayer" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /SFI/Upload.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | destination 6 | upload 7 | method 8 | app-store 9 | manageAppVersionAndBuildNumber 10 | 11 | uploadSymbols 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "1920 x 720 pt.png", 5 | "idiom" : "tv", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "1920 x 720 pt@2x.png", 10 | "idiom" : "tv", 11 | "scale" : "2x" 12 | } 13 | ], 14 | "info" : { 15 | "author" : "xcode", 16 | "version" : 1 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SFI/Application.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Library 3 | import SwiftUI 4 | 5 | @main 6 | struct Application: App { 7 | @UIApplicationDelegateAdaptor private var appDelegate: ApplicationDelegate 8 | @StateObject private var environments = ExtensionEnvironments() 9 | 10 | var body: some Scene { 11 | WindowGroup { 12 | MainView() 13 | .environmentObject(environments) 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SFT/Application.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Library 3 | import SwiftUI 4 | 5 | @main 6 | struct Application: App { 7 | @UIApplicationDelegateAdaptor private var appDelegate: ApplicationDelegate 8 | @StateObject private var environments = ExtensionEnvironments() 9 | 10 | var body: some Scene { 11 | WindowGroup { 12 | MainView() 13 | .environmentObject(environments) 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SFT/SFT.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.networking.networkextension 6 | 7 | packet-tunnel-provider 8 | 9 | com.apple.security.application-groups 10 | 11 | group.com.zsheep.box 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Extension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSExtension 6 | 7 | NSExtensionPointIdentifier 8 | com.apple.networkextension.packet-tunnel 9 | NSExtensionPrincipalClass 10 | $(PRODUCT_MODULE_NAME).PacketTunnelProvider 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "tv - Top Shelf - Wide - 2320 x 720 pt.png", 5 | "idiom" : "tv", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "tv - Top Shelf - Wide - 2320 x 720 pt@2x.png", 10 | "idiom" : "tv", 11 | "scale" : "2x" 12 | } 13 | ], 14 | "info" : { 15 | "author" : "xcode", 16 | "version" : 1 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /IntentsExtension/IntentsExtension.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.application-groups 8 | 9 | group.com.zsheep.box 10 | 11 | com.apple.security.network.client 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Library/Shared/Variant.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum Variant { 4 | #if os(macOS) 5 | public static var useSystemExtension = false 6 | #else 7 | public static let useSystemExtension = false 8 | #endif 9 | 10 | #if os(iOS) 11 | public static let applicationName = "SFI" 12 | #elseif os(macOS) 13 | public static let applicationName = "SFM" 14 | #elseif os(tvOS) 15 | public static let applicationName = "SFT" 16 | #endif 17 | } 18 | -------------------------------------------------------------------------------- /TVExtension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSExtension 6 | 7 | NSExtensionPointIdentifier 8 | com.apple.networkextension.packet-tunnel 9 | NSExtensionPrincipalClass 10 | $(PRODUCT_MODULE_NAME).PacketTunnelProvider 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /TVExtension/TVExtension.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.networking.networkextension 6 | 7 | packet-tunnel-provider 8 | 9 | com.apple.security.application-groups 10 | 11 | group.com.zsheep.box 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "tv- App Icon Small - Back - 400 x 240 pt.png", 5 | "idiom" : "tv", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "tv - App Icon Small - Back - 400 x 240 pt@2x.png", 10 | "idiom" : "tv", 11 | "scale" : "2x" 12 | } 13 | ], 14 | "info" : { 15 | "author" : "xcode", 16 | "version" : 1 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "tv- App Icon Small - Front - 400 x 240 pt.png", 5 | "idiom" : "tv", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "tv - App Icon Small - Front - 400 x 240 pt@2x.png", 10 | "idiom" : "tv", 11 | "scale" : "2x" 12 | } 13 | ], 14 | "info" : { 15 | "author" : "xcode", 16 | "version" : 1 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SystemExtension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NetworkExtension 6 | 7 | NEMachServiceName 8 | group.com.zsheep.box.system 9 | NEProviderClasses 10 | 11 | com.apple.networkextension.packet-tunnel 12 | $(PRODUCT_MODULE_NAME).PacketTunnelProvider 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /ApplicationLibrary/Views/Abstract/NavigationStackCompat.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | public func NavigationStackCompat(@ViewBuilder content: () -> some View) -> some View { 4 | viewBuilder { 5 | if #available(iOS 17.0, *) { 6 | // view not updating in iOS 16, but why? 7 | NavigationStack { 8 | content() 9 | } 10 | } else { 11 | NavigationView(content: content) 12 | #if !os(macOS) 13 | .navigationViewStyle(.stack) 14 | #endif 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SystemExtension/SystemExtension.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.networking.networkextension 6 | 7 | packet-tunnel-provider-systemextension 8 | 9 | com.apple.security.app-sandbox 10 | 11 | com.apple.security.application-groups 12 | 13 | group.com.zsheep.box 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Library/Database/Profile+Update.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import GRDB 3 | import Libbox 4 | 5 | public extension Profile { 6 | nonisolated func updateRemoteProfile() async throws { 7 | if type != .remote { 8 | return 9 | } 10 | let remoteContent = try HTTPClient().getString(remoteURL) 11 | var error: NSError? 12 | LibboxCheckConfig(remoteContent, &error) 13 | if let error { 14 | throw error 15 | } 16 | try write(remoteContent) 17 | lastUpdated = Date() 18 | try await ProfileManager.update(self) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SFM.System/Upload.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | destination 6 | upload 7 | method 8 | developer-id 9 | uploadSymbols 10 | 11 | provisioningProfiles 12 | 13 | com.zsheep.box.independent 14 | XC com zsheep box independent 15 | com.zsheep.box.system 16 | XC com zsheep box system 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Library/Shared/Color+Extension.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | #if canImport(UIKit) 4 | import UIKit 5 | #elseif canImport(AppKit) 6 | import AppKit 7 | #endif 8 | 9 | public extension Color { 10 | static var textColor: Color { 11 | #if canImport(UIKit) 12 | return Color(uiColor: .label) 13 | #elseif canImport(AppKit) 14 | return Color(nsColor: .textColor) 15 | #endif 16 | } 17 | 18 | static var linkColor: Color { 19 | #if canImport(UIKit) 20 | return Color(uiColor: .link) 21 | #elseif canImport(AppKit) 22 | return Color(nsColor: .linkColor) 23 | #endif 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2022 by nekohasekai 2 | 3 | This program is free software: you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation, either version 3 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program. If not, see . -------------------------------------------------------------------------------- /ApplicationLibrary/Views/Groups/OutboundGroup.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Libbox 3 | import SwiftUI 4 | 5 | public struct OutboundGroup: Codable { 6 | let tag: String 7 | let type: String 8 | let icon: String 9 | var selected: String 10 | let selectable: Bool 11 | var isExpand: Bool 12 | let items: [OutboundGroupItem] 13 | 14 | var hashValue: Int { 15 | var value = tag.hashValue 16 | (value, _) = value.addingReportingOverflow(selected.hashValue) 17 | for item in items { 18 | (value, _) = value.addingReportingOverflow(item.urlTestTime.hashValue) 19 | } 20 | return value 21 | } 22 | } 23 | 24 | public extension OutboundGroup { 25 | var displayType: String { 26 | LibboxProxyDisplayType(type) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ApplicationLibrary/Views/Groups/OutboundGroupItem.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Libbox 3 | import SwiftUI 4 | 5 | public struct OutboundGroupItem: Codable { 6 | public let tag: String 7 | public let type: String 8 | 9 | public let urlTestTime: Date 10 | public let urlTestDelay: UInt16 11 | } 12 | 13 | public extension OutboundGroupItem { 14 | var displayType: String { 15 | LibboxProxyDisplayType(type) 16 | } 17 | 18 | var delayString: String { 19 | "\(urlTestDelay)ms" 20 | } 21 | 22 | var delayColor: Color { 23 | switch urlTestDelay { 24 | case 0: 25 | return .gray 26 | case ..<800: 27 | return .green 28 | case 800 ..< 1500: 29 | return .yellow 30 | default: 31 | return .orange 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ApplicationLibrary/Views/Connections/ConnectionListPage.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | 4 | public enum ConnectionListPage: Int, CaseIterable, Identifiable { 5 | public var id: Self { 6 | self 7 | } 8 | 9 | case active 10 | case closed 11 | } 12 | 13 | public extension ConnectionListPage { 14 | var title: String { 15 | switch self { 16 | case .active: 17 | return NSLocalizedString("Active", comment: "") 18 | case .closed: 19 | return NSLocalizedString("Closed", comment: "") 20 | } 21 | } 22 | 23 | var label: some View { 24 | switch self { 25 | case .active: 26 | return Label(title, systemImage: "play.fill") 27 | case .closed: 28 | return Label(title, systemImage: "stop.fill") 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SFT/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "assets" : [ 3 | { 4 | "filename" : "App Icon - App Store.imagestack", 5 | "idiom" : "tv", 6 | "role" : "primary-app-icon", 7 | "size" : "1280x768" 8 | }, 9 | { 10 | "filename" : "App Icon.imagestack", 11 | "idiom" : "tv", 12 | "role" : "primary-app-icon", 13 | "size" : "400x240" 14 | }, 15 | { 16 | "filename" : "Top Shelf Image Wide.imageset", 17 | "idiom" : "tv", 18 | "role" : "top-shelf-image-wide", 19 | "size" : "2320x720" 20 | }, 21 | { 22 | "filename" : "Top Shelf Image.imageset", 23 | "idiom" : "tv", 24 | "role" : "top-shelf-image", 25 | "size" : "1920x720" 26 | } 27 | ], 28 | "info" : { 29 | "author" : "xcode", 30 | "version" : 1 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SFI/SFI.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.icloud-container-identifiers 6 | 7 | iCloud.com.zsheep.box 8 | 9 | com.apple.developer.icloud-services 10 | 11 | CloudDocuments 12 | 13 | com.apple.developer.networking.networkextension 14 | 15 | packet-tunnel-provider 16 | 17 | com.apple.developer.ubiquity-container-identifiers 18 | 19 | iCloud.com.zsheep.box 20 | 21 | com.apple.security.application-groups 22 | 23 | group.com.zsheep.box 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ApplicationLibrary/Views/Abstract/ViewCompat.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | public extension View { 4 | func onChangeCompat(of value: some Equatable, _ action: @escaping () -> Void) -> some View { 5 | // if #available(iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0, *) { 6 | // return onChange(of: value, action) 7 | // } else { 8 | onChange(of: value) { _ in 9 | action() 10 | } 11 | // } 12 | } 13 | 14 | func onChangeCompat(of value: V, _ action: @escaping (_ newValue: V) -> Void) -> some View where V: Equatable { 15 | // if #available(iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0, *) { 16 | // return onChange(of: value) { _, newValue in 17 | // action(newValue) 18 | // } 19 | // } else { 20 | onChange(of: value, perform: action) 21 | // } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SystemExtension/PacketTunnelProvider.swift: -------------------------------------------------------------------------------- 1 | import Library 2 | import NetworkExtension 3 | 4 | class PacketTunnelProvider: ExtensionProvider { 5 | override func startTunnel(options: [String: NSObject]?) async throws { 6 | guard let usernameObject = options?["username"] else { 7 | writeFatalError("missing start options") 8 | return 9 | } 10 | let username = usernameObject as! NSString 11 | FilePath.sharedDirectory = URL(filePath: "/Users/\(username)/Library/Group Containers/\(FilePath.groupName)") 12 | FilePath.iCloudDirectory = URL(filePath: "/Users/\(username)/Library/Mobile Documents/iCloud~\(FilePath.packageName.replacingOccurrences(of: ".", with: "~"))").appendingPathComponent("Documents", isDirectory: true) 13 | self.username = String(username) 14 | try await super.startTunnel(options: options) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SFM.System/IndependentApplicationDelegate.swift: -------------------------------------------------------------------------------- 1 | import AppKit 2 | import Foundation 3 | import Library 4 | import MacLibrary 5 | 6 | class IndependentApplicationDelegate: ApplicationDelegate { 7 | public func applicationWillFinishLaunching(_: Notification) { 8 | Variant.useSystemExtension = true 9 | Task { 10 | await setupSystemExtension() 11 | } 12 | } 13 | 14 | private nonisolated func setupSystemExtension() async { 15 | do { 16 | if await SystemExtension.isInstalled() { 17 | if let result = try await SystemExtension.install() { 18 | if result == .willCompleteAfterReboot { 19 | return 20 | } 21 | } 22 | } 23 | } catch { 24 | NSLog("setup system extension error: \(error.localizedDescription)") 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SFT/ApplicationDelegate.swift: -------------------------------------------------------------------------------- 1 | import ApplicationLibrary 2 | import Foundation 3 | import Libbox 4 | import Library 5 | import UIKit 6 | 7 | class ApplicationDelegate: NSObject, UIApplicationDelegate { 8 | func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool { 9 | NSLog("Here I stand") 10 | LibboxSetup(FilePath.sharedDirectory.relativePath, FilePath.workingDirectory.relativePath, FilePath.cacheDirectory.relativePath, true) 11 | Task { 12 | await setup() 13 | } 14 | return true 15 | } 16 | 17 | private func setup() async { 18 | do { 19 | try await UIProfileUpdateTask.configure() 20 | NSLog("setup background task success") 21 | } catch { 22 | NSLog("setup background task error: \(error.localizedDescription)") 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /make_ios.sh: -------------------------------------------------------------------------------- 1 | XCODEPROJ_NAME=sing-box 2 | APPLICATION_NAME=sing-box 3 | SCHEME_NAME=SFI 4 | 5 | xcodebuild -project $XCODEPROJ_NAME.xcodeproj -scheme $SCHEME_NAME -destination generic/platform=iOS -configuration Debug -sdk iphoneos build install STRIP_INSTALLED_PRODUCT=NO ARCHS=arm64 CODE_SIGNING_ALLOWED=NO ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES=NO ENABLE_BITCODE=NO DSTROOT=packages/ 6 | 7 | ldid -SSFI/SFI.entitlements packages/Applications/$APPLICATION_NAME.app/$APPLICATION_NAME 8 | ldid -SExtension/Extension.entitlements packages/Applications/$APPLICATION_NAME.app/PlugIns/Extension.appex/Extension 9 | ldid -SIntentsExtension/IntentsExtension.entitlements packages/Applications/$APPLICATION_NAME.app/Extensions/IntentsExtension.appex/IntentsExtension 10 | 11 | mkdir -p packages/Payload 12 | cp -rp packages/Applications/$APPLICATION_NAME.app packages/Payload 13 | cd packages 14 | zip -qr $APPLICATION_NAME.tipa Payload 15 | rm -r Payload -------------------------------------------------------------------------------- /ApplicationLibrary/Views/Dashboard/InstallProfileButton.swift: -------------------------------------------------------------------------------- 1 | import Library 2 | import SwiftUI 3 | 4 | @MainActor 5 | public struct InstallProfileButton: View { 6 | @State private var alert: Alert? 7 | 8 | private let callback: () async -> Void 9 | public init(_ callback: @escaping (() async -> Void)) { 10 | self.callback = callback 11 | } 12 | 13 | public var body: some View { 14 | FormButton { 15 | Task { 16 | await installProfile() 17 | } 18 | } label: { 19 | Label("Install Network Extension", systemImage: "lock.doc.fill") 20 | } 21 | .alertBinding($alert) 22 | } 23 | 24 | private func installProfile() async { 25 | do { 26 | try await ExtensionProfile.install() 27 | await callback() 28 | } catch { 29 | alert = Alert(error) 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ApplicationLibrary/Views/Abstract/Binding+Unwrap.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | public extension Binding { 4 | func unwrapped(_ defaultValue: T) -> Binding where Value == T? { 5 | Binding(get: { 6 | wrappedValue ?? defaultValue 7 | }, set: { newValue in 8 | wrappedValue = newValue 9 | }) 10 | } 11 | } 12 | 13 | public extension Binding where Value == Int32 { 14 | func stringBinding(defaultValue: Int32) -> Binding { 15 | Binding { 16 | var intValue = wrappedValue 17 | if intValue == 0 { 18 | intValue = defaultValue 19 | } 20 | return String(intValue) 21 | } set: { newValue in 22 | var newIntValue = Int32(newValue) ?? defaultValue 23 | if newIntValue == 0 { 24 | newIntValue = defaultValue 25 | } 26 | wrappedValue = newIntValue 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Library/Network/NEVPNStatus+isConnected.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import NetworkExtension 3 | 4 | public extension NEVPNStatus { 5 | var isEnabled: Bool { 6 | switch self { 7 | case .connected, .disconnected, .reasserting: 8 | return true 9 | default: 10 | return false 11 | } 12 | } 13 | 14 | var isSwitchable: Bool { 15 | switch self { 16 | case .connected, .disconnected: 17 | return true 18 | default: 19 | return false 20 | } 21 | } 22 | 23 | var isConnected: Bool { 24 | switch self { 25 | case .connecting, .connected, .disconnecting, .reasserting: 26 | return true 27 | default: 28 | return false 29 | } 30 | } 31 | 32 | var isConnectedStrict: Bool { 33 | switch self { 34 | case .connected, .reasserting: 35 | return true 36 | default: 37 | return false 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sing-box-for-apple 2 | 3 | Experimental iOS/macOS/tvOS client for sing-box, the universal proxy platform. 4 | 5 | ## Documentation 6 | 7 | [SFI](https://sing-box.sagernet.org/installation/clients/sfi/) | [SFM](https://sing-box.sagernet.org/installation/clients/sfm/) 8 | 9 | ## License 10 | 11 | ``` 12 | Copyright (C) 2022 by nekohasekai 13 | 14 | This program is free software: you can redistribute it and/or modify 15 | it under the terms of the GNU General Public License as published by 16 | the Free Software Foundation, either version 3 of the License, or 17 | (at your option) any later version. 18 | 19 | This program is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | GNU General Public License for more details. 23 | 24 | You should have received a copy of the GNU General Public License 25 | along with this program. If not, see . 26 | ``` -------------------------------------------------------------------------------- /ApplicationLibrary/Views/Setting/SponsorsView.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | 4 | public struct SponsorsView: View { 5 | @Environment(\.openURL) private var openURL 6 | 7 | public init() {} 8 | public var body: some View { 9 | FormView { 10 | Section { 11 | EmptyView() 12 | } footer: { 13 | Text("**If I’ve defended your modern life, please consider sponsoring me.**") 14 | .frame(maxWidth: .infinity, alignment: .leading) 15 | } 16 | 17 | FormButton(String(localized: "GitHub Sponsor (recommended)")) { 18 | openURL(URL(string: "https://github.com/sponsors/nekohasekai")!) 19 | } 20 | FormButton(String(localized: "Other methods")) { 21 | openURL(URL(string: "https://sekai.icu/sponsors/")!) 22 | } 23 | } 24 | .navigationTitle("Sponsors") 25 | #if os(iOS) 26 | .navigationBarTitleDisplayMode(.inline) 27 | #endif 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Library/Network/Extension+RunBlocking.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Libbox 3 | import NetworkExtension 4 | 5 | func runBlocking(_ block: @escaping () async -> T) -> T { 6 | let semaphore = DispatchSemaphore(value: 0) 7 | let box = resultBox() 8 | Task.detached { 9 | let value = await block() 10 | box.result0 = value 11 | semaphore.signal() 12 | } 13 | semaphore.wait() 14 | return box.result0 15 | } 16 | 17 | func runBlocking(_ tBlock: @escaping () async throws -> T) throws -> T { 18 | let semaphore = DispatchSemaphore(value: 0) 19 | let box = resultBox() 20 | Task.detached { 21 | do { 22 | let value = try await tBlock() 23 | box.result = .success(value) 24 | } catch { 25 | box.result = .failure(error) 26 | } 27 | semaphore.signal() 28 | } 29 | semaphore.wait() 30 | return try box.result.get() 31 | } 32 | 33 | private class resultBox { 34 | var result: Result! 35 | var result0: T! 36 | } 37 | -------------------------------------------------------------------------------- /SFM/SFM.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.icloud-container-identifiers 6 | 7 | iCloud.com.zsheep.box 8 | 9 | com.apple.developer.icloud-services 10 | 11 | CloudDocuments 12 | 13 | com.apple.developer.networking.networkextension 14 | 15 | packet-tunnel-provider 16 | 17 | com.apple.developer.ubiquity-container-identifiers 18 | 19 | iCloud.com.zsheep.box 20 | 21 | com.apple.security.app-sandbox 22 | 23 | com.apple.security.application-groups 24 | 25 | group.icom.zsheep.box 26 | 27 | com.apple.security.files.user-selected.read-write 28 | 29 | com.apple.security.network.client 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Extension/Extension.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.icloud-container-identifiers 6 | 7 | iCloud.com.zsheep.box 8 | 9 | com.apple.developer.icloud-services 10 | 11 | CloudDocuments 12 | 13 | com.apple.developer.networking.networkextension 14 | 15 | packet-tunnel-provider 16 | 17 | com.apple.developer.networking.wifi-info 18 | 19 | com.apple.developer.ubiquity-container-identifiers 20 | 21 | iCloud.com.zsheep.box 22 | 23 | com.apple.security.app-sandbox 24 | 25 | com.apple.security.application-groups 26 | 27 | group.com.zsheep.box 28 | 29 | com.apple.security.network.client 30 | 31 | com.apple.security.network.server 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /SFM.System/SFM.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.icloud-container-identifiers 6 | 7 | iCloud.com.zsheep.box 8 | 9 | com.apple.developer.icloud-services 10 | 11 | CloudDocuments 12 | 13 | com.apple.developer.networking.networkextension 14 | 15 | packet-tunnel-provider-systemextension 16 | 17 | com.apple.developer.system-extension.install 18 | 19 | com.apple.developer.ubiquity-container-identifiers 20 | 21 | iCloud.com.zsheep.box 22 | 23 | com.apple.security.app-sandbox 24 | 25 | com.apple.security.application-groups 26 | 27 | group.com.zsheep.box 28 | 29 | com.apple.security.files.user-selected.read-write 30 | 31 | com.apple.security.network.client 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Library/Database/Profile+RW.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension Profile { 4 | func read() throws -> String { 5 | switch type { 6 | case .local, .remote: 7 | return try String(contentsOfFile: path) 8 | case .icloud: 9 | let saveURL = FilePath.iCloudDirectory.appendingPathComponent(path) 10 | _ = saveURL.startAccessingSecurityScopedResource() 11 | defer { 12 | saveURL.stopAccessingSecurityScopedResource() 13 | } 14 | return try String(contentsOf: saveURL) 15 | } 16 | } 17 | 18 | func write(_ content: String) throws { 19 | switch type { 20 | case .local, .remote: 21 | try content.write(toFile: path, atomically: true, encoding: .utf8) 22 | case .icloud: 23 | let saveURL = FilePath.iCloudDirectory.appendingPathComponent(path) 24 | _ = saveURL.startAccessingSecurityScopedResource() 25 | defer { 26 | saveURL.stopAccessingSecurityScopedResource() 27 | } 28 | try content.write(to: saveURL, atomically: true, encoding: .utf8) 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Library/Network/HTTPClient.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Libbox 3 | 4 | public class HTTPClient { 5 | private static var userAgent: String { 6 | var userAgent = Variant.applicationName 7 | userAgent += "/" 8 | userAgent += Bundle.main.version 9 | userAgent += " (Build " 10 | userAgent += Bundle.main.versionNumber 11 | userAgent += "; sing-box " 12 | userAgent += LibboxVersion() 13 | userAgent += ")" 14 | return userAgent 15 | } 16 | 17 | private let client: any LibboxHTTPClientProtocol 18 | 19 | public init() { 20 | client = LibboxNewHTTPClient()! 21 | client.modernTLS() 22 | } 23 | 24 | public func getString(_ url: String?) throws -> String { 25 | let request = client.newRequest()! 26 | request.setUserAgent(HTTPClient.userAgent) 27 | try request.setURL(url) 28 | let response = try request.execute() 29 | var error: NSError? 30 | let contentString = response.getContentString(&error) 31 | if let error { 32 | throw error 33 | } 34 | return contentString 35 | } 36 | 37 | deinit { 38 | client.close() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /SFT/MainView.swift: -------------------------------------------------------------------------------- 1 | import ApplicationLibrary 2 | import Libbox 3 | import Library 4 | import SwiftUI 5 | 6 | struct MainView: View { 7 | @Environment(\.scenePhase) private var scenePhase 8 | @EnvironmentObject private var environments: ExtensionEnvironments 9 | @State private var selection = NavigationPage.dashboard 10 | 11 | var body: some View { 12 | TabView(selection: $selection) { 13 | ForEach(NavigationPage.allCases, id: \.self) { page in 14 | NavigationStackCompat { 15 | page.contentView 16 | .focusSection() 17 | } 18 | .tag(page) 19 | .tabItem { page.label } 20 | } 21 | } 22 | .onAppear { 23 | environments.postReload() 24 | } 25 | .onChangeCompat(of: scenePhase) { newValue in 26 | if newValue == .active { 27 | environments.postReload() 28 | } 29 | } 30 | .onChangeCompat(of: selection) { newValue in 31 | if newValue == .logs { 32 | environments.connectLog() 33 | } 34 | } 35 | .environment(\.selection, $selection) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ApplicationLibrary/Views/Dashboard/InstallSystemExtensionButton.swift: -------------------------------------------------------------------------------- 1 | #if os(macOS) 2 | 3 | import Library 4 | import SwiftUI 5 | 6 | @MainActor 7 | public struct InstallSystemExtensionButton: View { 8 | @State private var alert: Alert? 9 | private let callback: () async -> Void 10 | public init(_ callback: @escaping () async -> Void) { 11 | self.callback = callback 12 | } 13 | 14 | public var body: some View { 15 | FormButton { 16 | Task { 17 | await installSystemExtension() 18 | } 19 | } label: { 20 | Label("Install System Extension", systemImage: "lock.doc.fill") 21 | } 22 | .alertBinding($alert) 23 | } 24 | 25 | private func installSystemExtension() async { 26 | do { 27 | if let result = try await SystemExtension.install() { 28 | if result == .willCompleteAfterReboot { 29 | alert = Alert(errorMessage: String(localized: "Need Reboot")) 30 | } 31 | } 32 | await callback() 33 | } catch { 34 | alert = Alert(error) 35 | } 36 | } 37 | } 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /SFT/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BGTaskSchedulerPermittedIdentifiers 6 | 7 | com.zsheep.box.update_profiles 8 | 9 | CFBundleURLTypes 10 | 11 | 12 | CFBundleTypeRole 13 | Viewer 14 | CFBundleURLIconFile 15 | AppIcon.icns 16 | CFBundleURLName 17 | sing-box 18 | CFBundleURLSchemes 19 | 20 | sing-box 21 | 22 | 23 | 24 | ITSAppUsesNonExemptEncryption 25 | 26 | NSApplicationServices 27 | 28 | Browses 29 | 30 | 31 | NSApplicationServiceIdentifier 32 | sing-box:profile 33 | NSApplicationServicePlatformSupport 34 | 35 | iOS 36 | iPadOS 37 | 38 | NSApplicationServiceUsageDescription 39 | Import sing-box profile from other devices 40 | 41 | 42 | 43 | UIBackgroundModes 44 | 45 | fetch 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /MacLibrary/MenuLabel.swift: -------------------------------------------------------------------------------- 1 | import Libbox 2 | import Library 3 | import SwiftUI 4 | 5 | public struct MenuLabel: View { 6 | @EnvironmentObject private var environments: ExtensionEnvirnments 7 | 8 | public init() {} 9 | public var body: some View { 10 | // if let profile = environments.extensionProfile { 11 | // MenuLabel0().environmentObject(profile) 12 | // } else { 13 | // } 14 | } 15 | 16 | private struct MenuLabel0: View { 17 | @EnvironmentObject private var environments: ExtensionEnvirnments 18 | @EnvironmentObject private var extensionProfile: ExtensionProfile 19 | @StateObject private var commandClient = CommandClient(.status) 20 | 21 | var body: some View { 22 | HStack { 23 | if extensionProfile.status.isConnectedStrict, let message = commandClient.status { 24 | Image("MenuIcon") 25 | Text(" ↑ \(LibboxFormatBytes(message.uplink))/s ↓ \(LibboxFormatBytes(message.downlink))/s") 26 | } else { 27 | Image("MenuIcon") 28 | } 29 | } 30 | .onAppear { 31 | commandClient.connect() 32 | } 33 | .onChangeCompat(of: extensionProfile.status) { newValue in 34 | if newValue.isConnectedStrict { 35 | commandClient.connect() 36 | } 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ApplicationLibrary/Views/Abstract/Alert.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | 4 | public extension Alert { 5 | init(_ error: Error, _ dismissAction: (() -> Void)? = nil) { 6 | self.init( 7 | errorMessage: error.localizedDescription, 8 | dismissAction 9 | ) 10 | } 11 | 12 | init(errorMessage: String, _ dismissAction: (() -> Void)? = nil) { 13 | self.init( 14 | title: Text("Error"), 15 | message: Text(errorMessage), 16 | dismissButton: .default(Text("Ok")) { 17 | dismissAction?() 18 | } 19 | ) 20 | } 21 | } 22 | 23 | public extension View { 24 | func alertBinding(_ binding: Binding) -> some View { 25 | alert(isPresented: Binding(get: { 26 | binding.wrappedValue != nil 27 | }, set: { newValue, _ in 28 | if !newValue { 29 | binding.wrappedValue = nil 30 | } 31 | })) { 32 | binding.wrappedValue! 33 | } 34 | } 35 | 36 | func alertBinding(_ binding: Binding, _ isLoading: Binding) -> some View { 37 | alert(isPresented: Binding(get: { 38 | binding.wrappedValue != nil 39 | }, set: { newValue, _ in 40 | if !newValue, !isLoading.wrappedValue { 41 | binding.wrappedValue = nil 42 | } 43 | })) { 44 | binding.wrappedValue! 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ApplicationLibrary/Views/Abstract/DeleteButton.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | 4 | public struct DeleteButton