-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathApp.swift
148 lines (125 loc) · 4.26 KB
/
App.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import Foundation
import Cocoa
import RxSwift
struct DownloadProgress: Equatable {
let current: UInt64
let total: UInt64
init(_ a: UInt64, _ b: UInt64) {
current = a
total = b
}
}
enum TransactionProcessState: Equatable {
case downloading(state: [PackageKey: DownloadProgress])
case installing(current: PackageKey)
case completed
static func defaultDownloading(for actions: [ResolvedAction], current: UInt64 = 0, total: UInt64 = 0) -> TransactionProcessState {
var out = [PackageKey: DownloadProgress]()
for action in actions {
if action.action.action == .install {
out[action.action.key] = DownloadProgress(current, total)
}
}
return .downloading(state: out)
}
}
struct TransactionProgressState: Equatable {
let actions: [ResolvedAction]
let isRebootRequired: Bool
private(set) var state: TransactionProcessState
func copy(with state: TransactionProcessState) -> TransactionProgressState {
var copied = self
copied.state = state
return copied
}
}
enum TransactionState: Equatable {
case notStarted
case inProgress(TransactionProgressState)
case error(String)
var isNotStarted: Bool {
switch self {
case .notStarted:
return true
default:
return false
}
}
var isInProgress: Bool {
switch self {
case .inProgress:
return true
default:
return false
}
}
var isError: Bool {
switch self {
case .error:
return true
default:
return false
}
}
func reduce(event: TransactionEvent) -> TransactionState {
switch event {
case let .transactionStarted(actions, isRebootRequired):
return TransactionState.inProgress(TransactionProgressState(
actions: actions,
isRebootRequired: isRebootRequired,
state: .defaultDownloading(for: actions)))
case let .downloadProgress(key, current, total):
if case let .inProgress(progress) = self {
if case let .downloading(dl) = progress.state {
var map = dl
map[key] = DownloadProgress(current, total)
return .inProgress(progress.copy(with: .downloading(state: map)))
}
}
case let .installStarted(packageKey: key), let .uninstallStarted(packageKey: key):
if case let .inProgress(progress) = self {
return .inProgress(progress.copy(with: .installing(current: key)))
}
case .transactionComplete:
if case let .inProgress(progress) = self {
return .inProgress(progress.copy(with: .completed))
}
case let .transactionError(packageKey: _, error: message):
return .error(message ?? Strings.downloadError)
// We don't need to handle these two
case .downloadComplete, .transactionProgress, .transactionQueued:
break
}
return self
}
}
var AppContext: AppContextImpl!
class App: NSApplication {
private lazy var appDelegate = AppDelegate()
override init() {
super.init()
let _ = log
self.delegate = appDelegate
do {
AppContext = try AppContextImpl()
} catch let error {
// TODO: show an NSAlert to the user indicating the actual problem and how to fix it
fatalError("\(error)")
}
let language: String? = AppContext.settings.read(key: .language)
log.debug("Setting default language: \(String(describing: language))")
if let language = language {
UserDefaults.standard.set([language], forKey: "AppleLanguages")
} else {
UserDefaults.standard.removeObject(forKey: "AppleLanguages")
}
UserDefaults.standard.synchronize()
}
override func terminate(_ sender: Any?) {
AppContext = nil
super.terminate(sender)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}