summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2015-11-16 14:30:25 -0800
committerAdam Ierymenko <adam.ierymenko@gmail.com>2015-11-16 14:30:25 -0800
commit220552af62cb229d70a62851a35c6b38a0bc3345 (patch)
treedb18925295f023c9fa0a60b1e07d3fae76bdec60
parent637d50a9dee40fd18393d48d232f7a1099424289 (diff)
downloadinfinitytier-220552af62cb229d70a62851a35c6b38a0bc3345.tar.gz
infinitytier-220552af62cb229d70a62851a35c6b38a0bc3345.zip
GitHub issue #241 -- and also some appearance updates. Eventually this might get replaced by a native Mac app.
-rw-r--r--ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Info.plist21
-rwxr-xr-xext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/MacOS/ZeroTier Onebin194640 -> 152736 bytes
-rw-r--r--ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/MainMenu.nibbin25733 -> 25269 bytes
-rw-r--r--ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Window.nibbin3785 -> 3723 bytes
-rw-r--r--ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/_CodeSignature/CodeResources8
-rw-r--r--ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.pbxproj7
-rw-r--r--ext/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.m28
-rw-r--r--ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.m10
-rw-r--r--ext/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Info.plist11
-rw-r--r--ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Window.xib381
-rw-r--r--ui/ZeroTierNetwork.jsx24
-rw-r--r--ui/ZeroTierNode.jsx74
-rw-r--r--ui/zerotier.css98
-rw-r--r--ui/ztui.min.js2
14 files changed, 129 insertions, 535 deletions
diff --git a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Info.plist b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Info.plist
index a11af6d9..c67923c7 100644
--- a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Info.plist
+++ b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Info.plist
@@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
- <string>14E46</string>
+ <string>15B42</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
@@ -22,26 +22,35 @@
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
+ <key>CFBundleSupportedPlatforms</key>
+ <array>
+ <string>MacOSX</string>
+ </array>
<key>CFBundleVersion</key>
<string>1</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
- <string>6E35b</string>
+ <string>7B1005</string>
<key>DTPlatformVersion</key>
<string>GM</string>
<key>DTSDKBuild</key>
- <string>14D125</string>
+ <string>15A278</string>
<key>DTSDKName</key>
- <string>macosx10.10</string>
+ <string>macosx10.11</string>
<key>DTXcode</key>
- <string>0640</string>
+ <string>0711</string>
<key>DTXcodeBuild</key>
- <string>6E35b</string>
+ <string>7B1005</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>
<string>10.7</string>
+ <key>NSAppTransportSecurity</key>
+ <dict>
+ <key>NSAllowsArbitraryLoads</key>
+ <true/>
+ </dict>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
diff --git a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/MacOS/ZeroTier One b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/MacOS/ZeroTier One
index 429efc0b..ba15bca9 100755
--- a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/MacOS/ZeroTier One
+++ b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/MacOS/ZeroTier One
Binary files differ
diff --git a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/MainMenu.nib b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/MainMenu.nib
index 4cd319b2..bac7faa7 100644
--- a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/MainMenu.nib
+++ b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/MainMenu.nib
Binary files differ
diff --git a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Window.nib b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Window.nib
index 559409d9..69258da6 100644
--- a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Window.nib
+++ b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Window.nib
Binary files differ
diff --git a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/_CodeSignature/CodeResources b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/_CodeSignature/CodeResources
index bd79b1f3..14556923 100644
--- a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/_CodeSignature/CodeResources
+++ b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/_CodeSignature/CodeResources
@@ -30,7 +30,7 @@
<dict>
<key>hash</key>
<data>
- kkFJZm0JXF9gTUF2keyMJQ9p9SY=
+ 8JZXf4/3df3LD+o74Y8WM0dV8io=
</data>
<key>optional</key>
<true/>
@@ -39,7 +39,7 @@
<dict>
<key>hash</key>
<data>
- 42zB9+COYMmPW0WlnU1juN2B9SA=
+ 7dgumnPDtoIzhi9QoaFhDvCo9ys=
</data>
<key>optional</key>
<true/>
@@ -73,7 +73,7 @@
<dict>
<key>hash</key>
<data>
- kkFJZm0JXF9gTUF2keyMJQ9p9SY=
+ 8JZXf4/3df3LD+o74Y8WM0dV8io=
</data>
<key>optional</key>
<true/>
@@ -82,7 +82,7 @@
<dict>
<key>hash</key>
<data>
- 42zB9+COYMmPW0WlnU1juN2B9SA=
+ 7dgumnPDtoIzhi9QoaFhDvCo9ys=
</data>
<key>optional</key>
<true/>
diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.pbxproj b/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.pbxproj
index 08d72d06..775c5964 100644
--- a/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.pbxproj
+++ b/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.pbxproj
@@ -269,7 +269,7 @@
FAE451B114BA79C600190544 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0450;
+ LastUpgradeCheck = 0710;
ORGANIZATIONNAME = Twitter;
};
buildConfigurationList = FAE451B414BA79C600190544 /* Build configuration list for PBXProject "MacGap" */;
@@ -374,9 +374,9 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
- ARCHS = "$(ARCHS_STANDARD_64_BIT)";
CLANG_ENABLE_OBJC_ARC = YES;
COPY_PHASE_STRIP = NO;
+ ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
@@ -402,7 +402,6 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
- ARCHS = "$(ARCHS_STANDARD_64_BIT)";
CLANG_ENABLE_OBJC_ARC = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
@@ -434,6 +433,7 @@
GCC_VERSION = "";
INFOPLIST_FILE = "MacGap/MacGap-Info.plist";
MACOSX_DEPLOYMENT_TARGET = 10.7;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.zerotier.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "ZeroTier One";
SDKROOT = macosx;
WRAPPER_EXTENSION = app;
@@ -455,6 +455,7 @@
GCC_VERSION = "";
INFOPLIST_FILE = "MacGap/MacGap-Info.plist";
MACOSX_DEPLOYMENT_TARGET = 10.7;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.zerotier.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "ZeroTier One";
SDKROOT = macosx;
WRAPPER_EXTENSION = app;
diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.m
index 3e25ca13..45923bb3 100644
--- a/ext/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.m
+++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.m
@@ -32,6 +32,7 @@
- (void) applicationDidFinishLaunching:(NSNotification *)aNotification {
char buf[16384],userAuthTokenPath[4096];
+ struct stat systemAuthTokenStat,userAuthTokenStat;
FILE *pf = fopen("/Library/Application Support/ZeroTier/One/zerotier-one.port","r");
long port = 9993; // default
@@ -50,14 +51,27 @@
const char *homeDir = getenv("HOME");
if (homeDir) {
snprintf(userAuthTokenPath,sizeof(userAuthTokenPath),"%s/Library/Application Support/ZeroTier/One/authtoken.secret",homeDir);
- pf = fopen(userAuthTokenPath,"r");
- if (pf) {
- long n = fread(buf,1,sizeof(buf)-1,pf);
- if (n > 0) {
- buf[n] = (char)0;
- snprintf(url,sizeof(url),"http://127.0.0.1:%ld/index.html?authToken=%s",port,buf);
+
+ bool userAuthTokenOutOfDate = false;
+ memset(&systemAuthTokenStat,0,sizeof(systemAuthTokenStat));
+ memset(&userAuthTokenStat,0,sizeof(userAuthTokenStat));
+ if (stat("/Library/Application Support/ZeroTier/One/authtoken.secret",&systemAuthTokenStat) == 0) {
+ if (stat(userAuthTokenPath,&userAuthTokenStat) == 0) {
+ if (userAuthTokenStat.st_mtimespec.tv_sec < systemAuthTokenStat.st_mtimespec.tv_sec)
+ userAuthTokenOutOfDate = true;
+ }
+ }
+
+ if (!userAuthTokenOutOfDate) {
+ pf = fopen(userAuthTokenPath,"r");
+ if (pf) {
+ long n = fread(buf,1,sizeof(buf)-1,pf);
+ if (n > 0) {
+ buf[n] = (char)0;
+ snprintf(url,sizeof(url),"http://127.0.0.1:%ld/index.html?authToken=%s",port,buf);
+ }
+ fclose(pf);
}
- fclose(pf);
}
}
diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.m
index 24e58cd1..6558a191 100644
--- a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.m
+++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.m
@@ -39,11 +39,11 @@
[self.webView setApplicationNameForUserAgent: @"MacGap"];
self.delegate = [[WebViewDelegate alloc] initWithMenu:[NSApp mainMenu]];
- [self.webView setFrameLoadDelegate:self.delegate];
- [self.webView setUIDelegate:self.delegate];
- [self.webView setResourceLoadDelegate:self.delegate];
- [self.webView setDownloadDelegate:self.delegate];
- [self.webView setPolicyDelegate:self.delegate];
+// [self.webView setFrameLoadDelegate:self.delegate];
+// [self.webView setUIDelegate:self.delegate];
+// [self.webView setResourceLoadDelegate:self.delegate];
+// [self.webView setDownloadDelegate:self.delegate];
+// [self.webView setPolicyDelegate:self.delegate];
[self.webView setDrawsBackground:NO];
[self.webView setShouldCloseWithWindow:NO];
diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Info.plist b/ext/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Info.plist
index 7e10a7a6..7f71ea22 100644
--- a/ext/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Info.plist
+++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Info.plist
@@ -2,14 +2,14 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
- <key>CFBundleIconFile</key>
- <string>ZeroTierIcon</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>ZeroTier One</string>
+ <key>CFBundleIconFile</key>
+ <string>ZeroTierIcon</string>
<key>CFBundleIdentifier</key>
- <string>com.zerotier.$(PRODUCT_NAME:rfc1034identifier)</string>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@@ -30,5 +30,10 @@
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
+ <key>NSAppTransportSecurity</key>
+ <dict>
+ <key>NSAllowsArbitraryLoads</key>
+ <true/>
+ </dict>
</dict>
</plist>
diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Window.xib b/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Window.xib
index 70d0c57b..2c46b79f 100644
--- a/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Window.xib
+++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Window.xib
@@ -1,337 +1,44 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
- <data>
- <int key="IBDocument.SystemTarget">1070</int>
- <string key="IBDocument.SystemVersion">11C74</string>
- <string key="IBDocument.InterfaceBuilderVersion">1938</string>
- <string key="IBDocument.AppKitVersion">1138.23</string>
- <string key="IBDocument.HIToolboxVersion">567.00</string>
- <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSArray" key="dict.sortedKeys">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.WebKitIBPlugin</string>
- </object>
- <object class="NSMutableArray" key="dict.values">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>1938</string>
- <string>822</string>
- </object>
- </object>
- <object class="NSArray" key="IBDocument.IntegratedClassDependencies">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>NSWindowTemplate</string>
- <string>NSView</string>
- <string>NSCustomObject</string>
- <string>WebView</string>
- </object>
- <object class="NSArray" key="IBDocument.PluginDependencies">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.WebKitIBPlugin</string>
- </object>
- <object class="NSMutableDictionary" key="IBDocument.Metadata">
- <string key="NS.key.0">PluginDependencyRecalculationVersion</string>
- <integer value="1" key="NS.object.0"/>
- </object>
- <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSCustomObject" id="1001">
- <string key="NSClassName">WindowController</string>
- </object>
- <object class="NSCustomObject" id="1003">
- <string key="NSClassName">FirstResponder</string>
- </object>
- <object class="NSCustomObject" id="1004">
- <string key="NSClassName">NSApplication</string>
- </object>
- <object class="NSWindowTemplate" id="1005">
- <int key="NSWindowStyleMask">15</int>
- <int key="NSWindowBacking">2</int>
- <string key="NSWindowRect">{{196, 240}, {758, 410}}</string>
- <int key="NSWTFlags">544735232</int>
- <string key="NSWindowTitle">Window</string>
- <string key="NSWindowClass">NSWindow</string>
- <nil key="NSViewClass"/>
- <nil key="NSUserInterfaceItemIdentifier"/>
- <object class="NSView" key="NSWindowView" id="1006">
- <reference key="NSNextResponder"/>
- <int key="NSvFlags">256</int>
- <object class="NSMutableArray" key="NSSubviews">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="WebView" id="807146547">
- <reference key="NSNextResponder" ref="1006"/>
- <int key="NSvFlags">274</int>
- <object class="NSMutableSet" key="NSDragTypes">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSArray" key="set.sortedObjects">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>Apple HTML pasteboard type</string>
- <string>Apple PDF pasteboard type</string>
- <string>Apple PICT pasteboard type</string>
- <string>Apple URL pasteboard type</string>
- <string>Apple Web Archive pasteboard type</string>
- <string>NSColor pasteboard type</string>
- <string>NSFilenamesPboardType</string>
- <string>NSStringPboardType</string>
- <string>NeXT RTFD pasteboard type</string>
- <string>NeXT Rich Text Format v1.0 pasteboard type</string>
- <string>NeXT TIFF v4.0 pasteboard type</string>
- <string>WebURLsWithTitlesPboardType</string>
- <string>public.png</string>
- <string>public.url</string>
- <string>public.url-name</string>
- </object>
- </object>
- <string key="NSFrameSize">{758, 410}</string>
- <reference key="NSSuperview" ref="1006"/>
- <reference key="NSWindow"/>
- <reference key="NSNextKeyView"/>
- <int key="NSViewLayerContentsRedrawPolicy">2</int>
- <string key="NSReuseIdentifierKey">_NS:51</string>
- <string key="FrameName"/>
- <string key="GroupName"/>
- <object class="WebPreferences" key="Preferences">
- <string key="Identifier"/>
- <object class="NSMutableDictionary" key="Values">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSArray" key="dict.sortedKeys">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>WebKitDefaultFixedFontSize</string>
- <string>WebKitDefaultFontSize</string>
- <string>WebKitMinimumFontSize</string>
- </object>
- <object class="NSMutableArray" key="dict.values">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <integer value="12"/>
- <integer value="12"/>
- <integer value="1"/>
- </object>
- </object>
- </object>
- <bool key="UseBackForwardList">YES</bool>
- <bool key="AllowsUndo">YES</bool>
- </object>
- </object>
- <string key="NSFrameSize">{758, 410}</string>
- <reference key="NSSuperview"/>
- <reference key="NSWindow"/>
- <reference key="NSNextKeyView" ref="807146547"/>
- </object>
- <string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string>
- <string key="NSMaxSize">{10000000000000, 10000000000000}</string>
- <int key="NSWindowCollectionBehavior">128</int>
- <bool key="NSWindowIsRestorable">YES</bool>
- </object>
- </object>
- <object class="IBObjectContainer" key="IBDocument.Objects">
- <object class="NSMutableArray" key="connectionRecords">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="IBConnectionRecord">
- <object class="IBOutletConnection" key="connection">
- <string key="label">contentView</string>
- <reference key="source" ref="1001"/>
- <reference key="destination" ref="1006"/>
- </object>
- <int key="connectionID">23</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBOutletConnection" key="connection">
- <string key="label">window</string>
- <reference key="source" ref="1001"/>
- <reference key="destination" ref="1005"/>
- </object>
- <int key="connectionID">25</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBBindingConnection" key="connection">
- <string key="label">title: contentView.webView.mainFrameTitle</string>
- <reference key="source" ref="1005"/>
- <reference key="destination" ref="1001"/>
- <object class="NSNibBindingConnector" key="connector">
- <reference key="NSSource" ref="1005"/>
- <reference key="NSDestination" ref="1001"/>
- <string key="NSLabel">title: contentView.webView.mainFrameTitle</string>
- <string key="NSBinding">title</string>
- <string key="NSKeyPath">contentView.webView.mainFrameTitle</string>
- <int key="NSNibBindingConnectorVersion">2</int>
- </object>
- </object>
- <int key="connectionID">31</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBOutletConnection" key="connection">
- <string key="label">webView</string>
- <reference key="source" ref="1006"/>
- <reference key="destination" ref="807146547"/>
- </object>
- <int key="connectionID">19</int>
- </object>
- </object>
- <object class="IBMutableOrderedSet" key="objectRecords">
- <object class="NSArray" key="orderedObjects">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="IBObjectRecord">
- <int key="objectID">0</int>
- <object class="NSArray" key="object" id="1002">
- <bool key="EncodedWithXMLCoder">YES</bool>
- </object>
- <reference key="children" ref="1000"/>
- <nil key="parent"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">-2</int>
- <reference key="object" ref="1001"/>
- <reference key="parent" ref="1002"/>
- <string key="objectName">File's Owner</string>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">-1</int>
- <reference key="object" ref="1003"/>
- <reference key="parent" ref="1002"/>
- <string key="objectName">First Responder</string>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">-3</int>
- <reference key="object" ref="1004"/>
- <reference key="parent" ref="1002"/>
- <string key="objectName">Application</string>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">1</int>
- <reference key="object" ref="1005"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="1006"/>
- </object>
- <reference key="parent" ref="1002"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">2</int>
- <reference key="object" ref="1006"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="807146547"/>
- </object>
- <reference key="parent" ref="1005"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">5</int>
- <reference key="object" ref="807146547"/>
- <reference key="parent" ref="1006"/>
- </object>
- </object>
- </object>
- <object class="NSMutableDictionary" key="flattenedProperties">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSArray" key="dict.sortedKeys">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>-1.IBPluginDependency</string>
- <string>-2.IBPluginDependency</string>
- <string>-3.IBPluginDependency</string>
- <string>1.IBPluginDependency</string>
- <string>1.IBWindowTemplateEditedContentRect</string>
- <string>1.NSWindowTemplate.visibleAtLaunch</string>
- <string>2.CustomClassName</string>
- <string>2.IBPluginDependency</string>
- <string>5.IBPluginDependency</string>
- </object>
- <object class="NSMutableArray" key="dict.values">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{357, 418}, {480, 270}}</string>
- <integer value="1"/>
- <string>ContentView</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.WebKitIBPlugin</string>
- </object>
- </object>
- <object class="NSMutableDictionary" key="unlocalizedProperties">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference key="dict.sortedKeys" ref="1002"/>
- <reference key="dict.values" ref="1002"/>
- </object>
- <nil key="activeLocalization"/>
- <object class="NSMutableDictionary" key="localizations">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference key="dict.sortedKeys" ref="1002"/>
- <reference key="dict.values" ref="1002"/>
- </object>
- <nil key="sourceID"/>
- <int key="maxID">31</int>
- </object>
- <object class="IBClassDescriber" key="IBDocument.Classes">
- <object class="NSMutableArray" key="referencedPartialClassDescriptions">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="IBPartialClassDescription">
- <string key="className">ContentView</string>
- <string key="superclassName">NSView</string>
- <object class="NSMutableDictionary" key="outlets">
- <string key="NS.key.0">webView</string>
- <string key="NS.object.0">WebView</string>
- </object>
- <object class="NSMutableDictionary" key="toOneOutletInfosByName">
- <string key="NS.key.0">webView</string>
- <object class="IBToOneOutletInfo" key="NS.object.0">
- <string key="name">webView</string>
- <string key="candidateClassName">WebView</string>
- </object>
- </object>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBProjectSource</string>
- <string key="minorKey">./Classes/ContentView.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">WebView</string>
- <object class="NSMutableDictionary" key="actions">
- <string key="NS.key.0">reloadFromOrigin:</string>
- <string key="NS.object.0">id</string>
- </object>
- <object class="NSMutableDictionary" key="actionInfosByName">
- <string key="NS.key.0">reloadFromOrigin:</string>
- <object class="IBActionInfo" key="NS.object.0">
- <string key="name">reloadFromOrigin:</string>
- <string key="candidateClassName">id</string>
- </object>
- </object>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBProjectSource</string>
- <string key="minorKey">./Classes/WebView.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">WindowController</string>
- <string key="superclassName">NSWindowController</string>
- <object class="NSMutableDictionary" key="outlets">
- <string key="NS.key.0">contentView</string>
- <string key="NS.object.0">ContentView</string>
- </object>
- <object class="NSMutableDictionary" key="toOneOutletInfosByName">
- <string key="NS.key.0">contentView</string>
- <object class="IBToOneOutletInfo" key="NS.object.0">
- <string key="name">contentView</string>
- <string key="candidateClassName">ContentView</string>
- </object>
- </object>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBProjectSource</string>
- <string key="minorKey">./Classes/WindowController.h</string>
- </object>
- </object>
- </object>
- </object>
- <int key="IBDocument.localizationMode">0</int>
- <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
- <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
- <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
- <integer value="3000" key="NS.object.0"/>
- </object>
- <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
- <int key="IBDocument.defaultPropertyAccessControl">3</int>
- </data>
-</archive>
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
+ <dependencies>
+ <deployment identifier="macosx"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="9060"/>
+ <plugIn identifier="com.apple.WebKitIBPlugin" version="9060"/>
+ </dependencies>
+ <objects>
+ <customObject id="-2" userLabel="File's Owner" customClass="WindowController">
+ <connections>
+ <outlet property="contentView" destination="2" id="23"/>
+ <outlet property="window" destination="1" id="25"/>
+ </connections>
+ </customObject>
+ <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+ <customObject id="-3" userLabel="Application"/>
+ <window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" animationBehavior="default" id="1">
+ <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
+ <rect key="contentRect" x="575" y="564" width="500" height="700"/>
+ <rect key="screenRect" x="0.0" y="0.0" width="1920" height="1178"/>
+ <value key="minSize" type="size" width="500" height="700"/>
+ <value key="maxSize" type="size" width="500" height="700"/>
+ <view key="contentView" id="2" customClass="ContentView">
+ <rect key="frame" x="0.0" y="0.0" width="500" height="700"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <webView id="5">
+ <rect key="frame" x="0.0" y="0.0" width="500" height="700"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <animations/>
+ <webPreferences key="preferences" defaultFontSize="12" defaultFixedFontSize="12"/>
+ </webView>
+ </subviews>
+ <animations/>
+ <connections>
+ <outlet property="webView" destination="5" id="19"/>
+ </connections>
+ </view>
+ <connections>
+ <binding destination="-2" name="title" keyPath="contentView.webView.mainFrameTitle" id="31"/>
+ </connections>
+ </window>
+ </objects>
+</document>
diff --git a/ui/ZeroTierNetwork.jsx b/ui/ZeroTierNetwork.jsx
index 4b37d888..f842d758 100644
--- a/ui/ZeroTierNetwork.jsx
+++ b/ui/ZeroTierNetwork.jsx
@@ -4,19 +4,17 @@ var ZeroTierNetwork = React.createClass({
},
leaveNetwork: function(event) {
- if (confirm("Are you sure you want to leave this network?")) {
- Ajax.call({
- url: 'network/'+this.props.nwid+'?auth='+this.props.authToken,
- cache: false,
- type: 'DELETE',
- success: function(data) {
- if (this.props.onNetworkDeleted)
- this.props.onNetworkDeleted(this.props.nwid);
- }.bind(this),
- error: function(error) {
- }.bind(this)
- });
- }
+ Ajax.call({
+ url: 'network/'+this.props.nwid+'?auth='+this.props.authToken,
+ cache: false,
+ type: 'DELETE',
+ success: function(data) {
+ if (this.props.onNetworkDeleted)
+ this.props.onNetworkDeleted(this.props.nwid);
+ }.bind(this),
+ error: function(error) {
+ }.bind(this)
+ });
event.preventDefault();
},
diff --git a/ui/ZeroTierNode.jsx b/ui/ZeroTierNode.jsx
index 49d73460..b4c29220 100644
--- a/ui/ZeroTierNode.jsx
+++ b/ui/ZeroTierNode.jsx
@@ -122,7 +122,6 @@ var ZeroTierNode = React.createClass({
},
componentDidMount: function() {
- this.tabIndex = 0;
this.updateAll();
this.updateIntervalId = setInterval(this.updateAll,2500);
},
@@ -130,74 +129,19 @@ var ZeroTierNode = React.createClass({
clearInterval(this.updateIntervalId);
},
render: function() {
- /* We implement tabs in a very simple way here with a React JSX conditional. The tabIndex
- * local variable indicates the tab, and switching it determines which set of things we
- * render in the main middle portion. On tab switch calls forceUpdate(). */
return (
<div className="zeroTierNode">
- <div className="top">&nbsp;&nbsp;
- <button disabled={this.tabIndex === 0} onClick={function() {this.tabIndex = 0; this.forceUpdate();}.bind(this)}>Networks</button>
- <button disabled={this.tabIndex === 1} onClick={function() {this.tabIndex = 1; this.forceUpdate();}.bind(this)}>Peers</button>
- </div>
<div className="middle"><div className="middleCell">
<div className="middleScroll">
- {
- (this.tabIndex === 1) ? (
- <div className="peers" key="_peers">
- <div className="peerHeader" key="_peersHeader">
- <div className="f">Address</div>
- <div className="f">Version</div>
- <div className="f">Latency</div>
- <div className="f">Data&nbsp;Paths</div>
- <div className="f">Last&nbsp;Unicast</div>
- <div className="f">Last&nbsp;Multicast</div>
- <div className="f">Role</div>
- </div>
- {
- this.state._peers.map(function(peer) {
- return (
- <div className="peer" key={peer['address']}>
- <div className="f zeroTierAddress">{peer['address']}</div>
- <div className="f">{(peer['version'] === '-1.-1.-1') ? '-' : peer['version']}</div>
- <div className="f">{peer['latency']}</div>
- <div className="f">
- {
- (peer['paths'].length === 0) ? (
- <div className="peerPath"></div>
- ) : (
- <div>
- {
- peer['paths'].map(function(path) {
- var cn = ((path.active)||(path.fixed)) ? (path.preferred ? 'peerPathPreferred' : 'peerPathActive') : 'peerPathInactive';
- return (
- <div className={cn}>{path.address}&nbsp;&nbsp;{this.ago(path.lastSend)}/{this.ago(path.lastReceive)}</div>
- );
- }.bind(this))
- }
- </div>
- )
- }
- </div>
- <div className="f">{this.ago(peer['lastUnicastFrame'])}</div>
- <div className="f">{this.ago(peer['lastMulticastFrame'])}</div>
- <div className="f">{peer['role']}</div>
- </div>
- );
- }.bind(this))
- }
- </div>
- ) : (
- <div className="networks" key="_networks">
- {
- this.state._networks.map(function(network) {
- network['authToken'] = this.props.authToken;
- network['onNetworkDeleted'] = this.handleNetworkDelete;
- return React.createElement('div',{className: 'network',key: network.nwid},React.createElement(ZeroTierNetwork,network));
- }.bind(this))
- }
- </div>
- )
- }
+ <div className="networks" key="_networks">
+ {
+ this.state._networks.map(function(network) {
+ network['authToken'] = this.props.authToken;
+ network['onNetworkDeleted'] = this.handleNetworkDelete;
+ return React.createElement('div',{className: 'network',key: network.nwid},React.createElement(ZeroTierNetwork,network));
+ }.bind(this))
+ }
+ </div>
</div>
</div></div>
<div className="bottom">
diff --git a/ui/zerotier.css b/ui/zerotier.css
index cde5cea8..e5c58838 100644
--- a/ui/zerotier.css
+++ b/ui/zerotier.css
@@ -25,34 +25,6 @@ html,body {
display: table;
}
-.zeroTierNode > .top {
- width: 100%;
- overflow: hidden;
- display: table-row;
- white-space: nowrap;
- background: #234447;
- color: #ffffff;
- padding: 0;
- margin: 0;
-}
-.zeroTierNode > .top button {
- display: inline-block;
- padding: 0.25rem 0.75rem 0.25rem 0.75rem;
- color: #ffffff;
- margin: 0;
- border: 0;
- outline: none;
- background: #234447;
- font-size: 12pt;
- cursor: pointer;
-}
-.zeroTierNode > .top button:hover {
- background: #91a2a3;
-}
-.zeroTierNode > .top button:disabled {
- background: #91a2a3;
-}
-
.zeroTierNode > .middle {
width: 100%;
height: 100%;
@@ -65,6 +37,7 @@ html,body {
width: 100%;
height: 100%;
display: table-cell;
+ border-bottom: 1px solid #000000;
}
.zeroTierNode > .middle > .middleCell > .middleScroll {
display: block;
@@ -87,76 +60,19 @@ html,body {
border-collapse: collapse;
}
.zeroTierNode > .middle > .middleCell > .middleScroll > .networks > .network {
- display: inline-block;
+ display: block;
+ border-top: 0.12rem solid #dddddd;
+ border-bottom: 0.12rem solid #dddddd;
padding: 0.25rem;
- margin: 0.25rem 0 0 1%;
- min-width: 31%;
- max-width: 98%;
- border: 1px solid #234447;
- background: #ffffff;
-}
-.zeroTierNode > .middle > .middleCell > .middleScroll > .peers {
- display: table;
- width: 100%;
- margin: 0;
- border-collapse: collapse;
-}
-.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer {
- width: 100%;
- display: table-row;
background: #ffffff;
}
-.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer:nth-child(odd) {
- background: #f3f3f3;
-}
-.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer:nth-child(even) {
-}
-.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer .peerPathActive {
- font-size: 8pt;
- color: #555555;
- font-style: italic;
- font-family: monospace;
- white-space: nowrap;
-}
-.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer .peerPathPreferred {
- font-size: 8pt;
- color: #000000;
- font-family: monospace;
- white-space: nowrap;
-}
-.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer .peerPathInactive {
- font-size: 8pt;
- font-family: monospace;
- color: #aaaaaa;
- font-style: italic;
- text-decoration: line-through;
- white-space: nowrap;
-}
-.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer > .f {
- display: table-cell;
- padding: 0.05rem 0.15rem 0.05rem 0.15rem;
- font-size: 8pt;
-}
-.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peerHeader {
- width: 100%;
- font-size: 8pt;
- display: table-row;
- background: #ffffff;
- border-bottom: 1px solid #000000;
-}
-.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peerHeader > .f {
- display: table-cell;
- font-size: 8pt;
- padding: 0.05rem 0.15rem 0.05rem 0.15rem;
- font-weight: bold;
-}
.zeroTierNode > .bottom {
font-size: 12pt;
width: 100%;
overflow: hidden;
display: table-row;
- background: #234447;
+ background: #000000;
color: #ffffff;
}
.zeroTierNode > .bottom > .left {
@@ -233,7 +149,7 @@ html,body {
.zeroTierNetwork .networkInfo .networkId {
font-size: 11pt;
font-family: monospace;
- color: #91a2a3;
+ color: #000000;
}
.zeroTierNetwork .networkInfo .networkName {
padding: 0 0 0 1rem;
@@ -271,7 +187,7 @@ html,body {
.zeroTierNetwork .leaveNetworkButton {
padding: 0.25rem 0.5rem 0.25rem 0.5rem;
margin: 0.25rem 0 0 0;
- font-size: 10pt;
+ font-size: 9pt;
background: #ffffff;
outline: none;
background: #ffb354;
diff --git a/ui/ztui.min.js b/ui/ztui.min.js
index dbde7734..17982839 100644
--- a/ui/ztui.min.js
+++ b/ui/ztui.min.js
@@ -1 +1 @@
-var ZeroTierNetwork=React.createClass({displayName:"ZeroTierNetwork",getInitialState:function(){return{}},leaveNetwork:function(e){confirm("Are you sure you want to leave this network?")&&Ajax.call({url:"network/"+this.props.nwid+"?auth="+this.props.authToken,cache:!1,type:"DELETE",success:function(e){this.props.onNetworkDeleted&&this.props.onNetworkDeleted(this.props.nwid)}.bind(this),error:function(e){}.bind(this)}),e.preventDefault()},render:function(){return React.createElement("div",{className:"zeroTierNetwork"},React.createElement("div",{className:"networkInfo"},React.createElement("span",{className:"networkId"},this.props.nwid)," ",React.createElement("span",{className:"networkName"},this.props.name)),React.createElement("div",{className:"networkProps"},React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Status"),React.createElement("div",{className:"value"},this.props.status)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Type"),React.createElement("div",{className:"value"},this.props.type)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"MAC"),React.createElement("div",{className:"value zeroTierAddress"},this.props.mac)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"MTU"),React.createElement("div",{className:"value"},this.props.mtu)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Broadcast"),React.createElement("div",{className:"value"},this.props.broadcastEnabled?"ENABLED":"DISABLED")),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Bridging"),React.createElement("div",{className:"value"},this.props.bridge?"ACTIVE":"DISABLED")),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Device"),React.createElement("div",{className:"value"},this.props.portDeviceName?this.props.portDeviceName:"(none)")),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Managed IPs"),React.createElement("div",{className:"value ipList"},this.props.assignedAddresses.map(function(e){return React.createElement("div",{key:e,className:"ipAddress"},e)})))),React.createElement("button",{type:"button",className:"leaveNetworkButton",onClick:this.leaveNetwork},"Leave Network"))}}); var ZeroTierNode=React.createClass({displayName:"ZeroTierNode",getInitialState:function(){return{address:"----------",online:!1,version:"_._._",_networks:[],_peers:[]}},ago:function(e){if(e>0){var t=Math.round((Date.now()-e)/1e3);return t>0?t:0}return 0},updatePeers:function(){Ajax.call({url:"peer?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(e){var t=JSON.parse(e);Array.isArray(t)&&this.setState({_peers:t})}}.bind(this),error:function(){}.bind(this)})},updateNetworks:function(){Ajax.call({url:"network?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(e){var t=JSON.parse(e);Array.isArray(t)&&this.setState({_networks:t})}}.bind(this),error:function(){}.bind(this)})},updateAll:function(){Ajax.call({url:"status?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(this.alertedToFailure=!1,e){var t=JSON.parse(e);this.setState(t),document.title="ZeroTier One ["+t.address+"]"}this.updateNetworks(),this.updatePeers()}.bind(this),error:function(){this.setState(this.getInitialState()),this.alertedToFailure||(this.alertedToFailure=!0,alert("Authorization token invalid or ZeroTier One service not running."))}.bind(this)})},joinNetwork:function(e){e.preventDefault(),this.networkToJoin&&16===this.networkToJoin.length?Ajax.call({url:"network/"+this.networkToJoin+"?auth="+this.props.authToken,cache:!1,type:"POST",success:function(e){this.networkToJoin="",this.networkInputElement&&(this.networkInputElement.value=""),this.updateNetworks()}.bind(this),error:function(){}.bind(this)}):alert("To join a network, enter its 16-digit network ID.")},handleNetworkIdEntry:function(e){this.networkInputElement=e.target;var t=this.networkInputElement.value;if(t){t=t.toLowerCase();for(var a="",s=0;s<t.length&&16>s;++s)"0123456789abcdef".indexOf(t.charAt(s))>=0&&(a+=t.charAt(s));this.networkToJoin=a,this.networkInputElement.value=a}else this.networkToJoin="",this.networkInputElement.value=""},handleNetworkDelete:function(e){for(var t=[],a=0;a<this.state._networks.length;++a)this.state._networks[a].nwid!==e&&t.push(this.state._networks[a]);this.setState({_networks:t})},componentDidMount:function(){this.tabIndex=0,this.updateAll(),this.updateIntervalId=setInterval(this.updateAll,2500)},componentWillUnmount:function(){clearInterval(this.updateIntervalId)},render:function(){return React.createElement("div",{className:"zeroTierNode"},React.createElement("div",{className:"top"},"  ",React.createElement("button",{disabled:0===this.tabIndex,onClick:function(){this.tabIndex=0,this.forceUpdate()}.bind(this)},"Networks"),React.createElement("button",{disabled:1===this.tabIndex,onClick:function(){this.tabIndex=1,this.forceUpdate()}.bind(this)},"Peers")),React.createElement("div",{className:"middle"},React.createElement("div",{className:"middleCell"},React.createElement("div",{className:"middleScroll"},1===this.tabIndex?React.createElement("div",{className:"peers",key:"_peers"},React.createElement("div",{className:"peerHeader",key:"_peersHeader"},React.createElement("div",{className:"f"},"Address"),React.createElement("div",{className:"f"},"Version"),React.createElement("div",{className:"f"},"Latency"),React.createElement("div",{className:"f"},"Data Paths"),React.createElement("div",{className:"f"},"Last Unicast"),React.createElement("div",{className:"f"},"Last Multicast"),React.createElement("div",{className:"f"},"Role")),this.state._peers.map(function(e){return React.createElement("div",{className:"peer",key:e.address},React.createElement("div",{className:"f zeroTierAddress"},e.address),React.createElement("div",{className:"f"},"-1.-1.-1"===e.version?"-":e.version),React.createElement("div",{className:"f"},e.latency),React.createElement("div",{className:"f"},0===e.paths.length?React.createElement("div",{className:"peerPath"}):React.createElement("div",null,e.paths.map(function(e){var t=e.active||e.fixed?e.preferred?"peerPathPreferred":"peerPathActive":"peerPathInactive";return React.createElement("div",{className:t},e.address,"  ",this.ago(e.lastSend),"/",this.ago(e.lastReceive))}.bind(this)))),React.createElement("div",{className:"f"},this.ago(e.lastUnicastFrame)),React.createElement("div",{className:"f"},this.ago(e.lastMulticastFrame)),React.createElement("div",{className:"f"},e.role))}.bind(this))):React.createElement("div",{className:"networks",key:"_networks"},this.state._networks.map(function(e){return e.authToken=this.props.authToken,e.onNetworkDeleted=this.handleNetworkDelete,React.createElement("div",{className:"network",key:e.nwid},React.createElement(ZeroTierNetwork,e))}.bind(this)))))),React.createElement("div",{className:"bottom"},React.createElement("div",{className:"left"},React.createElement("span",{className:"statusLine"},React.createElement("span",{className:"zeroTierAddress"},this.state.address),"  ",this.state.online?this.state.tcpFallbackActive?"TUNNELED":"ONLINE":"OFFLINE","  ",this.state.version)),React.createElement("div",{className:"right"},React.createElement("form",{onSubmit:this.joinNetwork},React.createElement("input",{type:"text",maxlength:"16",placeholder:"[ Network ID ]",onChange:this.handleNetworkIdEntry,size:"16"}),React.createElement("button",{type:"button",onClick:this.joinNetwork},"Join")))))}});
+var ZeroTierNetwork=React.createClass({displayName:"ZeroTierNetwork",getInitialState:function(){return{}},leaveNetwork:function(e){Ajax.call({url:"network/"+this.props.nwid+"?auth="+this.props.authToken,cache:!1,type:"DELETE",success:function(e){this.props.onNetworkDeleted&&this.props.onNetworkDeleted(this.props.nwid)}.bind(this),error:function(e){}.bind(this)}),e.preventDefault()},render:function(){return React.createElement("div",{className:"zeroTierNetwork"},React.createElement("div",{className:"networkInfo"},React.createElement("span",{className:"networkId"},this.props.nwid)," ",React.createElement("span",{className:"networkName"},this.props.name)),React.createElement("div",{className:"networkProps"},React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Status"),React.createElement("div",{className:"value"},this.props.status)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Type"),React.createElement("div",{className:"value"},this.props.type)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"MAC"),React.createElement("div",{className:"value zeroTierAddress"},this.props.mac)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"MTU"),React.createElement("div",{className:"value"},this.props.mtu)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Broadcast"),React.createElement("div",{className:"value"},this.props.broadcastEnabled?"ENABLED":"DISABLED")),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Bridging"),React.createElement("div",{className:"value"},this.props.bridge?"ACTIVE":"DISABLED")),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Device"),React.createElement("div",{className:"value"},this.props.portDeviceName?this.props.portDeviceName:"(none)")),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Managed IPs"),React.createElement("div",{className:"value ipList"},this.props.assignedAddresses.map(function(e){return React.createElement("div",{key:e,className:"ipAddress"},e)})))),React.createElement("button",{type:"button",className:"leaveNetworkButton",onClick:this.leaveNetwork},"Leave Network"))}}); var ZeroTierNode=React.createClass({displayName:"ZeroTierNode",getInitialState:function(){return{address:"----------",online:!1,version:"_._._",_networks:[],_peers:[]}},ago:function(e){if(e>0){var t=Math.round((Date.now()-e)/1e3);return t>0?t:0}return 0},updatePeers:function(){Ajax.call({url:"peer?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(e){var t=JSON.parse(e);Array.isArray(t)&&this.setState({_peers:t})}}.bind(this),error:function(){}.bind(this)})},updateNetworks:function(){Ajax.call({url:"network?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(e){var t=JSON.parse(e);Array.isArray(t)&&this.setState({_networks:t})}}.bind(this),error:function(){}.bind(this)})},updateAll:function(){Ajax.call({url:"status?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(this.alertedToFailure=!1,e){var t=JSON.parse(e);this.setState(t),document.title="ZeroTier One ["+t.address+"]"}this.updateNetworks(),this.updatePeers()}.bind(this),error:function(){this.setState(this.getInitialState()),this.alertedToFailure||(this.alertedToFailure=!0,alert("Authorization token invalid or ZeroTier One service not running."))}.bind(this)})},joinNetwork:function(e){e.preventDefault(),this.networkToJoin&&16===this.networkToJoin.length?Ajax.call({url:"network/"+this.networkToJoin+"?auth="+this.props.authToken,cache:!1,type:"POST",success:function(e){this.networkToJoin="",this.networkInputElement&&(this.networkInputElement.value=""),this.updateNetworks()}.bind(this),error:function(){}.bind(this)}):alert("To join a network, enter its 16-digit network ID.")},handleNetworkIdEntry:function(e){this.networkInputElement=e.target;var t=this.networkInputElement.value;if(t){t=t.toLowerCase();for(var n="",a=0;a<t.length&&16>a;++a)"0123456789abcdef".indexOf(t.charAt(a))>=0&&(n+=t.charAt(a));this.networkToJoin=n,this.networkInputElement.value=n}else this.networkToJoin="",this.networkInputElement.value=""},handleNetworkDelete:function(e){for(var t=[],n=0;n<this.state._networks.length;++n)this.state._networks[n].nwid!==e&&t.push(this.state._networks[n]);this.setState({_networks:t})},componentDidMount:function(){this.updateAll(),this.updateIntervalId=setInterval(this.updateAll,2500)},componentWillUnmount:function(){clearInterval(this.updateIntervalId)},render:function(){return React.createElement("div",{className:"zeroTierNode"},React.createElement("div",{className:"middle"},React.createElement("div",{className:"middleCell"},React.createElement("div",{className:"middleScroll"},React.createElement("div",{className:"networks",key:"_networks"},this.state._networks.map(function(e){return e.authToken=this.props.authToken,e.onNetworkDeleted=this.handleNetworkDelete,React.createElement("div",{className:"network",key:e.nwid},React.createElement(ZeroTierNetwork,e))}.bind(this)))))),React.createElement("div",{className:"bottom"},React.createElement("div",{className:"left"},React.createElement("span",{className:"statusLine"},React.createElement("span",{className:"zeroTierAddress"},this.state.address),"  ",this.state.online?this.state.tcpFallbackActive?"TUNNELED":"ONLINE":"OFFLINE","  ",this.state.version)),React.createElement("div",{className:"right"},React.createElement("form",{onSubmit:this.joinNetwork},React.createElement("input",{type:"text",maxlength:"16",placeholder:"[ Network ID ]",onChange:this.handleNetworkIdEntry,size:"16"}),React.createElement("button",{type:"button",onClick:this.joinNetwork},"Join")))))}});