Fixes #2518, fixes #2590 - Implement public room search list paginati… (#2607)

* Fixes #2518, fixes #2590 - Implement public room search list pagination and room joining

* Address PR comments
This commit is contained in:
Stefan Ceriu
2024-03-27 10:50:53 +02:00
committed by GitHub
parent d72fa02ac6
commit be9cf8713e
16 changed files with 248 additions and 59 deletions
@@ -20,6 +20,7 @@ import SwiftUI
struct RoomDirectorySearchCell: View {
let result: RoomDirectorySearchResult
let imageProvider: ImageProviderProtocol?
let joinAction: () -> Void
private var description: String? {
if let topic = result.topic {
@@ -36,9 +37,17 @@ struct RoomDirectorySearchCell: View {
}
var body: some View {
ListRow(label: .avatar(title: result.name ?? result.alias ?? result.id,
description: description,
icon: avatar), kind: .label)
if result.canBeJoined {
ListRow(label: .avatar(title: result.name ?? result.alias ?? result.id,
description: description,
icon: avatar),
details: .label(title: L10n.actionJoin, icon: EmptyView()),
kind: .navigationLink(action: joinAction))
} else {
ListRow(label: .avatar(title: result.name ?? result.alias ?? result.id,
description: description,
icon: avatar), kind: .label)
}
}
private var avatar: some View {
@@ -56,14 +65,69 @@ struct RoomDirectorySearchCell: View {
struct RoomDirectorySearchCell_Previews: PreviewProvider, TestablePreview {
static var previews: some View {
List {
RoomDirectorySearchCell(result: .init(id: "!test_id_1:matrix.org", alias: "#test:example.com", name: "Test title", topic: "test description", avatarURL: nil, canBeJoined: false), imageProvider: MockMediaProvider())
RoomDirectorySearchCell(result: .init(id: "!test_id_2:matrix.org", alias: "#test:example.com", name: nil, topic: "test description", avatarURL: nil, canBeJoined: false), imageProvider: MockMediaProvider())
RoomDirectorySearchCell(result: .init(id: "!test_id_3:example.com", alias: "#test_no_topic:example.com", name: "Test title no topic", topic: nil, avatarURL: nil, canBeJoined: false), imageProvider: MockMediaProvider())
RoomDirectorySearchCell(result: .init(id: "!test_id_4:example.com", alias: "#test_no_topic:example.com", name: nil, topic: nil, avatarURL: nil, canBeJoined: false), imageProvider: MockMediaProvider())
RoomDirectorySearchCell(result: .init(id: "!test_id_5:example.com", alias: nil, name: "Test title no alias", topic: nil, avatarURL: nil, canBeJoined: false), imageProvider: MockMediaProvider())
RoomDirectorySearchCell(result: .init(id: "!test_id_6:example.com", alias: nil, name: "Test title no alias", topic: "Topic", avatarURL: nil, canBeJoined: false), imageProvider: MockMediaProvider())
RoomDirectorySearchCell(result: .init(id: "!test_id_7:example.com", alias: nil, name: nil, topic: "Topic", avatarURL: nil, canBeJoined: false), imageProvider: MockMediaProvider())
RoomDirectorySearchCell(result: .init(id: "!test_id_8:example.com", alias: nil, name: nil, topic: nil, avatarURL: nil, canBeJoined: false), imageProvider: MockMediaProvider())
RoomDirectorySearchCell(result: .init(id: "!test_id_1:matrix.org",
alias: "#test:example.com",
name: "Test title",
topic: "test description",
avatarURL: nil,
canBeJoined: false),
imageProvider: MockMediaProvider()) { }
RoomDirectorySearchCell(result: .init(id: "!test_id_2:matrix.org",
alias: "#test:example.com",
name: nil,
topic: "test description",
avatarURL: nil,
canBeJoined: false),
imageProvider: MockMediaProvider()) { }
RoomDirectorySearchCell(result: .init(id: "!test_id_3:example.com",
alias: "#test_no_topic:example.com",
name: "Test title no topic",
topic: nil,
avatarURL: nil,
canBeJoined: false),
imageProvider: MockMediaProvider()) { }
RoomDirectorySearchCell(result: .init(id: "!test_id_4:example.com",
alias: "#test_no_topic:example.com",
name: nil,
topic: nil,
avatarURL: nil,
canBeJoined: false),
imageProvider: MockMediaProvider()) { }
RoomDirectorySearchCell(result: .init(id: "!test_id_5:example.com",
alias: nil,
name: "Test title no alias",
topic: nil,
avatarURL: nil,
canBeJoined: false),
imageProvider: MockMediaProvider()) { }
RoomDirectorySearchCell(result: .init(id: "!test_id_6:example.com",
alias: nil,
name: "Test title no alias",
topic: "Topic",
avatarURL: nil,
canBeJoined: false),
imageProvider: MockMediaProvider()) { }
RoomDirectorySearchCell(result: .init(id: "!test_id_7:example.com",
alias: nil,
name: nil,
topic: "Topic",
avatarURL: nil,
canBeJoined: false),
imageProvider: MockMediaProvider()) { }
RoomDirectorySearchCell(result: .init(id: "!test_id_8:example.com",
alias: nil,
name: nil,
topic: nil,
avatarURL: nil,
canBeJoined: false),
imageProvider: MockMediaProvider()) { }
}
}
}
@@ -24,8 +24,22 @@ struct RoomDirectorySearchScreen: View {
NavigationStack {
List {
Section {
ForEach(context.viewState.searchResults) {
RoomDirectorySearchCell(result: $0, imageProvider: context.imageProvider)
ForEach(context.viewState.rooms) { room in
RoomDirectorySearchCell(result: room, imageProvider: context.imageProvider) {
context.send(viewAction: .join(roomID: room.id))
}
}
} footer: {
VStack(spacing: 0) {
if context.viewState.isLoading {
ProgressView()
.frame(maxWidth: .infinity)
}
emptyRectangle
.onAppear {
context.send(viewAction: .reachedBottom)
}
}
}
}
@@ -46,25 +60,39 @@ struct RoomDirectorySearchScreen: View {
}
}
}
// The greedy size of Rectangle can create an issue with the navigation bar when the search is highlighted, so is best to use a fixed frame instead of hidden() or EmptyView()
private var emptyRectangle: some View {
Rectangle()
.frame(width: 0, height: 0)
}
}
// MARK: - Previews
struct RoomDirectorySearchScreenScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = RoomDirectorySearchScreenViewModel(roomDirectorySearch: RoomDirectorySearchProxyMock(configuration: .init(results: [.init(id: "test_1",
alias: "#test_1:example.com",
name: "Test 1",
topic: "Test description 1",
avatarURL: nil,
canBeJoined: true),
.init(id: "test_2",
alias: "#test_2:example.com",
name: "Test 2",
topic: "Test description 2",
avatarURL: URL.documentsDirectory,
canBeJoined: false)])),
userIndicatorController: UserIndicatorControllerMock(),
imageProvider: MockMediaProvider())
static let viewModel: RoomDirectorySearchScreenViewModel = {
let results = [RoomDirectorySearchResult(id: "test_1",
alias: "#test_1:example.com",
name: "Test 1",
topic: "Test description 1",
avatarURL: nil,
canBeJoined: true),
RoomDirectorySearchResult(id: "test_2",
alias: "#test_2:example.com",
name: "Test 2",
topic: nil,
avatarURL: URL.documentsDirectory,
canBeJoined: false)]
let roomDirectorySearchProxy = RoomDirectorySearchProxyMock(configuration: .init(results: results))
let clientProxy = ClientProxyMock(.init(roomDirectorySearchProxy: roomDirectorySearchProxy))
return RoomDirectorySearchScreenViewModel(clientProxy: clientProxy,
userIndicatorController: UserIndicatorControllerMock(),
imageProvider: MockMediaProvider())
}()
static var previews: some View {
RoomDirectorySearchScreen(context: viewModel.context)