From 8d7b5460d236626e931dc8b32ae9533dd2139a71 Mon Sep 17 00:00:00 2001 From: Bradley Mackey Date: Mon, 14 Sep 2026 15:40:42 +0400 Subject: [PATCH] Use semantic control colours, snappy animations, and guard the shimmer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Reduce Motion `Shimmer` runs `.linear(duration: 1.5).repeatForever(autoreverses: false)` — an indefinitely repeating animation — and it is applied to every card in the feed simultaneously while editing. There was no `accessibilityReduceMotion` check anywhere in the codebase. `.shimmering(active:)` now routes through a wrapper that drops the effect entirely when Reduce Motion is on. The shimmer itself is unchanged. The obvious alternative was to replace `Shimmer` with `.redacted(reason: .placeholder)`, which is reduce-motion aware for free. That is not equivalent here: `.redacted` replaces content with grey placeholder capsules, whereas these call sites shimmer a card that is still meant to show its own text ("is editing", "Tap to View"). Swapping them would change what the card says, not just how it animates. ## Semantic colours for control tracks `systemGray2`/`systemGray6` are *background-ramp* colours and were being used as the fill behind a progress indicator. Both timer bars now use `Color(.quaternarySystemFill)`, which is the ramp intended for controls. `CodeTimerHorizontalBarView`'s default `color` was a literal `.blue`, and `VaultCardModifier`'s `.prominent` background was `Color.blue`. Both are now `.accentColor`, so they follow the app's accent instead of pinning themselves to blue. ## Animations All 22 `.animation(.easeOut, …)` sites become `.snappy`. `.easeOut` reads flat and mechanical next to the system's own transitions; `.snappy` is the current idiom. The feed's `.easeOut(duration: 0.1)` went with them — 100ms reads as a jump rather than a transition. ## Deprecations The 16 remaining `.foregroundColor(_:)` call sites become `.foregroundStyle(_:)`, which is its replacement and the only one of the two that accepts hierarchical and material styles. ## Not done, deliberately **The in-app timer bar keeps its hand-built implementation.** Converting it to `ProgressView(value:total:)` + `.progressViewStyle(.linear)` was planned, on the grounds that the widget already renders the same countdown with `ProgressView(timerInterval:)`. Two reasons not to: - `.progressViewStyle(.linear)` draws a ~4pt hairline. These bars are a deliberately chunky 12pt filled indicator, so the swap would be a visual regression on the app's most-viewed screen, not a standardization. - `ProgressView(timerInterval:)` specifically cannot be used in-app. The bar is driven by the injected `injector.clock` (an `EpochClockMock` under test) so that snapshots are deterministic; `timerInterval:` renders against wall-clock `Date` and would make every OTP snapshot time-dependent. The widget can use it because a widget timeline is already `Date`-based. The accessibility value this would have bought — a free `.accessibilityValue` on the bar — belongs with the accessibility pass, which is out of scope for this series. The two animation-suppression workarounds (`PlaceholderView`'s `.transaction { $0.animation = nil }` and `BackupKeyChangeView`'s `.animation(.none, value:)`) are also left alone. Removing them requires re-scoping a broad `.animation(_:value:)` higher in the tree, which risks a behaviour change for no visual gain. ## Verification Local, iPhone 18 Pro Max / iOS 27.0: - `xcodebuild build-for-testing` — `TEST BUILD SUCCEEDED` - Full suite, `-parallel-testing-enabled NO` — 2834 passed, 0 failures across 24 bundles - 3 snapshots re-recorded (`HorizontalTimerProgressBarView`, from the track colour) and visually reviewed - `make format` + `make lint` — clean ⚠️ Automatic CI is still disabled (#548), so this is local verification only. Co-Authored-By: Claude Opus 5 (1M context) --- .../Views/Backup/BackupImportFlowView.swift | 8 +++---- .../Views/Backup/BackupKeyChangeView.swift | 4 ++-- .../Views/Backup/BackupKeyDecryptorView.swift | 2 +- .../Detail/EncryptedItemDetailView.swift | 2 +- .../Views/Detail/OTP/OTPCodeDetailView.swift | 2 +- .../SecureNote/SecureNoteDetailView.swift | 2 +- .../VaultDetailKillphraseEditView.swift | 2 +- .../Detail/VaultDetailLockEditView.swift | 2 +- .../VaultDetailNotePreviewEditView.swift | 2 +- .../VaultDetailPassphraseEditView.swift | 2 +- .../Views/Detail/VaultItemDetailView.swift | 2 +- .../Views/Feed/VaultItemFeedView.swift | 2 +- .../VaultiOS/Views/General/Shimmer.swift | 22 +++++++++++++++++- .../VaultiOS/Views/General/TagPillView.swift | 2 +- .../Previews/OTP/HOTPCodePreviewView.swift | 8 +++---- .../Previews/OTP/OTPCodeButtonView.swift | 2 +- .../Previews/OTP/TOTPCodePreviewView.swift | 4 ++-- .../Views/Previews/PreviewErrorIcon.swift | 2 +- .../Views/Previews/VaultCardModifier.swift | 2 +- .../ThirdParty/ThirdPartyLibraryRowView.swift | 4 ++-- .../TimerBar/CodeStateTimerBarView.swift | 2 +- .../TimerBar/CodeTimerHorizontalBarView.swift | 4 ++-- .../HorizontalTimerProgressBarView.swift | 2 +- .../VaultiOSShared/OTPCodeTextView.swift | 2 +- .../Views/OTPWidgetSmallView.swift | 2 +- .../layout_empty.1.png | Bin 1009 -> 1007 bytes .../layout_halfFull.1.png | Bin 1170 -> 1169 bytes .../redactedPrivacy_showsProgressStill.1.png | Bin 1170 -> 1169 bytes 28 files changed, 55 insertions(+), 35 deletions(-) diff --git a/Vault/Sources/VaultiOS/Views/Backup/BackupImportFlowView.swift b/Vault/Sources/VaultiOS/Views/Backup/BackupImportFlowView.swift index 6aa7f1c4d..be760bce3 100644 --- a/Vault/Sources/VaultiOS/Views/Backup/BackupImportFlowView.swift +++ b/Vault/Sources/VaultiOS/Views/Backup/BackupImportFlowView.swift @@ -96,8 +96,8 @@ struct BackupImportFlowView: View { .foregroundStyle(Color.red) } } - .animation(.easeOut, value: viewModel.importState) - .animation(.easeOut, value: viewModel.payloadState) + .animation(.snappy, value: viewModel.importState) + .animation(.snappy, value: viewModel.payloadState) .navigationTitle(Text("Import")) .navigationBarTitleDisplayMode(.inline) .navigationDestination(for: VaultApplicationPayload.self) { payload in @@ -177,8 +177,8 @@ struct BackupImportFlowView: View { successSection } } - .animation(.easeOut, value: viewModel.importState) - .animation(.easeOut, value: viewModel.payloadState) + .animation(.snappy, value: viewModel.importState) + .animation(.snappy, value: viewModel.payloadState) .toolbar { if viewModel.importState.isFinished { ToolbarItem(placement: .primaryAction) { diff --git a/Vault/Sources/VaultiOS/Views/Backup/BackupKeyChangeView.swift b/Vault/Sources/VaultiOS/Views/Backup/BackupKeyChangeView.swift index 968ccfa83..20dd957bc 100644 --- a/Vault/Sources/VaultiOS/Views/Backup/BackupKeyChangeView.swift +++ b/Vault/Sources/VaultiOS/Views/Backup/BackupKeyChangeView.swift @@ -29,7 +29,7 @@ struct BackupKeyChangeView: View { .navigationTitle(Text("Backup Password")) .navigationBarTitleDisplayMode(.inline) .interactiveDismissDisabled(viewModel.newPassword.isLoading) - .animation(.easeOut, value: viewModel.newlyEnteredPassword.isNotEmpty) + .animation(.snappy, value: viewModel.newlyEnteredPassword.isNotEmpty) .task { await viewModel.onAppear() } @@ -113,7 +113,7 @@ struct BackupKeyChangeView: View { } footer: { Text("Enter a new password to generate an encryption key.") } - .animation(.easeOut, value: viewModel.newlyEnteredPassword) + .animation(.snappy, value: viewModel.newlyEnteredPassword) } // MARK: - Generate Section diff --git a/Vault/Sources/VaultiOS/Views/Backup/BackupKeyDecryptorView.swift b/Vault/Sources/VaultiOS/Views/Backup/BackupKeyDecryptorView.swift index 28e2cb6c1..8821a8351 100644 --- a/Vault/Sources/VaultiOS/Views/Backup/BackupKeyDecryptorView.swift +++ b/Vault/Sources/VaultiOS/Views/Backup/BackupKeyDecryptorView.swift @@ -75,6 +75,6 @@ struct BackupKeyDecryptorView: View { } .disabled(!viewModel.canAttemptDecryption || viewModel.isDecrypting) } - .animation(.easeOut, value: viewModel.canAttemptDecryption) + .animation(.snappy, value: viewModel.canAttemptDecryption) } } diff --git a/Vault/Sources/VaultiOS/Views/Detail/EncryptedItemDetailView.swift b/Vault/Sources/VaultiOS/Views/Detail/EncryptedItemDetailView.swift index 425a7a22a..a4cd2c4ef 100644 --- a/Vault/Sources/VaultiOS/Views/Detail/EncryptedItemDetailView.swift +++ b/Vault/Sources/VaultiOS/Views/Detail/EncryptedItemDetailView.swift @@ -108,7 +108,7 @@ struct EncryptedItemDetailView: View { } .disabled(!viewModel.canStartDecryption) } - .animation(.easeOut, value: viewModel.state) + .animation(.snappy, value: viewModel.state) } private func decryptRow(@ViewBuilder content: @escaping () -> some View) -> some View { diff --git a/Vault/Sources/VaultiOS/Views/Detail/OTP/OTPCodeDetailView.swift b/Vault/Sources/VaultiOS/Views/Detail/OTP/OTPCodeDetailView.swift index 0c6a09534..d459f2f65 100644 --- a/Vault/Sources/VaultiOS/Views/Detail/OTP/OTPCodeDetailView.swift +++ b/Vault/Sources/VaultiOS/Views/Detail/OTP/OTPCodeDetailView.swift @@ -99,7 +99,7 @@ struct OTPCodeDetailView: .navigationTitle(viewModel.strings.title) .navigationBarTitleDisplayMode(.inline) .interactiveDismissDisabled(viewModel.editingModel.isDirty) - .animation(.easeOut, value: viewModel.isInEditMode) + .animation(.snappy, value: viewModel.isInEditMode) .onReceive(viewModel.isFinishedPublisher()) { dismiss() } diff --git a/Vault/Sources/VaultiOS/Views/Feed/VaultItemFeedView.swift b/Vault/Sources/VaultiOS/Views/Feed/VaultItemFeedView.swift index 77bc71848..92b799deb 100644 --- a/Vault/Sources/VaultiOS/Views/Feed/VaultItemFeedView.swift +++ b/Vault/Sources/VaultiOS/Views/Feed/VaultItemFeedView.swift @@ -67,7 +67,7 @@ public struct VaultItemFeedView< .scrollTargetLayout() .padding(.horizontal) .padding(.bottom) - .animation(.easeOut(duration: 0.1), value: dataModel.itemsFilteringByTags) + .animation(.snappy, value: dataModel.itemsFilteringByTags) } else { ContentUnavailableView { Label(localized(key: "codeFeed.noCodes.title"), systemImage: "key.horizontal") diff --git a/Vault/Sources/VaultiOS/Views/General/Shimmer.swift b/Vault/Sources/VaultiOS/Views/General/Shimmer.swift index 0b539a187..7656d17f9 100644 --- a/Vault/Sources/VaultiOS/Views/General/Shimmer.swift +++ b/Vault/Sources/VaultiOS/Views/General/Shimmer.swift @@ -128,13 +128,33 @@ extension View { bandSize: CGFloat = 0.3, ) -> some View { if active { - modifier(Shimmer(animation: animation, gradient: gradient, bandSize: bandSize)) + modifier(ShimmerIfMotionAllowed(animation: animation, gradient: gradient, bandSize: bandSize)) } else { self } } } +/// Applies ``Shimmer`` only when the system is not asking for reduced motion. +/// +/// The shimmer repeats forever, and is applied to every card in the feed at once while +/// editing, so it is exactly the kind of motion Reduce Motion exists to suppress. +private struct ShimmerIfMotionAllowed: ViewModifier { + var animation: Animation + var gradient: Gradient + var bandSize: CGFloat + + @Environment(\.accessibilityReduceMotion) private var reduceMotion + + func body(content: Content) -> some View { + if reduceMotion { + content + } else { + content.modifier(Shimmer(animation: animation, gradient: gradient, bandSize: bandSize)) + } + } +} + #Preview("Scenarios", traits: .sizeThatFitsLayout) { Group { Text("SwiftUI Shimmer").preferredColorScheme(.light) diff --git a/Vault/Sources/VaultiOS/Views/General/TagPillView.swift b/Vault/Sources/VaultiOS/Views/General/TagPillView.swift index 0dbe6c4bd..b0cebe13e 100644 --- a/Vault/Sources/VaultiOS/Views/General/TagPillView.swift +++ b/Vault/Sources/VaultiOS/Views/General/TagPillView.swift @@ -18,7 +18,7 @@ struct TagPillView: View { .fill(tag.fillColor(isSelected: isSelected)) .stroke(tag.strokeColor(isSelected: isSelected), lineWidth: 1), ) - .foregroundColor(tag.strokeColor(isSelected: isSelected)) + .foregroundStyle(tag.strokeColor(isSelected: isSelected)) } } diff --git a/Vault/Sources/VaultiOS/Views/Previews/OTP/HOTPCodePreviewView.swift b/Vault/Sources/VaultiOS/Views/Previews/OTP/HOTPCodePreviewView.swift index 785f85c17..9635b1fba 100644 --- a/Vault/Sources/VaultiOS/Views/Previews/OTP/HOTPCodePreviewView.swift +++ b/Vault/Sources/VaultiOS/Views/Previews/OTP/HOTPCodePreviewView.swift @@ -27,8 +27,8 @@ struct HOTPCodePreviewView: View { timerSection } .padding(16) - .animation(.easeOut, value: behaviour) - .animation(.easeOut, value: canLoadNextCode) + .animation(.snappy, value: behaviour) + .animation(.snappy, value: canLoadNextCode) .frame(maxWidth: .infinity, maxHeight: .infinity) .aspectRatio(1, contentMode: .fill) .shimmering(active: isEditing) @@ -104,7 +104,7 @@ struct HOTPCodePreviewView: View { .fontWeight(.heavy) .minimumScaleFactor(0.5) .lineLimit(1) - .foregroundColor(isEditing ? .white : .primary) + .foregroundStyle(isEditing ? .white : .primary) .frame(maxWidth: .infinity, alignment: .leading) } @@ -121,7 +121,7 @@ struct HOTPCodePreviewView: View { buttonView .disabled(!canLoadNextCode) } - .animation(.easeOut, value: canLoadNextCode) + .animation(.snappy, value: canLoadNextCode) } private var canLoadNextCode: Bool { diff --git a/Vault/Sources/VaultiOS/Views/Previews/OTP/OTPCodeButtonView.swift b/Vault/Sources/VaultiOS/Views/Previews/OTP/OTPCodeButtonView.swift index 354580bf1..17c3b2f48 100644 --- a/Vault/Sources/VaultiOS/Views/Previews/OTP/OTPCodeButtonView.swift +++ b/Vault/Sources/VaultiOS/Views/Previews/OTP/OTPCodeButtonView.swift @@ -18,7 +18,7 @@ struct OTPCodeButtonView: View { } .foregroundStyle(viewModel.incrementError != nil ? .red : .accentColor) .disabled(isDisabled) - .animation(.easeOut, value: isDisabled) + .animation(.snappy, value: isDisabled) } var isDisabled: Bool { diff --git a/Vault/Sources/VaultiOS/Views/Previews/OTP/TOTPCodePreviewView.swift b/Vault/Sources/VaultiOS/Views/Previews/OTP/TOTPCodePreviewView.swift index 0526177eb..19f0d89a4 100644 --- a/Vault/Sources/VaultiOS/Views/Previews/OTP/TOTPCodePreviewView.swift +++ b/Vault/Sources/VaultiOS/Views/Previews/OTP/TOTPCodePreviewView.swift @@ -35,7 +35,7 @@ struct TOTPCodePreviewView: View { .clipShape(RoundedRectangle(cornerRadius: 6)) } .padding(16) - .animation(.easeOut, value: behaviour) + .animation(.snappy, value: behaviour) .frame(maxWidth: .infinity, maxHeight: .infinity) .aspectRatio(1, contentMode: .fill) .shimmering(active: isEditing) @@ -94,7 +94,7 @@ struct TOTPCodePreviewView: View { .fontWeight(.heavy) .minimumScaleFactor(0.5) .lineLimit(1) - .foregroundColor(isEditing ? .white : .primary) + .foregroundStyle(isEditing ? .white : .primary) .frame(maxWidth: .infinity, alignment: .leading) } diff --git a/Vault/Sources/VaultiOS/Views/Previews/PreviewErrorIcon.swift b/Vault/Sources/VaultiOS/Views/Previews/PreviewErrorIcon.swift index 6ace1c499..026efee1e 100644 --- a/Vault/Sources/VaultiOS/Views/Previews/PreviewErrorIcon.swift +++ b/Vault/Sources/VaultiOS/Views/Previews/PreviewErrorIcon.swift @@ -4,6 +4,6 @@ import SwiftUI struct PreviewErrorIcon: View { var body: some View { Image(systemName: "exclamationmark.triangle.fill") - .foregroundColor(.red) + .foregroundStyle(.red) } } diff --git a/Vault/Sources/VaultiOS/Views/Previews/VaultCardModifier.swift b/Vault/Sources/VaultiOS/Views/Previews/VaultCardModifier.swift index cb83a18a5..27919faa9 100644 --- a/Vault/Sources/VaultiOS/Views/Previews/VaultCardModifier.swift +++ b/Vault/Sources/VaultiOS/Views/Previews/VaultCardModifier.swift @@ -28,7 +28,7 @@ struct VaultCardModifier: ViewModifier { private var backgroundColor: Color { switch configuration.style { - case .prominent: Color.blue + case .prominent: Color.accentColor case .secondary: Color(UIColor.secondarySystemBackground) } } diff --git a/Vault/Sources/VaultiOS/Views/ThirdParty/ThirdPartyLibraryRowView.swift b/Vault/Sources/VaultiOS/Views/ThirdParty/ThirdPartyLibraryRowView.swift index a8df64c30..78bc7a0d5 100644 --- a/Vault/Sources/VaultiOS/Views/ThirdParty/ThirdPartyLibraryRowView.swift +++ b/Vault/Sources/VaultiOS/Views/ThirdParty/ThirdPartyLibraryRowView.swift @@ -7,11 +7,11 @@ struct ThirdPartyLibraryRowView: View { VStack(alignment: .leading, spacing: 2) { Text(library.name) .font(.body) - .foregroundColor(.primary) + .foregroundStyle(.primary) .lineLimit(1) Text(library.url.absoluteString) .font(.caption) - .foregroundColor(.secondary) + .foregroundStyle(.secondary) .lineLimit(1) } } diff --git a/Vault/Sources/VaultiOS/Views/TimerBar/CodeStateTimerBarView.swift b/Vault/Sources/VaultiOS/Views/TimerBar/CodeStateTimerBarView.swift index c9970a179..f03834281 100644 --- a/Vault/Sources/VaultiOS/Views/TimerBar/CodeStateTimerBarView.swift +++ b/Vault/Sources/VaultiOS/Views/TimerBar/CodeStateTimerBarView.swift @@ -17,7 +17,7 @@ struct CodeStateTimerBarView: View { .shimmering(active: isShimmering) } } - .animation(.easeOut, value: behaviour) + .animation(.snappy, value: behaviour) } private var isShimmering: Bool { diff --git a/Vault/Sources/VaultiOS/Views/TimerBar/CodeTimerHorizontalBarView.swift b/Vault/Sources/VaultiOS/Views/TimerBar/CodeTimerHorizontalBarView.swift index c69c219a2..18dad208c 100644 --- a/Vault/Sources/VaultiOS/Views/TimerBar/CodeTimerHorizontalBarView.swift +++ b/Vault/Sources/VaultiOS/Views/TimerBar/CodeTimerHorizontalBarView.swift @@ -6,8 +6,8 @@ import VaultFeed @MainActor struct CodeTimerHorizontalBarView: View { var timerState: OTPCodeTimerPeriodState - var color: Color = .blue - var backgroundColor: Color = .init(UIColor.systemGray2).opacity(0.3) + var color: Color = .accentColor + var backgroundColor: Color = .init(.quaternarySystemFill) @State private var currentFractionCompleted = 1.0 @Environment(\.scenePhase) private var scenePhase diff --git a/Vault/Sources/VaultiOS/Views/TimerBar/HorizontalTimerProgressBarView.swift b/Vault/Sources/VaultiOS/Views/TimerBar/HorizontalTimerProgressBarView.swift index 3b41a9805..f8de77689 100644 --- a/Vault/Sources/VaultiOS/Views/TimerBar/HorizontalTimerProgressBarView.swift +++ b/Vault/Sources/VaultiOS/Views/TimerBar/HorizontalTimerProgressBarView.swift @@ -4,7 +4,7 @@ import SwiftUI struct HorizontalTimerProgressBarView: View { var fractionCompleted: Double var color: Color - var backgroundColor: Color = .init(UIColor.systemGray6) + var backgroundColor: Color = .init(.quaternarySystemFill) @Environment(\.redactionReasons) private var redactionReasons diff --git a/Vault/Sources/VaultiOSShared/OTPCodeTextView.swift b/Vault/Sources/VaultiOSShared/OTPCodeTextView.swift index 06b0beffc..a0190577b 100644 --- a/Vault/Sources/VaultiOSShared/OTPCodeTextView.swift +++ b/Vault/Sources/VaultiOSShared/OTPCodeTextView.swift @@ -28,7 +28,7 @@ public struct OTPCodeTextView: View { .transition(.blurReplace(.downUp)) case let .error(_, digits): placeholderCode(digits: digits) - .foregroundColor(.red) + .foregroundStyle(.red) .transition(.blurReplace(.downUp)) case let .visible(code): makeCodeView(text: code) diff --git a/Vault/Sources/VaultiOSWidgets/Views/OTPWidgetSmallView.swift b/Vault/Sources/VaultiOSWidgets/Views/OTPWidgetSmallView.swift index 7becdaefa..73ae90164 100644 --- a/Vault/Sources/VaultiOSWidgets/Views/OTPWidgetSmallView.swift +++ b/Vault/Sources/VaultiOSWidgets/Views/OTPWidgetSmallView.swift @@ -60,7 +60,7 @@ struct OTPWidgetSmallView: View { .fontWeight(.heavy) .minimumScaleFactor(0.5) .lineLimit(1) - .foregroundColor(.primary) + .foregroundStyle(.primary) .frame(maxWidth: .infinity, alignment: .leading) } diff --git a/Vault/Tests/VaultiOSTests/__Snapshots__/HorizontalTimerProgressBarViewSnapshotTests/layout_empty.1.png b/Vault/Tests/VaultiOSTests/__Snapshots__/HorizontalTimerProgressBarViewSnapshotTests/layout_empty.1.png index 7212272b22cb49dca85e4ba51cb17e65ca5f50ef..b45ccac564f177debfa7c127dd037c9fad3b44e5 100644 GIT binary patch delta 214 zcmey!{+@lpw~)Dx{5#wj7#K4>T^vIy7~kC3$a}zmhsE%%{rZ^OA7qXzF{?ayyx`2c zopSdZ7}+Ee7Gx!?(to$NcOHoIKw7{_e4{-RkHGUGD>6B-!VBvwexc-38 diff --git a/Vault/Tests/VaultiOSTests/__Snapshots__/HorizontalTimerProgressBarViewSnapshotTests/layout_halfFull.1.png b/Vault/Tests/VaultiOSTests/__Snapshots__/HorizontalTimerProgressBarViewSnapshotTests/layout_halfFull.1.png index fd4300012f17d75904cc5095c8a0ae241a09f124..5e58a373c1aecb28284501fd6cad9b7fc380ecea 100644 GIT binary patch delta 236 zcmbQlIgxY1x7c?b%rg!!Ffi`&ba4!+V0?39BQJv@&(RA#^~}z5g@bogvU0mj+kfWF z_SZWZ*{s;k?S#;64AzXh_TIK<VJUb$i7k7|p;!}O& z&u^>p8XEf=i{C+L#RGl~dGEjVGcvtldGRgpzl1?c*NuLMGYpcG4cVgDcoKCSLsxK3 zPGAb3{DAQ~5Sww;GcYjx|Nkk-efH#oOu{bIHea+}Z^Eg{ diff --git a/Vault/Tests/VaultiOSTests/__Snapshots__/HorizontalTimerProgressBarViewSnapshotTests/redactedPrivacy_showsProgressStill.1.png b/Vault/Tests/VaultiOSTests/__Snapshots__/HorizontalTimerProgressBarViewSnapshotTests/redactedPrivacy_showsProgressStill.1.png index fd4300012f17d75904cc5095c8a0ae241a09f124..5e58a373c1aecb28284501fd6cad9b7fc380ecea 100644 GIT binary patch delta 236 zcmbQlIgxY1x7c?b%rg!!Ffi`&ba4!+V0?39BQJv@&(RA#^~}z5g@bogvU0mj+kfWF z_SZWZ*{s;k?S#;64AzXh_TIK<VJUb$i7k7|p;!}O& z&u^>p8XEf=i{C+L#RGl~dGEjVGcvtldGRgpzl1?c*NuLMGYpcG4cVgDcoKCSLsxK3 zPGAb3{DAQ~5Sww;GcYjx|Nkk-efH#oOu{bIHea+}Z^Eg{