jellyflood/JellyfinPlayer/MultiSelector.swift

74 lines
2.1 KiB
Swift

//
// MultiSelector.swift
// JellyfinPlayer
//
// Created by Aiden Vigue on 5/2/21.
//
import SwiftUI
private struct MultiSelectionView<Selectable: Identifiable & Hashable>: View {
let options: [Selectable]
let optionToString: (Selectable) -> String
let label: String
@Binding var selected: Set<Selectable>
var body: some View {
List {
ForEach(options) { selectable in
Button(action: { toggleSelection(selectable: selectable) }) {
HStack {
Text(optionToString(selectable)).foregroundColor(Color.primary)
Spacer()
if selected.contains { $0.id == selectable.id } {
Image(systemName: "checkmark").foregroundColor(.accentColor)
}
}
}.tag(selectable.id)
}
}.listStyle(GroupedListStyle())
}
private func toggleSelection(selectable: Selectable) {
if let existingIndex = selected.firstIndex(where: { $0.id == selectable.id }) {
selected.remove(at: existingIndex)
} else {
selected.insert(selectable)
}
}
}
struct MultiSelector<Selectable: Identifiable & Hashable>: View {
let label: String
let options: [Selectable]
let optionToString: (Selectable) -> String
var selected: Binding<Set<Selectable>>
private var formattedSelectedListString: String {
ListFormatter.localizedString(byJoining: selected.wrappedValue.map { optionToString($0) })
}
var body: some View {
NavigationLink(destination: multiSelectionView()) {
HStack {
Text(label)
Spacer()
Text(formattedSelectedListString)
.foregroundColor(.gray)
.multilineTextAlignment(.trailing)
}
}
}
private func multiSelectionView() -> some View {
MultiSelectionView(
options: options,
optionToString: optionToString,
label: self.label,
selected: selected
)
}
}