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 .events: EventsScreen() 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 } if tab == .events { return app.eventsEnabled } return true } } }