Filter Toggles [iOS] [iPadOS] (#847)

Co-authored-by: Joe Kribs <joseph@kribs.net>
This commit is contained in:
Joe 2023-09-20 13:28:32 -06:00 committed by GitHub
parent 984134f4b6
commit 48e608e62b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 324 additions and 58 deletions

View File

@ -34,6 +34,8 @@ final class SettingsCoordinator: NavigationCoordinatable {
@Route(.push)
var experimentalSettings = makeExperimentalSettings
@Route(.push)
var filterDrawerButtonSelector = makeFilterDrawerButtonSelector
@Route(.push)
var indicatorSettings = makeIndicatorSettings
@Route(.push)
var serverDetail = makeServerDetail
@ -115,9 +117,14 @@ final class SettingsCoordinator: NavigationCoordinatable {
}
#endif
func makeFilterDrawerButtonSelector(selectedButtonsBinding: Binding<[FilterDrawerButtonSelection]>) -> some View {
FilterDrawerButtonSelectorView(selectedButtonsBinding: selectedButtonsBinding)
}
func makeVideoPlayerSettings() -> VideoPlayerSettingsCoordinator {
VideoPlayerSettingsCoordinator()
}
#endif
#if os(tvOS)

View File

@ -0,0 +1,92 @@
//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2023 Jellyfin & Jellyfin Contributors
//
import Defaults
import Foundation
enum FilterDrawerButtonSelection: String, CaseIterable, Defaults.Serializable, Displayable, Identifiable {
case filters
case genres
case order
case sort
var displayTitle: String {
switch self {
case .filters:
return L10n.filters
case .genres:
return L10n.genres
case .order:
return L10n.order
case .sort:
return L10n.sort
}
}
var id: String {
rawValue
}
var itemFilter: WritableKeyPath<ItemFilters, [ItemFilters.Filter]> {
switch self {
case .filters:
return \.filters
case .genres:
return \.genres
case .order:
return \.sortOrder
case .sort:
return \.sortBy
}
}
var selectorType: SelectorType {
switch self {
case .filters, .genres:
return .multi
case .order, .sort:
return .single
}
}
var itemFilterDefault: [ItemFilters.Filter] {
switch self {
case .filters:
return []
case .genres:
return []
case .order:
return [APISortOrder.ascending.filter]
case .sort:
return [SortBy.name.filter]
}
}
func isItemsFilterActive(activeFilters: ItemFilters) -> Bool {
switch self {
case .filters:
return activeFilters.filters != self.itemFilterDefault
case .genres:
return activeFilters.genres != self.itemFilterDefault
case .order:
return activeFilters.sortOrder != self.itemFilterDefault
case .sort:
return activeFilters.sortBy != self.itemFilterDefault
}
}
static var defaultFilterDrawerButtons: [FilterDrawerButtonSelection] {
[
.filters,
.genres,
.order,
.sort,
]
}
}

View File

@ -72,6 +72,19 @@ extension Defaults.Keys {
static let showFavorites: Key<Bool> = .init("libraryShowFavorites", default: true, suite: .generalSuite)
static let viewType = Key<LibraryViewType>("libraryViewType", default: .grid, suite: .generalSuite)
}
enum Filters {
static let libraryFilterDrawerButtons: Key<[FilterDrawerButtonSelection]> = .init(
"defaultLibraryFilterDrawerButtons",
default: FilterDrawerButtonSelection.defaultFilterDrawerButtons,
suite: .generalSuite
)
static let searchFilterDrawerButtons: Key<[FilterDrawerButtonSelection]> = .init(
"defaultSearchFilterDrawerButtons",
default: FilterDrawerButtonSelection.defaultFilterDrawerButtons,
suite: .generalSuite
)
}
}
enum VideoPlayer {

View File

@ -9,6 +9,10 @@
/* Begin PBXBuildFile section */
091B5A8A2683142E00D78B61 /* ServerDiscovery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 091B5A872683142E00D78B61 /* ServerDiscovery.swift */; };
091B5A8D268315D400D78B61 /* ServerDiscovery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 091B5A872683142E00D78B61 /* ServerDiscovery.swift */; };
4E5E48E52AB59806003F1B48 /* CustomizeViewsSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E5E48E42AB59806003F1B48 /* CustomizeViewsSettings.swift */; };
4E8B34EA2AB91B6E0018F305 /* FilterDrawerSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E8B34E92AB91B6E0018F305 /* FilterDrawerSelection.swift */; };
4E8B34EB2AB91B6E0018F305 /* FilterDrawerSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E8B34E92AB91B6E0018F305 /* FilterDrawerSelection.swift */; };
4EAA35BB2AB9699B00D840DD /* FilterDrawerButtonSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EAA35BA2AB9699B00D840DD /* FilterDrawerButtonSelectorView.swift */; };
531690E7267ABD79005D8AB9 /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531690E6267ABD79005D8AB9 /* HomeView.swift */; };
53192D5D265AA78A008A4215 /* DeviceProfileBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53192D5C265AA78A008A4215 /* DeviceProfileBuilder.swift */; };
531AC8BF26750DE20091C7EB /* ImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531AC8BE26750DE20091C7EB /* ImageView.swift */; };
@ -622,7 +626,6 @@
E1CCF12E28ABF989006CAC9E /* PosterType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1CCF12D28ABF989006CAC9E /* PosterType.swift */; };
E1CCF13128AC07EC006CAC9E /* PosterHStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1CCF13028AC07EC006CAC9E /* PosterHStack.swift */; };
E1CD13EF28EF364100CB46CA /* DetectOrientationModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1CD13EE28EF364100CB46CA /* DetectOrientationModifier.swift */; };
E1CEFBF527914C7700F60429 /* CustomizeViewsSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1CEFBF427914C7700F60429 /* CustomizeViewsSettings.swift */; };
E1CEFBF727914E6400F60429 /* CustomizeViewsSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1CEFBF627914E6400F60429 /* CustomizeViewsSettings.swift */; };
E1CFE28028FA606800B7D34C /* ChapterTrack.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1CFE27F28FA606800B7D34C /* ChapterTrack.swift */; };
E1D3043228D175CE00587289 /* StaticLibraryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D3043128D175CE00587289 /* StaticLibraryViewModel.swift */; };
@ -771,6 +774,9 @@
/* Begin PBXFileReference section */
091B5A872683142E00D78B61 /* ServerDiscovery.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServerDiscovery.swift; sourceTree = "<group>"; };
4E5E48E42AB59806003F1B48 /* CustomizeViewsSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomizeViewsSettings.swift; sourceTree = "<group>"; };
4E8B34E92AB91B6E0018F305 /* FilterDrawerSelection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FilterDrawerSelection.swift; sourceTree = "<group>"; };
4EAA35BA2AB9699B00D840DD /* FilterDrawerButtonSelectorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FilterDrawerButtonSelectorView.swift; sourceTree = "<group>"; };
531690E6267ABD79005D8AB9 /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = "<group>"; };
531690F9267AD6EC005D8AB9 /* PlainNavigationLinkButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlainNavigationLinkButton.swift; sourceTree = "<group>"; };
53192D5C265AA78A008A4215 /* DeviceProfileBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceProfileBuilder.swift; sourceTree = "<group>"; };
@ -1193,7 +1199,6 @@
E1CCF12D28ABF989006CAC9E /* PosterType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PosterType.swift; sourceTree = "<group>"; };
E1CCF13028AC07EC006CAC9E /* PosterHStack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PosterHStack.swift; sourceTree = "<group>"; };
E1CD13EE28EF364100CB46CA /* DetectOrientationModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetectOrientationModifier.swift; sourceTree = "<group>"; };
E1CEFBF427914C7700F60429 /* CustomizeViewsSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomizeViewsSettings.swift; sourceTree = "<group>"; };
E1CEFBF627914E6400F60429 /* CustomizeViewsSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomizeViewsSettings.swift; sourceTree = "<group>"; };
E1CFE27F28FA606800B7D34C /* ChapterTrack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChapterTrack.swift; sourceTree = "<group>"; };
E1D3043128D175CE00587289 /* StaticLibraryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticLibraryViewModel.swift; sourceTree = "<group>"; };
@ -1375,6 +1380,22 @@
path = ServerDiscovery;
sourceTree = "<group>";
};
4EAA35B82AB9694000D840DD /* FilterDrawerSettingsView */ = {
isa = PBXGroup;
children = (
4EAA35B92AB9694D00D840DD /* Components */,
);
path = FilterDrawerSettingsView;
sourceTree = "<group>";
};
4EAA35B92AB9694D00D840DD /* Components */ = {
isa = PBXGroup;
children = (
4EAA35BA2AB9699B00D840DD /* FilterDrawerButtonSelectorView.swift */,
);
path = Components;
sourceTree = "<group>";
};
5310694F2684E7EE00CFFDBA /* VideoPlayer */ = {
isa = PBXGroup;
children = (
@ -1503,6 +1524,7 @@
53192D5C265AA78A008A4215 /* DeviceProfileBuilder.swift */,
E17FB55128C119D400311DFE /* Displayable.swift */,
E129429728F4785200796AC6 /* EnumPicker.swift */,
4E8B34E92AB91B6E0018F305 /* FilterDrawerSelection.swift */,
E1092F4B29106F9F00163F57 /* GestureAction.swift */,
E19169CD272514760085832A /* HTTPScheme.swift */,
535870AC2669D8DD00D05A09 /* ItemFilters.swift */,
@ -2694,7 +2716,8 @@
E1E5D54A2783E26100692DFE /* SettingsView */ = {
isa = PBXGroup;
children = (
E1CEFBF427914C7700F60429 /* CustomizeViewsSettings.swift */,
4EAA35B82AB9694000D840DD /* FilterDrawerSettingsView */,
4E5E48E42AB59806003F1B48 /* CustomizeViewsSettings.swift */,
E175AFF2299AC117004DCF52 /* DebugSettingsView.swift */,
E1E5D54B2783E27200692DFE /* ExperimentalSettingsView.swift */,
E104C86F296E087200C1C3F9 /* IndicatorSettingsView.swift */,
@ -3279,6 +3302,7 @@
C4BE077A2726EE82003F4AD1 /* LiveTVTabCoordinator.swift in Sources */,
E193D553271943D500900D82 /* tvOSMainTabCoordinator.swift in Sources */,
E1575E83293E784A001665B1 /* MediaItemViewModel.swift in Sources */,
4E8B34EB2AB91B6E0018F305 /* FilterDrawerSelection.swift in Sources */,
E174121029AE9D94003EF3B5 /* NavigationCoordinatable.swift in Sources */,
E154965F296CA2EF00C4EF88 /* DownloadTask.swift in Sources */,
E154967E296CCB6C00C4EF88 /* BasicNavigationCoordinator.swift in Sources */,
@ -3300,6 +3324,7 @@
E1B33ECF28EB6EA90073B0FD /* OverlayMenu.swift in Sources */,
6220D0B426D5ED8000B8E046 /* LibraryCoordinator.swift in Sources */,
E17AC96D2954E9CA003D2BC2 /* DownloadListView.swift in Sources */,
4E8B34EA2AB91B6E0018F305 /* FilterDrawerSelection.swift in Sources */,
E1A1528828FD229500600579 /* ChevronButton.swift in Sources */,
E1B490472967E2E500D3EDCE /* CoreStore.swift in Sources */,
6220D0C026D61C5000B8E046 /* ItemCoordinator.swift in Sources */,
@ -3405,7 +3430,6 @@
E1C8CE5B28FE512400DF5D7B /* CGPoint.swift in Sources */,
E18ACA922A15A32F00BB4F35 /* (null) in Sources */,
E1E1E24D28DF8A2E000DF5FD /* PreferenceKeys.swift in Sources */,
E1CEFBF527914C7700F60429 /* CustomizeViewsSettings.swift in Sources */,
E1C812BC277A8E5D00918266 /* PlaybackSpeed.swift in Sources */,
E15756322935642A00976E1F /* Float.swift in Sources */,
E139CC1D28EC836F00688DE2 /* ChapterOverlay.swift in Sources */,
@ -3434,6 +3458,7 @@
E1171A1928A2212600FA1AF5 /* QuickConnectView.swift in Sources */,
E1DC9819296DD1CD00982F06 /* CinematicBackgroundView.swift in Sources */,
E11CEB8D28999B4A003E74C7 /* Font.swift in Sources */,
4EAA35BB2AB9699B00D840DD /* FilterDrawerButtonSelectorView.swift in Sources */,
E139CC1F28EC83E400688DE2 /* Int.swift in Sources */,
E11895A9289383BC0042947B /* ScrollViewOffsetModifier.swift in Sources */,
E1DA656C28E78C1700592A73 /* MenuPosterHStackModel.swift in Sources */,
@ -3568,6 +3593,7 @@
E1937A3E288F0D3D00CB80AA /* UIScreen.swift in Sources */,
C4BE076F2720FEFF003F4AD1 /* PlainNavigationLinkButton.swift in Sources */,
E1EBCB46278BD595009FE6E9 /* ItemOverviewView.swift in Sources */,
4E5E48E52AB59806003F1B48 /* CustomizeViewsSettings.swift in Sources */,
E19F6C5D28F5189300C5197E /* MediaStreamInfoView.swift in Sources */,
E1D8429329340B8300D1041A /* Utilities.swift in Sources */,
E18CE0B428A22EDA0092E7F1 /* RepeatingTimer.swift in Sources */,

View File

@ -6,6 +6,7 @@
// Copyright (c) 2023 Jellyfin & Jellyfin Contributors
//
import Defaults
import JellyfinAPI
import SwiftUI
@ -13,7 +14,7 @@ struct FilterDrawerHStack: View {
@ObservedObject
private var viewModel: FilterViewModel
private var filterDrawerButtonSelection: [FilterDrawerButtonSelection]
private var onSelect: (FilterCoordinator.Parameters) -> Void
var body: some View {
@ -29,55 +30,29 @@ struct FilterDrawerHStack: View {
FilterDrawerButton(systemName: "line.3.horizontal.decrease.circle.fill", activated: true)
}
}
FilterDrawerButton(title: L10n.genres, activated: viewModel.currentFilters.genres != [])
ForEach(filterDrawerButtonSelection, id: \.self) { button in
FilterDrawerButton(title: button.displayTitle, activated: button.isItemsFilterActive(
activeFilters: viewModel.currentFilters
))
.onSelect {
onSelect(.init(
title: L10n.genres,
title: button.displayTitle,
viewModel: viewModel,
filter: \.genres,
selectorType: .multi
))
}
FilterDrawerButton(title: L10n.filters, activated: viewModel.currentFilters.filters != [])
.onSelect {
onSelect(.init(
title: L10n.filters,
viewModel: viewModel,
filter: \.filters,
selectorType: .multi
))
}
FilterDrawerButton(title: L10n.order, activated: viewModel.currentFilters.sortOrder != [APISortOrder.ascending.filter])
.onSelect {
onSelect(.init(
title: L10n.order,
viewModel: viewModel,
filter: \.sortOrder,
selectorType: .single
))
}
FilterDrawerButton(title: L10n.sort, activated: viewModel.currentFilters.sortBy != [SortBy.name.filter])
.onSelect {
onSelect(.init(
title: L10n.sort,
viewModel: viewModel,
filter: \.sortBy,
selectorType: .single
filter: button.itemFilter,
selectorType: button.selectorType
))
}
}
}
}
}
extension FilterDrawerHStack {
init(viewModel: FilterViewModel) {
init(viewModel: FilterViewModel, filterDrawerButtonSelection: [FilterDrawerButtonSelection]) {
self.init(
viewModel: viewModel,
filterDrawerButtonSelection: filterDrawerButtonSelection,
onSelect: { _ in }
)
}

View File

@ -16,6 +16,9 @@ struct LibraryView: View {
@Default(.Customization.Library.viewType)
private var libraryViewType
@Default(.Customization.Filters.libraryFilterDrawerButtons)
private var filterDrawerButtonSelection
@EnvironmentObject
private var router: LibraryCoordinator.Router
@ -67,14 +70,16 @@ struct LibraryView: View {
}
.navigationTitle(viewModel.parent?.displayTitle ?? "")
.navigationBarTitleDisplayMode(.inline)
.navBarDrawer {
ScrollView(.horizontal, showsIndicators: false) {
FilterDrawerHStack(viewModel: viewModel.filterViewModel)
.onSelect { filterCoordinatorParameters in
router.route(to: \.filter, filterCoordinatorParameters)
}
.padding(.horizontal)
.padding(.vertical, 1)
.if(!filterDrawerButtonSelection.isEmpty) { view in
view.navBarDrawer {
ScrollView(.horizontal, showsIndicators: false) {
FilterDrawerHStack(viewModel: viewModel.filterViewModel, filterDrawerButtonSelection: filterDrawerButtonSelection)
.onSelect { filterCoordinatorParameters in
router.route(to: \.filter, filterCoordinatorParameters)
}
.padding(.horizontal)
.padding(.vertical, 1)
}
}
}
.toolbar {

View File

@ -16,6 +16,9 @@ struct SearchView: View {
@Default(.Customization.searchPosterType)
private var searchPosterType
@Default(.Customization.Filters.searchFilterDrawerButtons)
private var filterDrawerButtonSelection
@EnvironmentObject
private var router: SearchCoordinator.Router
@ -105,14 +108,16 @@ struct SearchView: View {
}
.navigationTitle(L10n.search)
.navigationBarTitleDisplayMode(.inline)
.navBarDrawer {
ScrollView(.horizontal, showsIndicators: false) {
FilterDrawerHStack(viewModel: viewModel.filterViewModel)
.onSelect { filterCoordinatorParameters in
router.route(to: \.filter, filterCoordinatorParameters)
}
.padding(.horizontal)
.padding(.vertical, 1)
.if(!filterDrawerButtonSelection.isEmpty) { view in
view.navBarDrawer {
ScrollView(.horizontal, showsIndicators: false) {
FilterDrawerHStack(viewModel: viewModel.filterViewModel, filterDrawerButtonSelection: filterDrawerButtonSelection)
.onSelect { filterCoordinatorParameters in
router.route(to: \.filter, filterCoordinatorParameters)
}
.padding(.horizontal)
.padding(.vertical, 1)
}
}
}
.searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always), prompt: L10n.search)

View File

@ -24,6 +24,11 @@ struct CustomizeViewsSettings: View {
@Default(.Customization.shouldShowMissingEpisodes)
var shouldShowMissingEpisodes
@Default(.Customization.Filters.libraryFilterDrawerButtons)
var libraryFilterDrawerButtons
@Default(.Customization.Filters.searchFilterDrawerButtons)
var searchFilterDrawerButtons
@Default(.Customization.showPosterLabels)
var showPosterLabels
@Default(.Customization.nextUpPosterType)
@ -72,12 +77,28 @@ struct CustomizeViewsSettings: View {
Section {
Toggle(L10n.favorites, isOn: $showFavorites)
Toggle(L10n.randomImage, isOn: $libraryRandomImage)
} header: {
L10n.library.text
}
Section {
ChevronButton(title: L10n.library)
.onSelect {
router.route(to: \.filterDrawerButtonSelector, $libraryFilterDrawerButtons)
}
ChevronButton(title: L10n.search)
.onSelect {
router.route(to: \.filterDrawerButtonSelector, $searchFilterDrawerButtons)
}
} header: {
L10n.filters.text
}
Section {
Toggle(L10n.showMissingSeasons, isOn: $shouldShowMissingSeasons)
Toggle(L10n.showMissingEpisodes, isOn: $shouldShowMissingEpisodes)

View File

@ -0,0 +1,122 @@
//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2023 Jellyfin & Jellyfin Contributors
//
import Defaults
import SwiftUI
// TODO: Look at moving across sections
// TODO: Look at general implementation in SelectorView
struct FilterDrawerButtonSelectorView: View {
@Binding
var selectedButtonsBinding: [FilterDrawerButtonSelection]
@Environment(\.editMode)
private var editMode
@State
private var _selectedButtons: [FilterDrawerButtonSelection]
private var disabledButtons: [FilterDrawerButtonSelection] {
FilterDrawerButtonSelection.allCases.filter { !_selectedButtons.contains($0) }
}
var body: some View {
List {
Section {
ForEach(_selectedButtons) { item in
Button {
if !(editMode?.wrappedValue.isEditing ?? true) {
select(item: item)
}
} label: {
HStack {
Text(item.displayTitle)
Spacer()
if !(editMode?.wrappedValue.isEditing ?? false) {
Image(systemName: "minus.circle.fill")
.foregroundColor(.red)
}
}
.foregroundColor(.primary)
}
}
.onMove(perform: move)
if _selectedButtons.isEmpty {
Text("None")
.foregroundColor(.secondary)
}
} header: {
Text("Enabled")
}
Section {
ForEach(disabledButtons) { item in
Button {
if !(editMode?.wrappedValue.isEditing ?? true) {
select(item: item)
}
} label: {
HStack {
Text(item.displayTitle)
Spacer()
if !(editMode?.wrappedValue.isEditing ?? false) {
Image(systemName: "plus.circle.fill")
.foregroundColor(.green)
}
}
.foregroundColor(.primary)
}
}
if disabledButtons.isEmpty {
Text("None")
.foregroundColor(.secondary)
}
} header: {
Text("Disabled")
}
}
.animation(.linear(duration: 0.2), value: _selectedButtons)
.toolbar {
EditButton()
}
.onChange(of: _selectedButtons) { newValue in
selectedButtonsBinding = newValue
}
}
func move(from source: IndexSet, to destination: Int) {
_selectedButtons.move(fromOffsets: source, toOffset: destination)
}
private func select(item: FilterDrawerButtonSelection) {
if _selectedButtons.contains(item) {
_selectedButtons.removeAll(where: { $0.id == item.id })
} else {
_selectedButtons.append(item)
}
}
}
extension FilterDrawerButtonSelectorView {
init(selectedButtonsBinding: Binding<[FilterDrawerButtonSelection]>) {
self.init(
selectedButtonsBinding: selectedButtonsBinding,
_selectedButtons: selectedButtonsBinding.wrappedValue
)
// self._selectedButtonsBinding = selectedButtonsBinding
// self._selectedButtons = selectedButtonsBinding.wrappedValue
}
}