├── .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