Skip to content

Commit 51967d7

Browse files
committed
change versions
1 parent 5a0de14 commit 51967d7

10 files changed

Lines changed: 235 additions & 21 deletions

File tree

mac/Base.lproj/Main.storyboard

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,7 @@
718718
<textField key="view" horizontalHuggingPriority="251" verticalHuggingPriority="750" id="sma-bh-gC0">
719719
<rect key="frame" x="0.0" y="14" width="204" height="17"/>
720720
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
721-
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Current Version: Node.js 8.10.0" id="5Fm-KL-l2e">
721+
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Current Version" id="5Fm-KL-l2e">
722722
<font key="font" metaFont="system"/>
723723
<color key="textColor" name="controlDarkShadowColor" catalog="System" colorSpace="catalog"/>
724724
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
@@ -816,7 +816,7 @@
816816
</textFieldCell>
817817
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
818818
<prototypeCellViews>
819-
<tableCellView id="qgf-8d-cAX">
819+
<tableCellView identifier="VERSION_CELL" id="qgf-8d-cAX">
820820
<rect key="frame" x="1" y="1" width="116" height="17"/>
821821
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
822822
<subviews>
@@ -849,7 +849,7 @@
849849
</textFieldCell>
850850
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
851851
<prototypeCellViews>
852-
<tableCellView id="Mjn-om-FRo">
852+
<tableCellView identifier="DATE_CELL" id="Mjn-om-FRo">
853853
<rect key="frame" x="120" y="1" width="100" height="17"/>
854854
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
855855
<subviews>
@@ -870,7 +870,7 @@
870870
</prototypeCellViews>
871871
</tableColumn>
872872
<tableColumn width="200" minWidth="40" maxWidth="1000" id="FCK-MN-vb2">
873-
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Action">
873+
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
874874
<font key="font" metaFont="smallSystem"/>
875875
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
876876
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
@@ -882,7 +882,7 @@
882882
</textFieldCell>
883883
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
884884
<prototypeCellViews>
885-
<tableCellView id="sbF-al-GT5">
885+
<tableCellView identifier="ACTION_CELL" id="sbF-al-GT5">
886886
<rect key="frame" x="223" y="1" width="200" height="17"/>
887887
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
888888
<subviews>
@@ -903,6 +903,11 @@
903903
</prototypeCellViews>
904904
</tableColumn>
905905
</tableColumns>
906+
<connections>
907+
<action trigger="doubleAction" selector="doubleClick:" target="lJa-C7-a57" id="BHP-js-7ib"/>
908+
<outlet property="dataSource" destination="lJa-C7-a57" id="5ce-jC-WUF"/>
909+
<outlet property="delegate" destination="lJa-C7-a57" id="yzA-Vq-Hqa"/>
910+
</connections>
906911
</tableView>
907912
</subviews>
908913
</clipView>
@@ -966,6 +971,7 @@
966971
</customView>
967972
<connections>
968973
<outlet property="emptyBox" destination="XhX-17-J3n" id="6q1-YI-pSt"/>
974+
<outlet property="versionView" destination="UbR-P8-ihK" id="13B-4S-U2q"/>
969975
</connections>
970976
</viewController>
971977
<customObject id="J57-eZ-a42" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
@@ -1162,7 +1168,7 @@
11621168
</textFieldCell>
11631169
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
11641170
<prototypeCellViews>
1165-
<tableCellView id="edq-6e-xy3">
1171+
<tableCellView identifier="DOWNLOAD_CELL" id="edq-6e-xy3">
11661172
<rect key="frame" x="290" y="1" width="64" height="17"/>
11671173
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
11681174
<subviews>
@@ -1184,13 +1190,14 @@
11841190
</tableColumn>
11851191
</tableColumns>
11861192
<connections>
1193+
<action trigger="doubleAction" selector="doubleClick:" target="zfF-Kx-ABF" id="MyX-Le-jeP"/>
11871194
<outlet property="dataSource" destination="zfF-Kx-ABF" id="a0C-O5-oA7"/>
11881195
<outlet property="delegate" destination="zfF-Kx-ABF" id="LMq-eh-Ft3"/>
11891196
</connections>
11901197
</tableView>
11911198
</subviews>
11921199
</clipView>
1193-
<scroller key="horizontalScroller" wantsLayer="YES" verticalHuggingPriority="750" doubleValue="0.97014925373134331" horizontal="YES" id="Dfq-nP-3hp">
1200+
<scroller key="horizontalScroller" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="Dfq-nP-3hp">
11941201
<rect key="frame" x="0.0" y="284" width="289" height="16"/>
11951202
<autoresizingMask key="autoresizingMask"/>
11961203
</scroller>

