Rename SpaceRoomProxy to SpaceServiceRoom and stop proxying the struct. (#4952)

* Rename SpaceRoomProxy to SpaceServiceRoom.

The underlying type is a struct, we don't need to proxy it.

* Actually stop proxying the SpaceRoom.
This commit is contained in:
Doug
2026-01-13 12:00:20 +00:00
committed by GitHub
parent de1753a766
commit 334df3f5cd
43 changed files with 620 additions and 604 deletions
@@ -10,36 +10,36 @@ import Compound
import SwiftUI
struct SpaceHeaderView: View {
let spaceRoomProxy: SpaceRoomProxyProtocol
let spaceServiceRoom: SpaceServiceRoomProtocol
let mediaProvider: MediaProviderProtocol?
@State private var isPresentingTopic = false
var body: some View {
VStack(spacing: 16) {
RoomAvatarImage(avatar: spaceRoomProxy.avatar,
RoomAvatarImage(avatar: spaceServiceRoom.avatar,
avatarSize: .room(on: .spaceHeader),
mediaProvider: mediaProvider)
.accessibilityHidden(true)
VStack(spacing: 8) {
Text(spaceRoomProxy.name)
Text(spaceServiceRoom.name)
.font(.compound.headingLGBold)
.foregroundStyle(.compound.textPrimary)
.multilineTextAlignment(.center)
if let alias = spaceRoomProxy.canonicalAlias {
if let alias = spaceServiceRoom.canonicalAlias {
CopyTextButton(content: alias)
}
spaceDetails
JoinedMembersBadgeView(heroes: spaceRoomProxy.heroes,
joinedCount: spaceRoomProxy.joinedMembersCount,
JoinedMembersBadgeView(heroes: spaceServiceRoom.heroes,
joinedCount: spaceServiceRoom.joinedMembersCount,
mediaProvider: mediaProvider)
}
if let topic = spaceRoomProxy.topic {
if let topic = spaceServiceRoom.topic {
Button { isPresentingTopic = true } label: {
Text(topic)
.font(.compound.bodyMD)
@@ -60,7 +60,7 @@ struct SpaceHeaderView: View {
.frame(height: 1 / UIScreen.main.scale)
}
.sheet(isPresented: $isPresentingTopic) {
if let topic = spaceRoomProxy.topic {
if let topic = spaceServiceRoom.topic {
SpaceHeaderTopicSheetView(topic: topic)
}
}
@@ -79,7 +79,7 @@ struct SpaceHeaderView: View {
}
private var spaceDetailsVisibilityTitle: String {
switch spaceRoomProxy.visibility {
switch spaceServiceRoom.visibility {
case .public: L10n.commonPublicSpace
case .private: L10n.commonPrivateSpace
case .restricted: L10n.commonSharedSpace
@@ -88,7 +88,7 @@ struct SpaceHeaderView: View {
}
private var spaceDetailsVisibilityIcon: KeyPath<CompoundIcons, Image> {
switch spaceRoomProxy.visibility {
switch spaceServiceRoom.visibility {
case .public: \.public
case .private: \.lock
case .restricted: \.space
@@ -107,41 +107,41 @@ struct SpaceHeaderView_Previews: PreviewProvider, TestablePreview {
static var previews: some View {
VStack(spacing: 0) {
ForEach(spaces, id: \.id) { space in
SpaceHeaderView(spaceRoomProxy: space, mediaProvider: mediaProvider)
SpaceHeaderView(spaceServiceRoom: space, mediaProvider: mediaProvider)
}
}
}
static func makeSpaceRooms() -> [SpaceRoomProxyMock] {
static func makeSpaceRooms() -> [SpaceServiceRoomMock] {
[
SpaceRoomProxyMock(.init(id: "!space1:matrix.org",
name: "Company Space",
isSpace: true,
childrenCount: 10,
joinedMembersCount: 50)),
SpaceRoomProxyMock(.init(id: "!space2:matrix.org",
name: "Community Space",
avatarURL: .mockMXCAvatar,
isSpace: true,
childrenCount: 20,
joinedMembersCount: 78,
topic: "Description of the space goes right here.",
canonicalAlias: "#space:matrix.org",
joinRule: .public)),
SpaceRoomProxyMock(.init(id: "!space3:matrix.org",
name: "Subspace",
isSpace: true,
childrenCount: 30,
joinedMembersCount: 123,
heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose],
topic: ["Description of the space goes right here.",
"Lorem ipsum dolor sit amet consectetur.",
"Leo viverra morbi habitant in.",
"Sem amet enim habitant nibh augue mauris.",
"Interdum mauris ultrices tincidunt proin morbi erat aenean risus nibh.",
"Diam amet sit fermentum vulputate faucibus."].joined(separator: " "),
canonicalAlias: "#subspace:matrix.org",
joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")])))
SpaceServiceRoomMock(.init(id: "!space1:matrix.org",
name: "Company Space",
isSpace: true,
childrenCount: 10,
joinedMembersCount: 50)),
SpaceServiceRoomMock(.init(id: "!space2:matrix.org",
name: "Community Space",
avatarURL: .mockMXCAvatar,
isSpace: true,
childrenCount: 20,
joinedMembersCount: 78,
topic: "Description of the space goes right here.",
canonicalAlias: "#space:matrix.org",
joinRule: .public)),
SpaceServiceRoomMock(.init(id: "!space3:matrix.org",
name: "Subspace",
isSpace: true,
childrenCount: 30,
joinedMembersCount: 123,
heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose],
topic: ["Description of the space goes right here.",
"Lorem ipsum dolor sit amet consectetur.",
"Leo viverra morbi habitant in.",
"Sem amet enim habitant nibh augue mauris.",
"Interdum mauris ultrices tincidunt proin morbi erat aenean risus nibh.",
"Diam amet sit fermentum vulputate faucibus."].joined(separator: " "),
canonicalAlias: "#subspace:matrix.org",
joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")])))
]
}
}
@@ -13,32 +13,32 @@ import SwiftUI
struct SpaceRoomCell: View {
@Environment(\.dynamicTypeSize) var dynamicTypeSize
let spaceRoomProxy: SpaceRoomProxyProtocol
let spaceServiceRoom: SpaceServiceRoomProtocol
let isSelected: Bool
var isJoining = false
let mediaProvider: MediaProviderProtocol!
enum Action { case select(SpaceRoomProxyProtocol), join(SpaceRoomProxyProtocol) }
enum Action { case select(SpaceServiceRoomProtocol), join(SpaceServiceRoomProtocol) }
let action: (Action) -> Void
private let verticalInsets = 12.0
private let horizontalInsets = 16.0
private var subtitle: String {
if spaceRoomProxy.isSpace {
switch spaceRoomProxy.visibility {
if spaceServiceRoom.isSpace {
switch spaceServiceRoom.visibility {
case .public: L10n.commonPublicSpace
case .private: L10n.commonPrivateSpace
case .restricted: L10n.commonSharedSpace
case .none: L10n.commonPrivateSpace
}
} else {
L10n.commonMemberCount(spaceRoomProxy.joinedMembersCount)
L10n.commonMemberCount(spaceServiceRoom.joinedMembersCount)
}
}
var visibilityIcon: KeyPath<CompoundIcons, Image>? {
switch spaceRoomProxy.visibility {
switch spaceServiceRoom.visibility {
case .public: \.public
case .private: \.lockSolid
case .restricted: nil
@@ -47,16 +47,16 @@ struct SpaceRoomCell: View {
}
private var details: String {
if spaceRoomProxy.isSpace {
L10n.commonMemberCount(spaceRoomProxy.joinedMembersCount)
if spaceServiceRoom.isSpace {
L10n.commonMemberCount(spaceServiceRoom.joinedMembersCount)
} else {
spaceRoomProxy.topic ?? " " // Use a single space to reserve a consistent amount of space.
spaceServiceRoom.topic ?? " " // Use a single space to reserve a consistent amount of space.
}
}
var body: some View {
Button {
action(.select(spaceRoomProxy))
action(.select(spaceServiceRoom))
} label: {
HStack(spacing: 16.0) {
avatar
@@ -74,13 +74,13 @@ struct SpaceRoomCell: View {
.accessibilityElement(children: .combine)
}
.buttonStyle(SpaceRoomCellButtonStyle(isSelected: isSelected))
.accessibilityIdentifier(A11yIdentifiers.spaceListScreen.spaceRoomName(spaceRoomProxy.name))
.accessibilityIdentifier(A11yIdentifiers.spaceListScreen.spaceRoomName(spaceServiceRoom.name))
}
@ViewBuilder @MainActor
private var avatar: some View {
if dynamicTypeSize < .accessibility3 {
RoomAvatarImage(avatar: spaceRoomProxy.avatar,
RoomAvatarImage(avatar: spaceServiceRoom.avatar,
avatarSize: .room(on: .spaces),
mediaProvider: mediaProvider)
.dynamicTypeSize(dynamicTypeSize < .accessibility1 ? dynamicTypeSize : .accessibility1)
@@ -91,7 +91,7 @@ struct SpaceRoomCell: View {
private var content: some View {
HStack(spacing: 16) {
VStack(alignment: .leading, spacing: 2) {
Text(spaceRoomProxy.name)
Text(spaceServiceRoom.name)
.font(.compound.bodyLGSemibold)
.foregroundColor(.compound.textPrimary)
.lineLimit(1)
@@ -128,9 +128,9 @@ struct SpaceRoomCell: View {
@ViewBuilder
private var accessory: some View {
switch spaceRoomProxy.state {
switch spaceServiceRoom.state {
case .none, .left, .invited:
Button(L10n.actionJoin) { action(.join(spaceRoomProxy)) }
Button(L10n.actionJoin) { action(.join(spaceServiceRoom)) }
.font(.compound.bodyLG)
.foregroundStyle(.compound.textActionAccent)
.opacity(isJoining ? 0 : 1)
@@ -159,21 +159,21 @@ struct SpaceRoomCellButtonStyle: ButtonStyle {
struct SpaceRoomCell_Previews: PreviewProvider, TestablePreview {
static let mediaProvider = MediaProviderMock(configuration: .init())
static let spaces = [SpaceRoomProxyProtocol].mockSpaceList
static let spaces = [SpaceServiceRoomProtocol].mockSpaceList
static var previews: some View {
VStack(spacing: 0) {
ForEach(spaces, id: \.id) { space in
SpaceRoomCell(spaceRoomProxy: space,
SpaceRoomCell(spaceServiceRoom: space,
isSelected: false,
mediaProvider: mediaProvider) { _ in }
}
SpaceRoomCell(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "Space being joined", isSpace: true)),
SpaceRoomCell(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "Space being joined", isSpace: true)),
isSelected: false,
isJoining: true,
mediaProvider: mediaProvider) { _ in }
SpaceRoomCell(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "Room being joined", isSpace: false)),
SpaceRoomCell(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "Room being joined", isSpace: false)),
isSelected: false,
isJoining: true,
mediaProvider: mediaProvider) { _ in }
@@ -19,13 +19,13 @@ struct LeaveSpaceRoomDetailsCell: View {
let action: () -> Void
private var subtitle: String? {
guard !room.spaceRoomProxy.isSpace else { return nil }
let memberCount = L10n.commonMemberCount(room.spaceRoomProxy.joinedMembersCount)
guard !room.spaceServiceRoom.isSpace else { return nil }
let memberCount = L10n.commonMemberCount(room.spaceServiceRoom.joinedMembersCount)
return room.isLastAdmin ? L10n.screenLeaveSpaceLastAdminInfo(memberCount) : memberCount
}
var visibilityIcon: KeyPath<CompoundIcons, Image>? {
switch room.spaceRoomProxy.visibility {
switch room.spaceServiceRoom.visibility {
case .public: \.public
case .private: \.lockSolid
case .restricted: nil
@@ -37,13 +37,13 @@ struct LeaveSpaceRoomDetailsCell: View {
Button(action: action) {
HStack(spacing: 16) {
if dynamicTypeSize < .accessibility3 {
RoomAvatarImage(avatar: room.spaceRoomProxy.avatar,
RoomAvatarImage(avatar: room.spaceServiceRoom.avatar,
avatarSize: .room(on: .leaveSpace),
mediaProvider: mediaProvider)
}
VStack(alignment: .leading, spacing: 0) {
Text(room.spaceRoomProxy.name)
Text(room.spaceServiceRoom.name)
.font(.compound.bodyLGSemibold)
.foregroundStyle(.compound.textPrimary)
.lineLimit(1)
@@ -91,40 +91,40 @@ struct LeaveSpaceRoomDetailsCell: View {
struct LeaveSpaceRoomDetailsCell_Previews: PreviewProvider, TestablePreview {
static var previews: some View {
VStack(spacing: 0) {
LeaveSpaceRoomDetailsCell(room: .init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "1",
name: "Space",
isSpace: true)),
LeaveSpaceRoomDetailsCell(room: .init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "1",
name: "Space",
isSpace: true)),
isLastAdmin: false,
isSelected: true),
mediaProvider: MediaProviderMock(configuration: .init())) { }
LeaveSpaceRoomDetailsCell(room: .init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "2",
name: "My Space",
isSpace: true)),
LeaveSpaceRoomDetailsCell(room: .init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "2",
name: "My Space",
isSpace: true)),
isLastAdmin: true,
isSelected: false),
mediaProvider: MediaProviderMock(configuration: .init())) { }
LeaveSpaceRoomDetailsCell(room: .init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "2",
name: "My Space",
isSpace: true)),
LeaveSpaceRoomDetailsCell(room: .init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "2",
name: "My Space",
isSpace: true)),
isLastAdmin: true,
isSelected: false),
hideSelection: true,
mediaProvider: MediaProviderMock(configuration: .init())) { }
LeaveSpaceRoomDetailsCell(room: .init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "3",
name: "Room",
isSpace: false)),
LeaveSpaceRoomDetailsCell(room: .init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "3",
name: "Room",
isSpace: false)),
isLastAdmin: false,
isSelected: true),
mediaProvider: MediaProviderMock(configuration: .init())) { }
LeaveSpaceRoomDetailsCell(room: .init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "4",
name: "My Room",
isSpace: false)),
LeaveSpaceRoomDetailsCell(room: .init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "4",
name: "My Room",
isSpace: false)),
isLastAdmin: true,
isSelected: false),
mediaProvider: MediaProviderMock(configuration: .init())) { }
LeaveSpaceRoomDetailsCell(room: .init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "4",
name: "My Room",
isSpace: false)),
LeaveSpaceRoomDetailsCell(room: .init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "4",
name: "My Room",
isSpace: false)),
isLastAdmin: true,
isSelected: false),
hideSelection: true,
@@ -64,11 +64,11 @@ struct LeaveSpaceView: View {
context.viewState.leaveHandle.canLeave {
LazyVStack(spacing: 0, pinnedViews: .sectionHeaders) {
Section {
ForEach(context.viewState.leaveHandle.rooms, id: \.spaceRoomProxy.id) { room in
ForEach(context.viewState.leaveHandle.rooms, id: \.spaceServiceRoom.id) { room in
LeaveSpaceRoomDetailsCell(room: room,
hideSelection: context.viewState.leaveHandle.mode == .onlyAdminRooms,
mediaProvider: context.mediaProvider) {
context.send(viewAction: .toggleRoom(roomID: room.spaceRoomProxy.id))
context.send(viewAction: .toggleRoom(roomID: room.spaceServiceRoom.id))
}
.disabled(room.isLastAdmin)
}
@@ -136,27 +136,27 @@ struct LeaveSpaceView_Previews: PreviewProvider, TestablePreview {
.previewDisplayName("Last Space Admin")
}
static let spaceRoomProxy = SpaceRoomProxyMock(.init(id: "!eng-space:matrix.org",
name: "Engineering Team",
isSpace: true,
childrenCount: 30,
joinedMembersCount: 76,
heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose],
topic: "Description of the space goes right here. Lorem ipsum dolor sit amet consectetur. Leo viverra morbi habitant in.",
joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")])))
static let spaceServiceRoom = SpaceServiceRoomMock(.init(id: "!eng-space:matrix.org",
name: "Engineering Team",
isSpace: true,
childrenCount: 30,
joinedMembersCount: 76,
heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose],
topic: "Description of the space goes right here. Lorem ipsum dolor sit amet consectetur. Leo viverra morbi habitant in.",
joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")])))
static func makeViewModel(mode: LeaveSpaceHandleProxy.Mode) -> LeaveSpaceViewModel {
let rooms: [LeaveSpaceRoom] = switch mode {
case .manyRooms: .mockRooms
case .onlyAdminRooms: .mockAdminRooms
case .noRooms: .mockSingleSpace(spaceRoomProxy: spaceRoomProxy, isLastAdmin: false)
case .lastSpaceAdmin: .mockRoomsWithSpace(spaceRoomProxy: spaceRoomProxy, isLastAdmin: true)
case .noRooms: .mockSingleSpace(spaceServiceRoom: spaceServiceRoom, isLastAdmin: false)
case .lastSpaceAdmin: .mockRoomsWithSpace(spaceServiceRoom: spaceServiceRoom, isLastAdmin: true)
}
let leaveHandle = LeaveSpaceHandleProxy(spaceID: spaceRoomProxy.id,
let leaveHandle = LeaveSpaceHandleProxy(spaceID: spaceServiceRoom.id,
leaveHandle: LeaveSpaceHandleSDKMock(.init(rooms: rooms)))
return LeaveSpaceViewModel(spaceName: spaceRoomProxy.name,
return LeaveSpaceViewModel(spaceName: spaceServiceRoom.name,
canEditRolesAndPermissions: true,
leaveHandle: leaveHandle,
userIndicatorController: UserIndicatorControllerMock(),
@@ -18,7 +18,7 @@ struct SpaceListScreenViewState: BindableState {
var userDisplayName: String?
var userAvatarURL: URL?
var topLevelSpaces: [SpaceRoomProxyProtocol]
var topLevelSpaces: [SpaceServiceRoomProtocol]
var selectedSpaceID: String?
var isCreateSpaceEnabled: Bool
@@ -65,8 +65,8 @@ class SpaceListScreenViewModel: SpaceListScreenViewModelType, SpaceListScreenVie
MXLog.info("View model: received view action: \(viewAction)")
switch viewAction {
case .spaceAction(.select(let spaceRoomProxy)):
Task { await selectSpace(spaceRoomProxy) }
case .spaceAction(.select(let spaceServiceRoom)):
Task { await selectSpace(spaceServiceRoom) }
case .spaceAction(.join):
fatalError("There shouldn't be any unjoined spaces in the joined spaces list.")
case .showSettings:
@@ -86,8 +86,8 @@ class SpaceListScreenViewModel: SpaceListScreenViewModelType, SpaceListScreenVie
// MARK: - Private
private func selectSpace(_ spaceRoomProxy: SpaceRoomProxyProtocol) async {
switch await spaceServiceProxy.spaceRoomList(spaceID: spaceRoomProxy.id) {
private func selectSpace(_ spaceServiceRoom: SpaceServiceRoomProtocol) async {
switch await spaceServiceProxy.spaceRoomList(spaceID: spaceServiceRoom.id) {
case .success(let spaceRoomListProxy):
actionsSubject.send(.selectSpace(spaceRoomListProxy))
case .failure(let error):
@@ -85,9 +85,9 @@ struct SpaceListScreen: View {
}
private var spaces: some View {
ForEach(context.viewState.topLevelSpaces, id: \.id) { spaceRoomProxy in
SpaceRoomCell(spaceRoomProxy: spaceRoomProxy,
isSelected: spaceRoomProxy.id == context.viewState.selectedSpaceID,
ForEach(context.viewState.topLevelSpaces, id: \.id) { spaceServiceRoom in
SpaceRoomCell(spaceServiceRoom: spaceServiceRoom,
isSelected: spaceServiceRoom.id == context.viewState.selectedSpaceID,
mediaProvider: context.mediaProvider) { action in
context.send(viewAction: .spaceAction(action))
}
@@ -22,7 +22,7 @@ struct SpaceScreenCoordinatorParameters {
enum SpaceScreenCoordinatorAction {
case selectSpace(SpaceRoomListProxyProtocol)
case selectUnjoinedSpace(SpaceRoomProxyProtocol)
case selectUnjoinedSpace(SpaceServiceRoomProtocol)
case selectRoom(roomID: String)
case leftSpace
case displayMembers(roomProxy: JoinedRoomProxyProtocol)
@@ -60,8 +60,8 @@ final class SpaceScreenCoordinator: CoordinatorProtocol {
switch action {
case .selectSpace(let spaceRoomListProxy):
actionsSubject.send(.selectSpace(spaceRoomListProxy))
case .selectUnjoinedSpace(let spaceRoomProxy):
actionsSubject.send(.selectUnjoinedSpace(spaceRoomProxy))
case .selectUnjoinedSpace(let spaceServiceRoom):
actionsSubject.send(.selectUnjoinedSpace(spaceServiceRoom))
case .selectRoom(let roomID):
actionsSubject.send(.selectRoom(roomID: roomID))
case .leftSpace:
@@ -10,7 +10,7 @@ import Foundation
enum SpaceScreenViewModelAction {
case selectSpace(SpaceRoomListProxyProtocol)
case selectUnjoinedSpace(SpaceRoomProxyProtocol)
case selectUnjoinedSpace(SpaceServiceRoomProtocol)
case selectRoom(roomID: String)
case leftSpace
case presentRolesAndPermissions(roomProxy: JoinedRoomProxyProtocol)
@@ -19,13 +19,13 @@ enum SpaceScreenViewModelAction {
}
struct SpaceScreenViewState: BindableState {
var space: SpaceRoomProxyProtocol
var space: SpaceServiceRoomProtocol
var permalink: URL?
var roomProxy: JoinedRoomProxyProtocol?
var isPaginating = false
var rooms: [SpaceRoomProxyProtocol]
var rooms: [SpaceServiceRoomProtocol]
var selectedSpaceRoomID: String?
var joiningRoomIDs: Set<String> = []
@@ -37,12 +37,12 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc
self.userIndicatorController = userIndicatorController
self.appSettings = appSettings
super.init(initialViewState: SpaceScreenViewState(space: spaceRoomListProxy.spaceRoomProxyPublisher.value,
super.init(initialViewState: SpaceScreenViewState(space: spaceRoomListProxy.spaceServiceRoomPublisher.value,
rooms: spaceRoomListProxy.spaceRoomsPublisher.value,
selectedSpaceRoomID: selectedSpaceRoomPublisher.value),
mediaProvider: userSession.mediaProvider)
spaceRoomListProxy.spaceRoomProxyPublisher
spaceRoomListProxy.spaceServiceRoomPublisher
.receive(on: DispatchQueue.main)
.weakAssign(to: \.state.space, on: self)
.store(in: &cancellables)
@@ -107,19 +107,19 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc
MXLog.info("View model: received view action: \(viewAction)")
switch viewAction {
case .spaceAction(.select(let spaceRoomProxy)):
if spaceRoomProxy.isSpace {
if spaceRoomProxy.state != .joined {
actionsSubject.send(.selectUnjoinedSpace(spaceRoomProxy))
case .spaceAction(.select(let spaceServiceRoom)):
if spaceServiceRoom.isSpace {
if spaceServiceRoom.state != .joined {
actionsSubject.send(.selectUnjoinedSpace(spaceServiceRoom))
} else {
Task { await selectSpace(spaceRoomProxy) }
Task { await selectSpace(spaceServiceRoom) }
}
} else {
// No need to check the join state, the room flow will show an appropriately configured join screen if needed.
actionsSubject.send(.selectRoom(roomID: spaceRoomProxy.id))
actionsSubject.send(.selectRoom(roomID: spaceServiceRoom.id))
}
case .spaceAction(.join(let spaceRoomProxy)):
Task { await join(spaceRoomProxy) }
case .spaceAction(.join(let spaceServiceRoom)):
Task { await join(spaceServiceRoom) }
case .leaveSpace:
Task { await showLeaveSpaceConfirmation() }
case .displayMembers(let roomProxy):
@@ -136,11 +136,11 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc
// MARK: - Private
private func join(_ spaceRoomProxy: SpaceRoomProxyProtocol) async {
state.joiningRoomIDs.insert(spaceRoomProxy.id)
defer { state.joiningRoomIDs.remove(spaceRoomProxy.id) }
private func join(_ spaceServiceRoom: SpaceServiceRoomProtocol) async {
state.joiningRoomIDs.insert(spaceServiceRoom.id)
defer { state.joiningRoomIDs.remove(spaceServiceRoom.id) }
guard case .success = await clientProxy.joinRoom(spaceRoomProxy.id, via: spaceRoomProxy.via) else {
guard case .success = await clientProxy.joinRoom(spaceServiceRoom.id, via: spaceServiceRoom.via) else {
showFailureIndicator()
return
}
@@ -148,8 +148,8 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc
// We don't want to show the space room after joining it this way 🤷‍♂️
}
private func selectSpace(_ spaceRoomProxy: SpaceRoomProxyProtocol) async {
switch await spaceServiceProxy.spaceRoomList(spaceID: spaceRoomProxy.id) {
private func selectSpace(_ spaceServiceRoom: SpaceServiceRoomProtocol) async {
switch await spaceServiceProxy.spaceRoomList(spaceID: spaceServiceRoom.id) {
case .success(let spaceRoomListProxy):
actionsSubject.send(.selectSpace(spaceRoomListProxy))
case .failure(let error):
@@ -15,7 +15,7 @@ struct SpaceScreen: View {
var body: some View {
ScrollView {
LazyVStack(spacing: 0) {
SpaceHeaderView(spaceRoomProxy: context.viewState.space,
SpaceHeaderView(spaceServiceRoom: context.viewState.space,
mediaProvider: context.mediaProvider)
rooms
}
@@ -32,10 +32,10 @@ struct SpaceScreen: View {
@ViewBuilder
var rooms: some View {
ForEach(context.viewState.rooms, id: \.id) { spaceRoomProxy in
SpaceRoomCell(spaceRoomProxy: spaceRoomProxy,
isSelected: spaceRoomProxy.id == context.viewState.selectedSpaceRoomID,
isJoining: context.viewState.joiningRoomIDs.contains(spaceRoomProxy.id),
ForEach(context.viewState.rooms, id: \.id) { spaceServiceRoom in
SpaceRoomCell(spaceServiceRoom: spaceServiceRoom,
isSelected: spaceServiceRoom.id == context.viewState.selectedSpaceRoomID,
isJoining: context.viewState.joiningRoomIDs.contains(spaceServiceRoom.id),
mediaProvider: context.mediaProvider) { action in
context.send(viewAction: .spaceAction(action))
}
@@ -114,16 +114,16 @@ struct SpaceScreen_Previews: PreviewProvider, TestablePreview {
}
static func makeViewModel() -> SpaceScreenViewModel {
let spaceRoomProxy = SpaceRoomProxyMock(.init(id: "!eng-space:matrix.org",
name: "Engineering Team",
isSpace: true,
childrenCount: 30,
joinedMembersCount: 76,
heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose],
topic: "Description of the space goes right here. Lorem ipsum dolor sit amet consectetur. Leo viverra morbi habitant in.",
canonicalAlias: "#engineering-team:element.io",
joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")])))
let spaceRoomListProxy = SpaceRoomListProxyMock(.init(spaceRoomProxy: spaceRoomProxy,
let spaceServiceRoom = SpaceServiceRoomMock(.init(id: "!eng-space:matrix.org",
name: "Engineering Team",
isSpace: true,
childrenCount: 30,
joinedMembersCount: 76,
heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose],
topic: "Description of the space goes right here. Lorem ipsum dolor sit amet consectetur. Leo viverra morbi habitant in.",
canonicalAlias: "#engineering-team:element.io",
joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")])))
let spaceRoomListProxy = SpaceRoomListProxyMock(.init(spaceServiceRoom: spaceServiceRoom,
initialSpaceRooms: .mockSpaceList))
let clientProxy = ClientProxyMock(.init())