74 lines
2.0 KiB
Swift
74 lines
2.0 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 SwiftUI
|
|
|
|
// TODO: come up with better name along with `ListRowButton`
|
|
|
|
// Meant to be used when making a custom list without `List` or `Form`
|
|
struct ListRow<Leading: View, Content: View>: View {
|
|
|
|
@State
|
|
private var contentSize: CGSize = .zero
|
|
|
|
private let leading: Leading
|
|
private let content: Content
|
|
private var action: () -> Void
|
|
private var insets: EdgeInsets
|
|
private var isSeparatorVisible: Bool
|
|
|
|
var body: some View {
|
|
ZStack(alignment: .bottomTrailing) {
|
|
|
|
Button(action: action) {
|
|
HStack(alignment: .center, spacing: EdgeInsets.edgePadding) {
|
|
|
|
leading
|
|
|
|
content
|
|
.frame(maxHeight: .infinity)
|
|
.trackingSize($contentSize)
|
|
}
|
|
.padding(insets)
|
|
}
|
|
.foregroundStyle(.primary, .secondary)
|
|
.contentShape(.contextMenuPreview, Rectangle())
|
|
|
|
Color.secondarySystemFill
|
|
.frame(width: contentSize.width, height: 1)
|
|
.padding(.trailing, insets.trailing)
|
|
.isVisible(isSeparatorVisible)
|
|
}
|
|
}
|
|
}
|
|
|
|
extension ListRow {
|
|
|
|
init(
|
|
insets: EdgeInsets = .zero,
|
|
@ViewBuilder leading: @escaping () -> Leading,
|
|
@ViewBuilder content: @escaping () -> Content
|
|
) {
|
|
self.init(
|
|
leading: leading(),
|
|
content: content(),
|
|
action: {},
|
|
insets: insets,
|
|
isSeparatorVisible: true
|
|
)
|
|
}
|
|
|
|
func isSeparatorVisible(_ isVisible: Bool) -> Self {
|
|
copy(modifying: \.isSeparatorVisible, with: isVisible)
|
|
}
|
|
|
|
func onSelect(perform action: @escaping () -> Void) -> Self {
|
|
copy(modifying: \.action, with: action)
|
|
}
|
|
}
|