Joining a space from the room flow. (#4563)

* Add the More menu to SpaceScreen.

And a simple way to leave a space for testing.

* Start a space flow when accepting a space invite from the room flow.

* Minimise the tab bar on iOS 26 when scrolling down.

* Enable spaces by default!
This commit is contained in:
Doug
2025-10-02 10:58:38 +01:00
committed by GitHub
parent 3215f8c269
commit 621b72f162
13 changed files with 128 additions and 29 deletions
@@ -22,6 +22,7 @@ enum SpaceScreenCoordinatorAction {
case selectSpace(SpaceRoomListProxyProtocol)
case selectUnjoinedSpace(SpaceRoomProxyProtocol)
case selectRoom(roomID: String)
case leftSpace
}
final class SpaceScreenCoordinator: CoordinatorProtocol {
@@ -57,6 +58,8 @@ final class SpaceScreenCoordinator: CoordinatorProtocol {
actionsSubject.send(.selectUnjoinedSpace(spaceRoomProxy))
case .selectRoom(let roomID):
actionsSubject.send(.selectRoom(roomID: roomID))
case .leftSpace:
actionsSubject.send(.leftSpace)
}
}
.store(in: &cancellables)
@@ -11,11 +11,14 @@ enum SpaceScreenViewModelAction {
case selectSpace(SpaceRoomListProxyProtocol)
case selectUnjoinedSpace(SpaceRoomProxyProtocol)
case selectRoom(roomID: String)
case leftSpace
}
struct SpaceScreenViewState: BindableState {
let space: SpaceRoomProxyProtocol
var permalink: URL?
var isPaginating = false
var rooms: [SpaceRoomProxyProtocol]
var selectedSpaceRoomID: String?
@@ -30,4 +33,5 @@ struct SpaceScreenViewStateBindings { }
enum SpaceScreenViewAction {
case spaceAction(SpaceRoomCell.Action)
case leaveSpace
}
@@ -60,6 +60,13 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc
selectedSpaceRoomPublisher
.weakAssign(to: \.state.selectedSpaceRoomID, on: self)
.store(in: &cancellables)
Task {
if case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(spaceRoomListProxy.spaceRoomProxy.id),
case let .success(permalinkURL) = await roomProxy.matrixToPermalink() {
state.permalink = permalinkURL
}
}
}
// MARK: - Public
@@ -81,6 +88,15 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc
}
case .spaceAction(.join(let spaceRoomProxy)):
Task { await join(spaceRoomProxy) }
case .leaveSpace:
#if DEBUG
Task { // Temporary implementation to make joining a space easier to test.
if case let .joined(roomProxy) = await clientProxy.roomForIdentifier(spaceRoomListProxy.spaceRoomProxy.id),
case .success = await roomProxy.leaveRoom() {
actionsSubject.send(.leftSpace)
}
}
#endif
}
}
@@ -42,6 +42,7 @@ struct SpaceScreen: View {
}
}
@ToolbarContentBuilder
var toolbar: some ToolbarContent {
// Use the same trick as the RoomScreen for a leading title view that
// also hides the navigation title.
@@ -50,6 +51,22 @@ struct SpaceScreen: View {
roomAvatar: context.viewState.space.avatar,
mediaProvider: context.mediaProvider)
}
ToolbarItemGroup(placement: .secondaryAction) {
if let permalink = context.viewState.permalink {
Section {
ShareLink(item: permalink) {
Label(L10n.actionShare, icon: \.shareIos)
}
}
}
Section {
Button(role: .destructive) { context.send(viewAction: .leaveSpace) } label: {
Label(L10n.actionLeaveSpace, icon: \.leave)
}
}
}
}
}