mirror of
https://github.com/yggdrasil-network/yggdrasil-ios.git
synced 2025-04-28 22:25:10 +03:00
App updates
This commit is contained in:
parent
2cb5eebcd2
commit
5fbb735f56
9 changed files with 204 additions and 91 deletions
|
@ -13,6 +13,8 @@ import AppKit
|
|||
import SwiftUI
|
||||
import Yggdrasil
|
||||
import NetworkExtension
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
#if os(iOS)
|
||||
class PlatformItemSource: NSObject, UIActivityItemSource {
|
||||
|
@ -31,9 +33,10 @@ class PlatformItemSource: NSObject {}
|
|||
class ConfigurationProxy: PlatformItemSource {
|
||||
private var manager: NETunnelProviderManager?
|
||||
private var json: Data? = nil
|
||||
private var dict: [String: Any]? = nil
|
||||
private var dict: [String: Any]? = [:]
|
||||
private var timer: Timer?
|
||||
|
||||
init(manager: NETunnelProviderManager? = nil) {
|
||||
init(manager: NETunnelProviderManager) {
|
||||
self.manager = manager
|
||||
super.init()
|
||||
|
||||
|
@ -64,14 +67,13 @@ class ConfigurationProxy: PlatformItemSource {
|
|||
self.set("Listen", to: [] as [String])
|
||||
self.set("AdminListen", to: "none")
|
||||
self.set("IfName", to: "dummy")
|
||||
self.set("Peers", to: ["tcp://172.22.97.1.5190", "tls://172.22.97.1:5191"])
|
||||
|
||||
if self.get("AutoStart") == nil {
|
||||
self.set("AutoStart", to: ["Any": false, "WiFi": false, "Mobile": false, "Ethernet": false] as [String: Bool])
|
||||
}
|
||||
|
||||
let multicastInterfaces = self.get("MulticastInterfaces") as? [[String: Any]] ?? []
|
||||
if multicastInterfaces.count == 0 {
|
||||
if multicastInterfaces.count != 1 {
|
||||
self.set("MulticastInterfaces", to: [
|
||||
[
|
||||
"Regex": "en.*",
|
||||
|
@ -94,7 +96,7 @@ class ConfigurationProxy: PlatformItemSource {
|
|||
var multicastInterfaces = self.get("MulticastInterfaces") as? [[String: Any]] ?? []
|
||||
multicastInterfaces[0]["Beacon"] = newValue
|
||||
self.set("MulticastInterfaces", to: multicastInterfaces)
|
||||
self.trySave()
|
||||
self.saveSoon()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,7 +112,23 @@ class ConfigurationProxy: PlatformItemSource {
|
|||
var multicastInterfaces = self.get("MulticastInterfaces") as? [[String: Any]] ?? []
|
||||
multicastInterfaces[0]["Listen"] = newValue
|
||||
self.set("MulticastInterfaces", to: multicastInterfaces)
|
||||
self.trySave()
|
||||
self.saveSoon()
|
||||
}
|
||||
}
|
||||
|
||||
public var multicastPassword: String {
|
||||
get {
|
||||
let multicastInterfaces = self.get("MulticastInterfaces") as? [[String: Any]] ?? []
|
||||
if multicastInterfaces.count == 0 {
|
||||
return ""
|
||||
}
|
||||
return multicastInterfaces[0]["Password"] as? String ?? ""
|
||||
}
|
||||
set {
|
||||
var multicastInterfaces = self.get("MulticastInterfaces") as? [[String: Any]] ?? []
|
||||
multicastInterfaces[0]["Password"] = newValue
|
||||
self.set("MulticastInterfaces", to: multicastInterfaces)
|
||||
self.saveSoon()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,7 +138,7 @@ class ConfigurationProxy: PlatformItemSource {
|
|||
}
|
||||
set {
|
||||
self.set("Any", inSection: "AutoStart", to: newValue)
|
||||
self.trySave()
|
||||
self.saveSoon()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,7 +148,7 @@ class ConfigurationProxy: PlatformItemSource {
|
|||
}
|
||||
set {
|
||||
self.set("WiFi", inSection: "AutoStart", to: newValue)
|
||||
self.trySave()
|
||||
self.saveSoon()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,7 +158,7 @@ class ConfigurationProxy: PlatformItemSource {
|
|||
}
|
||||
set {
|
||||
self.set("Ethernet", inSection: "AutoStart", to: newValue)
|
||||
self.trySave()
|
||||
self.saveSoon()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,7 +168,17 @@ class ConfigurationProxy: PlatformItemSource {
|
|||
}
|
||||
set {
|
||||
self.set("Mobile", inSection: "AutoStart", to: newValue)
|
||||
self.trySave()
|
||||
self.saveSoon()
|
||||
}
|
||||
}
|
||||
|
||||
public var deviceName: String {
|
||||
get {
|
||||
return self.get("name", inSection: "NodeInfo") as? String ?? ""
|
||||
}
|
||||
set {
|
||||
self.set("name", inSection: "NodeInfo", to: newValue)
|
||||
self.saveSoon()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,7 +188,7 @@ class ConfigurationProxy: PlatformItemSource {
|
|||
}
|
||||
set {
|
||||
self.set("Peers", to: newValue)
|
||||
self.trySave()
|
||||
self.saveSoon()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,10 +267,22 @@ class ConfigurationProxy: PlatformItemSource {
|
|||
}
|
||||
}
|
||||
|
||||
private func trySave() {
|
||||
private func saveSoon() {
|
||||
self.timer?.invalidate()
|
||||
self.timer = Timer.scheduledTimer(
|
||||
timeInterval: 1.0,
|
||||
target: self,
|
||||
selector: #selector(saveFromTimer),
|
||||
userInfo: nil,
|
||||
repeats: false
|
||||
)
|
||||
}
|
||||
|
||||
@objc private func saveFromTimer() {
|
||||
if var manager = self.manager {
|
||||
try? self.save(to: &manager)
|
||||
}
|
||||
self.timer = nil
|
||||
}
|
||||
|
||||
func save(to manager: inout NETunnelProviderManager) throws {
|
||||
|
@ -254,6 +294,8 @@ class ConfigurationProxy: PlatformItemSource {
|
|||
providerProtocol.serverAddress = "yggdrasil"
|
||||
providerProtocol.username = self.get("PublicKey") as? String ?? self.get("SigningPublicKey") as? String ?? "(unknown public key)"
|
||||
|
||||
NSLog(String(data: data, encoding: .utf8) ?? "(unknown)")
|
||||
|
||||
let disconnectrule = NEOnDemandRuleDisconnect()
|
||||
var rules: [NEOnDemandRule] = [disconnectrule]
|
||||
if self.get("Any", inSection: "AutoStart") as? Bool ?? false {
|
||||
|
@ -283,10 +325,10 @@ class ConfigurationProxy: PlatformItemSource {
|
|||
manager.onDemandRules = rules
|
||||
manager.isOnDemandEnabled = rules.count > 1
|
||||
providerProtocol.disconnectOnSleep = rules.count > 1
|
||||
|
||||
|
||||
manager.protocolConfiguration = providerProtocol
|
||||
|
||||
manager.saveToPreferences(completionHandler: { (error:Error?) in
|
||||
manager.saveToPreferences(completionHandler: { error in
|
||||
if let error = error {
|
||||
print(error)
|
||||
} else {
|
||||
|
|
|
@ -22,11 +22,12 @@ typealias ApplicationDelegateAdaptor = NSApplicationDelegateAdaptor
|
|||
|
||||
class CrossPlatformAppDelegate: PlatformAppDelegate, ObservableObject {
|
||||
var vpnManager: NETunnelProviderManager = NETunnelProviderManager()
|
||||
var yggdrasilConfig: ConfigurationProxy = ConfigurationProxy()
|
||||
var yggdrasilConfig: ConfigurationProxy
|
||||
let yggdrasilComponent = "eu.neilalexander.yggdrasil.extension"
|
||||
private var adminTimer: DispatchSourceTimer?
|
||||
|
||||
override init() {
|
||||
self.yggdrasilConfig = ConfigurationProxy(manager: self.vpnManager)
|
||||
super.init()
|
||||
|
||||
NotificationCenter.default.addObserver(forName: .NEVPNStatusDidChange, object: nil, queue: nil, using: { notification in
|
||||
|
@ -34,7 +35,6 @@ class CrossPlatformAppDelegate: PlatformAppDelegate, ObservableObject {
|
|||
switch conn.status {
|
||||
case .connected:
|
||||
self.requestSummaryIPC()
|
||||
self.requestStatusIPC()
|
||||
case .disconnecting, .disconnected:
|
||||
self.clearStatus()
|
||||
default:
|
||||
|
@ -73,9 +73,7 @@ class CrossPlatformAppDelegate: PlatformAppDelegate, ObservableObject {
|
|||
@Published var yggdrasilSubnet: String = "N/A"
|
||||
@Published var yggdrasilCoords: String = "[]"
|
||||
|
||||
@Published var yggdrasilPeers: [[String: Any]] = [[:]]
|
||||
@Published var yggdrasilDHT: [[String: Any]] = [[:]]
|
||||
@Published var yggdrasilNodeInfo: [String: Any] = [:]
|
||||
@Published var yggdrasilPeers: [YggdrasilPeer] = []
|
||||
|
||||
func yggdrasilVersion() -> String {
|
||||
return Yggdrasil.MobileGetVersion()
|
||||
|
@ -111,7 +109,7 @@ class CrossPlatformAppDelegate: PlatformAppDelegate, ObservableObject {
|
|||
|
||||
func updateStatus(conn: NEVPNConnection) {
|
||||
if conn.status == .connected {
|
||||
self.requestStatusIPC()
|
||||
self.requestSummaryIPC()
|
||||
} else if conn.status == .disconnecting || conn.status == .disconnected {
|
||||
self.clearStatus()
|
||||
}
|
||||
|
@ -183,30 +181,14 @@ class CrossPlatformAppDelegate: PlatformAppDelegate, ObservableObject {
|
|||
if let session = self.vpnManager.connection as? NETunnelProviderSession {
|
||||
try? session.sendProviderMessage("summary".data(using: .utf8)!) { js in
|
||||
if let js = js, let summary = try? JSONDecoder().decode(YggdrasilSummary.self, from: js) {
|
||||
self.yggdrasilEnabled = true
|
||||
self.yggdrasilEnabled = summary.enabled
|
||||
self.yggdrasilIP = summary.address
|
||||
self.yggdrasilSubnet = summary.subnet
|
||||
self.yggdrasilPublicKey = summary.publicKey
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func requestStatusIPC() {
|
||||
if self.vpnManager.connection.status != .connected {
|
||||
return
|
||||
}
|
||||
if let session = self.vpnManager.connection as? NETunnelProviderSession {
|
||||
try? session.sendProviderMessage("status".data(using: .utf8)!) { js in
|
||||
if let js = js, let status = try? JSONDecoder().decode(YggdrasilStatus.self, from: js) {
|
||||
self.yggdrasilCoords = status.coords
|
||||
if let jsonResponse = try? JSONSerialization.jsonObject(with: status.peers, options: []) as? [[String: Any]] {
|
||||
self.yggdrasilPeers = jsonResponse
|
||||
}
|
||||
if let jsonResponse = try? JSONSerialization.jsonObject(with: status.dht, options: []) as? [[String: Any]] {
|
||||
self.yggdrasilDHT = jsonResponse
|
||||
}
|
||||
self.yggdrasilConnected = self.yggdrasilEnabled && self.yggdrasilPeers.count > 0 && self.yggdrasilDHT.count > 0
|
||||
self.yggdrasilPeers = summary.peers
|
||||
self.yggdrasilConnected = summary.peers.count > 0
|
||||
|
||||
print(self.yggdrasilPeers)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -218,6 +200,5 @@ class CrossPlatformAppDelegate: PlatformAppDelegate, ObservableObject {
|
|||
self.yggdrasilSubnet = "N/A"
|
||||
self.yggdrasilCoords = "[]"
|
||||
self.yggdrasilPeers = []
|
||||
self.yggdrasilDHT = []
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,11 +11,29 @@ struct YggdrasilSummary: Codable {
|
|||
var address: String
|
||||
var subnet: String
|
||||
var publicKey: String
|
||||
var enabled: Bool
|
||||
var peers: [YggdrasilPeer]
|
||||
|
||||
func list() -> [String] {
|
||||
return peers.map { $0.remote }
|
||||
}
|
||||
}
|
||||
|
||||
struct YggdrasilStatus: Codable {
|
||||
var enabled: Bool
|
||||
var coords: String
|
||||
var peers: Data
|
||||
var dht: Data
|
||||
struct YggdrasilPeer: Codable, Identifiable {
|
||||
var id: String { remote } // For Identifiable protocol
|
||||
let remote: String
|
||||
let up: Bool
|
||||
let address: String
|
||||
let key: String
|
||||
let priority: UInt8
|
||||
let cost: UInt16?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case remote = "URI"
|
||||
case up = "Up"
|
||||
case address = "IP"
|
||||
case key = "Key"
|
||||
case priority = "Priority"
|
||||
case cost = "Cost"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,25 +98,28 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||
let request = String(data: messageData, encoding: .utf8)
|
||||
switch request {
|
||||
case "summary":
|
||||
let pj = self.yggdrasil.getPeersJSON()
|
||||
var peers: [YggdrasilPeer] = []
|
||||
do {
|
||||
peers = try JSONDecoder().decode(
|
||||
[YggdrasilPeer].self,
|
||||
from: pj.data(using: .utf8)!
|
||||
)
|
||||
} catch {
|
||||
NSLog("JSON Error: \(error)")
|
||||
}
|
||||
let summary = YggdrasilSummary(
|
||||
address: self.yggdrasil.getAddressString(),
|
||||
subnet: self.yggdrasil.getSubnetString(),
|
||||
publicKey: self.yggdrasil.getPublicKeyString()
|
||||
publicKey: self.yggdrasil.getPublicKeyString(),
|
||||
enabled: true,
|
||||
peers: peers.sorted(by: { a, b in
|
||||
a.remote < b.remote
|
||||
})
|
||||
)
|
||||
if let json = try? JSONEncoder().encode(summary) {
|
||||
completionHandler?(json)
|
||||
}
|
||||
|
||||
case "status":
|
||||
let status = YggdrasilStatus(
|
||||
enabled: true,
|
||||
coords: self.yggdrasil.getCoordsString(),
|
||||
peers: self.yggdrasil.getPeersJSON().data(using: .utf8) ?? Data(),
|
||||
dht: self.yggdrasil.getDHTJSON().data(using: .utf8) ?? Data()
|
||||
)
|
||||
if let json = try? JSONEncoder().encode(status) {
|
||||
completionHandler?(json)
|
||||
}
|
||||
|
||||
default:
|
||||
completionHandler?(nil)
|
||||
|
|
|
@ -3,17 +3,18 @@
|
|||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 55;
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
391B72A82A2FD90100896278 /* PacketTunnelProvider+FileDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 391B72A62A2FD90100896278 /* PacketTunnelProvider+FileDescriptor.swift */; };
|
||||
3952ADB829945AF700B3835D /* ConfigurationProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3952ADB629945AF700B3835D /* ConfigurationProxy.swift */; };
|
||||
3996AF39270328080070947D /* Yggdrasil.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3996AF37270328080070947D /* Yggdrasil.xcframework */; };
|
||||
39B51A4A2997062E0059D29D /* PeersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39B51A492997062E0059D29D /* PeersView.swift */; };
|
||||
39B51A4B29994F240059D29D /* ConfigurationProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3952ADB629945AF700B3835D /* ConfigurationProxy.swift */; };
|
||||
39B51A4C29994F350059D29D /* CrossPlatformAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3952ADB929945AFA00B3835D /* CrossPlatformAppDelegate.swift */; };
|
||||
39B51A4D299951D60059D29D /* IPCResponses.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39CC924B221DEDCE004960DC /* IPCResponses.swift */; };
|
||||
39B9173C2BBD637200899F81 /* Yggdrasil.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3996AF37270328080070947D /* Yggdrasil.xcframework */; };
|
||||
39B9173D2BBD637200899F81 /* Yggdrasil.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3996AF37270328080070947D /* Yggdrasil.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
39BF9FC72A2F6FFD000E7269 /* Yggdrasil.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3996AF37270328080070947D /* Yggdrasil.xcframework */; };
|
||||
39CC924D221DEDD3004960DC /* IPCResponses.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39CC924B221DEDCE004960DC /* IPCResponses.swift */; };
|
||||
39F0205E2996CD760093F603 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39F0205D2996CD760093F603 /* Application.swift */; };
|
||||
|
@ -22,7 +23,7 @@
|
|||
39F020662996CD770093F603 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 39F020652996CD770093F603 /* Preview Assets.xcassets */; };
|
||||
39F0206B2996CF260093F603 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39F0206A2996CF260093F603 /* SettingsView.swift */; };
|
||||
39F99B342A48F6E50045BD10 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 39AE88382319C93F0010FFF6 /* NetworkExtension.framework */; };
|
||||
39F99B382A48F74F0045BD10 /* YggdrasilNetworkExtension.appex in CopyFiles */ = {isa = PBXBuildFile; fileRef = E593CE971DF905AF00D7265D /* YggdrasilNetworkExtension.appex */; platformFilters = (ios, macos, ); settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
39F99B382A48F74F0045BD10 /* YggdrasilNetworkExtension.appex in CopyFiles */ = {isa = PBXBuildFile; fileRef = E593CE971DF905AF00D7265D /* YggdrasilNetworkExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
E593CE9C1DF905AF00D7265D /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = E593CE9B1DF905AF00D7265D /* PacketTunnelProvider.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
|
@ -37,6 +38,17 @@
|
|||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
39B9173E2BBD637200899F81 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
39B9173D2BBD637200899F81 /* Yggdrasil.xcframework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
39F99B372A48F7380045BD10 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
@ -87,7 +99,7 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3996AF39270328080070947D /* Yggdrasil.xcframework in Frameworks */,
|
||||
39B9173C2BBD637200899F81 /* Yggdrasil.xcframework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -199,6 +211,7 @@
|
|||
E593CE931DF905AF00D7265D /* Sources */,
|
||||
E593CE941DF905AF00D7265D /* Frameworks */,
|
||||
E593CE951DF905AF00D7265D /* Resources */,
|
||||
39B9173E2BBD637200899F81 /* Embed Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
@ -309,10 +322,6 @@
|
|||
/* Begin PBXTargetDependency section */
|
||||
39F99B362A48F70F0045BD10 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
platformFilters = (
|
||||
ios,
|
||||
macos,
|
||||
);
|
||||
target = E593CE961DF905AF00D7265D /* YggdrasilNetworkExtension */;
|
||||
targetProxy = 39F99B352A48F70F0045BD10 /* PBXContainerItemProxy */;
|
||||
};
|
||||
|
@ -363,6 +372,7 @@
|
|||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
@ -413,6 +423,7 @@
|
|||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
@ -548,9 +559,13 @@
|
|||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "Yggdrasil Network Extension/YggdrasilNetworkExtension.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 32;
|
||||
DEVELOPMENT_TEAM = R9AV23TXF2;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = R9AV23TXF2;
|
||||
"DEVELOPMENT_TEAM[sdk=macosx*]" = R9AV23TXF2;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -566,8 +581,12 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = eu.neilalexander.yggdrasil.extension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Provisioning eu.neilalexander.yggdrasil.extension";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "Provisioning2 eu.neilalexander.yggdrasil.extension";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Yggdrasil Network Extension/YggdrasilNetworkExtension-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
@ -580,9 +599,13 @@
|
|||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "Yggdrasil Network Extension/YggdrasilNetworkExtension.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 32;
|
||||
DEVELOPMENT_TEAM = R9AV23TXF2;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = R9AV23TXF2;
|
||||
"DEVELOPMENT_TEAM[sdk=macosx*]" = R9AV23TXF2;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -599,8 +622,12 @@
|
|||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE = "8ce353d5-fd5f-4d5e-b664-8ad294091125";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Provisioning eu.neilalexander.yggdrasil.extension";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "Provisioning2 eu.neilalexander.yggdrasil.extension";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Yggdrasil Network Extension/YggdrasilNetworkExtension-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
|
|
@ -23,7 +23,7 @@ struct Application: App {
|
|||
var body: some Scene {
|
||||
WindowGroup {
|
||||
NavigationSplitView {
|
||||
ZStack {
|
||||
VStack {
|
||||
List(selection: $selection) {
|
||||
NavigationLink(destination: StatusView()) {
|
||||
HStack {
|
||||
|
|
|
@ -8,22 +8,25 @@
|
|||
import SwiftUI
|
||||
|
||||
struct PeersView: View {
|
||||
// @Binding public var yggdrasilConfiguration: ConfigurationProxy
|
||||
@ObservedObject private var appDelegate = Application.appDelegate
|
||||
#if os(iOS)
|
||||
@Environment(\.editMode) var editMode
|
||||
#endif
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
Section(content: {
|
||||
ForEach(Array(appDelegate.yggdrasilConfig.peers.enumerated()), id: \.offset) { index, peer in
|
||||
HStack() {
|
||||
Text(peer)
|
||||
//TextField("", text: $yggdrasilConfiguration.peers[index])
|
||||
// .multilineTextAlignment(.leading)
|
||||
TextField("Peer", text: $appDelegate.yggdrasilConfig.peers[index])
|
||||
.labelsHidden()
|
||||
#if os(iOS)
|
||||
.disabled(!editMode!.wrappedValue.isEditing)
|
||||
#endif
|
||||
#if os(macOS)
|
||||
Spacer()
|
||||
Button(role: .destructive) {
|
||||
// appDelegate.yggdrasilConfig.peers.remove { $0 == peerURI }
|
||||
// self.delete(at: appDelegate.yggdrasilConfig.peers.firstIndex { $0 == peerURI })
|
||||
appDelegate.yggdrasilConfig.peers.remove(at: index)
|
||||
} label: {
|
||||
Image(systemName: "xmark.circle.fill")
|
||||
}
|
||||
|
@ -38,13 +41,15 @@ struct PeersView: View {
|
|||
appDelegate.yggdrasilConfig.peers.remove(atOffsets: indexSet)
|
||||
}
|
||||
|
||||
#if os(macOS)
|
||||
Button {
|
||||
appDelegate.yggdrasilConfig.peers.append("foo")
|
||||
appDelegate.yggdrasilConfig.peers.append("")
|
||||
} label: {
|
||||
Label("Add peer", systemImage: "plus")
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.foregroundColor(.accentColor)
|
||||
#endif
|
||||
|
||||
Text("Yggdrasil will automatically attempt to connect to configured peers when started. If you configure more than one peer, your device may carry traffic on behalf of other network nodes. Avoid this by configuring only a single peer. Data charges may apply when using mobile data.")
|
||||
.font(.system(size: 11))
|
||||
|
@ -70,20 +75,27 @@ struct PeersView: View {
|
|||
.foregroundColor(.gray)
|
||||
}
|
||||
}
|
||||
TextField("Multicast password", text: $appDelegate.yggdrasilConfig.multicastPassword)
|
||||
}, header: {
|
||||
Text("Local connectivity")
|
||||
})
|
||||
}
|
||||
#if os(iOS)
|
||||
.toolbar {
|
||||
// EditButton()
|
||||
}
|
||||
#endif
|
||||
.formStyle(.grouped)
|
||||
.navigationTitle("Peers")
|
||||
#if os(iOS)
|
||||
#if os(iOS)
|
||||
.toolbar {
|
||||
Button("Add", systemImage: "plus") {
|
||||
appDelegate.yggdrasilConfig.peers.append("")
|
||||
}
|
||||
EditButton()
|
||||
.onChange(of: editMode!.wrappedValue) { edit in
|
||||
if !edit.isEditing {
|
||||
try? appDelegate.yggdrasilConfig.save(to: &appDelegate.vpnManager)
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationBarTitleDisplayMode(.large)
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ struct SettingsView: View {
|
|||
var body: some View {
|
||||
Form {
|
||||
Section(content: {
|
||||
TextField("Device Name", text: $deviceName)
|
||||
TextField("Device Name", text: $appDelegate.yggdrasilConfig.deviceName)
|
||||
}, header: {
|
||||
Text("Public Identity")
|
||||
})
|
||||
|
|
|
@ -93,6 +93,8 @@ struct StatusView: View {
|
|||
Text(appDelegate.yggdrasilVersion())
|
||||
.foregroundColor(Color.gray)
|
||||
}
|
||||
}, header: {
|
||||
Text("Status")
|
||||
})
|
||||
|
||||
Section(content: {
|
||||
|
@ -114,7 +116,7 @@ struct StatusView: View {
|
|||
.lineLimit(1)
|
||||
.textSelection(.enabled)
|
||||
}
|
||||
HStack {
|
||||
/*HStack {
|
||||
Text("Coordinates")
|
||||
Spacer()
|
||||
Text(appDelegate.yggdrasilCoords)
|
||||
|
@ -122,7 +124,7 @@ struct StatusView: View {
|
|||
.truncationMode(.tail)
|
||||
.lineLimit(1)
|
||||
.textSelection(.enabled)
|
||||
}
|
||||
}*/
|
||||
HStack {
|
||||
Text("Public Key")
|
||||
Spacer()
|
||||
|
@ -133,7 +135,35 @@ struct StatusView: View {
|
|||
.lineLimit(1)
|
||||
.textSelection(.enabled)
|
||||
}
|
||||
}, header: {
|
||||
Text("Details")
|
||||
})
|
||||
|
||||
if self.appDelegate.yggdrasilEnabled {
|
||||
Section(content: {
|
||||
List(self.appDelegate.yggdrasilPeers.sorted(by: { a, b in
|
||||
a.key < a.key
|
||||
}), id: \.remote) { peer in
|
||||
VStack {
|
||||
Text(peer.remote)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.truncationMode(.tail)
|
||||
.lineLimit(1)
|
||||
.textSelection(.enabled)
|
||||
Text(peer.address)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.foregroundColor(Color.gray)
|
||||
.font(.system(size: 11, design: .monospaced))
|
||||
.truncationMode(.tail)
|
||||
.lineLimit(1)
|
||||
.textSelection(.enabled)
|
||||
}
|
||||
.padding(.all, 2)
|
||||
}
|
||||
}, header: {
|
||||
Text("Peers")
|
||||
})
|
||||
}
|
||||
}
|
||||
.formStyle(.grouped)
|
||||
.navigationTitle("Yggdrasil")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue