redesigned empty state for the room members list
This commit is contained in:
@@ -630,6 +630,8 @@
|
|||||||
"screen_room_grouped_state_events_expand" = "Expand";
|
"screen_room_grouped_state_events_expand" = "Expand";
|
||||||
"screen_room_grouped_state_events_reduce" = "Reduce";
|
"screen_room_grouped_state_events_reduce" = "Reduce";
|
||||||
"screen_room_member_list_banned_header_title" = "%1$d Banned";
|
"screen_room_member_list_banned_header_title" = "%1$d Banned";
|
||||||
|
"screen_room_member_list_empty_search_subtitle" = "Check the spelling or try a new search";
|
||||||
|
"screen_room_member_list_empty_search_title" = "No results for “%1$@”";
|
||||||
"screen_room_member_list_pending_status" = "Pending";
|
"screen_room_member_list_pending_status" = "Pending";
|
||||||
"screen_room_roles_and_permissions_space_details" = "Space details";
|
"screen_room_roles_and_permissions_space_details" = "Space details";
|
||||||
"screen_room_timeline_tombstoned_room_action" = "Jump to new room";
|
"screen_room_timeline_tombstoned_room_action" = "Jump to new room";
|
||||||
|
|||||||
@@ -630,6 +630,8 @@
|
|||||||
"screen_room_grouped_state_events_expand" = "Expand";
|
"screen_room_grouped_state_events_expand" = "Expand";
|
||||||
"screen_room_grouped_state_events_reduce" = "Reduce";
|
"screen_room_grouped_state_events_reduce" = "Reduce";
|
||||||
"screen_room_member_list_banned_header_title" = "%1$d Banned";
|
"screen_room_member_list_banned_header_title" = "%1$d Banned";
|
||||||
|
"screen_room_member_list_empty_search_subtitle" = "Check the spelling or try a new search";
|
||||||
|
"screen_room_member_list_empty_search_title" = "No results for “%1$@”";
|
||||||
"screen_room_member_list_pending_status" = "Pending";
|
"screen_room_member_list_pending_status" = "Pending";
|
||||||
"screen_room_roles_and_permissions_space_details" = "Space details";
|
"screen_room_roles_and_permissions_space_details" = "Space details";
|
||||||
"screen_room_timeline_tombstoned_room_action" = "Jump to new room";
|
"screen_room_timeline_tombstoned_room_action" = "Jump to new room";
|
||||||
|
|||||||
@@ -2482,6 +2482,12 @@ internal enum L10n {
|
|||||||
internal static func screenRoomMemberListBannedHeaderTitle(_ p1: Int) -> String {
|
internal static func screenRoomMemberListBannedHeaderTitle(_ p1: Int) -> String {
|
||||||
return L10n.tr("Localizable", "screen_room_member_list_banned_header_title", p1)
|
return L10n.tr("Localizable", "screen_room_member_list_banned_header_title", p1)
|
||||||
}
|
}
|
||||||
|
/// Check the spelling or try a new search
|
||||||
|
internal static var screenRoomMemberListEmptySearchSubtitle: String { return L10n.tr("Localizable", "screen_room_member_list_empty_search_subtitle") }
|
||||||
|
/// No results for “%1$@”
|
||||||
|
internal static func screenRoomMemberListEmptySearchTitle(_ p1: Any) -> String {
|
||||||
|
return L10n.tr("Localizable", "screen_room_member_list_empty_search_title", String(describing: p1))
|
||||||
|
}
|
||||||
/// Plural format key: "%#@COUNT@"
|
/// Plural format key: "%#@COUNT@"
|
||||||
internal static func screenRoomMemberListHeaderTitle(_ p1: Int) -> String {
|
internal static func screenRoomMemberListHeaderTitle(_ p1: Int) -> String {
|
||||||
return L10n.tr("Localizable", "screen_room_member_list_header_title", p1)
|
return L10n.tr("Localizable", "screen_room_member_list_header_title", p1)
|
||||||
|
|||||||
@@ -75,6 +75,15 @@ struct RoomMembersListScreenViewState: BindableState {
|
|||||||
bannedMembers
|
bannedMembers
|
||||||
.filter { $0.member.matches(searchQuery: bindings.searchQuery) }
|
.filter { $0.member.matches(searchQuery: bindings.searchQuery) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var shouldShowEmptyState: Bool {
|
||||||
|
switch bindings.mode {
|
||||||
|
case .banned:
|
||||||
|
visibleBannedMembers.count == 0
|
||||||
|
case .members:
|
||||||
|
visibleInvitedMembers.count + visibleJoinedMembers.count == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RoomMembersListScreenViewStateBindings {
|
struct RoomMembersListScreenViewStateBindings {
|
||||||
|
|||||||
@@ -104,11 +104,15 @@ class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMe
|
|||||||
self.members = members
|
self.members = members
|
||||||
self.currentUserProxy = members.first { $0.userID == roomProxy.ownUserID }
|
self.currentUserProxy = members.first { $0.userID == roomProxy.ownUserID }
|
||||||
|
|
||||||
|
var newBindings = state.bindings
|
||||||
|
if state.bindings.mode == .banned, roomMembersDetails.bannedMembers.count == 0 {
|
||||||
|
newBindings.mode = .members
|
||||||
|
}
|
||||||
self.state = .init(joinedMembersCount: roomProxy.infoPublisher.value.joinedMembersCount,
|
self.state = .init(joinedMembersCount: roomProxy.infoPublisher.value.joinedMembersCount,
|
||||||
joinedMembers: roomMembersDetails.joinedMembers,
|
joinedMembers: roomMembersDetails.joinedMembers,
|
||||||
invitedMembers: roomMembersDetails.invitedMembers,
|
invitedMembers: roomMembersDetails.invitedMembers,
|
||||||
bannedMembers: roomMembersDetails.bannedMembers,
|
bannedMembers: roomMembersDetails.bannedMembers,
|
||||||
bindings: state.bindings)
|
bindings: newBindings)
|
||||||
|
|
||||||
if let powerLevels = roomProxy.infoPublisher.value.powerLevels {
|
if let powerLevels = roomProxy.infoPublisher.value.powerLevels {
|
||||||
self.state.canInviteUsers = powerLevels.canOwnUserInvite()
|
self.state.canInviteUsers = powerLevels.canOwnUserInvite()
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ struct RoomMembersListScreen: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
if context.viewState.canBanUsers {
|
if context.viewState.canBanUsers, context.viewState.bannedMembersCount > 0 {
|
||||||
Picker("", selection: $context.mode) {
|
Picker("", selection: $context.mode) {
|
||||||
Text(L10n.screenRoomMemberListModeMembers)
|
Text(L10n.screenRoomMemberListModeMembers)
|
||||||
.tag(RoomMembersListScreenMode.members)
|
.tag(RoomMembersListScreenMode.members)
|
||||||
@@ -25,19 +25,17 @@ struct RoomMembersListScreen: View {
|
|||||||
.padding(ListRowPadding.insets)
|
.padding(ListRowPadding.insets)
|
||||||
}
|
}
|
||||||
|
|
||||||
if context.mode == .members {
|
if context.viewState.shouldShowEmptyState {
|
||||||
roomMembers
|
emptySearchView
|
||||||
} else {
|
} else {
|
||||||
bannedUsers
|
Spacer()
|
||||||
}
|
.frame(height: 18)
|
||||||
}
|
switch context.mode {
|
||||||
.overlay {
|
case .members:
|
||||||
if context.mode == .banned, context.viewState.bannedMembersCount == 0 {
|
roomMembers
|
||||||
Text(L10n.screenRoomMemberListBannedEmpty)
|
case .banned:
|
||||||
.font(.compound.bodyMD)
|
bannedUsers
|
||||||
.foregroundStyle(.secondary)
|
}
|
||||||
.multilineTextAlignment(.center)
|
|
||||||
.frame(maxWidth: .infinity)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.compoundList()
|
.compoundList()
|
||||||
@@ -81,6 +79,7 @@ struct RoomMembersListScreen: View {
|
|||||||
}
|
}
|
||||||
.background(.compound.bgCanvasDefault)
|
.background(.compound.bgCanvasDefault)
|
||||||
.clipShape(sectionShape)
|
.clipShape(sectionShape)
|
||||||
|
.padding(.bottom, 32)
|
||||||
} header: {
|
} header: {
|
||||||
section.header(count: entries.count)
|
section.header(count: entries.count)
|
||||||
}
|
}
|
||||||
@@ -106,6 +105,26 @@ struct RoomMembersListScreen: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var emptySearchView: some View {
|
||||||
|
VStack(spacing: 16) {
|
||||||
|
BigIcon(icon: \.search, style: .default)
|
||||||
|
.accessibilityHidden(true)
|
||||||
|
VStack(spacing: 8) {
|
||||||
|
Text(L10n.screenRoomMemberListEmptySearchTitle(context.searchQuery))
|
||||||
|
.font(.compound.headingMDBold)
|
||||||
|
.foregroundStyle(.compound.textPrimary)
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
Text(L10n.screenRoomMemberListEmptySearchSubtitle)
|
||||||
|
.font(.compound.bodyMD)
|
||||||
|
.foregroundStyle(.compound.textSecondary)
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.accessibilityElement(children: .combine)
|
||||||
|
.padding(.horizontal, 24)
|
||||||
|
.padding(.top, 40)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum MembersSection {
|
private enum MembersSection {
|
||||||
@@ -118,9 +137,9 @@ private enum MembersSection {
|
|||||||
case .banned:
|
case .banned:
|
||||||
L10n.screenRoomMemberListBannedHeaderTitle(count)
|
L10n.screenRoomMemberListBannedHeaderTitle(count)
|
||||||
case .invited:
|
case .invited:
|
||||||
L10n.screenRoomMemberListHeaderTitle(count)
|
|
||||||
case .joined:
|
|
||||||
L10n.screenRoomMemberListPendingHeaderTitle(count)
|
L10n.screenRoomMemberListPendingHeaderTitle(count)
|
||||||
|
case .joined:
|
||||||
|
L10n.screenRoomMemberListHeaderTitle(count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,6 +158,7 @@ private enum MembersSection {
|
|||||||
text(count: count)
|
text(count: count)
|
||||||
.compoundListSectionHeader()
|
.compoundListSectionHeader()
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
.padding(.leading, 16)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +169,7 @@ struct RoomMembersListScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
static let invitesViewModel = makeViewModel(withInvites: true)
|
static let invitesViewModel = makeViewModel(withInvites: true)
|
||||||
static let adminViewModel = makeViewModel(isAdmin: true, initialMode: .members)
|
static let adminViewModel = makeViewModel(isAdmin: true, initialMode: .members)
|
||||||
static let bannedViewModel = makeViewModel(isAdmin: true, initialMode: .banned)
|
static let bannedViewModel = makeViewModel(isAdmin: true, initialMode: .banned)
|
||||||
static let emptyBannedViewModel = makeViewModel(withBanned: false, isAdmin: true, initialMode: .banned)
|
static let emptyBannedViewModel = makeViewModel(withBanned: false, isAdmin: false, initialMode: .members)
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
@@ -186,17 +206,17 @@ struct RoomMembersListScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
|
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
RoomMembersListScreen(context: emptyBannedViewModel.context)
|
RoomMembersListScreen(context: emptyBannedViewModel.context)
|
||||||
|
.onAppear { emptyBannedViewModel.context.searchQuery = "Dan" }
|
||||||
}
|
}
|
||||||
.snapshotPreferences(expect: emptyBannedViewModel.context.$viewState.map { state in
|
.snapshotPreferences(expect: emptyBannedViewModel.context.$viewState.map(\.shouldShowEmptyState))
|
||||||
state.canBanUsers == true
|
.previewDisplayName("Empty Search")
|
||||||
})
|
|
||||||
.previewDisplayName("Admin: Empty Banned")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static func makeViewModel(withInvites: Bool = false,
|
static func makeViewModel(withInvites: Bool = false,
|
||||||
withBanned: Bool = true,
|
withBanned: Bool = true,
|
||||||
isAdmin: Bool = false,
|
isAdmin: Bool = false,
|
||||||
initialMode: RoomMembersListScreenMode = .members) -> RoomMembersListScreenViewModel {
|
initialMode: RoomMembersListScreenMode = .members,
|
||||||
|
searchQuery: String = "") -> RoomMembersListScreenViewModel {
|
||||||
let mockAdmin = RoomMemberProxyMock.mockAdmin
|
let mockAdmin = RoomMemberProxyMock.mockAdmin
|
||||||
|
|
||||||
let ownUserID = isAdmin ? mockAdmin.userID : RoomMemberProxyMock.mockMe.userID
|
let ownUserID = isAdmin ? mockAdmin.userID : RoomMemberProxyMock.mockMe.userID
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:cbcfb604471fe40dd146fe4d8e0a956c0d301781ed5a0c3159734fcd58491406
|
oid sha256:64594d4de5278e5fb11675143814365e004e8e7a01dc2f71617017d10e73237e
|
||||||
size 121371
|
size 121799
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:781c81df49e21c06d9fdff9b75433f8f5f503f6e204365288b1f6d6cdca45390
|
oid sha256:15a446f80a68a21d52a063b0a172d0225bba82e0f85a9357bec8e1c76c24bff7
|
||||||
size 127670
|
size 128082
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:71d7553d6d3f0e2abc63993724b98f14019b4b1a33141d5f3d19912c78ef852c
|
oid sha256:a3011bd17616fd87eb8e2f5a832b4da91acba1418b9e83425d2df75564091c98
|
||||||
size 72866
|
size 72891
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:e6231f0e6186964a242496dc1e4a6cf3305eb07441ef563f8b69b9a37d2aae19
|
oid sha256:ca335a5c0a97bae768ffc0f4cdc2fe4b63bc344a93c7f3261f588cb5d769f1c0
|
||||||
size 78832
|
size 78931
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:fc17e0a24d8cc64bbbe65a7f676bf09256175accad59c20b259ae669502bbbfb
|
|
||||||
size 93333
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:6064da92e7315269aa38bc2ed679cff391b9da78db19673b06c8aa5a0aac11e1
|
|
||||||
size 97330
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:dce1a408d4ec5ae9962edc09bc01b0477fe16e510af431006469d48d6e4a29bf
|
|
||||||
size 47487
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:941e55f24c7a3fbedc55f075fbff6c61469347c1a40f9dc124f5c3c66e596a32
|
|
||||||
size 53536
|
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:26487be725ada6101341c7d2c763e2f951a5ed0c78a21728d8e8133f00f919a7
|
oid sha256:d3ab34fd185105c343d40903ac2bc626acd8dfe8deb9fc0057793ad21ad5eea0
|
||||||
size 158766
|
size 159093
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:4dc4ba4368f4a62de3e3ff56f0d7ad9db560850076f6df06a4fd2add88f388ba
|
oid sha256:f7de605410a6bf212344bb1379910377ce5c384d3c2a09a577f57be5907668b9
|
||||||
size 164680
|
size 167383
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:7add08193316c3e604894d4168fbe1f8a2ccec3bcb1ee75748c8a21948f90b73
|
oid sha256:ce953cae5fe45f4c46e6e9abb0bc1143c62e1e5e15d13c9ea6d38266adfcfe99
|
||||||
size 104760
|
size 105012
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:4376b92a41308856c4d072033614d1fd23b80eaabbf61341efb3f7c456304aef
|
oid sha256:a1a084777525883e7ee6c058a6830dc7e6d466eaa7e4ed65cd76fa0d86b6ffc9
|
||||||
size 115048
|
size 117035
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:9a604ec76efb23eb3099dbe7dc1c008f2907214ee0117082e679ff2e81eaa00e
|
||||||
|
size 97954
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:48eebdfe394d488fa0d3017256d6172f6ca048ed72ff8c4e02ac1a6c5bd0b831
|
||||||
|
size 104188
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:427a3ee811439a0fa6d722ad1c4b066bcf202151d20a1711796bdc9663388ba7
|
||||||
|
size 49179
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:72e57c69d4db38697d52e6c5031af15e0488796779bba7ab84a753d0a22a958e
|
||||||
|
size 60823
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:f2185e01f3bc1aad1691fecc6f37151b54b4d9407fe081d23a1c518249bd8a08
|
oid sha256:c1838411c8fe15cace383d62a189c3a80b155fa86982cbbe61a742632e8013a2
|
||||||
size 163295
|
size 163266
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:58cc3e279f005c41b2ca490a7761ebaf348ed76b9b38251203a7e655c1bbed08
|
oid sha256:2b789a9179fb3775cb3e7cda6db8e4e761704709e60a1340707c08b218defac2
|
||||||
size 172300
|
size 173157
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:12eed8cec6dbd7f95f3caa6c855e2945ad9038d8692c6441af2291811c1b3ddf
|
oid sha256:8b4ad538019bc7b02f6df3e40f73078bbeec6f6d0571cb910ea3dc537bda2e6c
|
||||||
size 108805
|
size 108920
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:ae20b89c56b784e58cd12a8703fc5a1fba2645c144d9dd0ec35623fbb64d0721
|
oid sha256:965855b8164bdb1d3c758a0b97cda79341c68851bf7fa1f27ee2f1b882d1ead5
|
||||||
size 121582
|
size 121545
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:200ac76b32fc16f4f27da59c265fe538102ba463409d4ce1c97aff7ab0a04e02
|
oid sha256:b46cead7dd0c0230dfdc4c5bc3b01740e8be0ce74e71cd465fce61bdc3fd55ac
|
||||||
size 152142
|
size 151876
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:552257279e96d8ec4841194e1f4dee4fa2ae4f2b337994bd03a1be08f09ffe24
|
oid sha256:7f84a9694119853b3071a3f28b85a225154af63c0c2ac2ef3ad291e3e3dc5534
|
||||||
size 156878
|
size 158881
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:bc454b71beceefe553e13085e35e2ff6fe473f622e4532bbb0d8f98cef7b6b50
|
oid sha256:026d44ae2512053965187d35f2ae6b6e48bdc616297193c68854ce20fd166f7b
|
||||||
size 98405
|
size 98760
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:62d46a736487e5c851e1c5c17cb08e6d7475018b97702af394c78c80b7acd8bf
|
oid sha256:8195872bc674430e06f38a95c49d8094df0cb655c9637ace207f5067cb53594f
|
||||||
size 108150
|
size 110389
|
||||||
|
|||||||
Reference in New Issue
Block a user