Skip to content

Commit

Permalink
[ABW-3644] Seed phrase entry/view updates (#1255)
Browse files Browse the repository at this point in the history
  • Loading branch information
matiasbzurovski committed Aug 6, 2024
1 parent 2a6ca95 commit d99829d
Show file tree
Hide file tree
Showing 21 changed files with 216 additions and 271 deletions.
18 changes: 12 additions & 6 deletions RadixWallet/Core/DesignSystem/Components/AppTextField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public struct AppTextField<FocusValue: Hashable, Accessory: View, InnerAccessory
let secondaryHeading: String?
let placeholder: String
let text: Binding<String>
let hint: Hint?
let hint: Hint.ViewState?
let focus: Focus?
let showClearButton: Bool
let accessory: Accessory
Expand All @@ -53,7 +53,7 @@ public struct AppTextField<FocusValue: Hashable, Accessory: View, InnerAccessory
secondaryHeading: String? = nil,
placeholder: String,
text: Binding<String>,
hint: Hint? = nil,
hint: Hint.ViewState? = nil,
focus: Focus,
showClearButton: Bool = false,
@ViewBuilder accessory: () -> Accessory = { EmptyView() },
Expand All @@ -79,7 +79,7 @@ public struct AppTextField<FocusValue: Hashable, Accessory: View, InnerAccessory
secondaryHeading: String? = nil,
placeholder: String,
text: Binding<String>,
hint: Hint? = nil,
hint: Hint.ViewState? = nil,
showClearButton: Bool = false,
@ViewBuilder accessory: () -> Accessory = { EmptyView() },
@ViewBuilder innerAccessory: () -> InnerAccessory = { EmptyView() }
Expand All @@ -99,7 +99,7 @@ public struct AppTextField<FocusValue: Hashable, Accessory: View, InnerAccessory

public var body: some View {
HStack(alignment: .textFieldAlignment, spacing: 0) {
VStack(alignment: .leading, spacing: .small1) {
VStack(alignment: .leading, spacing: Constants.appTextFieldSpacing) {
if primaryHeading != nil || secondaryHeading != nil {
HStack(spacing: 0) {
if let primaryHeading {
Expand Down Expand Up @@ -177,7 +177,9 @@ public struct AppTextField<FocusValue: Hashable, Accessory: View, InnerAccessory
.stroke(accentColor(isFocused: isFocused), lineWidth: 1)
)

hint
if let hint {
Hint(viewState: hint)
}
}

accessory
Expand All @@ -186,7 +188,7 @@ public struct AppTextField<FocusValue: Hashable, Accessory: View, InnerAccessory
}

private func accentColor(isFocused: Bool) -> Color {
switch hint?.viewState.kind {
switch hint?.kind {
case .none, .info:
isFocused ? .app.gray1 : .app.gray4
case .error:
Expand All @@ -207,6 +209,10 @@ extension VerticalAlignment {
fileprivate static let textFieldAlignment = VerticalAlignment(TextFieldAlignment.self)
}

extension Constants {
static let appTextFieldSpacing: CGFloat = .small1
}

#if DEBUG
struct AppTextField_Previews: PreviewProvider {
static var previews: some View {
Expand Down
79 changes: 42 additions & 37 deletions RadixWallet/Core/DesignSystem/Components/Hint.swift
Original file line number Diff line number Diff line change
@@ -1,68 +1,64 @@
// MARK: - Hint
public struct Hint: View, Equatable {
public struct ViewState: Equatable {
public struct ViewState: Sendable, Equatable {
public let kind: Kind
public let text: Text?
public let text: AttributedString?

public init(kind: Kind, text: Text?) {
public init(kind: Kind, text: String?) {
self.kind = kind
self.text = text
self.text = text.map { .init(stringLiteral: $0) }
}

public init(kind: Kind, text: some StringProtocol) {
public init(kind: Kind, attributed: AttributedString?) {
self.kind = kind
self.text = Text(text)
self.text = attributed
}

public static func info(_ string: String) -> Self {
.init(kind: .info, text: string)
}

public static func error(_ string: String) -> Self {
.init(kind: .error(imageSize: .smallest), text: string)
}

public static func error() -> Self {
.init(kind: .error(imageSize: .smallest), text: nil)
}

public static func iconError(_ string: String) -> Self {
.init(kind: .error(imageSize: .icon), text: string)
}

public static func iconError() -> Self {
.init(kind: .error(imageSize: .icon), text: nil)
}
}

public enum Kind: Equatable {
public enum Kind: Sendable, Equatable {
case info
case error
case error(imageSize: HitTargetSize)
case warning
case detail
}

public let viewState: ViewState

private init(kind: Kind, text: Text?) {
self.viewState = .init(kind: kind, text: text)
}

public init(viewState: ViewState) {
self.viewState = viewState
}

public static func info(_ text: () -> Text) -> Self {
.init(kind: .info, text: text())
}

public static func info(_ string: some StringProtocol) -> Self {
.init(kind: .info, text: Text(string))
}

public static func error(_ text: () -> Text) -> Self {
.init(kind: .error, text: text())
}

public static func error(_ string: some StringProtocol) -> Self {
.init(kind: .error, text: Text(string))
}

public static func error() -> Self {
.init(kind: .error, text: nil)
}

public var body: some View {
if let text = viewState.text {
HStack(spacing: .small3) {
if let iconResource {
Image(iconResource)
if let imageResource {
Image(imageResource)
.renderingMode(.template)
.resizable()
.scaledToFit()
.frame(.smallest)
.frame(imageSize)
}
text
Text(text)
.lineSpacing(0)
.textStyle(textStyle)
}
Expand All @@ -83,7 +79,7 @@ private extension Hint {
}
}

var iconResource: ImageResource? {
var imageResource: ImageResource? {
switch viewState.kind {
case .info, .detail:
nil
Expand All @@ -100,4 +96,13 @@ private extension Hint {
.body1Regular
}
}

var imageSize: HitTargetSize {
switch viewState.kind {
case .info, .detail, .warning:
.smallest
case let .error(imageSize):
imageSize
}
}
}
2 changes: 1 addition & 1 deletion RadixWallet/Core/DesignSystem/HitTargetSize.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// MARK: - HitTargetSize
public enum HitTargetSize: CGFloat {
public enum HitTargetSize: CGFloat, Sendable {
/// 18
case icon = 18

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ extension AddAsset.State {
case .valid:
return .none
case .wrongNetwork:
return .error(L10n.AssetTransfer.Error.wrongNetwork)
return .iconError(L10n.AssetTransfer.Error.wrongNetwork)
case .alreadyAdded:
return .error(L10n.AssetTransfer.Error.resourceAlreadyAdded)
return .iconError(L10n.AssetTransfer.Error.resourceAlreadyAdded)
case .invalid:
return .error(L10n.AssetTransfer.ChooseReceivingAccount.invalidAddressError)
return .iconError(L10n.AssetTransfer.ChooseReceivingAccount.invalidAddressError)
}
}(),
resourceAddressFieldFocused: resourceAddressFieldFocused,
Expand All @@ -32,7 +32,7 @@ extension AddAsset {
public struct ViewState: Equatable {
let resourceAddress: String
let validatedResourceAddress: ResourceViewState.Address?
let addressHint: Hint?
let addressHint: Hint.ViewState?
let resourceAddressFieldFocused: Bool
let mode: ResourcesListMode
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ extension UpdateAccountLabel.State {
)
}

private var hintAndControlState: (ControlState, Hint?) {
private var hintAndControlState: (ControlState, Hint.ViewState?) {
if let sanitizedName {
if sanitizedName.count > Account.nameMaxLength {
return (.disabled, .error(L10n.Error.AccountLabel.tooLong))
return (.disabled, .iconError(L10n.Error.AccountLabel.tooLong))
}
} else {
return (.disabled, .error(L10n.Error.AccountLabel.missing))
return (.disabled, .iconError(L10n.Error.AccountLabel.missing))
}

return (.enabled, nil)
Expand All @@ -31,7 +31,7 @@ extension UpdateAccountLabel {
let accountLabel: String
let sanitizedName: NonEmptyString?
let updateButtonControlState: ControlState
let hint: Hint?
let hint: Hint.ViewState?
let textFieldFocused: Bool
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ struct PreferenceSection<SectionId: Hashable, RowId: Hashable>: View {
guard let hint = row.hint else {
return []
}
return [.init(kind: .detail, text: Text(hint))]
return [.init(kind: .detail, text: hint)]
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ extension ChooseReceivingAccount.State {
manualAccountAddress.isEmpty
}

var manualAddressHint: Hint? {
var manualAddressHint: Hint.ViewState? {
guard !manualAccountAddressFocused, !manualAccountAddress.isEmpty else {
return .none
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ extension NameAccount {
public let subtitleText: String
public let entityName: String
public let sanitizedNameRequirement: SanitizedNameRequirement?
public let hint: Hint?
public let hint: Hint.ViewState?
public let useLedgerAsFactorSource: Bool

public struct SanitizedNameRequirement: Equatable {
Expand All @@ -31,7 +31,7 @@ extension NameAccount {
if let sanitizedName = state.sanitizedName {
if sanitizedName.count > Account.nameMaxLength {
self.sanitizedNameRequirement = nil
self.hint = .error(L10n.Error.AccountLabel.tooLong)
self.hint = .iconError(L10n.Error.AccountLabel.tooLong)
} else {
self.sanitizedNameRequirement = .init(sanitizedName: sanitizedName)
self.hint = nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,31 @@ extension PersonaDataPermissionBox.State {
.keys
.nilIfEmpty
.map { kinds in
.error {
Text {
L10n.DAppRequest.PersonalDataBox.requiredInformation.text.bold()
" "
kinds.sorted().map(\.title.localizedLowercase).joined(separator: ", ")
}
}
let items = kinds.sorted().map(\.title.localizedLowercase).joined(separator: ", ")
return try? AttributedString(markdown: "**\(L10n.DAppRequest.PersonalDataBox.requiredInformation)** \(items)")
}
.map {
.init(kind: .error(imageSize: .icon), attributed: $0)
}
)
}

private var missingEntries: String? {
responseValidation.missingEntries
.keys
.nilIfEmpty
.map { kinds in
let items = kinds.sorted().map(\.title.localizedLowercase).joined(separator: ", ")
return items
}
}
}

extension PersonaDataPermissionBox {
struct ViewState: Equatable {
let personaLabel: String
let existingRequiredEntries: String?
let missingRequiredEntries: Hint?
let missingRequiredEntries: Hint.ViewState?
}

@MainActor
Expand Down Expand Up @@ -77,7 +85,9 @@ extension PersonaDataPermissionBox {
.textStyle(.body2Regular)
}

viewStore.missingRequiredEntries
if let viewState = viewStore.missingRequiredEntries {
Hint(viewState: viewState)
}

Button(L10n.DAppRequest.PersonalDataBox.edit) {
viewStore.send(.editButtonTapped)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ extension EditPersonaField.State {
showsTitle ? behaviour.title : nil
}

var inputHint: Hint? {
var inputHint: Hint.ViewState? {
if let error = $input.errors?.first {
return .error(error)
return .iconError(error)
} else if let defaultInfoHint {
return .info(defaultInfoHint)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import ComposableArchitecture
import SwiftUI

extension AddNewGateway.State {
var fieldHint: Hint? {
errorText.map(Hint.error)
var fieldHint: Hint.ViewState? {
errorText.map(Hint.ViewState.iconError)
}
}

Expand Down
Loading

0 comments on commit d99829d

Please sign in to comment.