RTSDA-iOS/Views/MainAppView.swift
RTSDA 00679f927c docs: Update README for v2.0 release and fix git remote URL
- Comprehensive README update documenting v2.0 architectural changes
- Updated git remote to ssh://rockvilleav@git.rockvilletollandsda.church:10443/RTSDA/RTSDA-iOS.git
- Documented unified ChurchService and 60% code reduction
- Added new features: Home Feed, responsive reading, enhanced UI
- Corrected license information (GPL v3 with church content copyright)
- Updated build instructions and technical stack details
2025-08-16 18:41:51 -04:00

275 lines
8.5 KiB
Swift

import SwiftUI
import MapKit
enum SidebarSelection: Hashable {
case home
case events
case watch
case connect
case bulletins
}
struct MainAppView: View {
@State private var dataService = ChurchDataService.shared
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
@State private var selectedView: SidebarSelection = .home
var body: some View {
Group {
if horizontalSizeClass == .regular {
// iPad: Use standard NavigationSplitView
NavigationSplitView {
SidebarView(selectedView: $selectedView)
} detail: {
NavigationStack {
selectedDetailView
.environment(dataService)
}
}
} else {
// iPhone: Tab navigation
TabView {
NavigationStack {
HomeFeedView()
.environment(dataService)
}
.tabItem {
Label("Home", systemImage: "house.fill")
}
NavigationStack {
EventsListView()
.environment(dataService)
}
.tabItem {
Label("Events", systemImage: "calendar")
}
NavigationStack {
WatchView()
.environment(dataService)
}
.tabItem {
Label("Watch", systemImage: "play.rectangle.fill")
}
NavigationStack {
ConnectView()
.environment(dataService)
}
.tabItem {
Label("Connect", systemImage: "person.2.fill")
}
NavigationStack {
BulletinsView()
.environment(dataService)
}
.tabItem {
Label("Bulletins", systemImage: "newspaper.fill")
}
}
.tint(Color(hex: "fb8b23"))
}
}
.task {
await dataService.loadHomeFeed()
}
.overlay {
SharedVideoOverlay()
}
}
@ViewBuilder
private var selectedDetailView: some View {
switch selectedView {
case .home:
HomeFeedView()
case .events:
EventsListView() // Just use the regular list view - NavigationStack will handle details
case .watch:
WatchView()
case .connect:
ConnectView()
case .bulletins:
BulletinsView()
}
}
}
struct SidebarView: View {
@Binding var selectedView: SidebarSelection
var body: some View {
List {
Button(action: { selectedView = .home }) {
Label("Home", systemImage: "house.fill")
}
.foregroundColor(selectedView == .home ? .blue : .primary)
Button(action: { selectedView = .events }) {
Label("Events", systemImage: "calendar")
}
.foregroundColor(selectedView == .events ? .blue : .primary)
Button(action: { selectedView = .watch }) {
Label("Watch", systemImage: "play.rectangle.fill")
}
.foregroundColor(selectedView == .watch ? .blue : .primary)
Button(action: { selectedView = .connect }) {
Label("Connect", systemImage: "person.2.fill")
}
.foregroundColor(selectedView == .connect ? .blue : .primary)
Button(action: { selectedView = .bulletins }) {
Label("Bulletins", systemImage: "newspaper.fill")
}
.foregroundColor(selectedView == .bulletins ? .blue : .primary)
// Quick Actions removed - functionality available via main tabs
}
.navigationTitle("RTSDA")
.navigationBarTitleDisplayMode(.large)
}
}
// MARK: - Placeholder Views (to be implemented)
// MARK: - New iPad Cards
struct LiveStreamCard: View {
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
var body: some View {
Button {
// Use shared video player like sermons do
if let livestreamUrl = getLivestreamUrl() {
SharedVideoManager.shared.playVideo(url: livestreamUrl)
}
} label: {
VStack(spacing: 0) {
ZStack {
// Background gradient
LinearGradient(
colors: [Color.red, Color.red.opacity(0.8)],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
.frame(height: horizontalSizeClass == .regular ? 200 : 150)
// Live indicator and play button
VStack(spacing: 16) {
HStack {
// LIVE indicator
HStack(spacing: 6) {
Circle()
.fill(.white)
.frame(width: 8, height: 8)
.opacity(0.9)
Text("LIVE")
.font(.system(size: 14, weight: .bold))
.foregroundColor(.white)
}
.padding(.horizontal, 12)
.padding(.vertical, 6)
.background(.black.opacity(0.6))
.cornerRadius(20)
Spacer()
}
// Play button
Circle()
.fill(.white.opacity(0.9))
.frame(width: horizontalSizeClass == .regular ? 70 : 60,
height: horizontalSizeClass == .regular ? 70 : 60)
.overlay {
Image(systemName: "play.fill")
.font(.system(size: horizontalSizeClass == .regular ? 28 : 24))
.foregroundColor(.red)
.offset(x: 2) // Visual centering
}
.shadow(color: .black.opacity(0.3), radius: 4)
}
.padding(20)
}
// Content section
VStack(alignment: .leading, spacing: 12) {
HStack {
VStack(alignment: .leading, spacing: 6) {
Text("Live Stream")
.font(.system(size: horizontalSizeClass == .regular ? 20 : 18, weight: .bold))
.foregroundColor(.primary)
Text("Join our live worship service")
.font(.system(size: horizontalSizeClass == .regular ? 16 : 14))
.foregroundColor(.secondary)
}
Spacer()
Image(systemName: "chevron.right")
.font(.title2)
.foregroundColor(.secondary)
}
}
.padding(20)
}
}
.buttonStyle(PlainButtonStyle())
.background(.regularMaterial, in: RoundedRectangle(cornerRadius: 16))
.shadow(color: .black.opacity(0.1), radius: 8, x: 0, y: 4)
}
private func getLivestreamUrl() -> URL? {
// Use Rust function for JSON parsing - NO business logic in Swift!
let statusJson = fetchStreamStatusJson()
let streamUrl = extractStreamUrlFromStatus(statusJson: statusJson)
return streamUrl.isEmpty ? nil : URL(string: streamUrl)
}
}