Sanitised
|
@ -0,0 +1,16 @@
|
|||
//
|
||||
// AppDelegate+AppDelegateExtension.h
|
||||
// Yggdrasil Network
|
||||
//
|
||||
// Created by Neil Alexander on 11/01/2019.
|
||||
//
|
||||
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface AppDelegate ()
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
21
Yggdrasil Network iOS/Application/AppDelegate.swift
Normal file
|
@ -0,0 +1,21 @@
|
|||
import UIKit
|
||||
|
||||
#if os(iOS)
|
||||
class PlatformAppDelegate: UIResponder, UIApplicationDelegate {}
|
||||
#elseif os(OSX)
|
||||
class PlatformAppDelegate: NSObject, NSApplicationDelegate {}
|
||||
#endif
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: CrossPlatformAppDelegate {
|
||||
var window: UIWindow?
|
||||
|
||||
let configDir = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true)[0]
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
// Override point for customization after application launch
|
||||
self.vpnTunnelProviderManagerInit()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
19
Yggdrasil Network iOS/Application/NSNotification.swift
Normal file
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// NSNotification.swift
|
||||
// YggdrasilNetwork
|
||||
//
|
||||
// Created by Neil Alexander on 20/02/2019.
|
||||
//
|
||||
|
||||
#if canImport(UIKit)
|
||||
import UIKit
|
||||
#elseif canImport(AppKit)
|
||||
import AppKit
|
||||
#endif
|
||||
|
||||
extension Notification.Name {
|
||||
static let YggdrasilSelfUpdated = Notification.Name("YggdrasilSelfUpdated")
|
||||
static let YggdrasilPeersUpdated = Notification.Name("YggdrasilPeersUpdated")
|
||||
static let YggdrasilSwitchPeersUpdated = Notification.Name("YggdrasilSwitchPeersUpdated")
|
||||
static let YggdrasilSettingsUpdated = Notification.Name("YggdrasilSettingsUpdated")
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "drawing copy-1.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "drawing copy.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "20x20",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "20x20",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "drawing copy-2.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "drawing copy-3.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "83.5x83.5",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "drawing copy-5.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "1024x1024",
|
||||
"idiom" : "ios-marketing",
|
||||
"filename" : "drawing copy-4.png",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 4 KiB |
6
Yggdrasil Network iOS/Assets.xcassets/Contents.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
23
Yggdrasil Network iOS/Assets.xcassets/YggdrasilNetwork.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "img1.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "img2.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "img3.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
Yggdrasil Network iOS/Assets.xcassets/YggdrasilNetwork.imageset/img1.png
vendored
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
Yggdrasil Network iOS/Assets.xcassets/YggdrasilNetwork.imageset/img2.png
vendored
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
Yggdrasil Network iOS/Assets.xcassets/YggdrasilNetwork.imageset/img3.png
vendored
Normal file
After Width: | Height: | Size: 39 KiB |
28
Yggdrasil Network iOS/Extensions/UIDevice.swift
Normal file
|
@ -0,0 +1,28 @@
|
|||
import Foundation
|
||||
import UIKit
|
||||
|
||||
extension UIDevice {
|
||||
/// A Boolean value indicating whether the device has cellular data capabilities (true) or not (false).
|
||||
var hasCellularCapabilites: Bool {
|
||||
var addrs: UnsafeMutablePointer<ifaddrs>?
|
||||
var cursor: UnsafeMutablePointer<ifaddrs>?
|
||||
|
||||
defer { freeifaddrs(addrs) }
|
||||
|
||||
guard getifaddrs(&addrs) == 0 else { return false }
|
||||
cursor = addrs
|
||||
|
||||
while cursor != nil {
|
||||
guard
|
||||
let utf8String = cursor?.pointee.ifa_name,
|
||||
let name = NSString(utf8String: utf8String),
|
||||
name == "pdp_ip0"
|
||||
else {
|
||||
cursor = cursor?.pointee.ifa_next
|
||||
continue
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
76
Yggdrasil Network iOS/Info.plist
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Yggdrasil</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.1</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.utilities</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>LSSupportsOpeningDocumentsInPlace</key>
|
||||
<true/>
|
||||
<key>UIFileSharingEnabled</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UTExportedTypeDeclarations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.text</string>
|
||||
</array>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>Yggdrasil Configuration File</string>
|
||||
<key>UTTypeIconFiles</key>
|
||||
<array/>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>eu.neilalexander.yggdrasil.configuration</string>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>yggconf</string>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="YggdrasilNetwork" translatesAutoresizingMaskIntoConstraints="NO" id="3Lc-gG-kep">
|
||||
<rect key="frame" x="28" y="229.5" width="319" height="128"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="3Lc-gG-kep" secondAttribute="height" multiplier="159:64" id="NYe-AY-mCL"/>
|
||||
<constraint firstAttribute="width" relation="lessThanOrEqual" constant="400" id="lIj-gT-vW9"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Experimental" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0Nr-Vm-h9W">
|
||||
<rect key="frame" x="137.5" y="626" width="100" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="3Lc-gG-kep" secondAttribute="trailing" constant="28" id="J9j-Ek-mVq"/>
|
||||
<constraint firstItem="3Lc-gG-kep" firstAttribute="centerY" secondItem="6Tk-OE-BBY" secondAttribute="centerY" constant="-50" id="MLF-C3-5Is"/>
|
||||
<constraint firstItem="3Lc-gG-kep" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="28" id="VpK-lC-s00"/>
|
||||
<constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" secondItem="0Nr-Vm-h9W" secondAttribute="bottom" constant="20" id="WcT-Cw-bXi"/>
|
||||
<constraint firstItem="0Nr-Vm-h9W" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="ZHc-EA-sHG"/>
|
||||
<constraint firstItem="3Lc-gG-kep" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="xej-Yh-XPz"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="52" y="374.66266866566718"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="YggdrasilNetwork" width="785.45452880859375" height="256.90908813476562"/>
|
||||
</resources>
|
||||
</document>
|
704
Yggdrasil Network iOS/Storyboards/Base.lproj/Main.storyboard
Normal file
|
@ -0,0 +1,704 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="sjP-mj-LKX">
|
||||
<device id="retina4_0" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15510"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Peers-->
|
||||
<scene sceneID="YjI-Ak-tYt">
|
||||
<objects>
|
||||
<tableViewController title="Peers" id="Aro-kj-1Us" customClass="PeersViewController" customModule="YggdrasilNetwork" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="jrG-5P-x67">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="configuredPeerPrototype" textLabel="s5X-wa-HWH" style="IBUITableViewCellStyleDefault" id="8Oo-lj-bGn">
|
||||
<rect key="frame" x="0.0" y="55.5" width="320" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="8Oo-lj-bGn" id="l78-DB-hkK">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="(discovered)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="s5X-wa-HWH">
|
||||
<rect key="frame" x="16" y="0.0" width="288" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="discoveredPeerPrototype" textLabel="DBc-bQ-Fql" detailTextLabel="6Zr-Ab-5mg" style="IBUITableViewCellStyleSubtitle" id="GeY-vZ-Kfa">
|
||||
<rect key="frame" x="0.0" y="99" width="320" height="55.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="GeY-vZ-Kfa" id="CVl-gJ-x3R">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="55.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="(static)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="DBc-bQ-Fql">
|
||||
<rect key="frame" x="16" y="10" width="54.5" height="20.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="200:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="6Zr-Ab-5mg">
|
||||
<rect key="frame" x="16" y="31.5" width="26" height="14.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="12"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="menuPrototype" textLabel="hGp-hS-MXO" style="IBUITableViewCellStyleDefault" id="X8B-Ij-Uxu">
|
||||
<rect key="frame" x="0.0" y="154.5" width="320" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="X8B-Ij-Uxu" id="VFl-pZ-ioq">
|
||||
<rect key="frame" x="0.0" y="0.0" width="293" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Menu item" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hGp-hS-MXO">
|
||||
<rect key="frame" x="16" y="0.0" width="269" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="togglePrototype" id="7yi-ur-bht" customClass="ToggleTableViewCell" customModule="YggdrasilNetwork" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="198" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="7yi-ur-bht" id="xEb-l3-99b">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Toggle item" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ij2-ls-8ZT">
|
||||
<rect key="frame" x="16" y="12.5" width="231" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="MYo-S3-kzH">
|
||||
<rect key="frame" x="255" y="7" width="51" height="31.5"/>
|
||||
</switch>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="MYo-S3-kzH" secondAttribute="bottom" constant="5.5" id="GE4-ve-zue"/>
|
||||
<constraint firstItem="MYo-S3-kzH" firstAttribute="leading" secondItem="ij2-ls-8ZT" secondAttribute="trailing" constant="8" id="HY3-fl-iyt"/>
|
||||
<constraint firstItem="ij2-ls-8ZT" firstAttribute="leading" secondItem="xEb-l3-99b" secondAttribute="leadingMargin" id="K5Q-In-8A5"/>
|
||||
<constraint firstAttribute="trailing" secondItem="MYo-S3-kzH" secondAttribute="trailing" constant="16" id="OfU-Jc-Jh0"/>
|
||||
<constraint firstItem="ij2-ls-8ZT" firstAttribute="centerY" secondItem="MYo-S3-kzH" secondAttribute="centerY" id="g5U-4E-XRi"/>
|
||||
<constraint firstItem="MYo-S3-kzH" firstAttribute="top" secondItem="xEb-l3-99b" secondAttribute="top" constant="7" id="wvd-yp-ouw"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="label" destination="ij2-ls-8ZT" id="4kY-1u-gbw"/>
|
||||
<outlet property="toggle" destination="MYo-S3-kzH" id="WDg-LO-UM4"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
<sections/>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="Aro-kj-1Us" id="LKO-i9-QW7"/>
|
||||
<outlet property="delegate" destination="Aro-kj-1Us" id="Gth-NL-fBx"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
<toolbarItems>
|
||||
<barButtonItem systemItem="add" id="MOW-Lh-hSQ">
|
||||
<connections>
|
||||
<action selector="addNewPeerButtonPressed:" destination="Aro-kj-1Us" id="CS3-Z6-tRA"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</toolbarItems>
|
||||
<navigationItem key="navigationItem" title="Peers" id="4pr-Fq-FKY"/>
|
||||
<simulatedToolbarMetrics key="simulatedBottomBarMetrics"/>
|
||||
<connections>
|
||||
<outlet property="addButtonItem" destination="MOW-Lh-hSQ" id="2UM-tD-SnA"/>
|
||||
<outlet property="peerTable" destination="jrG-5P-x67" id="RPw-J3-r1C"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="nJT-Ej-FI5" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1761" y="1212"/>
|
||||
</scene>
|
||||
<!--Peers-->
|
||||
<scene sceneID="psN-bH-gYF">
|
||||
<objects>
|
||||
<navigationController title="Peers" id="LPj-bu-hdp" sceneMemberID="viewController">
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="ifJ-0T-bJ4">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<connections>
|
||||
<segue destination="Aro-kj-1Us" kind="relationship" relationship="rootViewController" id="rED-QI-0E9"/>
|
||||
</connections>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="gCh-Is-VRG" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1761" y="426"/>
|
||||
</scene>
|
||||
<!--Settings-->
|
||||
<scene sceneID="VfF-sj-c5P">
|
||||
<objects>
|
||||
<tableViewController title="Settings" id="FeQ-BB-bF5" customClass="SettingsViewController" customModule="YggdrasilNetwork" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="Cd3-Fg-6d3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
<sections>
|
||||
<tableViewSection headerTitle="Node Info" footerTitle="Information entered here is public and may be shown on network maps." id="su8-4b-N3L">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="nxn-IW-t8I">
|
||||
<rect key="frame" x="0.0" y="55.5" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="nxn-IW-t8I" id="a0m-Mn-9fE">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="250" contentHorizontalAlignment="trailing" contentVerticalAlignment="center" placeholder="None" textAlignment="right" adjustsFontForContentSizeCategory="YES" minimumFontSize="9" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="iRg-tv-diq">
|
||||
<rect key="frame" x="134" y="1" width="171" height="43"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="43" id="cRe-aZ-mWa"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="words" keyboardType="alphabet" enablesReturnKeyAutomatically="YES" textContentType="nickname"/>
|
||||
<connections>
|
||||
<action selector="deviceNameEdited:" destination="FeQ-BB-bF5" eventType="editingDidEnd" id="lfQ-f7-dSt"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Device Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" preferredMaxLayoutWidth="102" translatesAutoresizingMaskIntoConstraints="NO" id="ieL-P9-WNc">
|
||||
<rect key="frame" x="16" y="0.0" width="102" height="44"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="44" id="2cx-q4-by8"/>
|
||||
<constraint firstAttribute="width" constant="102" id="MVL-qb-gJw"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="iRg-tv-diq" secondAttribute="trailing" constant="15" id="5Ww-uH-INm"/>
|
||||
<constraint firstItem="ieL-P9-WNc" firstAttribute="top" secondItem="a0m-Mn-9fE" secondAttribute="top" id="Hoe-Le-Zln"/>
|
||||
<constraint firstItem="iRg-tv-diq" firstAttribute="leading" secondItem="ieL-P9-WNc" secondAttribute="trailing" constant="16" id="JXX-kn-TTD"/>
|
||||
<constraint firstAttribute="bottom" secondItem="ieL-P9-WNc" secondAttribute="bottom" id="MOQ-cH-sUE"/>
|
||||
<constraint firstItem="iRg-tv-diq" firstAttribute="top" secondItem="a0m-Mn-9fE" secondAttribute="top" constant="1" id="O3n-WK-oyd"/>
|
||||
<constraint firstAttribute="bottom" secondItem="iRg-tv-diq" secondAttribute="bottom" id="heq-bT-FXa"/>
|
||||
<constraint firstItem="ieL-P9-WNc" firstAttribute="leading" secondItem="a0m-Mn-9fE" secondAttribute="leading" constant="16" id="hy7-uL-DHk"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
<tableViewSection headerTitle="Automatically Start On" footerTitle="Yggdrasil will be automatically started when connected to the above networks." id="bjf-vx-Swh">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="checkmark" indentationWidth="10" textLabel="NYE-Pu-5Gk" style="IBUITableViewCellStyleDefault" id="pwi-5Y-UxD">
|
||||
<rect key="frame" x="0.0" y="191" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="pwi-5Y-UxD" id="631-3X-gfX">
|
||||
<rect key="frame" x="0.0" y="0.0" width="280" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Wi-Fi" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="NYE-Pu-5Gk">
|
||||
<rect key="frame" x="16" y="0.0" width="256" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<color key="tintColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="checkmark" indentationWidth="10" textLabel="ZdY-uX-KE6" style="IBUITableViewCellStyleDefault" id="iwW-oY-kqV">
|
||||
<rect key="frame" x="0.0" y="235" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="iwW-oY-kqV" id="Pe0-bO-Sd1">
|
||||
<rect key="frame" x="0.0" y="0.0" width="280" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Mobile Network" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ZdY-uX-KE6">
|
||||
<rect key="frame" x="16" y="0.0" width="256" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<color key="tintColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
<tableViewSection headerTitle="Allow traffic from" id="s6m-tK-gtR">
|
||||
<string key="footerTitle">The above options allow you to control whether your device is reachable from other devices on the network. "All outgoing traffic" allows connections only to devices that you initiate first. This does not affect peerings.</string>
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="checkmark" indentationWidth="10" textLabel="X1a-uW-3xE" style="IBUITableViewCellStyleDefault" id="SLl-8Z-hnZ">
|
||||
<rect key="frame" x="0.0" y="370.5" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="SLl-8Z-hnZ" id="erI-m7-1Qf">
|
||||
<rect key="frame" x="0.0" y="0.0" width="280" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Peered devices" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="X1a-uW-3xE">
|
||||
<rect key="frame" x="16" y="0.0" width="256" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<color key="tintColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="checkmark" indentationWidth="10" textLabel="aBz-rP-L1T" style="IBUITableViewCellStyleDefault" id="D0S-Qw-28s">
|
||||
<rect key="frame" x="0.0" y="414.5" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="D0S-Qw-28s" id="PQQ-JM-w0f">
|
||||
<rect key="frame" x="0.0" y="0.0" width="280" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Other devices" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="aBz-rP-L1T">
|
||||
<rect key="frame" x="16" y="0.0" width="256" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<color key="tintColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="checkmark" indentationWidth="10" textLabel="1NE-eU-QbN" style="IBUITableViewCellStyleDefault" id="LgH-VV-ofl">
|
||||
<rect key="frame" x="0.0" y="458.5" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="LgH-VV-ofl" id="TYk-M2-yjB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="280" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="All outgoing traffic" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="1NE-eU-QbN">
|
||||
<rect key="frame" x="16" y="0.0" width="256" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<color key="tintColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
<tableViewSection headerTitle="Public Keys" footerTitle="Your public keys form your identity on the network. They are safe to be shared." id="Bqi-0N-6vQ">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" textLabel="HTU-3c-4CN" detailTextLabel="P02-mF-z69" style="IBUITableViewCellStyleValue1" id="Osh-HO-1v1">
|
||||
<rect key="frame" x="0.0" y="642" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Osh-HO-1v1" id="GnT-sE-p01">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Encryption" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="HTU-3c-4CN">
|
||||
<rect key="frame" x="16" y="12" width="82.5" height="20.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Unknown" textAlignment="right" lineBreakMode="headTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="P02-mF-z69" customClass="CopyableLabel" customModule="YggdrasilNetwork" customModuleProvider="target">
|
||||
<rect key="frame" x="232" y="12" width="72" height="20.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" textLabel="SeD-oT-h3h" detailTextLabel="ISL-Pq-1z4" style="IBUITableViewCellStyleValue1" id="80f-wf-ING">
|
||||
<rect key="frame" x="0.0" y="686" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="80f-wf-ING" id="fed-pT-rbF">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Signing" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="SeD-oT-h3h">
|
||||
<rect key="frame" x="16" y="12" width="57.5" height="20.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Unknown" textAlignment="right" lineBreakMode="headTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ISL-Pq-1z4" customClass="CopyableLabel" customModule="YggdrasilNetwork" customModuleProvider="target">
|
||||
<rect key="frame" x="232" y="12" width="72" height="20.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
<tableViewSection headerTitle="Backup" id="mD0-CO-qvR">
|
||||
<string key="footerTitle">Configuration will be exported to the Files app. Your configuration contains your private keys which are extremely sensitive. You must not share it with others.</string>
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="0zV-IH-vF4" style="IBUITableViewCellStyleDefault" id="IgR-eA-aHt">
|
||||
<rect key="frame" x="0.0" y="821.5" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="IgR-eA-aHt" id="wsZ-KR-yUu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Import configuration" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="0zV-IH-vF4">
|
||||
<rect key="frame" x="16" y="0.0" width="288" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<color key="tintColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="n0W-r2-Cp7" style="IBUITableViewCellStyleDefault" id="Fgj-Ug-A8R">
|
||||
<rect key="frame" x="0.0" y="865.5" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Fgj-Ug-A8R" id="l0v-9n-Tzb">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Export configuration" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="n0W-r2-Cp7">
|
||||
<rect key="frame" x="15" y="0.0" width="297" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<color key="tintColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
<tableViewSection headerTitle="Reset" footerTitle="Resetting will overwrite with newly generated configuration. Your public keys and IP address on the network will change." id="QPd-T4-5id">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="Jc5-vz-oTA" style="IBUITableViewCellStyleDefault" id="Cgi-Yk-esa">
|
||||
<rect key="frame" x="0.0" y="1033" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Cgi-Yk-esa" id="qMT-ha-vJK">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Reset configuration" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Jc5-vz-oTA">
|
||||
<rect key="frame" x="15" y="0.0" width="297" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<color key="tintColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.81077963080000004" green="0.26273393630000003" blue="0.2154698987" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
</sections>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="FeQ-BB-bF5" id="UKi-St-qym"/>
|
||||
<outlet property="delegate" destination="FeQ-BB-bF5" id="Pbu-nP-u0N"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
<navigationItem key="navigationItem" title="Settings" id="13i-0q-HI5"/>
|
||||
<connections>
|
||||
<outlet property="autoStartMobileCell" destination="iwW-oY-kqV" id="kDV-jT-IBR"/>
|
||||
<outlet property="autoStartWiFiCell" destination="pwi-5Y-UxD" id="UJo-BZ-aXf"/>
|
||||
<outlet property="deviceNameField" destination="iRg-tv-diq" id="ffH-UY-BAT"/>
|
||||
<outlet property="encryptionPublicKeyLabel" destination="P02-mF-z69" id="Yee-Zz-cFd"/>
|
||||
<outlet property="sessionFirewallOtherCell" destination="D0S-Qw-28s" id="Wtm-yf-r4z"/>
|
||||
<outlet property="sessionFirewallOutboundCell" destination="LgH-VV-ofl" id="1hr-Qy-6ip"/>
|
||||
<outlet property="sessionFirewallPeeredCell" destination="SLl-8Z-hnZ" id="rR6-pc-7Jc"/>
|
||||
<outlet property="signingPublicKeyLabel" destination="ISL-Pq-1z4" id="SVQ-aX-N3C"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="eco-Zl-sgd" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="2571" y="1212"/>
|
||||
</scene>
|
||||
<!--Settings-->
|
||||
<scene sceneID="ot0-wd-NE5">
|
||||
<objects>
|
||||
<navigationController title="Settings" id="g4p-RE-Qtl" sceneMemberID="viewController">
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="p6Z-I0-Zza">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<connections>
|
||||
<segue destination="FeQ-BB-bF5" kind="relationship" relationship="rootViewController" id="pga-rT-3Jc"/>
|
||||
</connections>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="tUJ-Lk-YoU" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="2571" y="426"/>
|
||||
</scene>
|
||||
<!--Yggdrasil-->
|
||||
<scene sceneID="zY7-dE-7Ay">
|
||||
<objects>
|
||||
<tableViewController title="Yggdrasil" id="s1Q-pC-XBn" customClass="TableViewController" customModule="YggdrasilNetwork" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="vHG-eF-QEu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
<sections>
|
||||
<tableViewSection footerTitle="You must restart Yggdrasil to make configuration changes effective." id="Jwl-JP-RuU">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="49H-YI-ie3">
|
||||
<rect key="frame" x="0.0" y="18" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="49H-YI-ie3" id="ZPC-T2-kah">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Enable Yggdrasil" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="alk-ml-y9V">
|
||||
<rect key="frame" x="16" y="12" width="127" height="20"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="trailing" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="qre-Dz-rWw">
|
||||
<rect key="frame" x="255" y="7" width="51" height="31"/>
|
||||
<connections>
|
||||
<action selector="toggleVPNStatus:forEvent:" destination="s1Q-pC-XBn" eventType="valueChanged" id="Mvh-gf-qg0"/>
|
||||
</connections>
|
||||
</switch>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="qre-Dz-rWw" firstAttribute="top" secondItem="ZPC-T2-kah" secondAttribute="top" constant="7" id="6Yd-ne-dsL"/>
|
||||
<constraint firstItem="alk-ml-y9V" firstAttribute="top" secondItem="ZPC-T2-kah" secondAttribute="top" constant="12" id="Du8-1c-XP8"/>
|
||||
<constraint firstAttribute="trailing" secondItem="qre-Dz-rWw" secondAttribute="trailing" constant="16" id="SUT-kR-Vtj"/>
|
||||
<constraint firstAttribute="bottom" secondItem="alk-ml-y9V" secondAttribute="bottom" constant="12" id="Sz7-IF-DrB"/>
|
||||
<constraint firstItem="alk-ml-y9V" firstAttribute="leading" secondItem="ZPC-T2-kah" secondAttribute="leading" constant="16" id="kGE-t0-Aph"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" textLabel="dZv-7O-fZv" style="IBUITableViewCellStyleDefault" id="m9f-Bi-XeH">
|
||||
<rect key="frame" x="0.0" y="62" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="m9f-Bi-XeH" id="utU-J9-9M8">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="No active connections" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="dZv-7O-fZv">
|
||||
<rect key="frame" x="16" y="0.0" width="288" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="17"/>
|
||||
<color key="textColor" name="systemRedColor" catalog="System" colorSpace="catalog"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
<tableViewSection headerTitle="Statistics" id="nJf-RJ-qUC">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="0.0" textLabel="MUj-Ni-chU" detailTextLabel="ceY-dc-u9v" style="IBUITableViewCellStyleValue1" id="Ela-vk-pnR">
|
||||
<rect key="frame" x="0.0" y="190" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Ela-vk-pnR" id="fnr-ZG-yiF">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="IP" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="MUj-Ni-chU">
|
||||
<rect key="frame" x="16" y="12" width="15" height="20.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="N/A" textAlignment="right" lineBreakMode="headTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" adjustsFontForContentSizeCategory="YES" id="ceY-dc-u9v" customClass="CopyableLabel" customModule="YggdrasilNetwork" customModuleProvider="target">
|
||||
<rect key="frame" x="275.5" y="12" width="28.5" height="20.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="blue" indentationWidth="10" textLabel="Q8j-k7-HTk" detailTextLabel="MLH-EY-4VQ" style="IBUITableViewCellStyleValue1" id="1BH-o1-n90">
|
||||
<rect key="frame" x="0.0" y="234" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="1BH-o1-n90" id="aLD-3W-BlB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Subnet" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Q8j-k7-HTk">
|
||||
<rect key="frame" x="16" y="12" width="55" height="20.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="N/A" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" id="MLH-EY-4VQ" customClass="CopyableLabel" customModule="YggdrasilNetwork" customModuleProvider="target">
|
||||
<rect key="frame" x="275.5" y="12" width="28.5" height="20.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<color key="textColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" textLabel="9jY-kM-E6n" detailTextLabel="JYJ-ov-02q" style="IBUITableViewCellStyleValue1" id="g00-iP-grJ">
|
||||
<rect key="frame" x="0.0" y="278" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="g00-iP-grJ" id="C21-9O-H5d">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Coordinates" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="9jY-kM-E6n">
|
||||
<rect key="frame" x="16" y="12" width="93" height="20.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="[]" textAlignment="right" lineBreakMode="headTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" adjustsFontForContentSizeCategory="YES" id="JYJ-ov-02q" customClass="CopyableLabel" customModule="YggdrasilNetwork" customModuleProvider="target">
|
||||
<rect key="frame" x="291.5" y="12" width="12.5" height="20.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
<tableViewSection headerTitle="Configuration" id="gRf-Ts-qeJ">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="blue" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="rT6-UD-Cn5" detailTextLabel="vc0-Rq-wtq" style="IBUITableViewCellStyleValue1" id="qRF-c3-JyG">
|
||||
<rect key="frame" x="0.0" y="378" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="qRF-c3-JyG" id="gcO-mr-jgp">
|
||||
<rect key="frame" x="0.0" y="0.0" width="293" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Peers" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="rT6-UD-Cn5">
|
||||
<rect key="frame" x="16" y="12" width="43.5" height="20.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="No peers" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" id="vc0-Rq-wtq">
|
||||
<rect key="frame" x="215.5" y="12" width="69.5" height="20.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<color key="textColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<segue destination="LPj-bu-hdp" kind="showDetail" id="tx6-4f-Vm0"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="blue" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="CPw-Tm-fZl" style="IBUITableViewCellStyleDefault" id="Ugm-vO-zYq">
|
||||
<rect key="frame" x="0.0" y="422" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Ugm-vO-zYq" id="Jkh-no-wta">
|
||||
<rect key="frame" x="0.0" y="0.0" width="293" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Settings" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="CPw-Tm-fZl">
|
||||
<rect key="frame" x="16" y="0.0" width="269" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<segue destination="g4p-RE-Qtl" kind="showDetail" id="hEo-ra-aPX"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
</sections>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="s1Q-pC-XBn" id="ASk-mj-jQP"/>
|
||||
<outlet property="delegate" destination="s1Q-pC-XBn" id="3yd-vi-tqY"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
<navigationItem key="navigationItem" title="Yggdrasil" leftItemsSupplementBackButton="YES" largeTitleDisplayMode="always" id="zEJ-Ur-D8L">
|
||||
<barButtonItem key="backBarButtonItem" title="Status" id="kru-5r-NnH"/>
|
||||
<barButtonItem key="rightBarButtonItem" systemItem="refresh" id="SK1-2o-4fg">
|
||||
<connections>
|
||||
<action selector="onRefreshButton:" destination="s1Q-pC-XBn" id="Tqe-lm-dDv"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
<connections>
|
||||
<outlet property="connectedStatusLabel" destination="dZv-7O-fZv" id="DfM-cR-8VQ"/>
|
||||
<outlet property="statsSelfCoords" destination="JYJ-ov-02q" id="lcM-hA-tsY"/>
|
||||
<outlet property="statsSelfCoordsCell" destination="g00-iP-grJ" id="Ho9-VC-QSe"/>
|
||||
<outlet property="statsSelfIP" destination="ceY-dc-u9v" id="Zob-e3-cVr"/>
|
||||
<outlet property="statsSelfIPCell" destination="Ela-vk-pnR" id="01S-pD-zJc"/>
|
||||
<outlet property="statsSelfPeers" destination="vc0-Rq-wtq" id="usQ-EN-040"/>
|
||||
<outlet property="statsSelfSubnet" destination="MLH-EY-4VQ" id="33U-qS-FUE"/>
|
||||
<outlet property="statsSelfSubnetCell" destination="1BH-o1-n90" id="Njb-oQ-W5C"/>
|
||||
<outlet property="toggleConnect" destination="qre-Dz-rWw" id="Oox-v4-K0x"/>
|
||||
<outlet property="toggleLabel" destination="alk-ml-y9V" id="o4p-Xn-ofm"/>
|
||||
<outlet property="toggleTableView" destination="vHG-eF-QEu" id="iNr-0v-RoB"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Nbt-Cc-GRV" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="2571" y="-338"/>
|
||||
</scene>
|
||||
<!--Yggdrasil-->
|
||||
<scene sceneID="NHm-je-2CC">
|
||||
<objects>
|
||||
<navigationController title="Yggdrasil" id="Dz7-et-ljx" sceneMemberID="viewController">
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="uxo-U2-UUS">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="91"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<toolbar key="toolbar" opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="6hK-6f-rI2">
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</toolbar>
|
||||
<connections>
|
||||
<segue destination="s1Q-pC-XBn" kind="relationship" relationship="rootViewController" id="foA-iq-EPh"/>
|
||||
</connections>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="nYt-zg-2Gb" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1762" y="-337"/>
|
||||
</scene>
|
||||
<!--Split View Controller-->
|
||||
<scene sceneID="9co-Q0-BvB">
|
||||
<objects>
|
||||
<splitViewController modalPresentationStyle="pageSheet" id="sjP-mj-LKX" customClass="SplitViewController" customModule="YggdrasilNetwork" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<connections>
|
||||
<segue destination="Dz7-et-ljx" kind="relationship" relationship="masterViewController" id="QfQ-La-EfI"/>
|
||||
</connections>
|
||||
</splitViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Fe3-ey-WRA" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="811" y="-5"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
52
Yggdrasil Network iOS/UI Components/CopyableLabel.swift
Normal file
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// CopyableLabel.swift
|
||||
// YggdrasilNetwork
|
||||
//
|
||||
// Created by Neil Alexander on 26/02/2019.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class CopyableLabel: UILabel {
|
||||
override public var canBecomeFirstResponder: Bool {
|
||||
get {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
self.isUserInteractionEnabled = true
|
||||
self.addGestureRecognizer(UILongPressGestureRecognizer(
|
||||
target: self,
|
||||
action: #selector(showMenu(sender:))
|
||||
))
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
self.isUserInteractionEnabled = true
|
||||
self.addGestureRecognizer(UILongPressGestureRecognizer(
|
||||
target: self,
|
||||
action: #selector(showMenu(sender:))
|
||||
))
|
||||
}
|
||||
|
||||
override func copy(_ sender: Any?) {
|
||||
UIPasteboard.general.string = text
|
||||
UIMenuController.shared.setMenuVisible(false, animated: true)
|
||||
}
|
||||
|
||||
@objc func showMenu(sender: Any?) {
|
||||
self.becomeFirstResponder()
|
||||
let menu = UIMenuController.shared
|
||||
if !menu.isMenuVisible {
|
||||
menu.setTargetRect(bounds, in: self)
|
||||
menu.setMenuVisible(true, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
|
||||
return (action == #selector(copy(_:)))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
//
|
||||
// ToggleTableViewCell.swift
|
||||
// YggdrasilNetwork
|
||||
//
|
||||
// Created by Neil Alexander on 07/01/2019.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class ToggleTableViewCell: UITableViewCell {
|
||||
|
||||
@IBOutlet weak var label: UILabel!
|
||||
@IBOutlet weak var toggle: UISwitch!
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
// Initialization code
|
||||
}
|
||||
|
||||
override func setSelected(_ selected: Bool, animated: Bool) {
|
||||
super.setSelected(selected, animated: animated)
|
||||
|
||||
// Configure the view for the selected state
|
||||
}
|
||||
|
||||
}
|
312
Yggdrasil Network iOS/View Controllers/PeersViewController.swift
Normal file
|
@ -0,0 +1,312 @@
|
|||
//
|
||||
// PeersViewController.swift
|
||||
// YggdrasilNetwork
|
||||
//
|
||||
// Created by Neil Alexander on 07/01/2019.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import NetworkExtension
|
||||
import CoreTelephony
|
||||
|
||||
class PeersViewController: UITableViewController {
|
||||
var app = UIApplication.shared.delegate as! AppDelegate
|
||||
var config: [String: Any]? = nil
|
||||
|
||||
@IBOutlet var peerTable: UITableView!
|
||||
@IBOutlet weak var addButtonItem: UIBarButtonItem!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
if let proto = self.app.vpnManager.protocolConfiguration as? NETunnelProviderProtocol {
|
||||
config = proto.providerConfiguration ?? nil
|
||||
}
|
||||
|
||||
self.navigationItem.rightBarButtonItems = [
|
||||
self.editButtonItem,
|
||||
self.addButtonItem
|
||||
]
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(self.onYggdrasilPeersUpdated), name: NSNotification.Name.YggdrasilPeersUpdated, object: nil)
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.YggdrasilPeersUpdated, object: nil)
|
||||
}
|
||||
|
||||
@objc func onYggdrasilPeersUpdated(notification: NSNotification) {
|
||||
peerTable.reloadData()
|
||||
}
|
||||
|
||||
// MARK: - Table view data source
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return 3
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
switch section {
|
||||
case 0: return app.yggdrasilSwitchPeers.count
|
||||
case 1:
|
||||
if let config = self.app.yggdrasilConfig {
|
||||
if let peers = config.get("Peers") as? [String] {
|
||||
return peers.count
|
||||
}
|
||||
}
|
||||
return 0
|
||||
case 2:
|
||||
if UIDevice.current.hasCellularCapabilites {
|
||||
return 3
|
||||
}
|
||||
return 2
|
||||
default: return 0
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
switch indexPath.section {
|
||||
case 0:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "discoveredPeerPrototype", for: indexPath)
|
||||
let peers = app.yggdrasilSwitchPeers.sorted { (a, b) -> Bool in
|
||||
return (a["Port"] as! Int) < (b["Port"] as! Int)
|
||||
}
|
||||
|
||||
if indexPath.row < peers.count {
|
||||
let value = peers[indexPath.row]
|
||||
let proto = value["Protocol"] as? String ?? "tcp"
|
||||
let sent = value["BytesSent"] as? Double ?? 0
|
||||
let recvd = value["BytesRecvd"] as? Double ?? 0
|
||||
let rx = self.format(bytes: sent)
|
||||
let tx = self.format(bytes: recvd)
|
||||
|
||||
cell.textLabel?.text = "\(value["Endpoint"] ?? "unknown")"
|
||||
cell.detailTextLabel?.text = "\(proto.uppercased()) peer on port \(value["Port"] ?? "unknown"), sent \(tx), received \(rx)"
|
||||
}
|
||||
return cell
|
||||
case 1:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "configuredPeerPrototype", for: indexPath)
|
||||
if let config = self.app.yggdrasilConfig {
|
||||
if let peers = config.get("Peers") as? [String] {
|
||||
cell.textLabel?.text = peers[indexPath.last!]
|
||||
} else {
|
||||
cell.textLabel?.text = "(unknown)"
|
||||
}
|
||||
}
|
||||
return cell
|
||||
case 2:
|
||||
switch indexPath.last {
|
||||
case 0:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "togglePrototype", for: indexPath) as! ToggleTableViewCell
|
||||
cell.isUserInteractionEnabled = true
|
||||
cell.label?.text = "Search for multicast peers"
|
||||
cell.label?.isEnabled = true
|
||||
cell.toggle?.addTarget(self, action: #selector(toggledMulticast), for: .valueChanged)
|
||||
cell.toggle?.isEnabled = true
|
||||
if let config = self.app.yggdrasilConfig {
|
||||
let interfaces = config.get("MulticastInterfaces") as? [String] ?? []
|
||||
cell.toggle?.isOn = interfaces.contains("en*")
|
||||
}
|
||||
return cell
|
||||
case 1:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "togglePrototype", for: indexPath) as! ToggleTableViewCell
|
||||
cell.isUserInteractionEnabled = false
|
||||
cell.label?.text = "Search for nearby iOS peers"
|
||||
cell.label?.isEnabled = false
|
||||
cell.toggle?.addTarget(self, action: #selector(toggledAWDL), for: .valueChanged)
|
||||
cell.toggle?.setOn(false, animated: false)
|
||||
cell.toggle?.isEnabled = false
|
||||
/*if let config = self.app.yggdrasilConfig {
|
||||
let interfaces = config.get("MulticastInterfaces") as? [String] ?? []
|
||||
cell.toggle?.isOn = interfaces.contains("awdl0")
|
||||
}*/
|
||||
return cell
|
||||
case 2:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "menuPrototype", for: indexPath)
|
||||
cell.isUserInteractionEnabled = true
|
||||
cell.textLabel?.text = "Device settings"
|
||||
cell.textLabel?.isEnabled = true
|
||||
return cell
|
||||
default:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "menuPrototype", for: indexPath)
|
||||
cell.isUserInteractionEnabled = false
|
||||
cell.textLabel?.text = "Unknown"
|
||||
cell.textLabel?.isEnabled = true
|
||||
return cell
|
||||
}
|
||||
default:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "configuredPeerPrototype", for: indexPath)
|
||||
cell.textLabel?.text = "(unknown)"
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
func format(bytes: Double) -> String {
|
||||
guard bytes > 0 else {
|
||||
return "0 bytes"
|
||||
}
|
||||
|
||||
// Adapted from http://stackoverflow.com/a/18650828
|
||||
let suffixes = ["bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
|
||||
let k: Double = 1000
|
||||
let i = floor(log(bytes) / log(k))
|
||||
|
||||
// Format number with thousands separator and everything below 1 GB with no decimal places.
|
||||
let numberFormatter = NumberFormatter()
|
||||
numberFormatter.maximumFractionDigits = i < 3 ? 0 : 1
|
||||
numberFormatter.numberStyle = .decimal
|
||||
|
||||
let numberString = numberFormatter.string(from: NSNumber(value: bytes / pow(k, i))) ?? "Unknown"
|
||||
let suffix = suffixes[Int(i)]
|
||||
return "\(numberString) \(suffix)"
|
||||
}
|
||||
|
||||
@objc func toggledMulticast(_ sender: UISwitch) {
|
||||
if let config = self.app.yggdrasilConfig {
|
||||
var interfaces = config.get("MulticastInterfaces") as! [String]
|
||||
if sender.isOn {
|
||||
interfaces.append("en*")
|
||||
} else {
|
||||
interfaces.removeAll(where: { $0 == "en*" })
|
||||
}
|
||||
config.set("MulticastInterfaces", to: interfaces as [String])
|
||||
try? config.save(to: &app.vpnManager)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func toggledAWDL(_ sender: UISwitch) {
|
||||
if let config = self.app.yggdrasilConfig {
|
||||
var interfaces = config.get("MulticastInterfaces") as! [String]
|
||||
if sender.isOn {
|
||||
interfaces.append("awdl0")
|
||||
} else {
|
||||
interfaces.removeAll(where: { $0 == "awdl0" })
|
||||
}
|
||||
config.set("MulticastInterfaces", to: interfaces as [String])
|
||||
try? config.save(to: &app.vpnManager)
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
switch section {
|
||||
case 0:
|
||||
if self.app.yggdrasilPeers.count > 0 {
|
||||
return "Connected Peers"
|
||||
}
|
||||
return "No peers currently connected"
|
||||
case 1:
|
||||
if let config = self.app.yggdrasilConfig {
|
||||
if let peers = config.get("Peers") as? [String] {
|
||||
if peers.count > 0 {
|
||||
return "Configured Peers"
|
||||
}
|
||||
}
|
||||
}
|
||||
return "No peers currently configured"
|
||||
case 2:
|
||||
return "Peer Connectivity"
|
||||
default: return "(Unknown)"
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
|
||||
switch section {
|
||||
case 1:
|
||||
return "Yggdrasil will automatically attempt to connect to configured peers when started."
|
||||
case 2:
|
||||
var str = "Multicast peers will be discovered on the same Wi-Fi network or via USB."
|
||||
if UIDevice.current.hasCellularCapabilites {
|
||||
str += " Data charges may apply when using mobile data. You can prevent mobile data usage in the device settings."
|
||||
}
|
||||
return str
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
|
||||
return indexPath.first == 1
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
|
||||
switch indexPath.first {
|
||||
case 0:
|
||||
return [UITableViewRowAction(style: UITableViewRowAction.Style.default, title: "Disconnect", handler: { (action, index) in
|
||||
|
||||
})]
|
||||
case 1:
|
||||
return [UITableViewRowAction(style: UITableViewRowAction.Style.normal, title: "Remove", handler: { (action, index) in
|
||||
print(action, index)
|
||||
if let config = self.app.yggdrasilConfig {
|
||||
config.remove(index: index.last!, from: "Peers")
|
||||
do {
|
||||
try config.save(to: &self.app.vpnManager)
|
||||
tableView.reloadSections(IndexSet(integer: 1), with: UITableView.RowAnimation.automatic)
|
||||
} catch {
|
||||
let alert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
|
||||
self.parent?.present(alert, animated: true, completion: nil)
|
||||
print("Error removing: \(error)")
|
||||
}
|
||||
}
|
||||
})]
|
||||
default:
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
switch indexPath.first {
|
||||
case 2:
|
||||
if let last = indexPath.last, last == 2 {
|
||||
UIApplication.shared.open(NSURL(string:UIApplication.openSettingsURLString)! as URL, options: [:]) { (result) in
|
||||
NSLog("Result " + result.description)
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
}
|
||||
|
||||
@IBAction func addNewPeerButtonPressed(_ sender: UIBarButtonItem) {
|
||||
let alert = UIAlertController(title: "Add Configured Peer", message: """
|
||||
Enter the full URI of the peer to add. Yggdrasil will automatically connect to this peer when started.
|
||||
""", preferredStyle: UIAlertController.Style.alert)
|
||||
let action = UIAlertAction(title: "Add", style: .default) { (alertAction) in
|
||||
let textField = alert.textFields![0] as UITextField
|
||||
if let text = textField.text?.trimmingCharacters(in: .whitespacesAndNewlines) {
|
||||
if let config = self.app.yggdrasilConfig {
|
||||
if let peers = config.get("Peers") as? [String], !peers.contains(text) {
|
||||
config.add(text, in: "Peers")
|
||||
do {
|
||||
try config.save(to: &self.app.vpnManager)
|
||||
if let index = config.get("Peers") as? [String] {
|
||||
self.peerTable.insertRows(at: [IndexPath(indexes: [1, index.count-1])], with: .automatic)
|
||||
self.peerTable.reloadSections(IndexSet(integer: 1), with: UITableView.RowAnimation.automatic)
|
||||
}
|
||||
} catch {
|
||||
let alert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
|
||||
self.parent?.present(alert, animated: true, completion: nil)
|
||||
print("Add error: \(error)")
|
||||
}
|
||||
} else {
|
||||
let alert = UIAlertController(title: "Error", message: "Peer already exists", preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
|
||||
self.parent?.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let cancel = UIAlertAction(title: "Cancel", style: .cancel)
|
||||
alert.addTextField { (textField) in
|
||||
textField.placeholder = "tcp://hostname:port"
|
||||
}
|
||||
alert.addAction(action)
|
||||
alert.addAction(cancel)
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
//
|
||||
// SettingsTableViewController.swift
|
||||
// YggdrasilNetwork
|
||||
//
|
||||
// Created by Neil Alexander on 03/01/2019.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import NetworkExtension
|
||||
|
||||
class SettingsViewController: UITableViewController, UIDocumentBrowserViewControllerDelegate {
|
||||
var app = UIApplication.shared.delegate as! AppDelegate
|
||||
|
||||
@IBOutlet weak var deviceNameField: UITextField!
|
||||
|
||||
@IBOutlet weak var encryptionPublicKeyLabel: UILabel!
|
||||
@IBOutlet weak var signingPublicKeyLabel: UILabel!
|
||||
|
||||
@IBOutlet weak var autoStartWiFiCell: UITableViewCell!
|
||||
@IBOutlet weak var autoStartMobileCell: UITableViewCell!
|
||||
|
||||
@IBOutlet weak var sessionFirewallPeeredCell: UITableViewCell!
|
||||
@IBOutlet weak var sessionFirewallOtherCell: UITableViewCell!
|
||||
@IBOutlet weak var sessionFirewallOutboundCell: UITableViewCell!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
if let config = self.app.yggdrasilConfig {
|
||||
deviceNameField.text = config.get("name", inSection: "NodeInfo") as? String ?? ""
|
||||
encryptionPublicKeyLabel.text = config.get("EncryptionPublicKey") as? String ?? "Unknown"
|
||||
signingPublicKeyLabel.text = config.get("SigningPublicKey") as? String ?? "Unknown"
|
||||
|
||||
sessionFirewallPeeredCell.accessoryType = config.get("AllowFromDirect", inSection: "SessionFirewall") as? Bool ?? true ? .checkmark : .none
|
||||
sessionFirewallOtherCell.accessoryType = config.get("AllowFromRemote", inSection: "SessionFirewall") as? Bool ?? true ? .checkmark : .none
|
||||
sessionFirewallOutboundCell.accessoryType = config.get("AlwaysAllowOutbound", inSection: "SessionFirewall") as? Bool ?? true ? .checkmark : .none
|
||||
|
||||
autoStartWiFiCell.accessoryType = config.get("WiFi", inSection: "AutoStart") as? Bool ?? false ? .checkmark : .none
|
||||
autoStartMobileCell.accessoryType = config.get("Mobile", inSection: "AutoStart") as? Bool ?? false ? .checkmark : .none
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func deviceNameEdited(_ sender: UITextField) {
|
||||
if let config = self.app.yggdrasilConfig {
|
||||
config.set("name", inSection: "NodeInfo", to: sender.text)
|
||||
try? config.save(to: &app.vpnManager)
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
switch indexPath.first {
|
||||
case 1:
|
||||
let settings = [
|
||||
"WiFi",
|
||||
"Mobile"
|
||||
]
|
||||
if let cell = tableView.cellForRow(at: indexPath) {
|
||||
cell.accessoryType = cell.accessoryType == .checkmark ? .none : .checkmark
|
||||
if let config = self.app.yggdrasilConfig {
|
||||
config.set(settings[indexPath.last!], inSection: "AutoStart", to: cell.accessoryType == .checkmark)
|
||||
try? config.save(to: &app.vpnManager)
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
let settings = [
|
||||
"AllowFromDirect",
|
||||
"AllowFromRemote",
|
||||
"AlwaysAllowOutbound"
|
||||
]
|
||||
if let cell = tableView.cellForRow(at: indexPath) {
|
||||
cell.accessoryType = cell.accessoryType == .checkmark ? .none : .checkmark
|
||||
if let config = self.app.yggdrasilConfig {
|
||||
config.set(settings[indexPath.last!], inSection: "SessionFirewall", to: cell.accessoryType == .checkmark)
|
||||
try? config.save(to: &app.vpnManager)
|
||||
}
|
||||
}
|
||||
case 4:
|
||||
switch indexPath.last {
|
||||
case 0: // import
|
||||
if #available(iOS 11.0, *) {
|
||||
let open = UIDocumentBrowserViewController(forOpeningFilesWithContentTypes: ["eu.neilalexander.yggdrasil.configuration"])
|
||||
open.delegate = self
|
||||
open.allowsDocumentCreation = false
|
||||
open.allowsPickingMultipleItems = false
|
||||
open.additionalTrailingNavigationBarButtonItems = [ UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelDocumentBrowser)) ]
|
||||
self.present(open, animated: true, completion: nil)
|
||||
} else {
|
||||
let alert = UIAlertController(title: "Import Configuration", message: "Not supported on this version of iOS!", preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
case 1: // export
|
||||
if let config = self.app.yggdrasilConfig, let data = config.data() {
|
||||
var fileURL: URL?
|
||||
var fileDir: URL?
|
||||
do {
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
|
||||
dateFormatter.dateFormat = "yyyy-MM-dd"
|
||||
let date = dateFormatter.string(from: Date())
|
||||
fileDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
|
||||
fileURL = fileDir?.appendingPathComponent("Yggdrasil Backup \(date).yggconf")
|
||||
try? data.write(to: fileURL!)
|
||||
} catch {
|
||||
break
|
||||
}
|
||||
if let dir = fileDir {
|
||||
let sharedurl = dir.absoluteString.replacingOccurrences(of: "file://", with: "shareddocuments://")
|
||||
let furl: URL = URL(string: sharedurl)!
|
||||
UIApplication.shared.open(furl, options: [:], completionHandler: nil)
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
case 5:
|
||||
let alert = UIAlertController(title: "Warning", message: "This operation will reset your configuration and generate new keys. This is not reversible unless your configuration has been exported. Changes will not take effect until the next time Yggdrasil is restarted.", preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "Reset", style: .destructive, handler: { action in
|
||||
self.app.yggdrasilConfig = ConfigurationProxy()
|
||||
if let config = self.app.yggdrasilConfig {
|
||||
try? config.save(to: &self.app.vpnManager)
|
||||
self.viewDidLoad()
|
||||
}}))
|
||||
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
default:
|
||||
break
|
||||
}
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
}
|
||||
|
||||
@objc func cancelDocumentBrowser() {
|
||||
self.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
||||
@available(iOS 11.0, *)
|
||||
func documentBrowser(_ controller: UIDocumentBrowserViewController, didPickDocumentsAt documentURLs: [URL]) {
|
||||
do {
|
||||
if let url = documentURLs.first {
|
||||
let data = try Data(contentsOf: url)
|
||||
let conf = try ConfigurationProxy(json: data)
|
||||
try conf.save(to: &self.app.vpnManager)
|
||||
self.app.yggdrasilConfig = conf
|
||||
|
||||
controller.dismiss(animated: true, completion: nil)
|
||||
let alert = UIAlertController(title: "Import Configuration", message: "Configuration file has been imported.", preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
} catch {
|
||||
controller.dismiss(animated: true, completion: nil)
|
||||
let alert = UIAlertController(title: "Import Failed", message: "Unable to import this configuration file.", preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
self.viewDidLoad()
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// SplitViewController.swift
|
||||
// YggdrasilNetwork
|
||||
//
|
||||
// Created by Neil Alexander on 02/01/2019.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class SplitViewController: UISplitViewController, UISplitViewControllerDelegate {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.delegate = self
|
||||
self.preferredDisplayMode = .allVisible
|
||||
}
|
||||
|
||||
}
|
133
Yggdrasil Network iOS/View Controllers/TableViewController.swift
Normal file
|
@ -0,0 +1,133 @@
|
|||
import UIKit
|
||||
import NetworkExtension
|
||||
import Yggdrasil
|
||||
|
||||
class TableViewController: UITableViewController {
|
||||
var app = UIApplication.shared.delegate as! AppDelegate
|
||||
|
||||
@IBOutlet var connectedStatusLabel: UILabel!
|
||||
|
||||
@IBOutlet var toggleTableView: UITableView!
|
||||
@IBOutlet var toggleLabel: UILabel!
|
||||
@IBOutlet var toggleConnect: UISwitch!
|
||||
|
||||
@IBOutlet weak var statsSelfIPCell: UITableViewCell!
|
||||
@IBOutlet weak var statsSelfSubnetCell: UITableViewCell!
|
||||
@IBOutlet weak var statsSelfCoordsCell: UITableViewCell!
|
||||
|
||||
@IBOutlet var statsSelfIP: UILabel!
|
||||
@IBOutlet var statsSelfSubnet: UILabel!
|
||||
@IBOutlet var statsSelfCoords: UILabel!
|
||||
@IBOutlet var statsSelfPeers: UILabel!
|
||||
|
||||
override func viewDidLoad() {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(self.onYggdrasilSelfUpdated), name: NSNotification.Name.YggdrasilSelfUpdated, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(self.onYggdrasilPeersUpdated), name: NSNotification.Name.YggdrasilPeersUpdated, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(self.onYggdrasilSwitchPeersUpdated), name: NSNotification.Name.YggdrasilSwitchPeersUpdated, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(self.onYggdrasilSettingsUpdated), name: NSNotification.Name.YggdrasilSettingsUpdated, object: nil)
|
||||
}
|
||||
|
||||
@IBAction func onRefreshButton(_ sender: UIButton) {
|
||||
sender.isEnabled = false
|
||||
app.makeIPCRequests()
|
||||
sender.isEnabled = true
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
//NotificationCenter.default.addObserver(self, selector: #selector(TableViewController.VPNStatusDidChange(_:)), name: NSNotification.Name.NEVPNStatusDidChange, object: nil)
|
||||
|
||||
if let row = self.tableView.indexPathForSelectedRow {
|
||||
self.tableView.deselectRow(at: row, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
//NotificationCenter.default.removeObserver(self, name: NSNotification.Name.NEVPNStatusDidChange, object: nil)
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
self.onYggdrasilSelfUpdated(notification: NSNotification.init(name: NSNotification.Name.YggdrasilSettingsUpdated, object: nil))
|
||||
}
|
||||
|
||||
override func viewWillLayoutSubviews() {
|
||||
self.onYggdrasilSelfUpdated(notification: NSNotification.init(name: NSNotification.Name.YggdrasilSettingsUpdated, object: nil))
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
if let row = self.tableView.indexPathForSelectedRow {
|
||||
self.tableView.deselectRow(at: row, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func onYggdrasilSettingsUpdated(notification: NSNotification) {
|
||||
toggleLabel.isEnabled = !app.vpnManager.isOnDemandEnabled
|
||||
toggleConnect.isEnabled = !app.vpnManager.isOnDemandEnabled
|
||||
|
||||
if let footer = toggleTableView.footerView(forSection: 0) {
|
||||
if let label = footer.textLabel {
|
||||
label.text = app.vpnManager.isOnDemandEnabled ? "Yggdrasil will automatically stop and start based on settings." : "You must restart Yggdrasil to make configuration changes effective."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateConnectedStatus() {
|
||||
if self.app.vpnManager.connection.status == .connected {
|
||||
if app.yggdrasilSwitchPeers.count > 0 {
|
||||
connectedStatusLabel.text = "Connected"
|
||||
connectedStatusLabel.textColor = UIColor(red: 0.37, green: 0.79, blue: 0.35, alpha: 1.0)
|
||||
} else {
|
||||
connectedStatusLabel.text = "No active connections"
|
||||
connectedStatusLabel.textColor = UIColor.red
|
||||
}
|
||||
} else {
|
||||
connectedStatusLabel.text = "Not enabled"
|
||||
connectedStatusLabel.textColor = UIColor.systemGray
|
||||
}
|
||||
}
|
||||
|
||||
override func didReceiveMemoryWarning() {
|
||||
super.didReceiveMemoryWarning()
|
||||
}
|
||||
|
||||
@objc func onYggdrasilSelfUpdated(notification: NSNotification) {
|
||||
statsSelfIP.text = app.yggdrasilSelfIP
|
||||
statsSelfSubnet.text = app.yggdrasilSelfSubnet
|
||||
statsSelfCoords.text = app.yggdrasilSelfCoords
|
||||
|
||||
statsSelfIPCell.layoutSubviews()
|
||||
statsSelfSubnetCell.layoutSubviews()
|
||||
statsSelfCoordsCell.layoutSubviews()
|
||||
|
||||
let status = self.app.vpnManager.connection.status
|
||||
toggleConnect.isOn = status == .connecting || status == .connected
|
||||
|
||||
self.updateConnectedStatus()
|
||||
}
|
||||
|
||||
@objc func onYggdrasilSwitchPeersUpdated(notification: NSNotification) {
|
||||
self.updateConnectedStatus()
|
||||
}
|
||||
|
||||
@objc func onYggdrasilPeersUpdated(notification: NSNotification) {
|
||||
let peercount = app.yggdrasilSwitchPeers.count
|
||||
if peercount <= 0 {
|
||||
statsSelfPeers.text = "No peers"
|
||||
} else if peercount == 1 {
|
||||
statsSelfPeers.text = "\(peercount) peer"
|
||||
} else {
|
||||
statsSelfPeers.text = "\(peercount) peers"
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func toggleVPNStatus(_ sender: UISwitch, forEvent event: UIEvent) {
|
||||
if sender.isOn {
|
||||
do {
|
||||
try self.app.vpnManager.connection.startVPNTunnel()
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
} else {
|
||||
self.app.vpnManager.connection.stopVPNTunnel()
|
||||
}
|
||||
}
|
||||
}
|