mac/DownloadViewController.swift

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class DownloadViewController: NSSplitViewController,
2222
fileprivate enum CellIdentifiers {
2323
static let VersionCell = "VERSION_CELL"
2424
static let DateCell = "DATE_CELL"
25+
static let DownloadCell = "DOWNLOAD_CELL"
2526
}
2627

2728
var store: Store?;
@@ -31,10 +32,11 @@ class DownloadViewController: NSSplitViewController,
3132
super.viewDidLoad()
3233
sidebarView.expandItem(rootElement)
3334
self.initStore()
35+
3436
}
3537

3638
/**
37-
* Prepare the downloadable version list for the app
39+
* Prepare the store for download list
3840
*/
3941
func initStore() {
4042
Store.getStore { (s) -> Void in
@@ -133,7 +135,16 @@ class DownloadViewController: NSSplitViewController,
133135
text = item.date
134136
identifier = CellIdentifiers.DateCell
135137
} else if tableColumn == tableView.tableColumns[2] {
136-
138+
if item.isDownloading {
139+
text = String(format: "%.0f%%", item.percentage)
140+
} else if item.isDownloaded {
141+
text = "Downloaded"
142+
} else if item.isError {
143+
text = "Error, try again"
144+
} else {
145+
text = "Double click to download"
146+
}
147+
identifier = CellIdentifiers.DownloadCell
137148
}
138149

139150
if let cell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: identifier), owner: nil) as? NSTableCellView {
@@ -143,4 +154,20 @@ class DownloadViewController: NSSplitViewController,
143154

144155
return nil
145156
}
157+
158+
@IBAction func doubleClick(_ sender: NSTableView) {
159+
if sender.clickedRow > -1 {
160+
if let version = currentList?[ sender.clickedRow ] {
161+
if version.isDownloading || version.isDownloaded {
162+
print("no action")
163+
} else {
164+
version.download {
165+
self.tableView.reloadData()
166+
}
167+
}
168+
}
169+
} else {
170+
print("no row clicked")
171+
}
172+
}
146173
}

mac/Store.swift

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import Alamofire
1212
let VERSION_URL = "https://raw.githubusercontent.com/learning/node-box/master/data.json"
1313

