Skip to content

Commit d380106

Browse files
committed
Return success from SelfUpdater.update
Change SelfUpdater.update to return a Bool indicating whether the install/relaunch succeeded (true) or failed (false). Update AccountsViewModel.installUpdate to await that result and only record the rolling release timestamp after a successful install; remove the pre-install timestamp recording. This ensures rolling timestamps are only recorded on successful updates.
1 parent cc02196 commit d380106

3 files changed

Lines changed: 25 additions & 8 deletions

File tree

CodexAccounts/Services/SelfUpdater.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ enum SelfUpdater {
2727
static func update(
2828
dmgURL: URL,
2929
onStateChange: @escaping @MainActor (SelfUpdateState) -> Void
30-
) async {
30+
) async -> Bool {
3131
do {
3232
// 1 — Download
3333
await MainActor.run { onStateChange(.downloading(progress: 0)) }
@@ -54,9 +54,11 @@ enum SelfUpdater {
5454

5555
// 7 — Relaunch
5656
relaunchApp(at: runningAppURL)
57+
return true
5758

5859
} catch {
5960
await MainActor.run { onStateChange(.failed(error.localizedDescription)) }
61+
return false
6062
}
6163
}
6264

CodexAccounts/Services/UpdateChecker.swift

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,13 @@ enum UpdateChecker {
6060
if let latest = releases.first(where: { $0.tagName == "latest" }),
6161
let publishedAt = latest.publishedAt {
6262
let baseline = max(buildTimestamp, lastInstalledRollingTimestamp)
63-
if baseline > 0 && publishedAt > baseline + 60 {
63+
let releaseVersion = version(from: latest.name)
64+
if releaseVersion.map({ isNewer($0, than: currentVersion) }) == true
65+
|| (baseline > 0 && publishedAt > baseline + 60)
66+
{
6467
// Remote is at least 1 min newer — a real push happened
6568
return UpdateInfo(
66-
version: "latest",
69+
version: releaseVersion ?? "latest",
6770
tagName: "latest",
6871
releaseURL: URL(string: latest.htmlURL) ?? releasesPage,
6972
downloadURL: preferredDMGURL(in: latest),
@@ -112,6 +115,16 @@ enum UpdateChecker {
112115
return s
113116
}
114117

118+
private static func version(from text: String?) -> String? {
119+
guard let text else { return nil }
120+
let pattern = #"\b(\d+)\.(\d+)\.(\d+)\b"#
121+
guard let regex = try? NSRegularExpression(pattern: pattern),
122+
let match = regex.firstMatch(in: text, range: NSRange(text.startIndex..., in: text)),
123+
let range = Range(match.range, in: text)
124+
else { return nil }
125+
return String(text[range])
126+
}
127+
115128
private static func isNewer(_ a: String, than b: String) -> Bool {
116129
let av = a.split(separator: ".").compactMap { Int($0) }
117130
let bv = b.split(separator: ".").compactMap { Int($0) }
@@ -134,6 +147,7 @@ enum UpdateChecker {
134147

135148
private struct GitHubRelease: Decodable {
136149
let tagName: String
150+
let name: String?
137151
let htmlURL: String
138152
let draft: Bool
139153
let prerelease: Bool
@@ -143,6 +157,7 @@ private struct GitHubRelease: Decodable {
143157

144158
enum CodingKeys: String, CodingKey {
145159
case tagName = "tag_name"
160+
case name
146161
case htmlURL = "html_url"
147162
case draft, prerelease, body
148163
case publishedAt = "published_at"
@@ -152,6 +167,7 @@ private struct GitHubRelease: Decodable {
152167
init(from decoder: Decoder) throws {
153168
let c = try decoder.container(keyedBy: CodingKeys.self)
154169
tagName = try c.decode(String.self, forKey: .tagName)
170+
name = try c.decodeIfPresent(String.self, forKey: .name)
155171
htmlURL = try c.decode(String.self, forKey: .htmlURL)
156172
draft = try c.decode(Bool.self, forKey: .draft)
157173
prerelease = try c.decode(Bool.self, forKey: .prerelease)

CodexAccounts/ViewModels/AccountsViewModel.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -533,16 +533,15 @@ final class AccountsViewModel {
533533
func installUpdate() {
534534
guard let update = availableUpdate, let dmgURL = update.downloadURL else { return }
535535

536-
if update.isRolling, let ts = update.publishedAt {
537-
UpdateChecker.recordInstalledRollingTimestamp(ts)
538-
}
539-
540536
Task {
541-
await SelfUpdater.update(dmgURL: dmgURL) { [weak self] state in
537+
let didInstall = await SelfUpdater.update(dmgURL: dmgURL) { [weak self] state in
542538
Task { @MainActor in
543539
self?.selfUpdateState = state
544540
}
545541
}
542+
if didInstall, update.isRolling, let ts = update.publishedAt {
543+
UpdateChecker.recordInstalledRollingTimestamp(ts)
544+
}
546545
}
547546
}
548547

0 commit comments

Comments
 (0)