RTSDA-iOS/Views/SplashScreenView.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

158 lines
6.6 KiB
Swift

import SwiftUI
struct SplashScreenView: View {
@State private var dataService = ChurchDataService.shared
@State private var isActive = false
@State private var size = 0.8
@State private var opacity = 0.5
@State private var bibleVerse = ""
@State private var bibleReference = ""
// Timing constants
private let fadeInDuration: Double = 0.5
private let baseDisplayDuration: Double = 1.0
private let timePerWord: Double = 0.15
private let minDisplayDuration: Double = 1.5
private let maxDisplayDuration: Double = 3.0
private func calculateDisplayDuration(for text: String) -> Double {
let words = text.components(separatedBy: .whitespacesAndNewlines).filter { !$0.isEmpty }
let calculatedDuration = baseDisplayDuration + (Double(words.count) * timePerWord)
return min(max(calculatedDuration, minDisplayDuration), maxDisplayDuration)
}
var body: some View {
if isActive {
MainAppView()
} else {
ZStack {
// Modern background matching the app theme
LinearGradient(
colors: [.blue.opacity(0.1), .indigo.opacity(0.05)],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
.ignoresSafeArea()
// Background pattern for subtle texture
GeometryReader { geometry in
ForEach(0..<20, id: \.self) { _ in
Circle()
.fill(.white.opacity(0.02))
.frame(width: 20, height: 20)
.position(
x: CGFloat.random(in: 0...geometry.size.width),
y: CGFloat.random(in: 0...geometry.size.height)
)
}
}
VStack(spacing: 20) {
Spacer()
// Logo and church info card
VStack(spacing: 24) {
// Logo with modern background
ZStack {
Circle()
.fill(.regularMaterial)
.frame(width: 120, height: 120)
.shadow(color: .black.opacity(0.1), radius: 8, x: 0, y: 4)
Image("sdalogo")
.resizable()
.scaledToFit()
.frame(width: 80, height: 80)
}
VStack(spacing: 12) {
Text("Rockville-Tolland")
.font(.custom("Montserrat-SemiBold", size: 28))
.foregroundStyle(.primary)
Text("SDA Church")
.font(.custom("Montserrat-Regular", size: 20))
.foregroundStyle(.secondary)
// Modern separator
Capsule()
.fill(Color(hex: "fb8b23"))
.frame(width: 80, height: 3)
}
}
Spacer()
.frame(maxHeight: 40)
// Bible verse card
if !bibleVerse.isEmpty {
VStack(spacing: 16) {
// Quote icon
Image(systemName: "quote.opening")
.font(.title2)
.foregroundStyle(Color(hex: "fb8b23").opacity(0.8))
VStack(spacing: 12) {
Text(bibleVerse)
.font(.custom("Lora-Italic", size: 18))
.foregroundStyle(.primary)
.multilineTextAlignment(.center)
.lineSpacing(6)
Text(bibleReference)
.font(.custom("Montserrat-Regular", size: 14))
.foregroundStyle(Color(hex: "fb8b23"))
.fontWeight(.medium)
}
}
.padding(24)
.background(.regularMaterial, in: RoundedRectangle(cornerRadius: 20))
.shadow(color: .black.opacity(0.1), radius: 12, x: 0, y: 6)
.padding(.horizontal, 20)
}
Spacer()
}
.padding()
.scaleEffect(size)
.opacity(opacity)
.task {
// Load a random Bible verse from the Rust crate
await dataService.loadDailyVerse()
if let verse = dataService.dailyVerse {
bibleVerse = verse.text
bibleReference = verse.reference
} else {
// Fallback to a default verse if API fails
bibleVerse = "For God so loved the world that he gave his one and only Son, that whoever believes in him shall not perish but have eternal life."
bibleReference = "John 3:16"
}
// Calculate display duration based on verse length
let displayDuration = calculateDisplayDuration(for: bibleVerse)
// Start fade in animation after verse is loaded
withAnimation(.easeIn(duration: fadeInDuration)) {
self.size = 0.9
self.opacity = 1.0
}
// Wait for fade in + calculated display duration before transitioning
DispatchQueue.main.asyncAfter(deadline: .now() + fadeInDuration + displayDuration) {
withAnimation {
self.isActive = true
}
}
}
}
}
}
}
// Color extension is already defined in FeedItemCard.swift
#Preview {
SplashScreenView()
}