1414
class Store {
15-
static private var directory: URL? = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first?.appendingPathComponent(Bundle.main.bundleIdentifier!, isDirectory: true)
1615
static private var store:Store? = nil;
1716

1817
var branches:Array<Branch>;
@@ -21,6 +20,18 @@ class Store {
2120
init(data: Dictionary<String, Any>) {
2221
self.branches = (data["branches"] as! Array<Dictionary<String, String>>).map { Branch(data: $0) }
2322
self.versions = (data["versions"] as! Array<Dictionary<String, Any>>).map { Version(data: $0) }
23+
do {
24+
let files = try FileManager.default.contentsOfDirectory(at: Utils.directory!, includingPropertiesForKeys: nil)
25+
let dirs = files.filter { $0.hasDirectoryPath }
26+
.map { $0.path.components(separatedBy: "/").last }
27+
dirs.forEach { dir in
28+
versions.first(where: { $0.filename == dir })?.isDownloaded = true
29+
}
30+
} catch {
31+
NotificationCenter.default.post(name: Notification.Name("alert"), object: "Error: list node.js downloaded versions")
32+
}
33+
let ver = Utils.runAndGetOutput("readlink", "current")?.trimmingCharacters(in: NSCharacterSet.newlines)
34+
versions.first(where: { $0.filename == ver })?.isActive = true
2435
}
2536

2637
static public func getStore(onSuccess success: @escaping (Store) -> Void) {
@@ -60,7 +71,7 @@ class Store {
6071
* - name: The file's name
6172
*/
6273
static private func getFile(name: String) -> URL? {
63-
if let pathComponent = directory?.appendingPathComponent(name) {
74+
if let pathComponent = Utils.directory?.appendingPathComponent(name) {
6475
let filePath = pathComponent.path
6576
let fileManager = FileManager.default
6677
if fileManager.fileExists(atPath: filePath) {
@@ -82,15 +93,15 @@ class Store {
8293
*/
8394
static private func writeFile(name: String, content: String) -> Bool {
8495
// If directory not exists, create it
85-
if !FileManager.default.fileExists(atPath: (directory?.path)!) {
96+
if !FileManager.default.fileExists(atPath: (Utils.directory?.path)!) {
8697
do {
87-
try FileManager.default.createDirectory(at: directory!, withIntermediateDirectories: false, attributes: nil)
98+
try FileManager.default.createDirectory(at: Utils.directory!, withIntermediateDirectories: false, attributes: nil)
8899
} catch {
89-
print("Create directory \(directory!.path) failed")
100+
print("Create directory \(Utils.directory!.path) failed")
90101
return false
91102
}
92103
}
93-
let file: URL? = directory?.appendingPathComponent(name)
104+
let file: URL? = Utils.directory?.appendingPathComponent(name)
94105
if file != nil {
95106
do {
96107
try content.write(to: file!, atomically: false, encoding: String.Encoding.utf8)
@@ -122,10 +133,10 @@ class Store {
122133
if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
123134
// Write json to file
124135
if writeFile(name: "data.json", content: utf8Text) {
125-
print("Wrote to \(directory!.path) success!")
136+
print("Wrote to \(Utils.directory!.path) success!")
126137
success()
127138
} else {
128-
NotificationCenter.default.post(name: Notification.Name("alert"), object: "wrote to \(directory!.path) failed")
139+
NotificationCenter.default.post(name: Notification.Name("alert"), object: "wrote to \(Utils.directory!.path) failed")
129140
}
130141
}
131142
}

mac/Utils.swift

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//
2+
// Utils.swift
3+
// node-box
4+
//
5+
// Created by Learning on 2019/1/25.
6+
// Copyright © 2019 Learning. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
class Utils {
12+
static var directory: URL? = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first?.appendingPathComponent(Bundle.main.bundleIdentifier!, isDirectory: true)
13+
14+
static public func run(_ args: String...) -> Int32 {
15+
let task = Process()
16+
task.launchPath = "/usr/bin/env"
17+
task.arguments = args
18+
task.currentDirectoryPath = directory!.path
19+
task.launch()
20+
task.waitUntilExit()
21+
return task.terminationStatus
22+
}
23+
24+
static public func runAndGetOutput(_ args: String...) -> String?
25+
{
26+
let task = Process()
27+
task.launchPath = "/usr/bin/env"
28+
task.arguments = args
29+
task.currentDirectoryPath = directory!.path
30+
31+
let pipe = Pipe()
32+
task.standardOutput = pipe
33+
task.launch()
34+
35+
let data = pipe.fileHandleForReading.readDataToEndOfFile()
36+
let output = String(data: data, encoding: String.Encoding.utf8)
37+
38+
return output
39+
}
40+
}

mac/Version.swift

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,20 @@
77
//
88

99
import Foundation
10+
import Alamofire
1011

1112
class Version {
1213
var version:String
1314
var npmVersion:String
1415
var v8Version:String
1516
var nodeModuleVersion:String
1617
var url:String
18+
var filename:String
1719
var date:String
1820
var isDownloaded:Bool
1921
var isDownloading:Bool
20-
var percentage:Float
22+
var isError:Bool
23+
var percentage:Double
2124
var isActive:Bool
2225

2326
init(data: Dictionary<String, Any>) {
@@ -26,10 +29,51 @@ class Version {
2629
self.v8Version = data["v8"] as? String ?? ""
2730
self.nodeModuleVersion = data["node-module-version"] as? String ?? ""
2831
self.url = (data["url"] as! Dictionary<String, String>)["darwin"] ?? ""
32+
self.filename = String((self.url.split(separator: "/").last?.dropLast(7))!)
2933
self.date = data["date"] as? String ?? ""
3034
self.isDownloaded = false
3135
self.isDownloading = false
36+
self.isError = false
3237
self.percentage = 0
3338
self.isActive = false
3439
}
40+
41+
func download (onProgress progress: @escaping () -> Void) {
42+
self.isDownloading = true
43+
self.percentage = 0
44+
progress()
45+
let destination: DownloadRequest.DownloadFileDestination = { _, _ in
46+
let documentsURL = Utils.directory!
47+
let fileURL = documentsURL.appendingPathComponent(self.filename + ".tar.xz")
48+
49+
return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
50+
}
51+
Alamofire.download(self.url, to: destination)
52+
.downloadProgress { p in
53+
self.percentage = p.fractionCompleted * 100
54+
progress()
55+
}
56+
.responseData { r in
57+
self.isDownloading = false
58+
if self.untar() == 0 {
59+
self.percentage = 100
60+
self.isDownloaded = true
61+
progress()
62+
} else {
63+
self.isError = true
64+
self.percentage = 0
65+
self.isDownloaded = false
66+
progress()
67+
}
68+
69+
}
70+
}
71+
72+
func untar() -> Int32 {
73+
let res = Utils.run("tar", "xf", self.filename + ".tar.xz")
74+
if res == 0 {
75+
return Utils.run("rm", self.filename + ".tar.xz")
76+
}
77+
return res
78+
}
3579
}

0 commit comments

Comments
 (0)