Skip to content

Commit 34f087c

Browse files
Closes #11
1 parent 66f3d57 commit 34f087c

File tree

6 files changed

+170
-4
lines changed

6 files changed

+170
-4
lines changed

Mission.xcodeproj/project.pbxproj

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
D83A42B127CDE3F700B558B6 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = D83A42B027CDE3F700B558B6 /* KeychainAccess */; };
2323
D8D3D7D427E2C74400BBE755 /* FileSelectDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8D3D7D327E2C74400BBE755 /* FileSelectDialog.swift */; };
2424
D8D4163C27F24FDA005EDF14 /* EditServersDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8D4163B27F24FDA005EDF14 /* EditServersDialog.swift */; };
25+
D8D4163E27F4EEDA005EDF14 /* UpdateDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8D4163D27F4EEDA005EDF14 /* UpdateDialog.swift */; };
26+
D8D4164027F4F089005EDF14 /* GitHub.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8D4163F27F4F089005EDF14 /* GitHub.swift */; };
27+
D8D4164227F53732005EDF14 /* Updater.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8D4164127F53732005EDF14 /* Updater.swift */; };
2528
D8D50C6427EE7AA10074B17C /* ErrorDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8D50C6327EE7AA10074B17C /* ErrorDialog.swift */; };
2629
D8F05BB527D28E320067CB10 /* AlertToast in Frameworks */ = {isa = PBXBuildFile; productRef = D8F05BB427D28E320067CB10 /* AlertToast */; };
2730
D8F05BB927D594D80067CB10 /* AddServerDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F05BB827D594D80067CB10 /* AddServerDialog.swift */; };
@@ -66,6 +69,9 @@
6669
D83A42AD27CBEFAB00B558B6 /* MissionStore.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MissionStore.xcdatamodel; sourceTree = "<group>"; };
6770
D8D3D7D327E2C74400BBE755 /* FileSelectDialog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileSelectDialog.swift; sourceTree = "<group>"; };
6871
D8D4163B27F24FDA005EDF14 /* EditServersDialog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditServersDialog.swift; sourceTree = "<group>"; };
72+
D8D4163D27F4EEDA005EDF14 /* UpdateDialog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateDialog.swift; sourceTree = "<group>"; };
73+
D8D4163F27F4F089005EDF14 /* GitHub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GitHub.swift; sourceTree = "<group>"; };
74+
D8D4164127F53732005EDF14 /* Updater.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Updater.swift; sourceTree = "<group>"; };
6975
D8D50C6327EE7AA10074B17C /* ErrorDialog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorDialog.swift; sourceTree = "<group>"; };
7076
D8F05BB627D2AAA80067CB10 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
7177
D8F05BB827D594D80067CB10 /* AddServerDialog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddServerDialog.swift; sourceTree = "<group>"; };
@@ -169,6 +175,8 @@
169175
children = (
170176
D8217C2327C82EDD009ABA7C /* Transmission.swift */,
171177
D8F05BBC27D5A4920067CB10 /* FileAccess.swift */,
178+
D8D4163F27F4F089005EDF14 /* GitHub.swift */,
179+
D8D4164127F53732005EDF14 /* Updater.swift */,
172180
);
173181
path = Remote;
174182
sourceTree = "<group>";
@@ -182,6 +190,7 @@
182190
D8D3D7D327E2C74400BBE755 /* FileSelectDialog.swift */,
183191
D8D50C6327EE7AA10074B17C /* ErrorDialog.swift */,
184192
D8D4163B27F24FDA005EDF14 /* EditServersDialog.swift */,
193+
D8D4163D27F4EEDA005EDF14 /* UpdateDialog.swift */,
185194
);
186195
path = Views;
187196
sourceTree = "<group>";
@@ -348,6 +357,7 @@
348357
isa = PBXSourcesBuildPhase;
349358
buildActionMask = 2147483647;
350359
files = (
360+
D8D4164027F4F089005EDF14 /* GitHub.swift in Sources */,
351361
D8F05BB927D594D80067CB10 /* AddServerDialog.swift in Sources */,
352362
D8217C2427C82EDD009ABA7C /* Transmission.swift in Sources */,
353363
D8D50C6427EE7AA10074B17C /* ErrorDialog.swift in Sources */,
@@ -358,7 +368,9 @@
358368
D8217BF727C82C7D009ABA7C /* ContentView.swift in Sources */,
359369
D81D47D627D1B58A0050C0B3 /* Store.swift in Sources */,
360370
D8217BF527C82C7D009ABA7C /* MissionApp.swift in Sources */,
371+
D8D4163E27F4EEDA005EDF14 /* UpdateDialog.swift in Sources */,
361372
D83A42AB27CBEF7100B558B6 /* Persistence.swift in Sources */,
373+
D8D4164227F53732005EDF14 /* Updater.swift in Sources */,
362374
D8D4163C27F24FDA005EDF14 /* EditServersDialog.swift in Sources */,
363375
D8F05BBD27D5A4920067CB10 /* FileAccess.swift in Sources */,
364376
);
@@ -521,7 +533,7 @@
521533
CODE_SIGN_IDENTITY = "-";
522534
CODE_SIGN_STYLE = Automatic;
523535
COMBINE_HIDPI_IMAGES = YES;
524-
CURRENT_PROJECT_VERSION = 10;
536+
CURRENT_PROJECT_VERSION = 1;
525537
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
526538
DEVELOPMENT_ASSET_PATHS = "\"Mission/Preview Content\"";
527539
DEVELOPMENT_TEAM = D44Y5BBJ48;
@@ -535,7 +547,7 @@
535547
"$(inherited)",
536548
"@executable_path/../Frameworks",
537549
);
538-
MARKETING_VERSION = 1.5;
550+
MARKETING_VERSION = 1.6;
539551
PRODUCT_BUNDLE_IDENTIFIER = com.jdiggity.Mission;
540552
PRODUCT_NAME = "$(TARGET_NAME)";
541553
SWIFT_EMIT_LOC_STRINGS = YES;
@@ -552,7 +564,7 @@
552564
CODE_SIGN_IDENTITY = "-";
553565
CODE_SIGN_STYLE = Automatic;
554566
COMBINE_HIDPI_IMAGES = YES;
555-
CURRENT_PROJECT_VERSION = 10;
567+
CURRENT_PROJECT_VERSION = 1;
556568
DEVELOPMENT_ASSET_PATHS = "\"Mission/Preview Content\"";
557569
DEVELOPMENT_TEAM = D44Y5BBJ48;
558570
ENABLE_HARDENED_RUNTIME = YES;
@@ -565,7 +577,7 @@
565577
"$(inherited)",
566578
"@executable_path/../Frameworks",
567579
);
568-
MARKETING_VERSION = 1.5;
580+
MARKETING_VERSION = 1.6;
569581
PRODUCT_BUNDLE_IDENTIFIER = com.jdiggity.Mission;
570582
PRODUCT_NAME = "$(TARGET_NAME)";
571583
SWIFT_EMIT_LOC_STRINGS = YES;

