mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
Filters UI Update and ordering (#2521)
This commit is contained in:
@@ -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)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<RoomListFilter>
|
||||
private(set) var activeFilters: OrderedSet<RoomListFilter>
|
||||
private var inactiveFilters: OrderedSet<RoomListFilter>
|
||||
|
||||
init(activeFilters: Set<RoomListFilter> = []) {
|
||||
self.activeFilters = activeFilters
|
||||
}
|
||||
|
||||
var sortedActiveFilters: [RoomListFilter] {
|
||||
activeFilters.sorted(by: { $0.rawValue < $1.rawValue })
|
||||
init(activeFilters: OrderedSet<RoomListFilter> = []) {
|
||||
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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user