From 1137f80c19dda250ebff21168bf0562d0d53682a Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Mon, 4 Mar 2024 18:32:59 +0100 Subject: [PATCH] Filters UI Update and ordering (#2521) --- ElementX.xcodeproj/project.pbxproj | 38 ++++++++--------- .../Sources/Other/Extensions/OrderedSet.swift | 25 +++++++++++ .../HomeScreen/HomeScreenViewModel.swift | 4 +- .../View/Filters/RoomListFilterModels.swift | 31 ++++++++------ .../View/Filters/RoomListFilterView.swift | 8 ++-- .../View/Filters/RoomListFiltersView.swift | 2 +- .../test_roomListFilterView.1.png | 4 +- .../test_roomListFilterView.2.png | 4 +- .../test_roomListFiltersView.1.png | 4 +- .../test_roomListFiltersView.2.png | 4 +- .../Sources/RoomListFiltersStateTests.swift | 41 ++++++++++++++++++- 11 files changed, 114 insertions(+), 51 deletions(-) create mode 100644 ElementX/Sources/Other/Extensions/OrderedSet.swift diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 104e7cdeb..35807ebda 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 56; objects = { /* Begin PBXAggregateTarget section */ @@ -680,6 +680,7 @@ A722F426FD81FC67706BB1E0 /* CustomLayoutLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42236480CF0431535EBE8387 /* CustomLayoutLabelStyle.swift */; }; A743841F91B62B0E56217B04 /* SecureBackupKeyBackupScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58DCB219D7B7B0299358FF81 /* SecureBackupKeyBackupScreenUITests.swift */; }; A74438ED16F8683A4B793E6A /* AnalyticsSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BCE3FAF40932AC7C7639AC4 /* AnalyticsSettingsScreenViewModel.swift */; }; + A77476862B960F9E003162F8 /* OrderedSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = A77476852B960F9E003162F8 /* OrderedSet.swift */; }; A7D48E44D485B143AADDB77D /* Strings+Untranslated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */; }; A7FD7B992E6EE6E5A8429197 /* RoomSummaryDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 142808B69851451AC32A2CEA /* RoomSummaryDetails.swift */; }; A816F7087C495D85048AC50E /* RoomMemberDetailsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B6E30BB748F3F480F077969 /* RoomMemberDetailsScreenModels.swift */; }; @@ -1106,7 +1107,7 @@ 033DB41C51865A2E83174E87 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; 035177BCD8E8308B098AC3C2 /* WindowManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowManager.swift; sourceTree = ""; }; 0376C429FAB1687C3D905F3E /* MockCoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCoder.swift; sourceTree = ""; }; - 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; path = test_voice_message.m4a; sourceTree = ""; }; + 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_voice_message.m4a; sourceTree = ""; }; 03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelProtocol.swift; sourceTree = ""; }; 03FABD73FD8086EFAB699F42 /* MediaUploadPreviewScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModelTests.swift; sourceTree = ""; }; 044E501B8331B339874D1B96 /* CompoundIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompoundIcon.swift; sourceTree = ""; }; @@ -1169,7 +1170,7 @@ 127A57D053CE8C87B5EFB089 /* Consumable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Consumable.swift; sourceTree = ""; }; 127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentValuePublisher.swift; sourceTree = ""; }; 12F1E7F9C2BE8BB751037826 /* WaitlistScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreenCoordinator.swift; sourceTree = ""; }; - 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; path = IntegrationTests.xctestplan; sourceTree = ""; }; + 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = IntegrationTests.xctestplan; sourceTree = ""; }; 130ED565A078F7E0B59D9D25 /* UNTextInputNotificationResponse+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNTextInputNotificationResponse+Creator.swift"; sourceTree = ""; }; 13802897C7AFA360EA74C0B0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = ""; }; 1423AB065857FA546444DB15 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = ""; }; @@ -1252,7 +1253,7 @@ 25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxy.swift; sourceTree = ""; }; 25F8664F1FB95AF3C4202478 /* PollFormScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenCoordinator.swift; sourceTree = ""; }; 260004737C573A56FA01E86E /* Encodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Encodable.swift; sourceTree = ""; }; - 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; path = PreviewTests.xctestplan; sourceTree = ""; }; + 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = PreviewTests.xctestplan; sourceTree = ""; }; 26B0A96B8FE4849227945067 /* VoiceMessageRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecorder.swift; sourceTree = ""; }; 26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockServiceProtocol.swift; sourceTree = ""; }; 2721D7B051F0159AA919DA05 /* RoomChangePermissionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -1626,7 +1627,7 @@ 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomStateEventStringBuilder.swift; sourceTree = ""; }; 8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; 8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStyle.swift; sourceTree = ""; }; - 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; path = UITests.xctestplan; sourceTree = ""; }; + 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UITests.xctestplan; sourceTree = ""; }; 8E1BBA73B611EDEEA6E20E05 /* InvitesScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitesScreenModels.swift; sourceTree = ""; }; 8EC57A32ABC80D774CC663DB /* SettingsScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenUITests.swift; sourceTree = ""; }; 8F21ED7205048668BEB44A38 /* AppActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppActivityView.swift; sourceTree = ""; }; @@ -1711,6 +1712,7 @@ A6B891A6DA826E2461DBB40F /* PHGPostHogConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHGPostHogConfiguration.swift; sourceTree = ""; }; A6C11AD9813045E44F950410 /* ElementCallWidgetDriverProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallWidgetDriverProtocol.swift; sourceTree = ""; }; A73A07BAEDD74C48795A996A /* AsyncSequence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncSequence.swift; sourceTree = ""; }; + A77476852B960F9E003162F8 /* OrderedSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderedSet.swift; sourceTree = ""; }; A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleTimelineItem.swift; sourceTree = ""; }; A84D413BF49F0E980F010A6B /* LogViewerScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewerScreenCoordinator.swift; sourceTree = ""; }; A861DA5932B128FE1DCB5CE2 /* InviteUsersScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenCoordinator.swift; sourceTree = ""; }; @@ -1775,7 +1777,7 @@ B50F03079F6B5EF9CA005F14 /* TimelineProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxyProtocol.swift; sourceTree = ""; }; B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableAvatarImage.swift; sourceTree = ""; }; B5B243E7818E5E9F6A4EDC7A /* NoticeRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineView.swift; sourceTree = ""; }; - B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; path = ConfettiScene.scn; sourceTree = ""; }; + B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = ConfettiScene.scn; sourceTree = ""; }; B6311F21F911E23BE4DF51B4 /* ReadMarkerRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadMarkerRoomTimelineView.swift; sourceTree = ""; }; B63B69F9A2BC74DD40DC75C8 /* AdvancedSettingsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenViewModel.swift; sourceTree = ""; }; B6404166CBF5CC88673FF9E2 /* RoomDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetails.swift; sourceTree = ""; }; @@ -1887,7 +1889,7 @@ CE47A97726F0675DEE387BF9 /* TypingIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TypingIndicatorView.swift; sourceTree = ""; }; CEE0E6043EFCF6FD2A341861 /* TimelineReplyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReplyView.swift; sourceTree = ""; }; CEE20623EB4A9B88FB29F2BA /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/SAS.strings; sourceTree = ""; }; - CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; path = UnitTests.xctestplan; sourceTree = ""; }; + CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UnitTests.xctestplan; sourceTree = ""; }; CF48AF076424DBC1615C74AD /* AuthenticationServiceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceProxy.swift; sourceTree = ""; }; D0140615D2232612C813FD6C /* EncryptedHistoryRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptedHistoryRoomTimelineItem.swift; sourceTree = ""; }; D071F86CD47582B9196C9D16 /* UserDiscoverySection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDiscoverySection.swift; sourceTree = ""; }; @@ -2004,7 +2006,7 @@ ED003DF1B7CF40E7073A2280 /* TracingConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracingConfiguration.swift; sourceTree = ""; }; ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenRoomCell.swift; sourceTree = ""; }; ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProtocol.swift; sourceTree = ""; }; - ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; path = message.caf; sourceTree = ""; }; + ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = message.caf; sourceTree = ""; }; ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreen.swift; sourceTree = ""; }; ED983D4DCA5AFA6E1ED96099 /* StateRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateRoomTimelineView.swift; sourceTree = ""; }; EDAA4472821985BF868CC21C /* ServerSelectionViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionViewModelTests.swift; sourceTree = ""; }; @@ -2024,7 +2026,7 @@ F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenModels.swift; sourceTree = ""; }; F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = ""; }; F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineItem.swift; sourceTree = ""; }; - F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; path = portrait_test_video.mp4; sourceTree = ""; }; + F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = portrait_test_video.mp4; sourceTree = ""; }; F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixEntityRegexTests.swift; sourceTree = ""; }; F348B5F2C12F9D4F4B4D3884 /* VideoRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineItem.swift; sourceTree = ""; }; F36C0A6D59717193F49EA986 /* UserSessionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionTests.swift; sourceTree = ""; }; @@ -2923,6 +2925,7 @@ AE40D4A5DD857AC16EED945A /* URLSession.swift */, 897DF5E9A70CE05A632FC8AF /* UTType.swift */, E992D7B8BE54B2AB454613AF /* XCUIElement.swift */, + A77476852B960F9E003162F8 /* OrderedSet.swift */, ); path = Extensions; sourceTree = ""; @@ -6040,6 +6043,7 @@ BA4C9049BC96DED3A2F3B82E /* RoomNotificationSettingsScreenViewModelProtocol.swift in Sources */, 491D62ACD19E6F134B1766AF /* RoomNotificationSettingsUserDefinedScreen.swift in Sources */, DBC8D1DBFE9F9CA7662BC8AA /* RoomPermissions.swift in Sources */, + A77476862B960F9E003162F8 /* OrderedSet.swift in Sources */, 7A02EB29F3B993AB20E0A198 /* RoomPollsHistoryScreen.swift in Sources */, E58F1F3276E98A93F7D39219 /* RoomPollsHistoryScreenCoordinator.swift in Sources */, 51B3B19FA5F91B455C807BA7 /* RoomPollsHistoryScreenModels.swift in Sources */, @@ -6513,9 +6517,7 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_NSE", - ); + OTHER_SWIFT_FLAGS = "-DIS_NSE"; PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; PRODUCT_NAME = NSE; @@ -6564,9 +6566,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_MAIN_APP", - ); + OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP"; PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; PRODUCT_NAME = "$(APP_NAME)"; @@ -6592,9 +6592,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_MAIN_APP", - ); + OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP"; PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; PRODUCT_NAME = "$(APP_NAME)"; @@ -6837,9 +6835,7 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_NSE", - ); + OTHER_SWIFT_FLAGS = "-DIS_NSE"; PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; PRODUCT_NAME = NSE; diff --git a/ElementX/Sources/Other/Extensions/OrderedSet.swift b/ElementX/Sources/Other/Extensions/OrderedSet.swift new file mode 100644 index 000000000..6eff263a0 --- /dev/null +++ b/ElementX/Sources/Other/Extensions/OrderedSet.swift @@ -0,0 +1,25 @@ +// +// 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 Foundation + +import OrderedCollections + +extension OrderedSet { + var set: Set { + Set(elements) + } +} diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift index 40adca1b4..efcbb023f 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift @@ -234,9 +234,9 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol } else { if state.bindings.isSearchFieldFocused { roomSummaryProvider?.setFilter(.include(.init(query: state.bindings.searchQuery, - filters: state.bindings.filtersState.activeFilters))) + filters: state.bindings.filtersState.activeFilters.set))) } else { - roomSummaryProvider?.setFilter(.include(.init(filters: state.bindings.filtersState.activeFilters))) + roomSummaryProvider?.setFilter(.include(.init(filters: state.bindings.filtersState.activeFilters.set))) } } } diff --git a/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFilterModels.swift b/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFilterModels.swift index 30908ae2a..9376e1509 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFilterModels.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFilterModels.swift @@ -18,15 +18,16 @@ import Combine import Foundation import MatrixRustSDK +import OrderedCollections enum RoomListFilter: Int, CaseIterable, Identifiable { var id: Int { rawValue } + case unreads case people case rooms - case unreads case favourites var localizedName: String { @@ -71,25 +72,22 @@ enum RoomListFilter: Int, CaseIterable, Identifiable { } struct RoomListFiltersState { - private(set) var activeFilters: Set + private(set) var activeFilters: OrderedSet + private var inactiveFilters: OrderedSet - init(activeFilters: Set = []) { - self.activeFilters = activeFilters - } - - var sortedActiveFilters: [RoomListFilter] { - activeFilters.sorted(by: { $0.rawValue < $1.rawValue }) + init(activeFilters: OrderedSet = []) { + self.activeFilters = .init(activeFilters) + inactiveFilters = OrderedSet(RoomListFilter.allCases).subtracting(activeFilters) } var availableFilters: [RoomListFilter] { - var availableFilters = Set(RoomListFilter.allCases) + var availableFilters = inactiveFilters for filter in activeFilters { - availableFilters.remove(filter) if let incompatibleFilter = filter.incompatibleFilter { availableFilters.remove(incompatibleFilter) } } - return availableFilters.sorted(by: { $0.rawValue < $1.rawValue }) + return availableFilters.elements } var isFiltering: Bool { @@ -101,15 +99,22 @@ struct RoomListFiltersState { activeFilters.contains(incompatibleFilter) { fatalError("[RoomListFiltersState] adding mutually exclusive filters is not allowed") } - activeFilters.insert(filter) + // We always want the most recently enabled filter to be at the bottom of the others. + activeFilters.append(filter) + inactiveFilters.remove(filter) } mutating func deactivateFilter(_ filter: RoomListFilter) { activeFilters.remove(filter) + // We always want the most recently disabled filter to be on top of the others + inactiveFilters.insert(filter, at: 0) } mutating func clearFilters() { - activeFilters.removeAll() + // We iterate in reverse because filters should get disabled from the first to last that has been used. + for filter in activeFilters.reversed() { + deactivateFilter(filter) + } } func isFilterActive(_ filter: RoomListFilter) -> Bool { diff --git a/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFilterView.swift b/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFilterView.swift index 83900ada1..9bbc1bf8b 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFilterView.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFilterView.swift @@ -37,21 +37,21 @@ struct RoomListFilterView_Previews: PreviewProvider, TestablePreview { private struct FilterToggleStyle: ToggleStyle { private func strokeColor(isOn: Bool) -> Color { - isOn ? .compound.bgActionPrimaryRest : .compound.borderInteractiveSecondary + isOn ? .compound.bgSubtleSecondary : .compound.borderInteractiveSecondary } private func backgroundColor(isOn: Bool) -> Color { - isOn ? .compound.bgActionPrimaryRest : .compound.bgCanvasDefault + isOn ? .compound.bgSubtleSecondary : .compound.bgCanvasDefault } private func foregroundColor(isOn: Bool) -> Color { - isOn ? .compound.textOnSolidPrimary : .compound.textPrimary + isOn ? .compound.textPrimary : .compound.textSecondary } func makeBody(configuration: Configuration) -> some View { let shape = RoundedRectangle(cornerRadius: 20) configuration.label - .font(.compound.bodyLG) + .font(.compound.bodyLGSemibold) .foregroundColor(foregroundColor(isOn: configuration.isOn)) .padding(.horizontal, 16) .padding(.vertical, 8) diff --git a/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFiltersView.swift b/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFiltersView.swift index ee60e6a05..30e6da844 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFiltersView.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/Filters/RoomListFiltersView.swift @@ -27,7 +27,7 @@ struct RoomListFiltersView: View { clearButton } - ForEach(state.sortedActiveFilters) { filter in + ForEach(state.activeFilters) { filter in RoomListFilterView(filter: filter, isActive: getBinding(for: filter)) .matchedGeometryEffect(id: filter.id, in: namespace) diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView.1.png index a860dd55a..f02294ffa 100644 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView.1.png +++ b/PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3ac210fff37bb6b8023fa1527ac1eeb5fdbad9c80357b42f68248f9940db3531 -size 62409 +oid sha256:28cde6aea3ba1a8dc8bf1d44359735c5cec7618ee51d4a087acd9ea0581c02bb +size 61950 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView.2.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView.2.png index 443cc1ac2..d527bbb20 100644 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView.2.png +++ b/PreviewTests/__Snapshots__/PreviewTests/test_roomListFilterView.2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:01003a81f1ace9c184c28728f8bee3528e326f0be88ebcbab3006af649208a10 -size 60619 +oid sha256:07160b58b8cc326f373622079b8513322aa27c1ef44fe95c60f41ef87d747ea1 +size 60192 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView.1.png index 4511df5a7..75344fe58 100644 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView.1.png +++ b/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:501bb3e6d29147f5f15c036fb5ac2d060cd5b80d00cbee44e050ce2b6f425270 -size 70180 +oid sha256:25da13ca12e10bb1a8634fb62b9073ec02aecbfe02872f81bdd49d619a9b1ca6 +size 69664 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView.2.png b/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView.2.png index 661455d5e..e5f8d1921 100644 --- a/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView.2.png +++ b/PreviewTests/__Snapshots__/PreviewTests/test_roomListFiltersView.2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:269445bf0caa7e3ca562e542028081fb5bf9c87d42b5509cce7f69dda472f46e -size 73468 +oid sha256:2af52fe41d2238cd6e16f759d533ad21445569270b583a2e268a7926d68e37e0 +size 73653 diff --git a/UnitTests/Sources/RoomListFiltersStateTests.swift b/UnitTests/Sources/RoomListFiltersStateTests.swift index ca0629c5d..f5488e9b9 100644 --- a/UnitTests/Sources/RoomListFiltersStateTests.swift +++ b/UnitTests/Sources/RoomListFiltersStateTests.swift @@ -47,8 +47,17 @@ final class RoomListFiltersStateTests: XCTestCase { XCTAssertTrue(state.isFiltering) XCTAssertEqual(state.activeFilters, [.people]) XCTAssertEqual(state.availableFilters, [.unreads, .favourites]) + state.deactivateFilter(.people) + XCTAssertFalse(state.isFiltering) + XCTAssertEqual(state.activeFilters, []) + XCTAssertEqual(state.availableFilters, [.people, .unreads, .rooms, .favourites]) + state.activateFilter(.rooms) + XCTAssertTrue(state.isFiltering) + XCTAssertEqual(state.activeFilters, [.rooms]) + XCTAssertEqual(state.availableFilters, [.unreads, .favourites]) + state.activateFilter(.unreads) XCTAssertTrue(state.isFiltering) XCTAssertEqual(state.activeFilters, [.rooms, .unreads]) @@ -57,14 +66,42 @@ final class RoomListFiltersStateTests: XCTestCase { func testClearFilters() { state.activateFilter(.people) + XCTAssertEqual(state.activeFilters, [.people]) + XCTAssertEqual(state.availableFilters, [.unreads, .favourites]) + state.activateFilter(.unreads) + XCTAssertEqual(state.activeFilters, [.people, .unreads]) + XCTAssertEqual(state.availableFilters, [.favourites]) + state.activateFilter(.favourites) - XCTAssertTrue(state.isFiltering) XCTAssertEqual(state.activeFilters, [.people, .unreads, .favourites]) XCTAssertEqual(state.availableFilters, []) + state.clearFilters() XCTAssertFalse(state.isFiltering) XCTAssertEqual(state.activeFilters, []) - XCTAssertEqual(state.availableFilters, RoomListFilter.allCases) + XCTAssertEqual(state.availableFilters, [.people, .unreads, .favourites, .rooms]) + } + + func testOrder() { + state.activateFilter(.favourites) + XCTAssertEqual(state.activeFilters, [.favourites]) + XCTAssertEqual(state.availableFilters, [.unreads, .people, .rooms]) + + state.deactivateFilter(.favourites) + XCTAssertEqual(state.activeFilters, []) + XCTAssertEqual(state.availableFilters, [.favourites, .unreads, .people, .rooms]) + + state.activateFilter(.rooms) + XCTAssertEqual(state.activeFilters, [.rooms]) + XCTAssertEqual(state.availableFilters, [.favourites, .unreads]) + + state.activateFilter(.unreads) + XCTAssertEqual(state.activeFilters, [.rooms, .unreads]) + XCTAssertEqual(state.availableFilters, [.favourites]) + + state.deactivateFilter(.unreads) + XCTAssertEqual(state.activeFilters, [.rooms]) + XCTAssertEqual(state.availableFilters, [.unreads, .favourites]) } }