Mission/ContentView.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ struct ContentView: View {
3333
AlertToast(type: .loading)
3434
}
3535
.onAppear(perform: {
36+
checkForUpdates()
3637
hosts.forEach { h in
3738
if (h.isDefault) {
3839
var config = TransmissionConfig()
@@ -148,6 +149,12 @@ struct ContentView: View {
148149
store.isError.toggle()
149150
})
150151
})
152+
// Update available dialog
153+
.sheet(isPresented: $store.hasUpdate, content: {
154+
UpdateDialog(changelog: store.latestChangelog, store: store)
155+
.frame(width: 400, height: 500)
156+
157+
})
151158
}
152159

153160
func binding(for torrent: Torrent) -> Binding<Torrent> {

Mission/Remote/GitHub.swift

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//
2+
// GitHub.swift
3+
// Mission
4+
//
5+
// Created by Joe Diragi on 3/30/22.
6+
//
7+
8+
import Foundation
9+
10+
enum GithubError: Error {
11+
case unauthorized
12+
case forbidden
13+
case success
14+
case failed
15+
}
16+
17+
struct Asset: Codable {
18+
var downloadLink: String
19+
20+
enum CodingKeys: String, CodingKey {
21+
case downloadLink = "browser_download_url"
22+
}
23+
}
24+
25+
struct Release: Codable {
26+
var version: String
27+
var changelog: String
28+
var title: String
29+
var assets: [Asset]
30+
31+
enum CodingKeys: String, CodingKey {
32+
case version = "tag_name"
33+
case changelog = "body"
34+
case title = "name"
35+
case assets
36+
}
37+
}
38+
39+
func getLatestRelease(onComplete: @escaping (Release?, Error?) -> Void) {
40+
41+
// Create the request with auth values
42+
var req = URLRequest(url: URL(string: "https://api.github.com/repos/TheNightmanCodeth/Mission/releases/latest")!)
43+
req.httpMethod = "GET"
44+
45+
let task = URLSession.shared.dataTask(with: req) { (data, resp, err) in
46+
if err != nil {
47+
onComplete(nil, err!)
48+
}
49+
50+
let httpResp = resp as? HTTPURLResponse
51+
let code = httpResp?.statusCode
52+
// Call `onAdd` with the status code
53+
switch httpResp?.statusCode {
54+
case 409?: // If we get a 409, save the token and try again
55+
return onComplete(nil, GithubError.unauthorized)
56+
case 401?:
57+
return onComplete(nil, GithubError.forbidden)
58+
case 200?:
59+
let response = try? JSONDecoder().decode(Release.self, from: data!)
60+
print(String(decoding: data!, as: UTF8.self))
61+
return onComplete(response, nil)
62+
default:
63+
return onComplete(nil, GithubError.failed)
64+
}
65+
}
66+
task.resume()
67+
}

Mission/Remote/Updater.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//
2+
// Updater.swift
3+
// Mission
4+
//
5+
// Created by Joe Diragi on 3/30/22.
6+
//
7+
8+
import Foundation
9+
10+
extension ContentView {
11+
func checkForUpdates() {
12+
getLatestRelease(onComplete: { (release, err) in
13+
if (err != nil) {
14+
store.debugBrief = "Error checking for updates"
15+
store.debugMessage = err.debugDescription
16+
store.isError.toggle()
17+
return
18+
}
19+
let appVersionString = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
20+
let appVersion = Double(appVersionString)
21+
let relVersion = Double(release!.version)
22+
// Download release and mount DMG
23+
if (appVersion! < relVersion!) {
24+
DispatchQueue.main.async {
25+
store.latestRelTitle = release!.title
26+
store.latestChangelog = release!.changelog
27+
store.latestRelease = release!.assets[0].downloadLink
28+
store.hasUpdate = true
29+
}
30+
}
31+
})
32+
}
33+
}

Mission/Store.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ class Store: NSObject, ObservableObject {
2828
@Published var transferToSetFiles: Int = 0
2929
@Published var editServers: Bool = false
3030
@Published var successToast: Bool = false
31+
@Published var hasUpdate: Bool = false
32+
@Published var latestRelease: String = ""
33+
@Published var latestRelTitle: String = ""
34+
@Published var latestChangelog: String = ""
3135

3236
@Published var isError: Bool = false
3337
@Published var debugBrief: String = ""

Mission/Views/UpdateDialog.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//
2+
// UpdateDialog.swift
3+
// Mission
4+
//
5+
// Created by Joe Diragi on 3/30/22.
6+
//
7+
8+
import SwiftUI
9+
import System
10+
11+
struct UpdateDialog: View {
12+
@Environment(\.openURL) var openURL
13+
@State var changelog: String
14+
var store: Store
15+
16+
var body: some View {
17+
VStack {
18+
HStack {
19+
Text(store.latestRelTitle)
20+
.padding(.top, 20)
21+
}
22+
ScrollView {
23+
Text(
24+
changelog
25+
).textFieldStyle(RoundedBorderTextFieldStyle())
26+
.padding(.horizontal, 20)
27+
.padding(.bottom, 20)
28+
}
29+
HStack {
30+
Button("Cancel") {
31+
store.hasUpdate.toggle()
32+
}.padding(20)
33+
Spacer()
34+
Button("Get Update") {
35+
openURL(URL(string: store.latestRelease)!)
36+
store.hasUpdate.toggle()
37+
}.padding(20)
38+
.keyboardShortcut(.defaultAction)
39+
}
40+
}
41+
}
42+
}
43+

0 commit comments

Comments
 (0)