* Implemented join room by address * improved the text field typing * some improvements to how the text is edited * remove navigation link * moved room directory search to the start chat flow * updated preview tests * added unit tests and improved the code * updated strings * some pr suggestions: - moving the file - changing the name of the action - reintroduce the debounce text queries - add comments * renamed the auth text field style to Element updated tests
96 lines
3.7 KiB
Swift
96 lines
3.7 KiB
Swift
//
|
|
// Copyright 2025 New Vector Ltd.
|
|
//
|
|
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
// Please see LICENSE files in the repository root for full details.
|
|
//
|
|
|
|
import Compound
|
|
import SwiftUI
|
|
|
|
struct JoinRoomByAddressView: View {
|
|
@ObservedObject var context: StartChatScreenViewModel.Context
|
|
|
|
@Environment(\.dismiss) private var dismiss
|
|
|
|
@State private var sheetHeight: CGFloat = .zero
|
|
@FocusState private var textFieldFocus
|
|
private let topPadding: CGFloat = 22
|
|
|
|
private var footerText: String {
|
|
switch context.viewState.joinByAddressState {
|
|
case .example:
|
|
L10n.screenStartChatJoinRoomByAddressSupportingText
|
|
case .addressNotFound:
|
|
L10n.screenStartChatJoinRoomByAddressRoomNotFound
|
|
case .addressFound:
|
|
L10n.screenStartChatJoinRoomByAddressRoomFound
|
|
case .invalidAddress:
|
|
L10n.screenStartChatJoinRoomByAddressInvalidAddress
|
|
}
|
|
}
|
|
|
|
private var textFieldState: ElementTextFieldStyle.State {
|
|
switch context.viewState.joinByAddressState {
|
|
case .addressFound:
|
|
.success
|
|
case .example:
|
|
.default
|
|
case .addressNotFound, .invalidAddress:
|
|
.error
|
|
}
|
|
}
|
|
|
|
var body: some View {
|
|
ScrollView {
|
|
VStack(spacing: 24) {
|
|
TextField(L10n.screenStartChatJoinRoomByAddressPlaceholder,
|
|
text: $context.roomAddress)
|
|
.textFieldStyle(.element(labelText: L10n.screenStartChatJoinRoomByAddressAction,
|
|
footerText: footerText,
|
|
state: textFieldState))
|
|
.textInputAutocapitalization(.never)
|
|
.autocorrectionDisabled()
|
|
.textContentType(.URL)
|
|
.focused($textFieldFocus)
|
|
.onChange(of: context.roomAddress) { _, newValue in
|
|
context.roomAddress = newValue.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
}
|
|
|
|
Button(L10n.actionContinue) {
|
|
context.send(viewAction: .joinRoomByAddress)
|
|
}
|
|
.buttonStyle(.compound(.primary))
|
|
}
|
|
.padding(.horizontal, 16)
|
|
.readHeight($sheetHeight)
|
|
}
|
|
.scrollBounceBehavior(.basedOnSize)
|
|
.padding(.top, topPadding) // For the drag indicator
|
|
.presentationDetents([.height(sheetHeight + topPadding)])
|
|
.presentationDragIndicator(.visible)
|
|
.presentationBackground(.compound.bgCanvasDefault)
|
|
.onAppear {
|
|
textFieldFocus = true
|
|
}
|
|
}
|
|
}
|
|
|
|
struct JoinRoomByAddressView_Previews: PreviewProvider, TestablePreview {
|
|
static let viewModel = {
|
|
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@userid:example.com"))))
|
|
let userDiscoveryService = UserDiscoveryServiceMock()
|
|
userDiscoveryService.searchProfilesWithReturnValue = .success([.mockAlice])
|
|
let viewModel = StartChatScreenViewModel(userSession: userSession,
|
|
analytics: ServiceLocator.shared.analytics,
|
|
userIndicatorController: UserIndicatorControllerMock(),
|
|
userDiscoveryService: userDiscoveryService,
|
|
appSettings: ServiceLocator.shared.settings)
|
|
return viewModel
|
|
}()
|
|
|
|
static var previews: some View {
|
|
JoinRoomByAddressView(context: viewModel.context)
|
|
}
|
|
}
|