jellyflood/jellypig iOS/Components/SplitContentView.swift

76 lines
1.9 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
class SplitContentViewProxy: ObservableObject {
@Published
private(set) var isPresentingSplitView: Bool = false
func present() {
isPresentingSplitView = true
}
func hide() {
isPresentingSplitView = false
}
}
struct SplitContentView: View {
@ObservedObject
private var proxy: SplitContentViewProxy
private var content: () -> any View
private var splitContent: () -> any View
private var splitContentWidth: CGFloat
var body: some View {
HStack(spacing: 0) {
content()
.eraseToAnyView()
.frame(maxWidth: .infinity)
if proxy.isPresentingSplitView {
splitContent()
.eraseToAnyView()
.transition(.move(edge: .bottom))
.frame(width: splitContentWidth)
.zIndex(100)
}
}
.animation(.easeInOut(duration: 0.35), value: proxy.isPresentingSplitView)
}
}
extension SplitContentView {
init(splitContentWidth: CGFloat = 400) {
self.init(
proxy: .init(),
content: { EmptyView() },
splitContent: { EmptyView() },
splitContentWidth: splitContentWidth
)
}
func proxy(_ proxy: SplitContentViewProxy) -> Self {
copy(modifying: \.proxy, with: proxy)
}
func content(@ViewBuilder _ content: @escaping () -> any View) -> Self {
copy(modifying: \.content, with: content)
}
func splitContent(@ViewBuilder _ content: @escaping () -> any View) -> Self {
copy(modifying: \.splitContent, with: content)
}
}