Room List Filters Empty State View (#2522)

This commit is contained in:
Mauro
2024-03-05 15:15:07 +01:00
committed by GitHub
parent 1b5db6c63d
commit 8c68f5a591
8 changed files with 141 additions and 1 deletions
+34
View File
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 {
@@ -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)
}
}
@@ -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 {
@@ -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)