SwiftUI app against master API: link, profiles, browse, live TV, favorites sync, and TestFlight-ready assets. Co-authored-by: Cursor <cursoragent@cursor.com>
80 lines
2.8 KiB
Swift
80 lines
2.8 KiB
Swift
import SwiftUI
|
|
|
|
struct MainShell: View {
|
|
@EnvironmentObject private var app: AppModel
|
|
|
|
var body: some View {
|
|
ZStack(alignment: .bottom) {
|
|
Group {
|
|
switch app.tab {
|
|
case .home:
|
|
NavigationStack { HomeScreen() }
|
|
case .movies:
|
|
NavigationStack { BrowseScreen(kind: "MOVIE", title: "Films") }
|
|
case .series:
|
|
NavigationStack { BrowseScreen(kind: "SERIES", title: "Series") }
|
|
case .tv:
|
|
NavigationStack { LiveTvScreen() }
|
|
case .search:
|
|
NavigationStack { SearchScreen() }
|
|
case .account:
|
|
NavigationStack { SettingsScreen() }
|
|
}
|
|
}
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
.padding(.bottom, app.isPlaybackActive ? 0 : 58)
|
|
|
|
if !app.isPlaybackActive {
|
|
footer
|
|
.transition(.move(edge: .bottom).combined(with: .opacity))
|
|
}
|
|
}
|
|
.animation(.easeOut(duration: 0.2), value: app.isPlaybackActive)
|
|
.ignoresSafeArea(.keyboard)
|
|
.background(McColors.bg.ignoresSafeArea())
|
|
}
|
|
|
|
private var footer: some View {
|
|
HStack(spacing: 0) {
|
|
ForEach(visibleTabs) { tab in
|
|
Button {
|
|
withAnimation(.spring(response: 0.32, dampingFraction: 0.84)) {
|
|
app.tab = tab
|
|
}
|
|
} label: {
|
|
VStack(spacing: 3) {
|
|
Image(systemName: tab.icon)
|
|
.font(.system(size: 16, weight: .semibold))
|
|
Text(tab.title)
|
|
.font(.system(size: 9, weight: .semibold, design: .rounded))
|
|
.lineLimit(1)
|
|
.minimumScaleFactor(0.8)
|
|
}
|
|
.foregroundStyle(app.tab == tab ? McColors.accent : McColors.textDim)
|
|
.frame(maxWidth: .infinity)
|
|
.padding(.top, 8)
|
|
.padding(.bottom, 6)
|
|
.contentShape(Rectangle())
|
|
}
|
|
.buttonStyle(.plain)
|
|
}
|
|
}
|
|
.background(
|
|
ZStack(alignment: .top) {
|
|
Rectangle().fill(.ultraThinMaterial)
|
|
McColors.footer
|
|
Rectangle()
|
|
.fill(McColors.surfaceSoft.opacity(0.55))
|
|
.frame(height: 0.5)
|
|
}
|
|
.ignoresSafeArea(edges: .bottom)
|
|
)
|
|
}
|
|
|
|
private var visibleTabs: [AppModel.MainTab] {
|
|
AppModel.MainTab.allCases.filter { tab in
|
|
if tab == .tv { return app.iptvEnabled }
|
|
return true
|
|
}
|
|
}
|
|
}
|