From 32d964367c35cee27fe93abaa52e259944f2d1af Mon Sep 17 00:00:00 2001 From: Janez Troha Date: Wed, 29 Dec 2021 14:14:31 +0100 Subject: [PATCH] Add auto updater --- Work Hours/ReportsGenerator.swift | 1 - Work Hours/Views/AboutSettingsView.swift | 64 +++++++++++++++++++++++- Work Hours/Views/TimerView.swift | 4 +- Work Hours/WorkHours.swift | 12 +++++ 4 files changed, 76 insertions(+), 5 deletions(-) diff --git a/Work Hours/ReportsGenerator.swift b/Work Hours/ReportsGenerator.swift index 2f4d629..1de2bb2 100644 --- a/Work Hours/ReportsGenerator.swift +++ b/Work Hours/ReportsGenerator.swift @@ -89,7 +89,6 @@ enum Events { } static func generateReport(formatter: DateFormatter) -> [Report]? { - os_log("Start, generateReport") var data: [String: Int] = [:] guard let logFile = logFile else { diff --git a/Work Hours/Views/AboutSettingsView.swift b/Work Hours/Views/AboutSettingsView.swift index 5085bcd..db8bbab 100644 --- a/Work Hours/Views/AboutSettingsView.swift +++ b/Work Hours/Views/AboutSettingsView.swift @@ -8,17 +8,43 @@ import SwiftUI struct AboutSettingsView: View { @State private var isLoading = false + @State private var status = UpdateStates.Checking + + enum UpdateStates: String { + case Checking = "Checking for updates" + case NewVersion = "New version found" + case Installing = "Installing new update" + case Updated = "App is up to date" + case Failed = "Failed to update, download manualy" + } var body: some View { HStack { Image("Logo").resizable() .aspectRatio(contentMode: .fit) + VStack(alignment: .leading) { Link("Work Hours", destination: URL(string: "https://niteo.co/work-hours-app")!).font(.title) VStack(alignment: .leading, spacing: 0) { Text("Version: \(AppInfo.appVersion) - \(AppInfo.buildVersion)") + HStack(spacing: 10) { + if status == UpdateStates.Failed { + HStack(spacing: 0) { + Text("Failed to update ") + Link("download manually", + destination: URL(string: "https://github.com/niteoweb/work-hours-mac/releases/latest/download/WorkHours.dmg")!) + } + } else { + Text(status.rawValue) + } + + if self.isLoading { + ProgressView().frame(width: 5.0, height: 5.0) + .scaleEffect(x: 0.5, y: 0.5, anchor: .center) + } + } } HStack(spacing: 0) { @@ -32,9 +58,43 @@ struct AboutSettingsView: View { Link("Niteo", destination: URL(string: "https://niteo.co/about")!) } - } + }.padding(.leading, 20.0) - }.frame(width: 350, height: 100).padding(25) + }.frame(width: 350, height: 100).padding(25).onAppear(perform: fetch) + } + + private func fetch() { + DispatchQueue.global(qos: .userInitiated).async { + isLoading = true + status = UpdateStates.Checking + let currentVersion = Bundle.main.version + if let release = try? AppDelegate.updater.getLatestRelease(allowPrereleases: false) { + isLoading = false + if currentVersion < release.version { + status = UpdateStates.NewVersion + if let zipURL = release.assets.filter({ $0.browserDownloadURL.path.hasSuffix(".zip") }).first { + status = UpdateStates.Installing + isLoading = true + + let done = AppDelegate.updater.downloadAndUpdate(withAsset: zipURL) + if !done { + status = UpdateStates.Failed + isLoading = false + } + + } else { + status = UpdateStates.Updated + isLoading = false + } + } else { + status = UpdateStates.Updated + isLoading = false + } + } else { + status = UpdateStates.Updated + isLoading = false + } + } } } diff --git a/Work Hours/Views/TimerView.swift b/Work Hours/Views/TimerView.swift index fa3e86b..d3ca9ee 100644 --- a/Work Hours/Views/TimerView.swift +++ b/Work Hours/Views/TimerView.swift @@ -13,11 +13,11 @@ struct TimerView: View { @Environment(\.colorScheme) var colorScheme @Default(.statusBarIcon) var statusBarIcon @Default(.hideBackground) var hideBackground - + var body: some View { if timerModel.isRunning { ZStack { - if #available(macOS 12.0, *){ + if #available(macOS 12.0, *) { Text(timerModel.display) .foregroundColor(.black.opacity(0.8)) .font(.headline) diff --git a/Work Hours/WorkHours.swift b/Work Hours/WorkHours.swift index 01151e9..121a448 100644 --- a/Work Hours/WorkHours.swift +++ b/Work Hours/WorkHours.swift @@ -7,6 +7,7 @@ import SwiftUI +import AppUpdater import Cocoa import Defaults import os.log @@ -32,6 +33,13 @@ class AppDelegate: NSObject, NSApplicationDelegate { var welcomeWindow: NSWindow? var statusBar: StatusBarController? + static let updater = GithubAppUpdater( + updateURL: "https://api.github.com/repos/niteoweb/work-hours-mac/releases", + allowPrereleases: false, + autoGuard: true, + interval: 60 * 60 + ) + func applicationWillFinishLaunching(_: Notification) {} func applicationDidFinishLaunching(_: Notification) { @@ -48,6 +56,10 @@ class AppDelegate: NSObject, NSApplicationDelegate { self.statusBar?.timerModel.stop() } } + + DispatchQueue.main.async { + _ = AppDelegate.updater.checkAndUpdate() + } } func application(_: NSApplication, open urls: [URL]) {