From c1e334d5d82b24531b3b8d2b53e8ad44a39dc22c Mon Sep 17 00:00:00 2001 From: Lukas Pistrol Date: Tue, 28 Nov 2023 14:49:27 +0100 Subject: [PATCH] improve menu bar icon (#5), minor UI improvements --- TimeMachineStatus/Localizable.xcstrings | 32 ++++++++++++++ .../Model/BackupState/Copying.swift | 4 ++ .../BackupState/FindingBackupVolume.swift | 4 ++ .../Model/BackupState/FindingChanges.swift | 4 ++ .../Model/BackupState/Finishing.swift | 4 ++ .../Model/BackupState/Idle.swift | 4 ++ .../Model/BackupState/Internal/_State.swift | 4 ++ .../Model/BackupState/Mounting.swift | 4 ++ .../Model/BackupState/Preparing.swift | 4 ++ .../Model/BackupState/Starting.swift | 4 ++ .../Model/BackupState/Stopping.swift | 4 ++ .../Model/BackupState/Thinning.swift | 4 ++ TimeMachineStatus/Symbols.swift | 1 + TimeMachineStatus/Views/DestinationCell.swift | 13 +++++- TimeMachineStatus/Views/SettingsView.swift | 24 +++++++++-- TimeMachineStatus/Views/StatusBarItem.swift | 43 +++++++++++++++++-- 16 files changed, 148 insertions(+), 9 deletions(-) diff --git a/TimeMachineStatus/Localizable.xcstrings b/TimeMachineStatus/Localizable.xcstrings index 10d708a..928817c 100644 --- a/TimeMachineStatus/Localizable.xcstrings +++ b/TimeMachineStatus/Localizable.xcstrings @@ -833,6 +833,22 @@ } } }, + "settings_item_boldicon" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fettes Symbol" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bold Icon" + } + } + } + }, "settings_item_cornerradius" : { "extractionState" : "manual", "localizations" : { @@ -933,6 +949,22 @@ } } }, + "settings_item_showpercentage" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prozent anzeigen" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Show Percentage" + } + } + } + }, "settings_item_showstatus" : { "extractionState" : "manual", "localizations" : { diff --git a/TimeMachineStatus/Model/BackupState/Copying.swift b/TimeMachineStatus/Model/BackupState/Copying.swift index d26d969..953d7d6 100644 --- a/TimeMachineStatus/Model/BackupState/Copying.swift +++ b/TimeMachineStatus/Model/BackupState/Copying.swift @@ -39,6 +39,10 @@ extension BackupState { override var statusString: String { "Copying Data" } + + override var shortStatusString: String { + "Copying" + } } } diff --git a/TimeMachineStatus/Model/BackupState/FindingBackupVolume.swift b/TimeMachineStatus/Model/BackupState/FindingBackupVolume.swift index 405f3ab..34f086c 100644 --- a/TimeMachineStatus/Model/BackupState/FindingBackupVolume.swift +++ b/TimeMachineStatus/Model/BackupState/FindingBackupVolume.swift @@ -21,5 +21,9 @@ extension BackupState { override var statusString: String { "Finding Backup Volume" } + + override var shortStatusString: String { + "Finding" + } } } diff --git a/TimeMachineStatus/Model/BackupState/FindingChanges.swift b/TimeMachineStatus/Model/BackupState/FindingChanges.swift index da12dce..fd7fb41 100644 --- a/TimeMachineStatus/Model/BackupState/FindingChanges.swift +++ b/TimeMachineStatus/Model/BackupState/FindingChanges.swift @@ -38,5 +38,9 @@ extension BackupState { override var statusString: String { "Finding Changes" } + + override var shortStatusString: String { + "Changes" + } } } diff --git a/TimeMachineStatus/Model/BackupState/Finishing.swift b/TimeMachineStatus/Model/BackupState/Finishing.swift index 588cd72..2c8277c 100644 --- a/TimeMachineStatus/Model/BackupState/Finishing.swift +++ b/TimeMachineStatus/Model/BackupState/Finishing.swift @@ -20,5 +20,9 @@ extension BackupState { override var statusString: String { "Finishing" } + + override var shortStatusString: String { + statusString + } } } diff --git a/TimeMachineStatus/Model/BackupState/Idle.swift b/TimeMachineStatus/Model/BackupState/Idle.swift index 7f02f78..3532639 100644 --- a/TimeMachineStatus/Model/BackupState/Idle.swift +++ b/TimeMachineStatus/Model/BackupState/Idle.swift @@ -27,5 +27,9 @@ extension BackupState { override var statusString: String { "Idle" } + + override var shortStatusString: String { + "Idle" + } } } diff --git a/TimeMachineStatus/Model/BackupState/Internal/_State.swift b/TimeMachineStatus/Model/BackupState/Internal/_State.swift index 4179c24..d1396e7 100644 --- a/TimeMachineStatus/Model/BackupState/Internal/_State.swift +++ b/TimeMachineStatus/Model/BackupState/Internal/_State.swift @@ -42,6 +42,10 @@ extension BackupState { fatalError("Implement!") } + var shortStatusString: String { + fatalError("Implement!") + } + var state: _BState { if let phase, running { switch phase { diff --git a/TimeMachineStatus/Model/BackupState/Mounting.swift b/TimeMachineStatus/Model/BackupState/Mounting.swift index 6f173a3..11dc19f 100644 --- a/TimeMachineStatus/Model/BackupState/Mounting.swift +++ b/TimeMachineStatus/Model/BackupState/Mounting.swift @@ -20,5 +20,9 @@ extension BackupState { override var statusString: String { "Mounting Disk Image" } + + override var shortStatusString: String { + "Mounting" + } } } diff --git a/TimeMachineStatus/Model/BackupState/Preparing.swift b/TimeMachineStatus/Model/BackupState/Preparing.swift index 36d3dd3..536b97a 100644 --- a/TimeMachineStatus/Model/BackupState/Preparing.swift +++ b/TimeMachineStatus/Model/BackupState/Preparing.swift @@ -20,5 +20,9 @@ extension BackupState { override var statusString: String { "Preparing" } + + override var shortStatusString: String { + statusString + } } } diff --git a/TimeMachineStatus/Model/BackupState/Starting.swift b/TimeMachineStatus/Model/BackupState/Starting.swift index e523cc5..66bd3fb 100644 --- a/TimeMachineStatus/Model/BackupState/Starting.swift +++ b/TimeMachineStatus/Model/BackupState/Starting.swift @@ -20,5 +20,9 @@ extension BackupState { override var statusString: String { "Starting" } + + override var shortStatusString: String { + statusString + } } } diff --git a/TimeMachineStatus/Model/BackupState/Stopping.swift b/TimeMachineStatus/Model/BackupState/Stopping.swift index 2391525..20804cc 100644 --- a/TimeMachineStatus/Model/BackupState/Stopping.swift +++ b/TimeMachineStatus/Model/BackupState/Stopping.swift @@ -20,5 +20,9 @@ extension BackupState { override var statusString: String { "Stopping" } + + override var shortStatusString: String { + statusString + } } } diff --git a/TimeMachineStatus/Model/BackupState/Thinning.swift b/TimeMachineStatus/Model/BackupState/Thinning.swift index 3d274c7..e4e2fb5 100644 --- a/TimeMachineStatus/Model/BackupState/Thinning.swift +++ b/TimeMachineStatus/Model/BackupState/Thinning.swift @@ -20,5 +20,9 @@ extension BackupState { override var statusString: String { "Thinning Backup Image" } + + override var shortStatusString: String { + "Thinning" + } } } diff --git a/TimeMachineStatus/Symbols.swift b/TimeMachineStatus/Symbols.swift index f640282..e24896f 100644 --- a/TimeMachineStatus/Symbols.swift +++ b/TimeMachineStatus/Symbols.swift @@ -12,6 +12,7 @@ import SwiftUI enum Symbols: String { + case arrowTriangleCirclepath = "arrow.triangle.2.circlepath" case checkmarkCircleFill = "checkmark.circle.fill" case exclamationMarkTriangleFill = "exclamationmark.triangle.fill" case externalDrive = "externaldrive.fill.badge.timemachine" diff --git a/TimeMachineStatus/Views/DestinationCell.swift b/TimeMachineStatus/Views/DestinationCell.swift index 5603873..a447de0 100644 --- a/TimeMachineStatus/Views/DestinationCell.swift +++ b/TimeMachineStatus/Views/DestinationCell.swift @@ -133,9 +133,18 @@ struct DestinationCell: View { utility.startBackup(id: dest.destinationID) } } label: { - utility.status.activeDestinationID == dest.destinationID ? Symbols.stopFill.image : Symbols.playFill.image + if utility.status.activeDestinationID == dest.destinationID { + Symbols.stopFill.image + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: 13) + } else { + Symbols.playFill.image + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: 13) + } } - .imageScale(.large) .buttonStyle(.custom) .focusable(false) } diff --git a/TimeMachineStatus/Views/SettingsView.swift b/TimeMachineStatus/Views/SettingsView.swift index b835c88..377a4af 100644 --- a/TimeMachineStatus/Views/SettingsView.swift +++ b/TimeMachineStatus/Views/SettingsView.swift @@ -22,10 +22,12 @@ enum StorageKeys { static let horizontalPadding = Key(id: "horizontalPadding", default: 0.0) static let verticalPadding = Key(id: "verticalPadding", default: 0.0) static let boldFont = Key(id: "boldFont", default: false) - static let showStatus = Key(id: "showStatus", default: false) + static let boldIcon = Key(id: "boldIcon", default: false) + static let showStatus = Key(id: "showStatus", default: true) static let spacing = Key(id: "spacing", default: 4.0) static let backgroundColor = Key(id: "backgroundColor", default: Color.clear) static let cornerRadius = Key(id: "cornerRadius", default: 5.0) + static let showPercentage = Key(id: "showPercentage", default: true) } struct SettingsView: View { @@ -39,9 +41,15 @@ struct SettingsView: View { @AppStorage(StorageKeys.boldFont.id) private var boldFont: Bool = StorageKeys.boldFont.default + @AppStorage(StorageKeys.boldIcon.id) + private var boldIcon: Bool = StorageKeys.boldIcon.default + @AppStorage(StorageKeys.showStatus.id) private var showStatus: Bool = StorageKeys.showStatus.default + @AppStorage(StorageKeys.showPercentage.id) + private var showPercentage: Bool = StorageKeys.showPercentage.default + @AppStorage(StorageKeys.spacing.id) private var spacing: Double = StorageKeys.spacing.default @@ -73,7 +81,7 @@ struct SettingsView: View { appearandeTab aboutTab } - .frame(width: 375, height: 420) + .frame(width: 375, height: 350) } private var generalTab: some View { @@ -127,6 +135,8 @@ struct SettingsView: View { } label: { Text("settings_item_horizontalpadding") } + } + Section { HStack { ColorPicker("settings_item_backgroundcolor", selection: $bgColor) Button("settings_button_default") { @@ -153,9 +163,15 @@ struct SettingsView: View { Text("settings_item_cornerradius") } } + } + Section { Toggle("settings_item_boldfont", isOn: $boldFont) + Toggle("settings_item_boldicon", isOn: $boldIcon) + } + Section { Toggle("settings_item_showstatus", isOn: $showStatus) - if showStatus { + Toggle("settings_item_showpercentage", isOn: $showPercentage) + if showStatus || showPercentage { LabeledContent { HStack { Text(spacing.formatted(.number) + " pt") @@ -174,7 +190,9 @@ struct SettingsView: View { horizontalPadding = StorageKeys.horizontalPadding.default verticalPadding = StorageKeys.verticalPadding.default boldFont = StorageKeys.boldFont.default + boldIcon = StorageKeys.boldIcon.default showStatus = StorageKeys.showStatus.default + showPercentage = StorageKeys.showPercentage.default spacing = StorageKeys.spacing.default bgColor = StorageKeys.backgroundColor.default cornerRadius = StorageKeys.cornerRadius.default diff --git a/TimeMachineStatus/Views/StatusBarItem.swift b/TimeMachineStatus/Views/StatusBarItem.swift index 6347195..29a49b0 100644 --- a/TimeMachineStatus/Views/StatusBarItem.swift +++ b/TimeMachineStatus/Views/StatusBarItem.swift @@ -33,9 +33,15 @@ struct StatusBarItem: View { @AppStorage(StorageKeys.boldFont.id) private var boldFont: Bool = StorageKeys.boldFont.default + @AppStorage(StorageKeys.boldIcon.id) + private var boldIcon: Bool = StorageKeys.boldIcon.default + @AppStorage(StorageKeys.showStatus.id) private var showStatus: Bool = StorageKeys.showStatus.default + @AppStorage(StorageKeys.showPercentage.id) + private var showPercentage: Bool = StorageKeys.showPercentage.default + @AppStorage(StorageKeys.spacing.id) private var spacing: Double = StorageKeys.spacing.default @@ -48,13 +54,24 @@ struct StatusBarItem: View { var sizePassthrough: PassthroughSubject @ObservedObject var utility: TMUtility + private var mainContent: some View { HStack(spacing: spacing) { - Symbols.timeMachine.image - .font(.body.weight(boldFont ? .bold : .medium)) - if showStatus { - Text(utility.status.statusString) + if utility.isIdle { + Symbols.timeMachine.image + .font(.body.weight(boldIcon ? .bold : .medium)) + } else { + AnimatedIcon() + .font(.body.weight(boldIcon ? .bold : .medium)) + } + if showStatus, !utility.isIdle { + Text(utility.status.shortStatusString) + .font(.caption2.weight(boldFont ? .bold : .medium)) + } + if let percentage = utility.status.progessPercentage, showPercentage { + Text(percentage, format: .percent.precision(.fractionLength(0))) .font(.caption2.weight(boldFont ? .bold : .medium)) + .monospacedDigit() } } .foregroundStyle(.primary) @@ -78,6 +95,24 @@ struct StatusBarItem: View { } .offset(y: -1) } + + struct AnimatedIcon: View { + @State private var isAnimating = false + + private var rotationAnimation: Animation { .linear(duration: 2).repeatForever(autoreverses: false) } + + var body: some View { + Symbols.arrowTriangleCirclepath.image + .rotationEffect(Angle(degrees: isAnimating ? 360 : 0), anchor: .center) + .onAppear { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + withAnimation(rotationAnimation) { + isAnimating = true + } + } + } + } + } } #Preview {