Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Room List Filters Empty State View #2522

Merged
merged 10 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ElementX.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,7 @@
BB784A02BADB03C820617A46 /* TextRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90A55430639712CFACA34F43 /* TextRoomTimelineItem.swift */; };
BB9B800C6094E34860E89DC5 /* AppLockSetupBiometricsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8CCF9A924521DECA44778C4 /* AppLockSetupBiometricsScreen.swift */; };
BCC864190651B3A3CF51E4DF /* MediaFileHandleProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEC1D382565A4E9CAC2F14EA /* MediaFileHandleProxy.swift */; };
BD0BE20DBCE31253AE4490A1 /* RoomListFiltersEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC1DDB2293A51EA4C2739351 /* RoomListFiltersEmptyStateView.swift */; };
BD203FC6A7AE7637EA003643 /* RoomProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ABDE6F66532CBEB0E016F94 /* RoomProxyMock.swift */; };
BD2BF1EC73FFB0C01552ECDA /* WelcomeScreenScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FB782CE6176A5D2C082EC5D /* WelcomeScreenScreenModels.swift */; };
BD6D98676111DA8FC2BE4908 /* InvitesScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86873A768B13069BB5CAECF6 /* InvitesScreenViewModelProtocol.swift */; };
Expand Down Expand Up @@ -1877,6 +1878,7 @@
CBF9AEA706926DD0DA2B954C /* JoinedRoomSize+MemberCount.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JoinedRoomSize+MemberCount.swift"; sourceTree = "<group>"; };
CC03209FDE8CE0810617BFFF /* RoomMembersListScreenMemberCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenMemberCell.swift; sourceTree = "<group>"; };
CC14E5209C262530E19BC4C1 /* InvitesScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitesScreenViewModelTests.swift; sourceTree = "<group>"; };
CC1DDB2293A51EA4C2739351 /* RoomListFiltersEmptyStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomListFiltersEmptyStateView.swift; sourceTree = "<group>"; };
CC680E0E79D818706CB28CF8 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
CC743C7A85E3171BCBF0A653 /* AvatarHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvatarHeaderView.swift; sourceTree = "<group>"; };
CCACD75595C40EACD6AD4A74 /* AuthenticationTextFieldStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationTextFieldStyle.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2207,6 +2209,7 @@
isa = PBXGroup;
children = (
E06AAD6D9D3F5833E7A5A2F9 /* RoomListFilterModels.swift */,
CC1DDB2293A51EA4C2739351 /* RoomListFiltersEmptyStateView.swift */,
E6372DD10DED30E7AD7BCE21 /* RoomListFiltersView.swift */,
24EC819497BB5F8C4998D760 /* RoomListFilterView.swift */,
);
Expand Down Expand Up @@ -6013,6 +6016,7 @@
04A16B45228F7678A027C079 /* RoomHeaderView.swift in Sources */,
F4996C82A4B3A5FF0C8EDD03 /* RoomListFilterModels.swift in Sources */,
4A9CEEE612D6D8B3DDBD28BA /* RoomListFilterView.swift in Sources */,
BD0BE20DBCE31253AE4490A1 /* RoomListFiltersEmptyStateView.swift in Sources */,
33F1FB19F222BA9930AB1A00 /* RoomListFiltersView.swift in Sources */,
8DC176CC5ABA24138EB443DD /* RoomMemberDetails.swift in Sources */,
19FE025AE9BA2959B6589B0D /* RoomMemberDetailsScreen.swift in Sources */,
Expand Down
16 changes: 16 additions & 0 deletions ElementX/Resources/Localizations/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"action_enter_pin" = "Enter PIN";
"action_forgot_password" = "Forgot password?";
"action_forward" = "Forward";
"action_go_back" = "Go back";
"action_invite" = "Invite";
"action_invite_friends" = "Invite people";
"action_invite_friends_to_app" = "Invite people to %1$@";
Expand Down Expand Up @@ -162,6 +163,7 @@
"common_room" = "Room";
"common_room_name" = "Room name";
"common_room_name_placeholder" = "e.g. your project name";
"common_saved_changes" = "Saved changes";
"common_saving" = "Saving";
"common_screen_lock" = "Screen lock";
"common_search_for_someone" = "Search for someone";
Expand Down Expand Up @@ -217,6 +219,8 @@
"dialog_permission_notification" = "In order to let the application display notifications, please grant the permission in the system settings.";
"dialog_title_confirmation" = "Confirmation";
"dialog_title_warning" = "Warning";
"dialog_unsaved_changes_description_ios" = "Your changes won’t be saved";
"dialog_unsaved_changes_title" = "Save changes?";
"emoji_picker_category_activity" = "Activities";
"emoji_picker_category_flags" = "Flags";
"emoji_picker_category_foods" = "Food & Drink";
Expand Down Expand Up @@ -510,6 +514,8 @@
"screen_room_change_role_confirm_demote_self_description" = "You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges.";
"screen_room_change_role_confirm_demote_self_title" = "Demote yourself?";
"screen_room_change_role_moderators_title" = "Edit Moderators";
"screen_room_change_role_unsaved_changes_description" = "You have unsaved changes.";
"screen_room_change_role_unsaved_changes_title" = "Save changes?";
"screen_room_details_add_topic_title" = "Add topic";
"screen_room_details_already_a_member" = "Already a member";
"screen_room_details_already_invited" = "Already invited";
Expand Down Expand Up @@ -577,6 +583,9 @@
"screen_room_retry_send_menu_send_again_action" = "Send again";
"screen_room_retry_send_menu_title" = "Your message failed to send";
"screen_room_roles_and_permissions_admins" = "Admins";
"screen_room_roles_and_permissions_change_my_role" = "Change my role";
"screen_room_roles_and_permissions_change_role_demote_to_member" = "Demote to member";
"screen_room_roles_and_permissions_change_role_demote_to_moderator" = "Demote to moderator";
"screen_room_roles_and_permissions_member_moderation" = "Member moderation";
"screen_room_roles_and_permissions_messages_and_content" = "Messages and content";
"screen_room_roles_and_permissions_moderators" = "Moderators";
Expand All @@ -596,9 +605,16 @@
"screen_roomlist_empty_message" = "Get started by messaging someone.";
"screen_roomlist_empty_title" = "No chats yet.";
"screen_roomlist_filter_favourites" = "Favourites";
"screen_roomlist_filter_favourites_empty_state_subtitle" = "You can add a chat to your favourites in the chat settings.\nFor now, you can deselect filters in order to see your other chats";
"screen_roomlist_filter_favourites_empty_state_title" = "You don’t have favourite chats yet";
"screen_roomlist_filter_low_priority" = "Low Priority";
"screen_roomlist_filter_mixed_empty_state_subtitle" = "You can deselect filters in order to see your other chats";
"screen_roomlist_filter_mixed_empty_state_title" = "You don’t have chats for this selection";
"screen_roomlist_filter_people_empty_state_title" = "You don’t have any DMs yet";
"screen_roomlist_filter_rooms" = "Rooms";
"screen_roomlist_filter_rooms_empty_state_title" = "You’re not in any room yet";
"screen_roomlist_filter_unreads" = "Unreads";
"screen_roomlist_filter_unreads_empty_state_title" = "Congrats!\nYou don’t have any unread messages!";
"screen_roomlist_main_space_title" = "Chats";
"screen_roomlist_mark_as_read" = "Mark as read";
"screen_roomlist_mark_as_unread" = "Mark as unread";
Expand Down
34 changes: 34 additions & 0 deletions ElementX/Sources/Generated/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ internal enum L10n {
internal static var actionForgotPassword: String { return L10n.tr("Localizable", "action_forgot_password") }
/// Forward
internal static var actionForward: String { return L10n.tr("Localizable", "action_forward") }
/// Go back
internal static var actionGoBack: String { return L10n.tr("Localizable", "action_go_back") }
/// Invite
internal static var actionInvite: String { return L10n.tr("Localizable", "action_invite") }
/// Invite people
Expand Down Expand Up @@ -378,6 +380,8 @@ internal enum L10n {
internal static var commonRoomName: String { return L10n.tr("Localizable", "common_room_name") }
/// e.g. your project name
internal static var commonRoomNamePlaceholder: String { return L10n.tr("Localizable", "common_room_name_placeholder") }
/// Saved changes
internal static var commonSavedChanges: String { return L10n.tr("Localizable", "common_saved_changes") }
/// Saving
internal static var commonSaving: String { return L10n.tr("Localizable", "common_saving") }
/// Screen lock
Expand Down Expand Up @@ -494,6 +498,10 @@ internal enum L10n {
internal static var dialogTitleSuccess: String { return L10n.tr("Localizable", "dialog_title_success") }
/// Warning
internal static var dialogTitleWarning: String { return L10n.tr("Localizable", "dialog_title_warning") }
/// Your changes won’t be saved
internal static var dialogUnsavedChangesDescriptionIos: String { return L10n.tr("Localizable", "dialog_unsaved_changes_description_ios") }
/// Save changes?
internal static var dialogUnsavedChangesTitle: String { return L10n.tr("Localizable", "dialog_unsaved_changes_title") }
/// Activities
internal static var emojiPickerCategoryActivity: String { return L10n.tr("Localizable", "emoji_picker_category_activity") }
/// Flags
Expand Down Expand Up @@ -1251,6 +1259,10 @@ internal enum L10n {
internal static var screenRoomChangeRoleConfirmDemoteSelfTitle: String { return L10n.tr("Localizable", "screen_room_change_role_confirm_demote_self_title") }
/// Edit Moderators
internal static var screenRoomChangeRoleModeratorsTitle: String { return L10n.tr("Localizable", "screen_room_change_role_moderators_title") }
/// You have unsaved changes.
internal static var screenRoomChangeRoleUnsavedChangesDescription: String { return L10n.tr("Localizable", "screen_room_change_role_unsaved_changes_description") }
/// Save changes?
internal static var screenRoomChangeRoleUnsavedChangesTitle: String { return L10n.tr("Localizable", "screen_room_change_role_unsaved_changes_title") }
/// Add topic
internal static var screenRoomDetailsAddTopicTitle: String { return L10n.tr("Localizable", "screen_room_details_add_topic_title") }
/// Already a member
Expand Down Expand Up @@ -1419,6 +1431,12 @@ internal enum L10n {
internal static var screenRoomRetrySendMenuTitle: String { return L10n.tr("Localizable", "screen_room_retry_send_menu_title") }
/// Admins
internal static var screenRoomRolesAndPermissionsAdmins: String { return L10n.tr("Localizable", "screen_room_roles_and_permissions_admins") }
/// Change my role
internal static var screenRoomRolesAndPermissionsChangeMyRole: String { return L10n.tr("Localizable", "screen_room_roles_and_permissions_change_my_role") }
/// Demote to member
internal static var screenRoomRolesAndPermissionsChangeRoleDemoteToMember: String { return L10n.tr("Localizable", "screen_room_roles_and_permissions_change_role_demote_to_member") }
/// Demote to moderator
internal static var screenRoomRolesAndPermissionsChangeRoleDemoteToModerator: String { return L10n.tr("Localizable", "screen_room_roles_and_permissions_change_role_demote_to_moderator") }
/// Member moderation
internal static var screenRoomRolesAndPermissionsMemberModeration: String { return L10n.tr("Localizable", "screen_room_roles_and_permissions_member_moderation") }
/// Messages and content
Expand Down Expand Up @@ -1473,14 +1491,30 @@ internal enum L10n {
internal static var screenRoomlistEmptyTitle: String { return L10n.tr("Localizable", "screen_roomlist_empty_title") }
/// Favourites
internal static var screenRoomlistFilterFavourites: String { return L10n.tr("Localizable", "screen_roomlist_filter_favourites") }
/// You can add a chat to your favourites in the chat settings.
/// For now, you can deselect filters in order to see your other chats
internal static var screenRoomlistFilterFavouritesEmptyStateSubtitle: String { return L10n.tr("Localizable", "screen_roomlist_filter_favourites_empty_state_subtitle") }
/// You don’t have favourite chats yet
internal static var screenRoomlistFilterFavouritesEmptyStateTitle: String { return L10n.tr("Localizable", "screen_roomlist_filter_favourites_empty_state_title") }
/// Low Priority
internal static var screenRoomlistFilterLowPriority: String { return L10n.tr("Localizable", "screen_roomlist_filter_low_priority") }
/// You can deselect filters in order to see your other chats
internal static var screenRoomlistFilterMixedEmptyStateSubtitle: String { return L10n.tr("Localizable", "screen_roomlist_filter_mixed_empty_state_subtitle") }
/// You don’t have chats for this selection
internal static var screenRoomlistFilterMixedEmptyStateTitle: String { return L10n.tr("Localizable", "screen_roomlist_filter_mixed_empty_state_title") }
/// People
internal static var screenRoomlistFilterPeople: String { return L10n.tr("Localizable", "screen_roomlist_filter_people") }
/// You don’t have any DMs yet
internal static var screenRoomlistFilterPeopleEmptyStateTitle: String { return L10n.tr("Localizable", "screen_roomlist_filter_people_empty_state_title") }
/// Rooms
internal static var screenRoomlistFilterRooms: String { return L10n.tr("Localizable", "screen_roomlist_filter_rooms") }
/// You’re not in any room yet
internal static var screenRoomlistFilterRoomsEmptyStateTitle: String { return L10n.tr("Localizable", "screen_roomlist_filter_rooms_empty_state_title") }
/// Unreads
internal static var screenRoomlistFilterUnreads: String { return L10n.tr("Localizable", "screen_roomlist_filter_unreads") }
/// Congrats!
/// You don’t have any unread messages!
internal static var screenRoomlistFilterUnreadsEmptyStateTitle: String { return L10n.tr("Localizable", "screen_roomlist_filter_unreads_empty_state_title") }
/// Chats
internal static var screenRoomlistMainSpaceTitle: String { return L10n.tr("Localizable", "screen_roomlist_main_space_title") }
/// Mark as read
Expand Down
4 changes: 4 additions & 0 deletions ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ struct HomeScreenViewState: BindableState {
var shouldHideRoomList: Bool {
bindings.isSearchFieldFocused && bindings.searchQuery.isEmpty
}

var shouldShowEmptyFilterState: Bool {
shouldShowFilters && bindings.filtersState.isFiltering && visibleRooms.isEmpty
}
}

struct HomeScreenViewStateBindings {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
// Copyright 2024 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import SwiftUI

struct RoomListFiltersEmptyStateView: View {
let state: RoomListFiltersState

private var emptyStateTitle: String {
if state.activeFilters.count == 1 {
switch state.activeFilters[0] {
case .unreads:
return L10n.screenRoomlistFilterUnreadsEmptyStateTitle
case .people:
return L10n.screenRoomlistFilterPeopleEmptyStateTitle
case .rooms:
return L10n.screenRoomlistFilterRoomsEmptyStateTitle
case .favourites:
return L10n.screenRoomlistFilterFavouritesEmptyStateTitle
}
}
return L10n.screenRoomlistFilterMixedEmptyStateTitle
}

private var emptyStateSubtitle: String {
if state.activeFilters.first == .favourites {
return L10n.screenRoomlistFilterFavouritesEmptyStateSubtitle
}
return L10n.screenRoomlistFilterMixedEmptyStateSubtitle
}

var body: some View {
VStack(spacing: 24) {
Text(emptyStateTitle)
.multilineTextAlignment(.center)
.font(.compound.headingSMSemibold)
.foregroundColor(.compound.textPrimary)

Text(emptyStateSubtitle)
.multilineTextAlignment(.center)
.font(.compound.bodyMD)
.foregroundColor(.compound.textSecondary)
}
.padding(.horizontal, 60)
}
}

struct RoomListFiltersEmptyStateView_Previews: PreviewProvider, TestablePreview {
static var previews: some View {
VStack(spacing: 24) {
ForEach(RoomListFilter.allCases) { filter in
RoomListFiltersEmptyStateView(state: .init(activeFilters: [filter]))
}
RoomListFiltersEmptyStateView(state: .init(activeFilters: [.people, .favourites]))
}
.previewLayout(.sizeThatFits)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ struct HomeScreenContent: View {
@Environment(\.verticalSizeClass) private var verticalSizeClass

@ObservedObject var context: HomeScreenViewModel.Context
@State private var topSectionFrame: CGRect = .zero
let scrollViewAdapter: ScrollViewAdapter

var body: some View {
Expand Down Expand Up @@ -56,9 +57,15 @@ struct HomeScreenContent: View {
// Showing empty views in pinned headers makes the room list spasm when reaching the top
LazyVStack(spacing: 0, pinnedViews: [.sectionHeaders]) {
Section {
HomeScreenRoomList(context: context)
if context.viewState.shouldShowEmptyFilterState {
RoomListFiltersEmptyStateView(state: context.filtersState)
.frame(height: geometry.size.height - topSectionFrame.height)
} else {
HomeScreenRoomList(context: context)
}
} header: {
topSection
.readFrame($topSectionFrame)
}
}
.searchable(text: $context.searchQuery)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions changelog.d/2522.wip
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added an empty state view when the filter returns no rooms.
Loading