Fix tap knockable room and custom keyboard did show scrolling (#3603)

* making knockable rooms tappable

* added a way to customise the keyboard scrolling

in case we want the focussed view/textview to display something outside its content

* better documentation
This commit is contained in:
Mauro
2024-12-11 16:09:52 +01:00
committed by GitHub
parent 4931ad0ed3
commit 9856e3e5b4
6 changed files with 64 additions and 28 deletions
@@ -0,0 +1,24 @@
//
// Copyright 2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
//
import SwiftUI
extension View {
/// Adds a scroll view reader to the view and scrolls to the provided id if the condition is true, so far it only works properly if the item is the last in the scroll view.
func shouldScrollOnKeyboardDidShow(_ shouldScroll: Bool, to id: any Hashable) -> some View {
ScrollViewReader { scrollView in
onReceive(NotificationCenter.default.publisher(for: UIApplication.keyboardDidShowNotification)) { _ in
guard shouldScroll else { return }
// Scroll to the footer of the alias when the keyboard appears
withAnimation {
// We could improve this in the future by also providing the anchor as an argument
scrollView.scrollTo(id, anchor: .top)
}
}
}
}
}
@@ -15,6 +15,7 @@ struct CreateRoomScreen: View {
private enum Focus {
case name
case topic
case alias
}
private var aliasBinding: Binding<String> {
@@ -52,6 +53,7 @@ struct CreateRoomScreen: View {
.toolbar { toolbar }
.readFrame($frame)
.alert(item: $context.alertInfo)
.shouldScrollOnKeyboardDidShow(focus == .alias, to: Focus.alias)
}
private var roomSection: some View {
@@ -197,6 +199,8 @@ struct CreateRoomScreen: View {
TextField("", text: aliasBinding)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
.textContentType(.URL)
.focused($focus, equals: .alias)
.tint(.compound.iconAccentTertiary)
.font(.compound.bodyLG)
.foregroundStyle(.compound.textPrimary)
@@ -209,6 +213,7 @@ struct CreateRoomScreen: View {
.environment(\.layoutDirection, .leftToRight)
.errorBackground(!context.viewState.aliasErrors.isEmpty)
})
.id(Focus.alias)
} header: {
Text(L10n.screenCreateRoomRoomAddressSectionTitle)
.compoundListSectionHeader()
@@ -13,7 +13,12 @@ struct JoinRoomScreen: View {
@Environment(\.dynamicTypeSize) private var dynamicTypeSize
@ObservedObject var context: JoinRoomScreenViewModel.Context
@FocusState private var focus: Focus?
private enum Focus {
case knockMessage
}
var body: some View {
FullscreenDialog(topPadding: context.viewState.mode == .knocked ? 151 : 35, background: .bloom) {
if context.viewState.mode == .loading {
@@ -29,6 +34,7 @@ struct JoinRoomScreen: View {
.backgroundStyle(.compound.bgCanvasDefault)
.navigationBarTitleDisplayMode(.inline)
.toolbar { toolbar }
.shouldScrollOnKeyboardDidShow(focus == .knockMessage, to: Focus.knockMessage)
}
@ViewBuilder
@@ -117,6 +123,7 @@ struct JoinRoomScreen: View {
VStack(alignment: .leading, spacing: 12) {
HStack(spacing: 0) {
TextField("", text: $context.knockMessage, axis: .vertical)
.focused($focus, equals: .knockMessage)
.onChange(of: context.knockMessage) { _, newValue in
context.knockMessage = String(newValue.prefix(maxKnockMessageLength))
}
@@ -124,6 +131,7 @@ struct JoinRoomScreen: View {
.font(.compound.bodyMD)
.padding(.horizontal, 16)
.padding(.vertical, 12)
.id(Focus.knockMessage)
}
.background(.compound.bgCanvasDefault)
.cornerRadius(8)
@@ -644,7 +644,7 @@ class ClientProxy: ClientProxyProtocol {
}
func roomDirectorySearchProxy() -> RoomDirectorySearchProxyProtocol {
RoomDirectorySearchProxy(roomDirectorySearch: client.roomDirectorySearch())
RoomDirectorySearchProxy(roomDirectorySearch: client.roomDirectorySearch(), appSettings: appSettings)
}
func resolveRoomAlias(_ alias: String) async -> Result<ResolvedRoomAlias, ClientProxyError> {
@@ -12,6 +12,7 @@ import MatrixRustSDK
final class RoomDirectorySearchProxy: RoomDirectorySearchProxyProtocol {
private let roomDirectorySearch: RoomDirectorySearchProtocol
private let appSettings: AppSettings
private let serialDispatchQueue = DispatchQueue(label: "io.element.elementx.roomdirectorysearch", qos: .default)
private let resultsSubject = CurrentValueSubject<[RoomDirectorySearchResult], Never>([])
@@ -31,8 +32,10 @@ final class RoomDirectorySearchProxy: RoomDirectorySearchProxyProtocol {
private var cancellables = Set<AnyCancellable>()
init(roomDirectorySearch: RoomDirectorySearchProtocol) {
init(roomDirectorySearch: RoomDirectorySearchProtocol,
appSettings: AppSettings) {
self.roomDirectorySearch = roomDirectorySearch
self.appSettings = appSettings
diffsPublisher
.receive(on: serialDispatchQueue)
.sink { [weak self] in self?.updateResultsWithDiffs($0) }
@@ -146,7 +149,7 @@ final class RoomDirectorySearchProxy: RoomDirectorySearchProxyProtocol {
name: value.name,
topic: value.topic,
avatar: .room(id: value.roomId, name: value.name, avatarURL: value.avatarUrl.flatMap(URL.init(string:))),
canBeJoined: value.joinRule == .public)
canBeJoined: value.joinRule == .public || (appSettings.knockingEnabled && value.joinRule == .knock))
}
}