// // Copyright 2025 Element Creations Ltd. // Copyright 2024-2025 New Vector Ltd. // // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. // Please see LICENSE in the repository root for full details. // import Compound import SwiftUI struct EditRoomAddressListRow: View { @Binding var aliasLocalPart: String var serverName: String /// The error to display, if any. Also associated with the field for VoiceOver. var errorDescription: String? /// The section's helper text, associated with the field for VoiceOver. var footerText: String? private var fullAddress: String { "#\(aliasLocalPart):\(serverName)" } /// Associates the helper text and any error with the field, as they're otherwise /// only shown in a separate section footer. private var accessibilityHint: String { [L10n.a11yEditRoomAddressHint(fullAddress), footerText, errorDescription] .compactMap { $0 } .joined(separator: "\n") } var body: some View { ListRow(kind: .custom { HStack(spacing: 0) { Text("#") .font(.compound.bodyLG) .foregroundStyle(.compound.textSecondary) .accessibilityHidden(true) TextField("", text: $aliasLocalPart) .textInputAutocapitalization(.never) .autocorrectionDisabled() .textContentType(.URL) .tint(.compound.iconAccentTertiary) .font(.compound.bodyLG) .foregroundStyle(.compound.textPrimary) .padding(.horizontal, 8) .accessibilityLabel(L10n.a11yAddress) .accessibilityHint(accessibilityHint) Text(":\(serverName)") .font(.compound.bodyLG) .foregroundStyle(.compound.textSecondary) .accessibilityHidden(true) } .padding(ListRowPadding.textFieldInsets) .environment(\.layoutDirection, .leftToRight) .errorBackground(errorDescription != nil) }) } } private extension View { @ViewBuilder private var shape: some View { if #available(iOS 26, *) { Capsule() .inset(by: 1) .fill(.compound.bgCriticalSubtleHovered) .stroke(Color.compound.borderCriticalPrimary) } else { RoundedRectangle(cornerRadius: 10) .inset(by: 1) .fill(.compound.bgCriticalSubtleHovered) .stroke(Color.compound.borderCriticalPrimary) } } func errorBackground(_ shouldDisplay: Bool) -> some View { listRowBackground(shouldDisplay ? AnyView(shape) : AnyView(Color.compound.bgCanvasDefaultLevel1)) } } enum EditRoomAddressErrorState { case alreadyExists case invalidSymbols } extension Set { var errorDescription: String? { if contains(.alreadyExists) { return L10n.errorRoomAddressAlreadyExists } else if contains(.invalidSymbols) { return L10n.errorRoomAddressInvalidSymbols } return nil } }