[#793] Polish debug menu and fix dark mode (#794)

- fixed alerts in debug menu
- fixed confirmation dialog in for rescan action
- fixed dark mode colors
- updated texts
- simplified texteditor UI so it's more consistent with the other components
- reduced debug menu items
- tests fixed
This commit is contained in:
Lukas Korba 2023-08-07 08:33:33 +02:00 committed by GitHub
parent 0206641fc6
commit 1de13698d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 68 additions and 116 deletions

View File

@ -60,7 +60,7 @@ let package = Package(
.package(url: "https://github.com/pointfreeco/swift-case-paths", from: "0.14.1"),
.package(url: "https://github.com/pointfreeco/swift-url-routing", from: "0.5.0"),
.package(url: "https://github.com/SwiftGen/SwiftGenPlugin", from: "6.6.0"),
.package(url: "https://github.com/zcash/ZcashLightClientKit", revision: "e4cea0c265e803ad2820d358c1daa565c3107497"),
.package(url: "https://github.com/zcash/ZcashLightClientKit", revision: "b9524ae1abfa54bbcaac802dbccb9e4eecc847cc"),
.package(url: "https://github.com/zcash-hackworks/MnemonicSwift", from: "2.2.4")
],
targets: [

View File

@ -12,17 +12,11 @@ import Generated
public struct ImportSeedEditor: View {
var store: ImportWalletStore
/// Clearance of the black color for the TextEditor under the text (.dark colorScheme)
public init(store: ImportWalletStore) {
self.store = store
UITextView.appearance().backgroundColor = .clear
}
public var body: some View {
WithViewStore(store) { viewStore in
TextEditor(text: viewStore.bindingForRedactableSeedPhrase(viewStore.importedSeedPhrase))
.autocapitalization(.none)
.importSeedEditorModifier()
.importSeedEditorModifier(Asset.Colors.Mfp.fontDark.color)
.padding(.horizontal, 28)
.padding(.vertical, 10)
}
@ -34,13 +28,9 @@ struct ImportSeedEditorModifier: ViewModifier {
func body(content: Content) -> some View {
content
.foregroundColor(Asset.Colors.Text.importSeedEditor.color)
.padding()
.foregroundColor(Asset.Colors.Mfp.fontDark.color)
.padding(1)
.background(backgroundColor)
.overlay(
Rectangle()
.stroke(Asset.Colors.Mfp.primary.color, lineWidth: 2)
)
}
}

View File

@ -43,7 +43,7 @@ public struct PlainOnboardingView: View {
viewStore.send(.importExistingWallet, animation: .easeInOut(duration: animationDuration))
}
.frame(height: 80)
.foregroundColor(.black)
.foregroundColor(Asset.Colors.Mfp.fontDark.color)
}
.padding(.all)
.navigationLinkEmpty(

View File

@ -16,7 +16,7 @@ import Models
/// for the `RootReducer` with a connection to the UI navigation.
extension RootReducer {
public struct DebugState: Equatable {
public var rescanDialog: ConfirmationDialogState<RootReducer.Action>?
@PresentationState public var rescanDialog: ConfirmationDialogState<Action>?
}
public indirect enum DebugAction: Equatable {
@ -43,15 +43,7 @@ extension RootReducer {
return .none
case .debug(.rescanBlockchain):
state.debugState.rescanDialog = .init(
title: TextState(L10n.Root.Debug.Dialog.Rescan.title),
message: TextState(L10n.Root.Debug.Dialog.Rescan.message),
buttons: [
.default(TextState(L10n.Root.Debug.Dialog.Rescan.Option.quick), action: .send(.debug(.quickRescan))),
.default(TextState(L10n.Root.Debug.Dialog.Rescan.Option.full), action: .send(.debug(.fullRescan))),
.cancel(TextState(L10n.General.cancel))
]
)
state.debugState.rescanDialog = ConfirmationDialogState.rescanRequest()
return .none
case .debug(.cancelRescan):
@ -103,7 +95,7 @@ extension RootReducer {
case .debug(.rateTheApp):
return .none
default: return .none
}
}

View File

@ -266,9 +266,6 @@ extension RootReducer {
state.appInitializationState = .failed
state.alert = AlertState.initializationFailed(error)
return .none
case .alert(.presented(let action)):
return EffectTask(value: action)
case .home, .destination, .onboarding, .phraseDisplay, .phraseValidation, .sandbox,
.welcome, .binding, .debug, .exportLogs, .alert:

View File

@ -148,6 +148,19 @@ public struct RootReducer: ReducerProtocol {
public var body: some ReducerProtocol<State, Action> {
self.core
Reduce { state, action in
switch action {
case .alert(.presented(let action)):
return EffectTask(value: action)
case .alert(.dismiss):
state.alert = nil
return .none
default: return .none
}
}
}
}
@ -276,6 +289,27 @@ extension AlertState where Action == RootReducer.Action {
}
}
}
extension ConfirmationDialogState where Action == RootReducer.Action {
public static func rescanRequest() -> ConfirmationDialogState {
ConfirmationDialogState {
TextState(L10n.Root.Debug.Dialog.Rescan.title)
} actions: {
ButtonState(role: .destructive, action: .debug(.quickRescan)) {
TextState(L10n.Root.Debug.Dialog.Rescan.Option.quick)
}
ButtonState(role: .destructive, action: .debug(.fullRescan)) {
TextState(L10n.Root.Debug.Dialog.Rescan.Option.full)
}
ButtonState(role: .cancel, action: .alert(.dismiss)) {
TextState(L10n.General.cancel)
}
} message: {
TextState(L10n.Root.Debug.Dialog.Rescan.message)
}
}
}
// MARK: Placeholders

View File

@ -173,52 +173,34 @@ private extension RootView {
List {
Section(header: Text(L10n.Root.Debug.title)) {
Button(L10n.Root.Debug.Option.gotoSandbox) {
viewStore.goToDestination(.sandbox)
}
Button(L10n.Root.Debug.Option.gotoOnboarding) {
viewStore.goToDestination(.onboarding)
}
Button(L10n.Root.Debug.Option.gotoPhraseValidationDemo) {
viewStore.goToDestination(.phraseValidation)
}
Button(L10n.Root.Debug.Option.restartApp) {
viewStore.goToDestination(.welcome)
}
Button(L10n.Root.Debug.Option.testCrashReporter) {
viewStore.send(.debug(.testCrashReporter))
}
Button(L10n.Root.Debug.Option.exportLogs) {
viewStore.send(.exportLogs(.start))
}
.disabled(viewStore.exportLogsState.exportLogsDisabled)
#if DEBUG
Button(L10n.Root.Debug.Option.appReview) {
viewStore.send(.debug(.rateTheApp))
if let currentScene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
SKStoreReviewController.requestReview(in: currentScene)
}
}
#endif
Button(L10n.Root.Debug.Option.rescanBlockchain) {
viewStore.send(.debug(.rescanBlockchain))
}
Button(L10n.Root.Debug.Option.nukeWallet) {
viewStore.send(.initialization(.nukeWalletRequest))
}
}
#if DEBUG
Section(header: Text(L10n.Root.Debug.featureFlags)) {
let flags = viewStore.state.walletConfig.flags
.map { FeatureFlagWrapper(name: $0.key, isEnabled: $0.value) }
.sorted()
ForEach(flags) { flag in
HStack {
Toggle(
@ -237,11 +219,12 @@ private extension RootView {
}
}
}
#endif
}
.confirmationDialog(
store.scope(
state: \.debugState.rescanDialog,
action: { _ in RootReducer.Action.debug(.cancelRescan) }
action: { $0 }
),
dismiss: .debug(.cancelRescan)
)

View File

@ -318,8 +318,8 @@ public enum L10n {
public static let featureFlags = L10n.tr("Localizable", "root.debug.featureFlags", fallback: "Feature flags")
/// Startup
public static let navigationTitle = L10n.tr("Localizable", "root.debug.navigationTitle", fallback: "Startup")
/// Debug options
public static let title = L10n.tr("Localizable", "root.debug.title", fallback: "Debug options")
/// Support options
public static let title = L10n.tr("Localizable", "root.debug.title", fallback: "Support options")
public enum Alert {
public enum Rewind {
public enum CantStartSync {
@ -355,24 +355,16 @@ public enum L10n {
}
}
public enum Option {
/// Rate the app
public static let appReview = L10n.tr("Localizable", "root.debug.option.appReview", fallback: "Rate the app")
/// Export logs
public static let exportLogs = L10n.tr("Localizable", "root.debug.option.exportLogs", fallback: "Export logs")
/// Go To Onboarding
public static let gotoOnboarding = L10n.tr("Localizable", "root.debug.option.gotoOnboarding", fallback: "Go To Onboarding")
/// Go To Phrase Validation Demo
public static let gotoPhraseValidationDemo = L10n.tr("Localizable", "root.debug.option.gotoPhraseValidationDemo", fallback: "Go To Phrase Validation Demo")
/// Go To Sandbox (navigation proof)
public static let gotoSandbox = L10n.tr("Localizable", "root.debug.option.gotoSandbox", fallback: "Go To Sandbox (navigation proof)")
/// Rate the App
public static let appReview = L10n.tr("Localizable", "root.debug.option.appReview", fallback: "Rate the App")
/// Export Logs
public static let exportLogs = L10n.tr("Localizable", "root.debug.option.exportLogs", fallback: "Export Logs")
/// [Be careful] Nuke Wallet
public static let nukeWallet = L10n.tr("Localizable", "root.debug.option.nukeWallet", fallback: "[Be careful] Nuke Wallet")
/// Rescan Blockchain
public static let rescanBlockchain = L10n.tr("Localizable", "root.debug.option.rescanBlockchain", fallback: "Rescan Blockchain")
/// Restart the app
public static let restartApp = L10n.tr("Localizable", "root.debug.option.restartApp", fallback: "Restart the app")
/// Test Crash Reporter
public static let testCrashReporter = L10n.tr("Localizable", "root.debug.option.testCrashReporter", fallback: "Test Crash Reporter")
/// Restart the App
public static let restartApp = L10n.tr("Localizable", "root.debug.option.restartApp", fallback: "Restart the App")
}
}
public enum Destination {

View File

@ -235,17 +235,13 @@
"root.destination.alert.failedToProcessDeeplink.title" = "Failed to process deeplink.";
"root.destination.alert.failedToProcessDeeplink.message" = "Deeplink: \(%@))\nError: \(%@) (code: %@)";
"root.debug.title" = "Debug options";
"root.debug.title" = "Support options";
"root.debug.navigationTitle" = "Startup";
"root.debug.option.gotoSandbox" = "Go To Sandbox (navigation proof)";
"root.debug.option.gotoOnboarding" = "Go To Onboarding";
"root.debug.option.gotoPhraseValidationDemo" = "Go To Phrase Validation Demo";
"root.debug.option.restartApp" = "Restart the app";
"root.debug.option.testCrashReporter" = "Test Crash Reporter";
"root.debug.option.restartApp" = "Restart the App";
"root.debug.option.rescanBlockchain" = "Rescan Blockchain";
"root.debug.option.nukeWallet" = "[Be careful] Nuke Wallet";
"root.debug.option.exportLogs" = "Export logs";
"root.debug.option.appReview" = "Rate the app";
"root.debug.option.exportLogs" = "Export Logs";
"root.debug.option.appReview" = "Rate the App";
"root.debug.featureFlags" = "Feature flags";
"root.debug.dialog.rescan.title" = "Rescan";
"root.debug.dialog.rescan.message" = "Select the rescan you want";

View File

@ -13,7 +13,7 @@ struct TextFieldTitleAccessoryButtonStyle: ButtonStyle {
configuration.label
.padding(.horizontal, 10)
.padding(.vertical, 3)
.foregroundColor(.white)
.foregroundColor(Asset.Colors.Mfp.fontLight.color)
.background(
configuration.isPressed ?
Asset.Colors.TextField.titleAccessoryButtonPressed.color :

View File

@ -238,7 +238,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/zcash/ZcashLightClientKit",
"state" : {
"revision" : "e4cea0c265e803ad2820d358c1daa565c3107497"
"revision" : "b9524ae1abfa54bbcaac802dbccb9e4eecc847cc"
}
}
],

View File

@ -20,30 +20,14 @@ class DebugTests: XCTestCase {
)
await store.send(.debug(.rescanBlockchain)) { state in
state.debugState.rescanDialog = .init(
title: TextState("Rescan"),
message: TextState("Select the rescan you want"),
buttons: [
.default(TextState("Quick rescan"), action: .send(.debug(.quickRescan))),
.default(TextState("Full rescan"), action: .send(.debug(.fullRescan))),
.cancel(TextState("Cancel"))
]
)
state.debugState.rescanDialog = ConfirmationDialogState.rescanRequest()
}
}
func testRescanBlockchain_Cancelling() async throws {
var mockState = RootReducer.State.placeholder
mockState.debugState.rescanDialog = .init(
title: TextState("Rescan"),
message: TextState("Select the rescan you want"),
buttons: [
.default(TextState("Quick rescan"), action: .send(.debug(.quickRescan))),
.default(TextState("Full rescan"), action: .send(.debug(.fullRescan))),
.cancel(TextState("Cancel"))
]
)
mockState.debugState.rescanDialog = ConfirmationDialogState.rescanRequest()
let store = TestStore(
initialState: mockState,
@ -58,15 +42,7 @@ class DebugTests: XCTestCase {
func testRescanBlockchain_QuickRescanClearance() async throws {
var mockState = RootReducer.State.placeholder
mockState.debugState.rescanDialog = .init(
title: TextState("Rescan"),
message: TextState("Select the rescan you want"),
buttons: [
.default(TextState("Quick rescan"), action: .send(.debug(.quickRescan))),
.default(TextState("Full rescan"), action: .send(.debug(.fullRescan))),
.cancel(TextState("Cancel"))
]
)
mockState.debugState.rescanDialog = ConfirmationDialogState.rescanRequest()
let store = TestStore(
initialState: mockState,
@ -87,15 +63,7 @@ class DebugTests: XCTestCase {
func testRescanBlockchain_FullRescanClearance() async throws {
var mockState = RootReducer.State.placeholder
mockState.debugState.rescanDialog = .init(
title: TextState("Rescan"),
message: TextState("Select the rescan you want"),
buttons: [
.default(TextState("Quick rescan"), action: .send(.debug(.quickRescan))),
.default(TextState("Full rescan"), action: .send(.debug(.fullRescan))),
.cancel(TextState("Cancel"))
]
)
mockState.debugState.rescanDialog = ConfirmationDialogState.rescanRequest()
let store = TestStore(
initialState: mockState,