Add some new space properties. (#4544)

* Use the via property on SpaceRoom.

* Fall back to the canonical alias as a space room name if needs be.

* Use SpaceRoom.isDirect for computing the name/avatar.

* Pass in the parent space as a workaround for no restricted join rules.
This commit is contained in:
Doug
2025-09-26 10:03:11 +01:00
committed by GitHub
parent 3d5901f90d
commit 12dc6f42ba
30 changed files with 178 additions and 102 deletions
@@ -14,8 +14,6 @@ struct SpaceHeaderView: View {
@State private var isPresentingTopic = false
var title: String { spaceRoomProxy.name ?? "" }
var body: some View {
VStack(spacing: 16) {
RoomAvatarImage(avatar: spaceRoomProxy.avatar,
@@ -24,7 +22,7 @@ struct SpaceHeaderView: View {
.accessibilityHidden(true)
VStack(spacing: 8) {
Text(title)
Text(spaceRoomProxy.computedName)
.font(.compound.headingLGBold)
.foregroundStyle(.compound.textPrimary)
.multilineTextAlignment(.center)
@@ -76,31 +74,24 @@ struct SpaceHeaderView: View {
}
var spaceDetailsVisibilityTitle: String {
switch spaceRoomProxy.joinRule {
case .public:
L10n.commonPublicSpace
case .restricted(let rules), .knockRestricted(let rules):
// FIXME: Get this from the rule (falling back to a passed in parent??)
"<Parent name> space"
case .invite, .knock, .private, .custom, .none:
L10n.commonPrivateSpace
switch spaceRoomProxy.visibility {
case .public: L10n.commonPublicSpace
case .private: L10n.commonPrivateSpace
case .restricted(let parentName): L10n.screenSpaceListParentSpace(parentName)
case .none: L10n.commonPrivateSpace
}
}
var spaceDetailsVisibilityIcon: KeyPath<CompoundIcons, Image> {
switch spaceRoomProxy.joinRule {
case .public:
\.public
case .restricted, .knockRestricted:
\.space
case .invite, .knock, .private, .custom, .none:
\.lock
switch spaceRoomProxy.visibility {
case .public: \.public
case .private: \.lock
case .restricted: \.space
case .none: \.lock
}
}
}
import MatrixRustSDK
struct SpaceHeaderMembersView: View {
let heroes: [UserProfileProxy]
let joinedCount: Int
@@ -159,6 +150,8 @@ struct SpaceHeaderMembersView: View {
}
}
// MARK: - Previews
struct SpaceHeaderView_Previews: PreviewProvider, TestablePreview {
static let mediaProvider = MediaProviderMock(configuration: .init())
@@ -190,6 +183,7 @@ struct SpaceHeaderView_Previews: PreviewProvider, TestablePreview {
SpaceRoomProxyMock(.init(id: "!space3:matrix.org",
name: "Subspace",
isSpace: true,
parent: SpaceRoomProxyMock(.init(name: "Foundation", isSpace: true)),
childrenCount: 30,
joinedMembersCount: 123,
heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose],
@@ -25,12 +25,26 @@ struct SpaceRoomCell: View {
private var subtitle: String {
if spaceRoomProxy.isSpace {
spaceRoomProxy.joinRule == .public ? L10n.commonPublicSpace : L10n.commonPrivateSpace
switch spaceRoomProxy.visibility {
case .public: L10n.commonPublicSpace
case .private: L10n.commonPrivateSpace
case .restricted(let parentName): L10n.screenSpaceListParentSpace(parentName)
case .none: L10n.commonPrivateSpace
}
} else {
L10n.commonMemberCount(spaceRoomProxy.joinedMembersCount)
}
}
var visibilityIcon: KeyPath<CompoundIcons, Image>? {
switch spaceRoomProxy.visibility {
case .public: \.public
case .private: \.lockSolid
case .restricted: nil
case .none: \.lockSolid
}
}
private var details: String {
if spaceRoomProxy.isSpace {
L10n.screenSpaceListDetails(L10n.commonRooms(spaceRoomProxy.childrenCount),
@@ -77,12 +91,12 @@ struct SpaceRoomCell: View {
private var content: some View {
HStack(spacing: 16) {
VStack(alignment: .leading, spacing: 2) {
Text(spaceRoomProxy.name ?? spaceRoomProxy.id)
Text(spaceRoomProxy.computedName)
.font(.compound.bodyLGSemibold)
.foregroundColor(.compound.textPrimary)
.lineLimit(1)
visibilityLabel
subtitleLabel
Text(details)
.font(.compound.bodyMD)
@@ -95,17 +109,19 @@ struct SpaceRoomCell: View {
}
}
private var visibilityLabel: some View {
private var subtitleLabel: some View {
Label {
Text(subtitle)
.font(.compound.bodyMD)
.foregroundStyle(.compound.textSecondary)
.lineLimit(1)
} icon: {
CompoundIcon(spaceRoomProxy.joinRule == .public ? \.public : \.lockSolid,
size: .xSmall,
relativeTo: .compound.bodyMD)
.foregroundStyle(.compound.iconTertiary)
if let visibilityIcon {
CompoundIcon(visibilityIcon,
size: .xSmall,
relativeTo: .compound.bodyMD)
.foregroundStyle(.compound.iconTertiary)
}
}
.labelStyle(.custom(spacing: 4))
}