Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ABW-3644] Seed phrase entry/view updates #1255

Merged
merged 22 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 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 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 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 @@ -9,7 +9,7 @@ extension ChooseReceivingAccount {
var chooseAccounts: ChooseAccounts.State
var canSelectOwnAccount: Bool
var validateAccountAddress: AccountAddress?
var manualAddressHint: Hint?
var manualAddressHint: Hint.ViewState?

init(state: ChooseReceivingAccount.State) {
manualAccountAddress = state.manualAccountAddress
Expand All @@ -24,12 +24,12 @@ extension ChooseReceivingAccount {

switch state.validateManualAccountAddress() {
case .invalid:
return .error(L10n.AssetTransfer.ChooseReceivingAccount.invalidAddressError)
return .iconError(L10n.AssetTransfer.ChooseReceivingAccount.invalidAddressError)
case .wrongNetwork:
return .error(L10n.AssetTransfer.Error.wrongNetwork)
return .iconError(L10n.AssetTransfer.Error.wrongNetwork)
case let .valid(validAddress):
if state.chooseAccounts.filteredAccounts.contains(where: { $0 == validAddress }) {
return .error(L10n.AssetTransfer.ChooseReceivingAccount.alreadyAddedError)
return .iconError(L10n.AssetTransfer.ChooseReceivingAccount.alreadyAddedError)
}
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
Loading