diff options
| author | Christian Cleberg <[email protected]> | 2026-04-13 09:57:23 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-04-13 09:57:23 -0500 |
| commit | 0e461a382257979037e8927e5f6b468635b0a7fe (patch) | |
| tree | 0aa3a19f6f8f966b0e90f4874ed54359a7898107 /Hutch/App | |
| parent | ee9f2904aa319231b7047fca3cb069f0c07019cd (diff) | |
| download | hutch-0e461a382257979037e8927e5f6b468635b0a7fe.tar.gz hutch-0e461a382257979037e8927e5f6b468635b0a7fe.tar.bz2 hutch-0e461a382257979037e8927e5f6b468635b0a7fe.zip | |
feat: add power user actions
Implements: https://todo.sr.ht/~ccleberg/hutch/52
Implements: https://todo.sr.ht/~ccleberg/hutch/53
Implements: https://todo.sr.ht/~ccleberg/hutch/54
Diffstat (limited to 'Hutch/App')
| -rw-r--r-- | Hutch/App/AppState.swift | 33 | ||||
| -rw-r--r-- | Hutch/App/AppStorageKeys.swift | 1 | ||||
| -rw-r--r-- | Hutch/App/RootView.swift | 7 |
3 files changed, 41 insertions, 0 deletions
diff --git a/Hutch/App/AppState.swift b/Hutch/App/AppState.swift index 2f14011..ebd25d1 100644 --- a/Hutch/App/AppState.swift +++ b/Hutch/App/AppState.swift @@ -1,5 +1,6 @@ import Foundation import SwiftUI +import UIKit import WebKit /// Central application state shared across the view hierarchy. @@ -63,6 +64,13 @@ final class AppState { private(set) var systemStatusRepository: SystemStatusRepository private var activeSession: AccountSession? private(set) var sessionIdentity = UUID() + var isDebugModeEnabled = UserDefaults.standard.bool(forKey: AppStorageKeys.debugModeEnabled) { + didSet { + UserDefaults.standard.set(isDebugModeEnabled, forKey: AppStorageKeys.debugModeEnabled) + } + } + private(set) var copyConfirmationMessage: String? + private var copyConfirmationTask: Task<Void, Never>? var accountDefaults: UserDefaults { activeSession?.defaults ?? .standard @@ -210,6 +218,7 @@ final class AppState { clearAllAccountArtifacts() authPhase = .unauthenticated selectedTab = .home + dismissCopyConfirmation() } func resetAppData() async { @@ -230,6 +239,19 @@ final class AppState { authPhase = .unauthenticated selectedTab = .home + isDebugModeEnabled = false + dismissCopyConfirmation() + } + + func copyToPasteboard(_ value: String, label: String) { + UIPasteboard.general.string = value + showCopyConfirmation(message: "Copied \(label)") + } + + func dismissCopyConfirmation() { + copyConfirmationTask?.cancel() + copyConfirmationTask = nil + copyConfirmationMessage = nil } // MARK: - Deep link resolution @@ -525,6 +547,17 @@ final class AppState { } } } + + private func showCopyConfirmation(message: String) { + copyConfirmationTask?.cancel() + copyConfirmationMessage = message + copyConfirmationTask = Task { @MainActor in + try? await Task.sleep(for: .seconds(1.6)) + guard !Task.isCancelled else { return } + copyConfirmationMessage = nil + copyConfirmationTask = nil + } + } } enum AppStateError: LocalizedError { diff --git a/Hutch/App/AppStorageKeys.swift b/Hutch/App/AppStorageKeys.swift index e151617..4be8004 100644 --- a/Hutch/App/AppStorageKeys.swift +++ b/Hutch/App/AppStorageKeys.swift @@ -19,4 +19,5 @@ enum AppStorageKeys { static let ticketSavedFilters = "ticketSavedFilters" static let appTheme = "appTheme" static let displayDensity = "displayDensity" + static let debugModeEnabled = "debugModeEnabled" } diff --git a/Hutch/App/RootView.swift b/Hutch/App/RootView.swift index e3baa76..f65bced 100644 --- a/Hutch/App/RootView.swift +++ b/Hutch/App/RootView.swift @@ -123,6 +123,13 @@ struct RootView: View { get: { appState.selectedTab }, set: { appState.selectedTab = $0 } ))) + .safeAreaInset(edge: .bottom) { + if let message = appState.copyConfirmationMessage { + CopyConfirmationBadge(message: message) + .padding(.bottom, 4) + .transition(.move(edge: .bottom).combined(with: .opacity)) + } + } .overlay { if isResolvingDeepLink { ZStack { |
