jellyflood/Swiftfin/Views/ItemEditorView/ItemMetadata/AddItemElementView/Components/SearchResultsSection.swift

111 lines
3.4 KiB
Swift

//
// 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) 2025 Jellyfin & Jellyfin Contributors
//
import JellyfinAPI
import SwiftUI
extension AddItemElementView {
struct SearchResultsSection: View {
// MARK: - Element Variables
@Binding
var name: String
@Binding
var id: String?
// MARK: - Element Search Variables
let type: ItemArrayElements
let population: [Element]
let isSearching: Bool
// MARK: - Body
var body: some View {
if name.isNotEmpty {
Section {
if population.isNotEmpty {
resultsView
.animation(.easeInOut, value: population.count)
} else if !isSearching {
noResultsView
.transition(.opacity)
.animation(.easeInOut, value: population.count)
}
} header: {
HStack {
Text(L10n.existingItems)
if isSearching {
DelayedProgressView()
} else {
Text("-")
Text(population.count.description)
}
}
.animation(.easeInOut, value: isSearching)
}
}
}
// MARK: - No Results View
private var noResultsView: some View {
Text(L10n.none)
.foregroundStyle(.secondary)
.frame(maxWidth: .infinity, alignment: .center)
}
// MARK: - Results View
private var resultsView: some View {
ForEach(population, id: \.self) { result in
Button {
name = type.getName(for: result)
id = type.getId(for: result)
} label: {
labelView(result)
}
.foregroundStyle(.primary)
.disabled(name == type.getName(for: result))
.transition(.opacity.combined(with: .move(edge: .top)))
.animation(.easeInOut, value: population.count)
}
}
// MARK: - Label View
@ViewBuilder
private func labelView(_ match: Element) -> some View {
switch type {
case .people:
let person = match as! BaseItemPerson
HStack {
ZStack {
Color.clear
ImageView(person.portraitImageSources(maxWidth: 30))
.failure {
SystemImageContentView(systemName: "person.fill")
}
}
.posterStyle(.portrait)
.frame(width: 30, height: 90)
.padding(.horizontal)
Text(type.getName(for: match))
.frame(maxWidth: .infinity, alignment: .leading)
}
default:
Text(type.getName(for: match))
.frame(maxWidth: .infinity, alignment: .leading)
}
}
}
}