From ec0f4dea0ec11fa98cabaa93f4936bd492a06586 Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Tue, 9 Feb 2021 00:15:26 +0800 Subject: [PATCH 1/7] Init auto update --- eul.xcodeproj/project.pbxproj | 6 ++ eul/Store/PreferenceStore.swift | 5 ++ eul/Utilities/AutoUpdate.swift | 87 +++++++++++++++++++ .../Preference/PreferenceGeneralView.swift | 4 + 4 files changed, 102 insertions(+) create mode 100644 eul/Utilities/AutoUpdate.swift diff --git a/eul.xcodeproj/project.pbxproj b/eul.xcodeproj/project.pbxproj index 251f41d0..b14703c9 100644 --- a/eul.xcodeproj/project.pbxproj +++ b/eul.xcodeproj/project.pbxproj @@ -104,6 +104,7 @@ 6C5F8549249FACE200CF0EF8 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6C5F8547249FACE200CF0EF8 /* Main.storyboard */; }; 6C5FBD4E253C7A060016F3A2 /* PreferenceMenuViewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C5FBD4D253C7A060016F3A2 /* PreferenceMenuViewView.swift */; }; 6C5FBD50253C83520016F3A2 /* MenuActionTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C5FBD4F253C83520016F3A2 /* MenuActionTextView.swift */; }; + 6C76846F25D1884A00E987BB /* AutoUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C76846E25D1884A00E987BB /* AutoUpdate.swift */; }; 6C79AD362539EBE60033845C /* ProcessUsage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C79AD352539EBE60033845C /* ProcessUsage.swift */; }; 6C79AD382539F9030033845C /* MenuActionButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C79AD372539F9030033845C /* MenuActionButtonView.swift */; }; 6C7A8D8A25578F8100FF52ED /* LineChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7A8D8925578F8100FF52ED /* LineChart.swift */; }; @@ -416,6 +417,7 @@ 6C68E07F2556643700595F83 /* PreferenceEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceEntry.swift; sourceTree = ""; }; 6C68E083255664F500595F83 /* SmcStruct.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmcStruct.swift; sourceTree = ""; }; 6C739CC025544D7200B30B0D /* SharedEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedEntry.swift; sourceTree = ""; }; + 6C76846E25D1884A00E987BB /* AutoUpdate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoUpdate.swift; sourceTree = ""; }; 6C79AD352539EBE60033845C /* ProcessUsage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProcessUsage.swift; sourceTree = ""; }; 6C79AD372539F9030033845C /* MenuActionButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuActionButtonView.swift; sourceTree = ""; }; 6C7A8D8925578F8100FF52ED /* LineChart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineChart.swift; sourceTree = ""; }; @@ -784,6 +786,7 @@ 6C831368253DCF1F00914BB0 /* Print.swift */, 6CFAB80525BC526E002F5F48 /* GPU.swift */, 6CFAB80825BC55C6002F5F48 /* IOHelper.swift */, + 6C76846E25D1884A00E987BB /* AutoUpdate.swift */, ); path = Utilities; sourceTree = ""; @@ -963,6 +966,8 @@ dependencies = ( ); name = SharedLibrary; + packageProductDependencies = ( + ); productName = SharedLibrary; productReference = 6C2688EE2556762B00FB7306 /* SharedLibrary.framework */; productType = "com.apple.product-type.framework"; @@ -1411,6 +1416,7 @@ 6C79AD362539EBE60033845C /* ProcessUsage.swift in Sources */, 6CDBB4C525447D8B00D01EA0 /* ComponentsStore.swift in Sources */, 6C7DB6D124E0300E00133B06 /* NetworkStore.swift in Sources */, + 6C76846F25D1884A00E987BB /* AutoUpdate.swift in Sources */, 6C33CEC92517634400345977 /* StatusMenuView.swift in Sources */, 6C02715F25BD40EA006C54E6 /* SystemProfiler.swift in Sources */, ); diff --git a/eul/Store/PreferenceStore.swift b/eul/Store/PreferenceStore.swift index c8070aa4..b65b7ad5 100644 --- a/eul/Store/PreferenceStore.swift +++ b/eul/Store/PreferenceStore.swift @@ -56,6 +56,7 @@ class PreferenceStore: ObservableObject { @Published var showNetworkTopActivities = false @Published var cpuMenuDisplay: Preference.CpuMenuDisplay = .usagePercentage @Published var checkStatusItemVisibility = true + @Published var autoUpdate = false @Published var isUpdateAvailable: Bool? = false @Published var checkUpdateFailed = true @@ -73,6 +74,7 @@ class PreferenceStore: ObservableObject { "showNetworkTopActivities": showNetworkTopActivities, "cpuMenuDisplay": cpuMenuDisplay.rawValue, "checkStatusItemVisibility": checkStatusItemVisibility, + "autoUpdate": autoUpdate, ]) } @@ -160,6 +162,9 @@ class PreferenceStore: ObservableObject { if let value = data["checkStatusItemVisibility"].bool { checkStatusItemVisibility = value } + if let value = data["autoUpdate"].bool { + autoUpdate = value + } } catch { print("Unable to get preference data from user defaults") } diff --git a/eul/Utilities/AutoUpdate.swift b/eul/Utilities/AutoUpdate.swift new file mode 100644 index 00000000..e40c5987 --- /dev/null +++ b/eul/Utilities/AutoUpdate.swift @@ -0,0 +1,87 @@ +// +// AutoUpdate.swift +// eul +// +// Created by Gao Sun on 2021/2/8. +// Copyright © 2021 Gao Sun. All rights reserved. +// + +import Foundation + +enum AutoUpdate { + static let fileManager = FileManager.default + static let appUrl = fileManager.temporaryDirectory.appendingPathComponent("eul.app") + static let zipUrl = fileManager.temporaryDirectory.appendingPathComponent("eul.app.zip") + + static func run() { + downloadLatest { + if $0 { + unzip { + print("???", $0) + } + } + } + } + + static func downloadLatest(completion: @escaping (Bool) -> Void) { + guard let url = URL(string: "https://github.com/gao-sun/eul/releases/latest/download/eul.app.zip") else { + completion(false) + return + } + + let session = URLSession(configuration: .ephemeral) + let task = session.downloadTask(with: url) { url, _, error in + if let error = error { + print("⚠️ error when downloading latest zip file", error.localizedDescription) + completion(false) + return + } + + guard let url = url else { + print("⚠️ no url") + completion(false) + return + } + + do { + Print("Checking if zip file exists") + if fileManager.fileExists(atPath: zipUrl.path) { + Print("Removing existing zip file") + try fileManager.removeItem(at: zipUrl) + } + + Print("Renaming file") + try fileManager.moveItem(at: url, to: zipUrl) + } catch { + print("⚠️ error when setting up the new app", error.localizedDescription) + completion(false) + return + } + + completion(true) + } + + task.resume() + } + + static func unzip(completion: @escaping (Bool) -> Void) { + do { + Print("Checking if app directory exists") + if fileManager.fileExists(atPath: appUrl.path) { + Print("Removing existing app directory") + try fileManager.removeItem(at: appUrl) + } + + guard shell("unzip -oq \(zipUrl.path) -d \(fileManager.temporaryDirectory.path)") != nil else { + completion(false) + return + } + } catch { + print("⚠️ error when unzipping the new app", error.localizedDescription) + completion(false) + return + } + + completion(true) + } +} diff --git a/eul/Views/Preference/PreferenceGeneralView.swift b/eul/Views/Preference/PreferenceGeneralView.swift index 2ae4dadd..47f0d642 100644 --- a/eul/Views/Preference/PreferenceGeneralView.swift +++ b/eul/Views/Preference/PreferenceGeneralView.swift @@ -67,6 +67,10 @@ extension Preference { Text("ui.launch_at_login".localized()) .inlineSection() } + Toggle(isOn: $preference.autoUpdate) { + Text("ui.auto_update".localized()) + .inlineSection() + } Toggle(isOn: $preference.checkStatusItemVisibility) { Text("ui.check_status_item_visibility".localized()) .inlineSection() From c4c44b4b5799b53eed17cbea9c6e9db10bce3222 Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Fri, 12 Feb 2021 21:39:19 +0800 Subject: [PATCH 2/7] Complete auto update --- SelfUpdate/AppDelegate.swift | 97 +++ .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 58 ++ SelfUpdate/Assets.xcassets/Contents.json | 6 + SelfUpdate/Base.lproj/Main.storyboard | 683 ++++++++++++++++++ SelfUpdate/ContentView.swift | 19 + SelfUpdate/Info.plist | 34 + .../Preview Assets.xcassets/Contents.json | 6 + SelfUpdate/SelfUpdate.entitlements | 5 + SharedLibrary/Extension/Double.swift | 4 + SharedLibrary/Utilities/ByteUnit.swift | 4 +- eul.xcodeproj/project.pbxproj | 176 ++++- eul/Utilities/AutoUpdate.swift | 49 +- 13 files changed, 1140 insertions(+), 12 deletions(-) create mode 100644 SelfUpdate/AppDelegate.swift create mode 100644 SelfUpdate/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 SelfUpdate/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 SelfUpdate/Assets.xcassets/Contents.json create mode 100644 SelfUpdate/Base.lproj/Main.storyboard create mode 100644 SelfUpdate/ContentView.swift create mode 100644 SelfUpdate/Info.plist create mode 100644 SelfUpdate/Preview Content/Preview Assets.xcassets/Contents.json create mode 100644 SelfUpdate/SelfUpdate.entitlements diff --git a/SelfUpdate/AppDelegate.swift b/SelfUpdate/AppDelegate.swift new file mode 100644 index 00000000..65a92790 --- /dev/null +++ b/SelfUpdate/AppDelegate.swift @@ -0,0 +1,97 @@ +// +// AppDelegate.swift +// SelfUpdate +// +// Created by Gao Sun on 2021/2/12. +// Copyright © 2021 Gao Sun. All rights reserved. +// + +import Cocoa +import SwiftUI + +@main +class AppDelegate: NSObject, NSApplicationDelegate { + var window: NSWindow! + let fileManager = FileManager.default + + static func quit() { + NSApplication.shared.terminate(self) + } + + func update() { + defer { + AppDelegate.quit() + } + + let arguments = CommandLine.arguments + let newAppUrl = URL(fileURLWithPath: arguments[1]).appendingPathComponent("eul.app") + let appUrl = URL(fileURLWithPath: arguments[2]).appendingPathComponent("eul.app") + let pidArg = pid_t(arguments[3]) + + guard + let pid = pidArg, + let currentApp = NSWorkspace.shared.runningApplications.first(where: { $0.processIdentifier == pid }) + else { + print("current app not found with pid", pidArg ?? "N/A") + return + } + + var isDirectory: ObjCBool = false + + guard fileManager.fileExists(atPath: newAppUrl.path, isDirectory: &isDirectory), isDirectory.boolValue else { + print("new app not found at", newAppUrl) + return + } + + print("terminating current app") + guard currentApp.terminate() || currentApp.forceTerminate() else { + print("cannot terminate current app") + return + } + + do { + print("removing old app", appUrl) + try fileManager.removeItem(at: appUrl) + print("copying new app from", newAppUrl, "to", appUrl) + try fileManager.copyItem(at: newAppUrl, to: appUrl) + } catch { + print("error when setting up new app", error) + return + } + + print("opening app") + guard NSWorkspace.shared.open(appUrl) else { + print("failed to open app") + return + } + + print("update fininshed") + } + + func applicationDidFinishLaunching(_: Notification) { + update() + + guard CommandLine.arguments.contains("--debug") else { + return + } + + // Create the SwiftUI view that provides the window contents. + let contentView = ContentView() + + // Create the window and set the content view. + window = NSWindow( + contentRect: NSRect(x: 0, y: 0, width: 480, height: 300), + styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], + backing: .buffered, defer: false + ) + window.isReleasedWhenClosed = false + window.center() + window.setFrameAutosaveName("Main Window") + window.contentView = NSHostingView(rootView: contentView) + window.makeKeyAndOrderFront(nil) + } + + func applicationWillTerminate(_: Notification) { + // Insert code here to tear down your application + } +} diff --git a/SelfUpdate/Assets.xcassets/AccentColor.colorset/Contents.json b/SelfUpdate/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/SelfUpdate/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SelfUpdate/Assets.xcassets/AppIcon.appiconset/Contents.json b/SelfUpdate/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..3f00db43 --- /dev/null +++ b/SelfUpdate/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SelfUpdate/Assets.xcassets/Contents.json b/SelfUpdate/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/SelfUpdate/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SelfUpdate/Base.lproj/Main.storyboard b/SelfUpdate/Base.lproj/Main.storyboard new file mode 100644 index 00000000..2beb1e34 --- /dev/null +++ b/SelfUpdate/Base.lproj/Main.storyboard @@ -0,0 +1,683 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SelfUpdate/ContentView.swift b/SelfUpdate/ContentView.swift new file mode 100644 index 00000000..28c9c0ca --- /dev/null +++ b/SelfUpdate/ContentView.swift @@ -0,0 +1,19 @@ +// +// ContentView.swift +// SelfUpdate +// +// Created by Gao Sun on 2021/2/12. +// Copyright © 2021 Gao Sun. All rights reserved. +// + +import SwiftUI + +struct ContentView: View { + var body: some View { + VStack { + ForEach(CommandLine.arguments, id: \.self) { + Text($0) + } + } + } +} diff --git a/SelfUpdate/Info.plist b/SelfUpdate/Info.plist new file mode 100644 index 00000000..f49cef98 --- /dev/null +++ b/SelfUpdate/Info.plist @@ -0,0 +1,34 @@ + + + + + LSUIElement + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2021 Gao Sun. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/SelfUpdate/Preview Content/Preview Assets.xcassets/Contents.json b/SelfUpdate/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/SelfUpdate/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SelfUpdate/SelfUpdate.entitlements b/SelfUpdate/SelfUpdate.entitlements new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/SelfUpdate/SelfUpdate.entitlements @@ -0,0 +1,5 @@ + + + + + diff --git a/SharedLibrary/Extension/Double.swift b/SharedLibrary/Extension/Double.swift index 12f098d9..579d81f4 100644 --- a/SharedLibrary/Extension/Double.swift +++ b/SharedLibrary/Extension/Double.swift @@ -23,4 +23,8 @@ public extension Double { func toFixed(_ decimal: Int) -> String { String(format: "%.\(decimal)f", self) } + + var zeroOrAbove: Double { + isNaN || isLess(than: 0) ? 0 : self + } } diff --git a/SharedLibrary/Utilities/ByteUnit.swift b/SharedLibrary/Utilities/ByteUnit.swift index 3c5f1b67..d56948d5 100644 --- a/SharedLibrary/Utilities/ByteUnit.swift +++ b/SharedLibrary/Utilities/ByteUnit.swift @@ -31,12 +31,12 @@ public struct ByteUnit { } public init(_ bytes: Double, kilo: UInt64 = 1024) { - self.bytes = UInt64(bytes) + self.bytes = UInt64(bytes.zeroOrAbove) self.kilo = kilo } public init(megaBytes: Double) { - self.init(megaBytes * Double(1024 * 1024)) + self.init(megaBytes.zeroOrAbove * Double(1024 * 1024)) } public var readable: String { diff --git a/eul.xcodeproj/project.pbxproj b/eul.xcodeproj/project.pbxproj index b14703c9..ee8582a6 100644 --- a/eul.xcodeproj/project.pbxproj +++ b/eul.xcodeproj/project.pbxproj @@ -156,6 +156,8 @@ 6C9A10CB2556C502000459E1 /* SharedLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C2688EE2556762B00FB7306 /* SharedLibrary.framework */; }; 6C9A10CC2556C502000459E1 /* SharedLibrary.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 6C2688EE2556762B00FB7306 /* SharedLibrary.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 6CAEED6524A62DF800C39597 /* SMC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CAEED6424A62DF800C39597 /* SMC.swift */; }; + 6CB3D25425D69FFF008C6627 /* SelfUpdate.app in Resources */ = {isa = PBXBuildFile; fileRef = 6CDEF06C25D69E8100B4C913 /* SelfUpdate.app */; }; + 6CB3D26125D6A859008C6627 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CB3D26025D6A858008C6627 /* ContentView.swift */; }; 6CC0798C250CD793000D7DAC /* PreferenceGeneralView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC0798B250CD793000D7DAC /* PreferenceGeneralView.swift */; }; 6CC1EBB725769B1F00BC05CA /* FanData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC1EBB625769B1F00BC05CA /* FanData.swift */; }; 6CC1EBBA25769B4400BC05CA /* TemperatureData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC1EBB925769B4400BC05CA /* TemperatureData.swift */; }; @@ -171,6 +173,10 @@ 6CDE6C7624F10C8000463114 /* StatusBarManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CDE6C7524F10C8000463114 /* StatusBarManager.swift */; }; 6CDE6C7824F112D700463114 /* EulComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CDE6C7724F112D700463114 /* EulComponent.swift */; }; 6CDE6C7D24F2AB8800463114 /* NSMenuItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CDE6C7C24F2AB8800463114 /* NSMenuItem.swift */; }; + 6CDEF06F25D69E8100B4C913 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CDEF06E25D69E8100B4C913 /* AppDelegate.swift */; }; + 6CDEF07325D69E8100B4C913 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6CDEF07225D69E8100B4C913 /* Assets.xcassets */; }; + 6CDEF07625D69E8100B4C913 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6CDEF07525D69E8100B4C913 /* Preview Assets.xcassets */; }; + 6CDEF07925D69E8100B4C913 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6CDEF07725D69E8100B4C913 /* Main.storyboard */; }; 6CE33C7F25260E3D00831857 /* PreferenceRefreshRateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CE33C7E25260E3D00831857 /* PreferenceRefreshRateView.swift */; }; 6CE7969325166916008BEB2B /* SwiftyJSON in Frameworks */ = {isa = PBXBuildFile; productRef = 6CE7969225166916008BEB2B /* SwiftyJSON */; }; 6CEF48A2255C33CE002E4D73 /* FramePreferenceKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEF48A1255C33CE002E4D73 /* FramePreferenceKey.swift */; }; @@ -250,6 +256,13 @@ remoteGlobalIDString = 6C2688ED2556762B00FB7306; remoteInfo = SharedLibrary; }; + 6CB3D25525D69FFF008C6627 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6C5F8533249FACE000CF0EF8 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6CDEF06B25D69E8100B4C913; + remoteInfo = SelfUpdate; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -268,7 +281,7 @@ isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; - dstSubfolderSpec = 16; + dstSubfolderSpec = 7; files = ( ); runOnlyForDeploymentPostprocessing = 0; @@ -465,6 +478,7 @@ 6CB260AA250DE26900328DAA /* ActivityIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityIndicatorView.swift; sourceTree = ""; }; 6CB260AF250DF1A900328DAA /* BatteryIconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatteryIconView.swift; sourceTree = ""; }; 6CB26F7824E8310900E809FE /* SectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionView.swift; sourceTree = ""; }; + 6CB3D26025D6A858008C6627 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 6CC0798B250CD793000D7DAC /* PreferenceGeneralView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceGeneralView.swift; sourceTree = ""; }; 6CC1EBB625769B1F00BC05CA /* FanData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FanData.swift; sourceTree = ""; }; 6CC1EBB925769B4400BC05CA /* TemperatureData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemperatureData.swift; sourceTree = ""; }; @@ -482,6 +496,13 @@ 6CDE6C7524F10C8000463114 /* StatusBarManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusBarManager.swift; sourceTree = ""; }; 6CDE6C7724F112D700463114 /* EulComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EulComponent.swift; sourceTree = ""; }; 6CDE6C7C24F2AB8800463114 /* NSMenuItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSMenuItem.swift; sourceTree = ""; }; + 6CDEF06C25D69E8100B4C913 /* SelfUpdate.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SelfUpdate.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 6CDEF06E25D69E8100B4C913 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 6CDEF07225D69E8100B4C913 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 6CDEF07525D69E8100B4C913 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 6CDEF07825D69E8100B4C913 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6CDEF07A25D69E8100B4C913 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6CDEF07B25D69E8100B4C913 /* SelfUpdate.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SelfUpdate.entitlements; sourceTree = ""; }; 6CE33C7C252601BB00831857 /* Int.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Int.swift; sourceTree = ""; }; 6CE33C7E25260E3D00831857 /* PreferenceRefreshRateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceRefreshRateView.swift; sourceTree = ""; }; 6CEF48A1255C33CE002E4D73 /* FramePreferenceKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FramePreferenceKey.swift; sourceTree = ""; }; @@ -568,6 +589,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 6CDEF06925D69E8100B4C913 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -720,6 +748,7 @@ isa = PBXGroup; children = ( 6C2688EF2556762B00FB7306 /* SharedLibrary */, + 6CDEF06D25D69E8100B4C913 /* SelfUpdate */, 6C16BEEB2552EC5800CCF5B7 /* Resource */, 6C5F853D249FACE000CF0EF8 /* eul */, 6C7E1F032552EB2600287D08 /* CpuWidget */, @@ -741,6 +770,7 @@ 6C45750525568DCB00A2AD84 /* MemoryWidgetExtension.appex */, 6C7CF46E25569B8100CEC263 /* BatteryWidgetExtension.appex */, 6C5DACFE2556B2FE005F67C3 /* NetworkWidgetExtension.appex */, + 6CDEF06C25D69E8100B4C913 /* SelfUpdate.app */, ); name = Products; sourceTree = ""; @@ -939,6 +969,28 @@ path = Menu; sourceTree = ""; }; + 6CDEF06D25D69E8100B4C913 /* SelfUpdate */ = { + isa = PBXGroup; + children = ( + 6CDEF06E25D69E8100B4C913 /* AppDelegate.swift */, + 6CB3D26025D6A858008C6627 /* ContentView.swift */, + 6CDEF07225D69E8100B4C913 /* Assets.xcassets */, + 6CDEF07725D69E8100B4C913 /* Main.storyboard */, + 6CDEF07A25D69E8100B4C913 /* Info.plist */, + 6CDEF07B25D69E8100B4C913 /* SelfUpdate.entitlements */, + 6CDEF07425D69E8100B4C913 /* Preview Content */, + ); + path = SelfUpdate; + sourceTree = ""; + }; + 6CDEF07425D69E8100B4C913 /* Preview Content */ = { + isa = PBXGroup; + children = ( + 6CDEF07525D69E8100B4C913 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -1037,6 +1089,7 @@ 6C45751325568DCC00A2AD84 /* PBXTargetDependency */, 6C7CF47C25569B8200CEC263 /* PBXTargetDependency */, 6C5DAD0C2556B2FF005F67C3 /* PBXTargetDependency */, + 6CB3D25625D69FFF008C6627 /* PBXTargetDependency */, ); name = eul; packageProductDependencies = ( @@ -1094,13 +1147,32 @@ productReference = 6C7E1EFD2552EB2600287D08 /* CpuWidgetExtension.appex */; productType = "com.apple.product-type.app-extension"; }; + 6CDEF06B25D69E8100B4C913 /* SelfUpdate */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6CDEF07C25D69E8100B4C913 /* Build configuration list for PBXNativeTarget "SelfUpdate" */; + buildPhases = ( + 6CDEF06825D69E8100B4C913 /* Sources */, + 6CDEF06925D69E8100B4C913 /* Frameworks */, + 6CDEF06A25D69E8100B4C913 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SelfUpdate; + packageProductDependencies = ( + ); + productName = SelfUpdate; + productReference = 6CDEF06C25D69E8100B4C913 /* SelfUpdate.app */; + productType = "com.apple.product-type.application"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 6C5F8533249FACE000CF0EF8 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1220; + LastSwiftUpdateCheck = 1240; LastUpgradeCheck = 1220; ORGANIZATIONNAME = "Gao Sun"; TargetAttributes = { @@ -1123,6 +1195,9 @@ 6C7E1EFC2552EB2600287D08 = { CreatedOnToolsVersion = 12.2; }; + 6CDEF06B25D69E8100B4C913 = { + CreatedOnToolsVersion = 12.4; + }; }; }; buildConfigurationList = 6C5F8536249FACE000CF0EF8 /* Build configuration list for PBXProject "eul" */; @@ -1163,6 +1238,7 @@ 6C45750425568DCB00A2AD84 /* MemoryWidgetExtension */, 6C7CF46D25569B8100CEC263 /* BatteryWidgetExtension */, 6C5DACFD2556B2FE005F67C3 /* NetworkWidgetExtension */, + 6CDEF06B25D69E8100B4C913 /* SelfUpdate */, ); }; /* End PBXProject section */ @@ -1201,6 +1277,7 @@ files = ( 6C5F8549249FACE200CF0EF8 /* Main.storyboard in Resources */, 6C58053D250CC6B8007F467A /* Localizable.strings in Resources */, + 6CB3D25425D69FFF008C6627 /* SelfUpdate.app in Resources */, 6C5F8543249FACE200CF0EF8 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1225,6 +1302,16 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 6CDEF06A25D69E8100B4C913 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6CDEF07925D69E8100B4C913 /* Main.storyboard in Resources */, + 6CDEF07625D69E8100B4C913 /* Preview Assets.xcassets in Resources */, + 6CDEF07325D69E8100B4C913 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ @@ -1440,6 +1527,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 6CDEF06825D69E8100B4C913 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6CB3D26125D6A859008C6627 /* ContentView.swift in Sources */, + 6CDEF06F25D69E8100B4C913 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -1488,6 +1584,11 @@ target = 6C2688ED2556762B00FB7306 /* SharedLibrary */; targetProxy = 6C9A10CD2556C502000459E1 /* PBXContainerItemProxy */; }; + 6CB3D25625D69FFF008C6627 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6CDEF06B25D69E8100B4C913 /* SelfUpdate */; + targetProxy = 6CB3D25525D69FFF008C6627 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -1520,6 +1621,14 @@ name = Main.storyboard; sourceTree = ""; }; + 6CDEF07725D69E8100B4C913 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6CDEF07825D69E8100B4C913 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ @@ -1530,7 +1639,7 @@ CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = M8G2RFZVFV; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1544,7 +1653,7 @@ "@loader_path/Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.15; - MARKETING_VERSION = 1.0.2; + MARKETING_VERSION = 1.0.3; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.SharedLibrary; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; @@ -1561,7 +1670,7 @@ CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = M8G2RFZVFV; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1575,7 +1684,7 @@ "@loader_path/Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.15; - MARKETING_VERSION = 1.0.2; + MARKETING_VERSION = 1.0.3; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.SharedLibrary; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; @@ -1971,6 +2080,52 @@ }; name = Release; }; + 6CDEF07D25D69E8100B4C913 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = SelfUpdate/SelfUpdate.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_ASSET_PATHS = "\"SelfUpdate/Preview Content\""; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_PREVIEWS = YES; + INFOPLIST_FILE = SelfUpdate/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.15; + PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.SelfUpdate; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 6CDEF07E25D69E8100B4C913 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = SelfUpdate/SelfUpdate.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_ASSET_PATHS = "\"SelfUpdate/Preview Content\""; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_PREVIEWS = YES; + INFOPLIST_FILE = SelfUpdate/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.15; + PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.SelfUpdate; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -2037,6 +2192,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 6CDEF07C25D69E8100B4C913 /* Build configuration list for PBXNativeTarget "SelfUpdate" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6CDEF07D25D69E8100B4C913 /* Debug */, + 6CDEF07E25D69E8100B4C913 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ diff --git a/eul/Utilities/AutoUpdate.swift b/eul/Utilities/AutoUpdate.swift index e40c5987..bfa86ced 100644 --- a/eul/Utilities/AutoUpdate.swift +++ b/eul/Utilities/AutoUpdate.swift @@ -6,6 +6,7 @@ // Copyright © 2021 Gao Sun. All rights reserved. // +import Cocoa import Foundation enum AutoUpdate { @@ -17,7 +18,47 @@ enum AutoUpdate { downloadLatest { if $0 { unzip { - print("???", $0) + if $0 { + if let resourceURL = Bundle.main.resourceURL { + let selfUpdateUrl = resourceURL.appendingPathComponent("SelfUpdate.app") + let tempSelfUpdateUrl = fileManager.temporaryDirectory.appendingPathComponent("SelfUpdate.app") + + do { + if fileManager.fileExists(atPath: tempSelfUpdateUrl.path) { + print("trying to remove legacy update app at", tempSelfUpdateUrl) + try fileManager.removeItem(at: tempSelfUpdateUrl) + } + print("trying to copy self update from", selfUpdateUrl, "to", tempSelfUpdateUrl) + try fileManager.copyItem(at: selfUpdateUrl, to: tempSelfUpdateUrl) + } catch { + print("⚠️ error when copying self update", error) + return + } + + let arguments: [String] = [ + fileManager.temporaryDirectory.path, + Bundle.main.bundleURL.deletingLastPathComponent().path, + NSRunningApplication.current.processIdentifier.description, + ] + + let options = NSWorkspace.OpenConfiguration() + options.arguments = arguments + + print("trying to run self update with arguments", tempSelfUpdateUrl, arguments) + do { + try NSWorkspace.shared.open( + tempSelfUpdateUrl, + options: .default, + configuration: [.arguments: arguments] + ) + } catch { + print("error when opening self update", error) + return + } + + print("started self update app") + } + } } } } @@ -32,7 +73,7 @@ enum AutoUpdate { let session = URLSession(configuration: .ephemeral) let task = session.downloadTask(with: url) { url, _, error in if let error = error { - print("⚠️ error when downloading latest zip file", error.localizedDescription) + print("⚠️ error when downloading latest zip file", error) completion(false) return } @@ -53,7 +94,7 @@ enum AutoUpdate { Print("Renaming file") try fileManager.moveItem(at: url, to: zipUrl) } catch { - print("⚠️ error when setting up the new app", error.localizedDescription) + print("⚠️ error when setting up the new app", error) completion(false) return } @@ -77,7 +118,7 @@ enum AutoUpdate { return } } catch { - print("⚠️ error when unzipping the new app", error.localizedDescription) + print("⚠️ error when unzipping the new app", error) completion(false) return } From f3de54bc6c74bcd41717dd50e785aa0271c71b11 Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Fri, 12 Feb 2021 22:01:30 +0800 Subject: [PATCH 3/7] Add update method picker --- eul/AppDelegate.swift | 103 +++++++++++------- eul/Store/ComponentConfigStore.swift | 2 +- eul/Store/ComponentsStore.swift | 2 +- eul/Store/PreferenceStore.swift | 20 +++- eul/Utilities/AutoUpdate.swift | 8 +- .../Preference/PreferenceGeneralView.swift | 11 +- 6 files changed, 91 insertions(+), 55 deletions(-) diff --git a/eul/AppDelegate.swift b/eul/AppDelegate.swift index 8cbece5c..219e8f60 100644 --- a/eul/AppDelegate.swift +++ b/eul/AppDelegate.swift @@ -7,53 +7,19 @@ // import Cocoa +import Combine import Localize_Swift import SharedLibrary import SwiftUI @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate { - static var statusBarHeight: CGFloat { - NSStatusBar.system.thickness - } - - static func openPreferences() { - (NSApp.delegate as! AppDelegate).window.makeKeyAndOrderFront(nil) - NSApp.activate(ignoringOtherApps: true) - NotificationCenter.default.post(name: .StatusBarMenuShouldClose, object: nil) - } - - static func quit() { - NSApplication.shared.terminate(self) - } - private var isSleeping = false + private var updateMethodCancellable: AnyCancellable? var window: NSWindow! @ObservedObject var preferenceStore = SharedStore.preference - func refreshSMCRepeatedly() { - guard !isSleeping else { - return - } - - NotificationCenter.default.post(name: .SMCShouldRefresh, object: nil) - DispatchQueue.main.asyncAfter(deadline: .now() + Double(preferenceStore.smcRefreshRate)) { [self] in - refreshSMCRepeatedly() - } - } - - func refreshNetworkRepeatedly() { - guard !isSleeping else { - return - } - - NotificationCenter.default.post(name: .NetworkShouldRefresh, object: nil) - DispatchQueue.main.asyncAfter(deadline: .now() + Double(preferenceStore.networkRefreshRate)) { [self] in - refreshNetworkRepeatedly() - } - } - func applicationDidFinishLaunching(_: Notification) { let contentView = ContentView() window = NSWindow( @@ -88,6 +54,11 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate { print("🤩 woke up") self.wakeUp() } + updateMethodCancellable = preferenceStore.$updateMethod.sink { _ in + DispatchQueue.main.async { + self.checkUpdateRepeatedly() + } + } } func applicationShouldTerminate(_: NSApplication) -> NSApplication.TerminateReply { @@ -100,17 +71,69 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate { isSleeping = false refreshSMCRepeatedly() refreshNetworkRepeatedly() + checkUpdateRepeatedly() } func sleep() { isSleeping = true } - func windowDidBecomeMain(_: Notification) { - preferenceStore.checkUpdate() - } - func applicationWillTerminate(_: Notification) { // Insert code here to tear down your application } } + +// MARK: Static Methods + +extension AppDelegate { + static var statusBarHeight: CGFloat { + NSStatusBar.system.thickness + } + + static func openPreferences() { + (NSApp.delegate as! AppDelegate).window.makeKeyAndOrderFront(nil) + NSApp.activate(ignoringOtherApps: true) + NotificationCenter.default.post(name: .StatusBarMenuShouldClose, object: nil) + } + + static func quit() { + NSApplication.shared.terminate(self) + } +} + +// MARK: Repeating Methods + +extension AppDelegate { + func refreshSMCRepeatedly() { + guard !isSleeping else { + return + } + + NotificationCenter.default.post(name: .SMCShouldRefresh, object: nil) + DispatchQueue.main.asyncAfter(deadline: .now() + Double(preferenceStore.smcRefreshRate)) { [self] in + refreshSMCRepeatedly() + } + } + + func refreshNetworkRepeatedly() { + guard !isSleeping else { + return + } + + NotificationCenter.default.post(name: .NetworkShouldRefresh, object: nil) + DispatchQueue.main.asyncAfter(deadline: .now() + Double(preferenceStore.networkRefreshRate)) { [self] in + refreshNetworkRepeatedly() + } + } + + func checkUpdateRepeatedly() { + guard !isSleeping, preferenceStore.updateMethod != .none else { + return + } + + preferenceStore.checkUpdate() + DispatchQueue.main.asyncAfter(deadline: .now() + Double(60 * 60)) { [self] in + checkUpdateRepeatedly() + } + } +} diff --git a/eul/Store/ComponentConfigStore.swift b/eul/Store/ComponentConfigStore.swift index a69cbfdb..7ed5e66d 100644 --- a/eul/Store/ComponentConfigStore.swift +++ b/eul/Store/ComponentConfigStore.swift @@ -98,7 +98,7 @@ class ComponentConfigStore: ObservableObject { let data = try json.rawData() UserDefaults.standard.set(data, forKey: userDefaultsKey) } catch { - print("Unable to get preference data") + print("Unable save status component config") } } } diff --git a/eul/Store/ComponentsStore.swift b/eul/Store/ComponentsStore.swift index e8500a4e..ea2a8665 100644 --- a/eul/Store/ComponentsStore.swift +++ b/eul/Store/ComponentsStore.swift @@ -104,7 +104,7 @@ class ComponentsStore: ObservableObject { let data = try json.rawData() UserDefaults.standard.set(data, forKey: userDefaultsKey) } catch { - print("Unable to get preference data") + print("Unable save components") } } } diff --git a/eul/Store/PreferenceStore.swift b/eul/Store/PreferenceStore.swift index b65b7ad5..2655dcd2 100644 --- a/eul/Store/PreferenceStore.swift +++ b/eul/Store/PreferenceStore.swift @@ -14,6 +14,12 @@ import SwiftyJSON import WidgetKit class PreferenceStore: ObservableObject { + enum UpdateMethod: String, CaseIterable { + case none + case showInStatusBar + case autoUpdate + } + static var availableLanguages: [String] { Localize.availableLanguages().filter { $0 != "Base" } } @@ -56,7 +62,7 @@ class PreferenceStore: ObservableObject { @Published var showNetworkTopActivities = false @Published var cpuMenuDisplay: Preference.CpuMenuDisplay = .usagePercentage @Published var checkStatusItemVisibility = true - @Published var autoUpdate = false + @Published var updateMethod = UpdateMethod.showInStatusBar @Published var isUpdateAvailable: Bool? = false @Published var checkUpdateFailed = true @@ -74,7 +80,7 @@ class PreferenceStore: ObservableObject { "showNetworkTopActivities": showNetworkTopActivities, "cpuMenuDisplay": cpuMenuDisplay.rawValue, "checkStatusItemVisibility": checkStatusItemVisibility, - "autoUpdate": autoUpdate, + "updateMethod": updateMethod.rawValue, ]) } @@ -107,6 +113,10 @@ class PreferenceStore: ObservableObject { "v\(version)".compare(tagName, options: .numeric) == .orderedAscending { self.isUpdateAvailable = true + + if self.updateMethod == .autoUpdate { + AutoUpdate.run() + } } else { self.isUpdateAvailable = false } @@ -162,8 +172,8 @@ class PreferenceStore: ObservableObject { if let value = data["checkStatusItemVisibility"].bool { checkStatusItemVisibility = value } - if let value = data["autoUpdate"].bool { - autoUpdate = value + if let raw = data["updateMethod"].string, let value = UpdateMethod(rawValue: raw) { + updateMethod = value } } catch { print("Unable to get preference data from user defaults") @@ -176,7 +186,7 @@ class PreferenceStore: ObservableObject { let data = try json.rawData() UserDefaults.standard.set(data, forKey: userDefaultsKey) } catch { - print("Unable to get preference data") + print("Unable to save preference") } } diff --git a/eul/Utilities/AutoUpdate.swift b/eul/Utilities/AutoUpdate.swift index bfa86ced..7a9baadb 100644 --- a/eul/Utilities/AutoUpdate.swift +++ b/eul/Utilities/AutoUpdate.swift @@ -25,10 +25,10 @@ enum AutoUpdate { do { if fileManager.fileExists(atPath: tempSelfUpdateUrl.path) { - print("trying to remove legacy update app at", tempSelfUpdateUrl) + Print("trying to remove legacy update app at", tempSelfUpdateUrl) try fileManager.removeItem(at: tempSelfUpdateUrl) } - print("trying to copy self update from", selfUpdateUrl, "to", tempSelfUpdateUrl) + Print("trying to copy self update from", selfUpdateUrl, "to", tempSelfUpdateUrl) try fileManager.copyItem(at: selfUpdateUrl, to: tempSelfUpdateUrl) } catch { print("⚠️ error when copying self update", error) @@ -44,7 +44,7 @@ enum AutoUpdate { let options = NSWorkspace.OpenConfiguration() options.arguments = arguments - print("trying to run self update with arguments", tempSelfUpdateUrl, arguments) + Print("trying to run self update with arguments", tempSelfUpdateUrl, arguments) do { try NSWorkspace.shared.open( tempSelfUpdateUrl, @@ -56,7 +56,7 @@ enum AutoUpdate { return } - print("started self update app") + Print("started self update app") } } } diff --git a/eul/Views/Preference/PreferenceGeneralView.swift b/eul/Views/Preference/PreferenceGeneralView.swift index 47f0d642..b118cfea 100644 --- a/eul/Views/Preference/PreferenceGeneralView.swift +++ b/eul/Views/Preference/PreferenceGeneralView.swift @@ -63,14 +63,17 @@ extension Preference { } .fixedSize() } + Picker("ui.update_method".localized(), selection: $preference.updateMethod) { + ForEach(PreferenceStore.UpdateMethod.allCases, id: \.self) { + Text("ui.update_method.\($0)".localized()) + .tag($0) + } + } + .fixedSize() Toggle(isOn: $launchAtLogin.isEnabled) { Text("ui.launch_at_login".localized()) .inlineSection() } - Toggle(isOn: $preference.autoUpdate) { - Text("ui.auto_update".localized()) - .inlineSection() - } Toggle(isOn: $preference.checkStatusItemVisibility) { Text("ui.check_status_item_visibility".localized()) .inlineSection() From 7b7a56ce4f6b8f0a3447a03a3514fbaac1ec0042 Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Fri, 12 Feb 2021 22:05:28 +0800 Subject: [PATCH 4/7] UpdateMethod -> Upgrade Method --- eul/AppDelegate.swift | 4 ++-- eul/Store/PreferenceStore.swift | 12 ++++++------ eul/Views/Preference/PreferenceGeneralView.swift | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/eul/AppDelegate.swift b/eul/AppDelegate.swift index 219e8f60..966395e6 100644 --- a/eul/AppDelegate.swift +++ b/eul/AppDelegate.swift @@ -54,7 +54,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate { print("🤩 woke up") self.wakeUp() } - updateMethodCancellable = preferenceStore.$updateMethod.sink { _ in + updateMethodCancellable = preferenceStore.$upgradeMethod.sink { _ in DispatchQueue.main.async { self.checkUpdateRepeatedly() } @@ -127,7 +127,7 @@ extension AppDelegate { } func checkUpdateRepeatedly() { - guard !isSleeping, preferenceStore.updateMethod != .none else { + guard !isSleeping, preferenceStore.upgradeMethod != .none else { return } diff --git a/eul/Store/PreferenceStore.swift b/eul/Store/PreferenceStore.swift index 2655dcd2..bd8c68dc 100644 --- a/eul/Store/PreferenceStore.swift +++ b/eul/Store/PreferenceStore.swift @@ -14,7 +14,7 @@ import SwiftyJSON import WidgetKit class PreferenceStore: ObservableObject { - enum UpdateMethod: String, CaseIterable { + enum UpgradeMethod: String, CaseIterable { case none case showInStatusBar case autoUpdate @@ -62,7 +62,7 @@ class PreferenceStore: ObservableObject { @Published var showNetworkTopActivities = false @Published var cpuMenuDisplay: Preference.CpuMenuDisplay = .usagePercentage @Published var checkStatusItemVisibility = true - @Published var updateMethod = UpdateMethod.showInStatusBar + @Published var upgradeMethod = UpgradeMethod.showInStatusBar @Published var isUpdateAvailable: Bool? = false @Published var checkUpdateFailed = true @@ -80,7 +80,7 @@ class PreferenceStore: ObservableObject { "showNetworkTopActivities": showNetworkTopActivities, "cpuMenuDisplay": cpuMenuDisplay.rawValue, "checkStatusItemVisibility": checkStatusItemVisibility, - "updateMethod": updateMethod.rawValue, + "upgradeMethod": upgradeMethod.rawValue, ]) } @@ -114,7 +114,7 @@ class PreferenceStore: ObservableObject { { self.isUpdateAvailable = true - if self.updateMethod == .autoUpdate { + if self.upgradeMethod == .autoUpdate { AutoUpdate.run() } } else { @@ -172,8 +172,8 @@ class PreferenceStore: ObservableObject { if let value = data["checkStatusItemVisibility"].bool { checkStatusItemVisibility = value } - if let raw = data["updateMethod"].string, let value = UpdateMethod(rawValue: raw) { - updateMethod = value + if let raw = data["updateMethod"].string, let value = UpgradeMethod(rawValue: raw) { + upgradeMethod = value } } catch { print("Unable to get preference data from user defaults") diff --git a/eul/Views/Preference/PreferenceGeneralView.swift b/eul/Views/Preference/PreferenceGeneralView.swift index b118cfea..03355d7b 100644 --- a/eul/Views/Preference/PreferenceGeneralView.swift +++ b/eul/Views/Preference/PreferenceGeneralView.swift @@ -63,9 +63,9 @@ extension Preference { } .fixedSize() } - Picker("ui.update_method".localized(), selection: $preference.updateMethod) { - ForEach(PreferenceStore.UpdateMethod.allCases, id: \.self) { - Text("ui.update_method.\($0)".localized()) + Picker("ui.upgrade_method".localized(), selection: $preference.upgradeMethod) { + ForEach(PreferenceStore.UpgradeMethod.allCases, id: \.self) { + Text("ui.upgrade_method.\($0)".localized()) .tag($0) } } From 61fdbf64ec04ea1ced321d29d39fb590e6c38235 Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Fri, 12 Feb 2021 22:57:08 +0800 Subject: [PATCH 5/7] Improved upgrade preference UX --- .../Upgrade.imageset/Contents.json | 16 ++++++++++++++++ .../Upgrade.imageset/arrow.up.circle.fill.pdf | Bin 0 -> 1903 bytes Resource/ar.lproj/Localizable.strings | 7 +++++++ Resource/cs.lproj/Localizable.strings | 7 +++++++ Resource/de.lproj/Localizable.strings | 7 +++++++ Resource/en.lproj/Localizable.strings | 7 +++++++ Resource/es.lproj/Localizable.strings | 7 +++++++ Resource/fr.lproj/Localizable.strings | 7 +++++++ Resource/it.lproj/Localizable.strings | 7 +++++++ Resource/ja.lproj/Localizable.strings | 7 +++++++ Resource/ko.lproj/Localizable.strings | 7 +++++++ Resource/mn.lproj/Localizable.strings | 7 +++++++ Resource/pt.lproj/Localizable.strings | 7 +++++++ Resource/ru.lproj/Localizable.strings | 7 +++++++ Resource/uk.lproj/Localizable.strings | 7 +++++++ Resource/zh-Hans.lproj/Localizable.strings | 7 +++++++ eul/Views/Menu/StatusMenuView.swift | 4 ++++ .../Preference/PreferenceGeneralView.swift | 3 +++ eul/Views/StatusBar/StatusBarView.swift | 8 ++++++++ 19 files changed, 129 insertions(+) create mode 100644 Resource/Assets.xcassets/Upgrade.imageset/Contents.json create mode 100644 Resource/Assets.xcassets/Upgrade.imageset/arrow.up.circle.fill.pdf diff --git a/Resource/Assets.xcassets/Upgrade.imageset/Contents.json b/Resource/Assets.xcassets/Upgrade.imageset/Contents.json new file mode 100644 index 00000000..b34f51af --- /dev/null +++ b/Resource/Assets.xcassets/Upgrade.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "arrow.up.circle.fill.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/Resource/Assets.xcassets/Upgrade.imageset/arrow.up.circle.fill.pdf b/Resource/Assets.xcassets/Upgrade.imageset/arrow.up.circle.fill.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7c7a140b8f7d3375ccf8da4be4b446d58ffb31b1 GIT binary patch literal 1903 zcmZuy%Z}7K5Z(JLycr1=IDVHcAtaaqgf57oVTV{WnJ_f!N$%}5SHRbE%1I|~hAdjn z>3W@0<;unN)r&_)kq|~|Ieh*mqL z)&0L~yUojI^74KC){f#oVU#Y9)ThIv<#hkQ<*)WmEa&@&vF%0B%BN&W&ylT@cY=~K zL-kr#+)aW$j(DbwPQb zEg}Hb2n$>1m9x<>rd3E>mUK=T9g6pYwZdss?e&?ZP2fq)DOlyaONdxuUXhDjJvy{n z29*ODwghLNG$tfOm7QZo$f7A3G8G>v5*3DvXMrY_O=3kzJAM zg$O-D8JcNiSF9DROmLiOMOkkuY7nZNN6ssgi)w4`R*){;q*&Ft7ldm~#DEg(5O$U%Z#u zfEwt9MK2xmq38&fdl9^f7&`P9GZ!X>fd*(CGk3k3&lTmqPP1Iwu2T=MvMuV{v0ktB z#_;|6B6{&o@MfIX-f2hjI-GVVYSGK;#0FYdYV)-3hvO(ee!_~y(|q{(Zzr4U?QJ&$ zZ@Qb^_Sx`5eq0yjvJd99l;~^)onmdeark~{yHWBQ-^>9ohyK|0$jLkW1YU0sz+{-A zYSS~cd;yw&b~h+iGKY;k<+&Wb!`IwnFaoI}#j{8g(aY^|yB}_6SEfDwt%x6o?u)=B z64NJxe`O581qpb54E8-gvR@#FI?o{E!k<={Tr}$3D){s#6fNYMt&WH7Zr>dQK8ek% xE6DL+9PYY@^1<%r;Ur448HS@|!bRZb{q9$X>dU8bdpH(4*l0#vTs(jK;y0^LkSYKG literal 0 HcmV?d00001 diff --git a/Resource/ar.lproj/Localizable.strings b/Resource/ar.lproj/Localizable.strings index 07cc9c5f..36f97992 100644 --- a/Resource/ar.lproj/Localizable.strings +++ b/Resource/ar.lproj/Localizable.strings @@ -166,6 +166,13 @@ "ui.hidden_by_system.open" = "افتح"; "ui.hidden_by_system.dismiss" = "رفض"; "ui.check_status_item_visibility" = "Check status item visibility"; +"ui.upgrade_method" = "Upgrade"; +"ui.upgrade_method.none" = "none"; +"ui.upgrade_method.none.description" = "eul will not check upgrade"; +"ui.upgrade_method.showInStatusBar" = "show in status bar"; +"ui.upgrade_method.showInStatusBar.description" = "Show upgrade icon when new version available"; +"ui.upgrade_method.autoUpdate" = "auto update"; +"ui.upgrade_method.autoUpdate.description" = "Perform upgrade automatically"; // MARK: Component "component.show_icon" = "Show icon"; diff --git a/Resource/cs.lproj/Localizable.strings b/Resource/cs.lproj/Localizable.strings index 9e5cf7ad..4b2c27b4 100644 --- a/Resource/cs.lproj/Localizable.strings +++ b/Resource/cs.lproj/Localizable.strings @@ -163,6 +163,13 @@ "ui.hidden_by_system.open" = "Otevřít"; "ui.hidden_by_system.dismiss" = "Zrušit"; "ui.check_status_item_visibility" = "Zkontrolovat status zobrazení položky"; +"ui.upgrade_method" = "Upgrade"; +"ui.upgrade_method.none" = "none"; +"ui.upgrade_method.none.description" = "eul will not check upgrade"; +"ui.upgrade_method.showInStatusBar" = "show in status bar"; +"ui.upgrade_method.showInStatusBar.description" = "Show upgrade icon when new version available"; +"ui.upgrade_method.autoUpdate" = "auto update"; +"ui.upgrade_method.autoUpdate.description" = "Perform upgrade automatically"; // MARK: Component "component.show_icon" = "Zobrazit ikonu"; diff --git a/Resource/de.lproj/Localizable.strings b/Resource/de.lproj/Localizable.strings index 560bf68a..4885a0c6 100644 --- a/Resource/de.lproj/Localizable.strings +++ b/Resource/de.lproj/Localizable.strings @@ -165,6 +165,13 @@ "ui.hidden_by_system.open" = "Öffnen"; "ui.hidden_by_system.dismiss" = "Ausblenden"; "ui.check_status_item_visibility" = "Sichtbarkeit in Menüleiste prüfen"; +"ui.upgrade_method" = "Upgrade"; +"ui.upgrade_method.none" = "none"; +"ui.upgrade_method.none.description" = "eul will not check upgrade"; +"ui.upgrade_method.showInStatusBar" = "show in status bar"; +"ui.upgrade_method.showInStatusBar.description" = "Show upgrade icon when new version available"; +"ui.upgrade_method.autoUpdate" = "auto update"; +"ui.upgrade_method.autoUpdate.description" = "Perform upgrade automatically"; // MARK: Component "component.show_icon" = "Symbol anzeigen"; diff --git a/Resource/en.lproj/Localizable.strings b/Resource/en.lproj/Localizable.strings index eae8c9ca..0eb5def9 100644 --- a/Resource/en.lproj/Localizable.strings +++ b/Resource/en.lproj/Localizable.strings @@ -165,6 +165,13 @@ "ui.hidden_by_system.open" = "Open"; "ui.hidden_by_system.dismiss" = "Dismiss"; "ui.check_status_item_visibility" = "Check status item visibility"; +"ui.upgrade_method" = "Upgrade"; +"ui.upgrade_method.none" = "none"; +"ui.upgrade_method.none.description" = "eul will not check upgrade"; +"ui.upgrade_method.showInStatusBar" = "show in status bar"; +"ui.upgrade_method.showInStatusBar.description" = "Show upgrade icon when new version available"; +"ui.upgrade_method.autoUpdate" = "auto update"; +"ui.upgrade_method.autoUpdate.description" = "Perform upgrade automatically"; // MARK: Component "component.show_icon" = "Show icon"; diff --git a/Resource/es.lproj/Localizable.strings b/Resource/es.lproj/Localizable.strings index 7c6ae8cb..729adbaf 100644 --- a/Resource/es.lproj/Localizable.strings +++ b/Resource/es.lproj/Localizable.strings @@ -165,6 +165,13 @@ "ui.hidden_by_system.open" = "Open"; "ui.hidden_by_system.dismiss" = "Dismiss"; "ui.check_status_item_visibility" = "Check status item visibility"; +"ui.upgrade_method" = "Upgrade"; +"ui.upgrade_method.none" = "none"; +"ui.upgrade_method.none.description" = "eul will not check upgrade"; +"ui.upgrade_method.showInStatusBar" = "show in status bar"; +"ui.upgrade_method.showInStatusBar.description" = "Show upgrade icon when new version available"; +"ui.upgrade_method.autoUpdate" = "auto update"; +"ui.upgrade_method.autoUpdate.description" = "Perform upgrade automatically"; // MARK: Component "component.show_icon" = "Mostrar icono"; diff --git a/Resource/fr.lproj/Localizable.strings b/Resource/fr.lproj/Localizable.strings index 51230f79..572f0a47 100644 --- a/Resource/fr.lproj/Localizable.strings +++ b/Resource/fr.lproj/Localizable.strings @@ -165,6 +165,13 @@ "ui.hidden_by_system.open" = "Ouvrir"; "ui.hidden_by_system.dismiss" = "Ignorer"; "ui.check_status_item_visibility" = "Vérifier la visibilité des composants"; +"ui.upgrade_method" = "Upgrade"; +"ui.upgrade_method.none" = "none"; +"ui.upgrade_method.none.description" = "eul will not check upgrade"; +"ui.upgrade_method.showInStatusBar" = "show in status bar"; +"ui.upgrade_method.showInStatusBar.description" = "Show upgrade icon when new version available"; +"ui.upgrade_method.autoUpdate" = "auto update"; +"ui.upgrade_method.autoUpdate.description" = "Perform upgrade automatically"; // MARK: Component "component.show_icon" = "Afficher l'icône"; diff --git a/Resource/it.lproj/Localizable.strings b/Resource/it.lproj/Localizable.strings index 6113eb8f..97e60ebc 100644 --- a/Resource/it.lproj/Localizable.strings +++ b/Resource/it.lproj/Localizable.strings @@ -162,6 +162,13 @@ "ui.hidden_by_system.open" = "Aperto"; "ui.hidden_by_system.dismiss" = "Chiudi"; "ui.check_status_item_visibility" = "Verifica visibilità nella barra dei menù"; +"ui.upgrade_method" = "Upgrade"; +"ui.upgrade_method.none" = "none"; +"ui.upgrade_method.none.description" = "eul will not check upgrade"; +"ui.upgrade_method.showInStatusBar" = "show in status bar"; +"ui.upgrade_method.showInStatusBar.description" = "Show upgrade icon when new version available"; +"ui.upgrade_method.autoUpdate" = "auto update"; +"ui.upgrade_method.autoUpdate.description" = "Perform upgrade automatically"; // MARK: Component "component.show_icon" = "Mostra icona"; diff --git a/Resource/ja.lproj/Localizable.strings b/Resource/ja.lproj/Localizable.strings index 2405ae32..31aba5ed 100644 --- a/Resource/ja.lproj/Localizable.strings +++ b/Resource/ja.lproj/Localizable.strings @@ -165,6 +165,13 @@ "ui.hidden_by_system.open" = "設定を開く"; "ui.hidden_by_system.dismiss" = "閉じる"; "ui.check_status_item_visibility" = "Check status item visibility"; +"ui.upgrade_method" = "Upgrade"; +"ui.upgrade_method.none" = "none"; +"ui.upgrade_method.none.description" = "eul will not check upgrade"; +"ui.upgrade_method.showInStatusBar" = "show in status bar"; +"ui.upgrade_method.showInStatusBar.description" = "Show upgrade icon when new version available"; +"ui.upgrade_method.autoUpdate" = "auto update"; +"ui.upgrade_method.autoUpdate.description" = "Perform upgrade automatically"; // MARK: Component "component.show_icon" = "アイコンを表示"; diff --git a/Resource/ko.lproj/Localizable.strings b/Resource/ko.lproj/Localizable.strings index 8a637376..a80042ce 100644 --- a/Resource/ko.lproj/Localizable.strings +++ b/Resource/ko.lproj/Localizable.strings @@ -168,6 +168,13 @@ battery.timeRemaining = "Time Rem."; "ui.hidden_by_system.open" = "열기"; "ui.hidden_by_system.dismiss" = "취소"; "ui.check_status_item_visibility" = "상태바 아이템이 보이는지 검사"; +"ui.upgrade_method" = "Upgrade"; +"ui.upgrade_method.none" = "none"; +"ui.upgrade_method.none.description" = "eul will not check upgrade"; +"ui.upgrade_method.showInStatusBar" = "show in status bar"; +"ui.upgrade_method.showInStatusBar.description" = "Show upgrade icon when new version available"; +"ui.upgrade_method.autoUpdate" = "auto update"; +"ui.upgrade_method.autoUpdate.description" = "Perform upgrade automatically"; // MARK: Component "component.show_icon" = "아이콘 보기"; diff --git a/Resource/mn.lproj/Localizable.strings b/Resource/mn.lproj/Localizable.strings index 853fc80f..324d72de 100644 --- a/Resource/mn.lproj/Localizable.strings +++ b/Resource/mn.lproj/Localizable.strings @@ -166,6 +166,13 @@ "ui.hidden_by_system.open" = "Нээх"; "ui.hidden_by_system.dismiss" = "Цуцлах"; "ui.check_status_item_visibility" = "Check status item visibility"; +"ui.upgrade_method" = "Upgrade"; +"ui.upgrade_method.none" = "none"; +"ui.upgrade_method.none.description" = "eul will not check upgrade"; +"ui.upgrade_method.showInStatusBar" = "show in status bar"; +"ui.upgrade_method.showInStatusBar.description" = "Show upgrade icon when new version available"; +"ui.upgrade_method.autoUpdate" = "auto update"; +"ui.upgrade_method.autoUpdate.description" = "Perform upgrade automatically"; // MARK: Component "component.show_icon" = "Аякон харах"; diff --git a/Resource/pt.lproj/Localizable.strings b/Resource/pt.lproj/Localizable.strings index c2eb8668..dfe71856 100644 --- a/Resource/pt.lproj/Localizable.strings +++ b/Resource/pt.lproj/Localizable.strings @@ -165,6 +165,13 @@ "ui.hidden_by_system.open" = "Open"; "ui.hidden_by_system.dismiss" = "Dismiss"; "ui.check_status_item_visibility" = "Check status item visibility"; +"ui.upgrade_method" = "Upgrade"; +"ui.upgrade_method.none" = "none"; +"ui.upgrade_method.none.description" = "eul will not check upgrade"; +"ui.upgrade_method.showInStatusBar" = "show in status bar"; +"ui.upgrade_method.showInStatusBar.description" = "Show upgrade icon when new version available"; +"ui.upgrade_method.autoUpdate" = "auto update"; +"ui.upgrade_method.autoUpdate.description" = "Perform upgrade automatically"; // MARK: Component "component.show_icon" = "Mostrar ícone"; diff --git a/Resource/ru.lproj/Localizable.strings b/Resource/ru.lproj/Localizable.strings index 20d72ed1..916baeda 100644 --- a/Resource/ru.lproj/Localizable.strings +++ b/Resource/ru.lproj/Localizable.strings @@ -165,6 +165,13 @@ "ui.hidden_by_system.open" = "Open"; "ui.hidden_by_system.dismiss" = "Dismiss"; "ui.check_status_item_visibility" = "Check status item visibility"; +"ui.upgrade_method" = "Upgrade"; +"ui.upgrade_method.none" = "none"; +"ui.upgrade_method.none.description" = "eul will not check upgrade"; +"ui.upgrade_method.showInStatusBar" = "show in status bar"; +"ui.upgrade_method.showInStatusBar.description" = "Show upgrade icon when new version available"; +"ui.upgrade_method.autoUpdate" = "auto update"; +"ui.upgrade_method.autoUpdate.description" = "Perform upgrade automatically"; // MARK: Component "component.show_icon" = "Показать иконки"; diff --git a/Resource/uk.lproj/Localizable.strings b/Resource/uk.lproj/Localizable.strings index 8a26625b..f48c41ec 100644 --- a/Resource/uk.lproj/Localizable.strings +++ b/Resource/uk.lproj/Localizable.strings @@ -165,6 +165,13 @@ "ui.hidden_by_system.open" = "Відкрити Налаштування"; "ui.hidden_by_system.dismiss" = "Відхилити"; "ui.check_status_item_visibility" = "Перевіряти видимість в смузі меню"; +"ui.upgrade_method" = "Upgrade"; +"ui.upgrade_method.none" = "none"; +"ui.upgrade_method.none.description" = "eul will not check upgrade"; +"ui.upgrade_method.showInStatusBar" = "show in status bar"; +"ui.upgrade_method.showInStatusBar.description" = "Show upgrade icon when new version available"; +"ui.upgrade_method.autoUpdate" = "auto update"; +"ui.upgrade_method.autoUpdate.description" = "Perform upgrade automatically"; // MARK: Component "component.show_icon" = "Відображати піктограму"; diff --git a/Resource/zh-Hans.lproj/Localizable.strings b/Resource/zh-Hans.lproj/Localizable.strings index 8cb5f956..f1b13e22 100644 --- a/Resource/zh-Hans.lproj/Localizable.strings +++ b/Resource/zh-Hans.lproj/Localizable.strings @@ -165,6 +165,13 @@ "ui.hidden_by_system.open" = "打开"; "ui.hidden_by_system.dismiss" = "忽略"; "ui.check_status_item_visibility" = "检查状态栏可见性"; +"ui.upgrade_method" = "升级"; +"ui.upgrade_method.none" = "无"; +"ui.upgrade_method.none.description" = "eul 将不会检查更新"; +"ui.upgrade_method.showInStatusBar" = "在状态栏展示"; +"ui.upgrade_method.showInStatusBar.description" = "当新版本可用时在状态栏显示图标"; +"ui.upgrade_method.autoUpdate" = "自动更新"; +"ui.upgrade_method.autoUpdate.description" = "自动进行升级"; // MARK: Component "component.show_icon" = "显示图标"; diff --git a/eul/Views/Menu/StatusMenuView.swift b/eul/Views/Menu/StatusMenuView.swift index a7eade35..0a9a9297 100644 --- a/eul/Views/Menu/StatusMenuView.swift +++ b/eul/Views/Menu/StatusMenuView.swift @@ -21,6 +21,10 @@ struct StatusMenuView: SizeChangeView { .font(.system(size: 12, weight: .semibold)) Text("v\(preferenceStore.version ?? "?")") .secondaryDisplayText() + if preferenceStore.isUpdateAvailable == true { + Text("ui.new_version".localized()) + .secondaryDisplayText() + } Spacer() MenuActionTextView(id: "menu.preferences", text: "menu.preferences", action: AppDelegate.openPreferences) MenuActionTextView(id: "menu.quit", text: "menu.quit", action: AppDelegate.quit) diff --git a/eul/Views/Preference/PreferenceGeneralView.swift b/eul/Views/Preference/PreferenceGeneralView.swift index 03355d7b..41274934 100644 --- a/eul/Views/Preference/PreferenceGeneralView.swift +++ b/eul/Views/Preference/PreferenceGeneralView.swift @@ -70,6 +70,9 @@ extension Preference { } } .fixedSize() + Text("ui.upgrade_method.\(preference.upgradeMethod.rawValue).description".localized()) + .secondaryDisplayText() + .padding(.bottom, 8) Toggle(isOn: $launchAtLogin.isEnabled) { Text("ui.launch_at_login".localized()) .inlineSection() diff --git a/eul/Views/StatusBar/StatusBarView.swift b/eul/Views/StatusBar/StatusBarView.swift index f20a212e..0ad8d1ae 100644 --- a/eul/Views/StatusBar/StatusBarView.swift +++ b/eul/Views/StatusBar/StatusBarView.swift @@ -28,6 +28,14 @@ struct StatusBarView: SizeChangeView { .resizable() .frame(width: 16, height: 16) } + if + preferenceStore.upgradeMethod == .showInStatusBar, + preferenceStore.isUpdateAvailable == true + { + Image("Upgrade") + .resizable() + .frame(width: 12, height: 12) + } } .fixedSize() .background(GeometryReader { self.reportSize($0) }) From 883ab7ba0036c2a25341f00f703433e727cbdb84 Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Fri, 12 Feb 2021 23:04:48 +0800 Subject: [PATCH 6/7] Skip install for SelfUpdate --- eul.xcodeproj/project.pbxproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/eul.xcodeproj/project.pbxproj b/eul.xcodeproj/project.pbxproj index ee8582a6..8e7e4b77 100644 --- a/eul.xcodeproj/project.pbxproj +++ b/eul.xcodeproj/project.pbxproj @@ -2099,6 +2099,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.SelfUpdate; PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; }; name = Debug; @@ -2122,6 +2123,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.SelfUpdate; PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; }; name = Release; From bde940fe294c36e4b04bbb3ab485c20a1829caff Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Fri, 12 Feb 2021 23:05:30 +0800 Subject: [PATCH 7/7] v1.5.11 --- eul.xcodeproj/project.pbxproj | 40 +++++++++++++++++------------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/eul.xcodeproj/project.pbxproj b/eul.xcodeproj/project.pbxproj index 8e7e4b77..b6254fe1 100644 --- a/eul.xcodeproj/project.pbxproj +++ b/eul.xcodeproj/project.pbxproj @@ -1702,7 +1702,7 @@ CODE_SIGN_ENTITLEMENTS = MemoryWidget/MemoryWidget.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 38; + CURRENT_PROJECT_VERSION = 39; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = MemoryWidget/Info.plist; @@ -1712,7 +1712,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.5.10; + MARKETING_VERSION = 1.5.11; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.MemoryWidget; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -1728,7 +1728,7 @@ CODE_SIGN_ENTITLEMENTS = MemoryWidget/MemoryWidget.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 38; + CURRENT_PROJECT_VERSION = 39; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = MemoryWidget/Info.plist; @@ -1738,7 +1738,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.5.10; + MARKETING_VERSION = 1.5.11; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.MemoryWidget; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -1754,7 +1754,7 @@ CODE_SIGN_ENTITLEMENTS = NetworkWidget/NetworkWidget.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 38; + CURRENT_PROJECT_VERSION = 39; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = NetworkWidget/Info.plist; @@ -1764,7 +1764,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.5.10; + MARKETING_VERSION = 1.5.11; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.NetworkWidget; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -1780,7 +1780,7 @@ CODE_SIGN_ENTITLEMENTS = NetworkWidget/NetworkWidget.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 38; + CURRENT_PROJECT_VERSION = 39; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = NetworkWidget/Info.plist; @@ -1790,7 +1790,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.5.10; + MARKETING_VERSION = 1.5.11; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.NetworkWidget; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -1925,7 +1925,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 38; + CURRENT_PROJECT_VERSION = 39; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; @@ -1937,7 +1937,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.15; - MARKETING_VERSION = 1.5.10; + MARKETING_VERSION = 1.5.11; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = ""; @@ -1956,7 +1956,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 38; + CURRENT_PROJECT_VERSION = 39; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; @@ -1968,7 +1968,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.15; - MARKETING_VERSION = 1.5.10; + MARKETING_VERSION = 1.5.11; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = ""; @@ -1984,7 +1984,7 @@ CODE_SIGN_ENTITLEMENTS = BatteryWidget/BatteryWidget.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 38; + CURRENT_PROJECT_VERSION = 39; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = BatteryWidget/Info.plist; @@ -1994,7 +1994,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.5.10; + MARKETING_VERSION = 1.5.11; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.BatteryWidget; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -2010,7 +2010,7 @@ CODE_SIGN_ENTITLEMENTS = BatteryWidget/BatteryWidget.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 38; + CURRENT_PROJECT_VERSION = 39; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = BatteryWidget/Info.plist; @@ -2020,7 +2020,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.5.10; + MARKETING_VERSION = 1.5.11; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.BatteryWidget; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -2036,7 +2036,7 @@ CODE_SIGN_ENTITLEMENTS = CpuWidget/CpuWidget.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 38; + CURRENT_PROJECT_VERSION = 39; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = CpuWidget/Info.plist; @@ -2046,7 +2046,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.5.10; + MARKETING_VERSION = 1.5.11; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.CpuWidget; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -2062,7 +2062,7 @@ CODE_SIGN_ENTITLEMENTS = CpuWidget/CpuWidget.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 38; + CURRENT_PROJECT_VERSION = 39; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = CpuWidget/Info.plist; @@ -2072,7 +2072,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.5.10; + MARKETING_VERSION = 1.5.11; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.CpuWidget; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES;