fix: splash screen uses actual app icon in a circle (Wenza style)
Replaces the custom 3-bar SwiftUI drawing with UIImage(named:"AppIcon") clipped to a circle, matching the Wenza splash pattern exactly: - Icon bounces in with spring (scale 0.82→1, opacity 0→1) - "jarvis" wordmark fades in 320ms later - Whole screen fades out at 1.6s, onDismiss fires at 1.9s - Main app renders underneath so it's warm when the splash clears Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,33 +5,53 @@ import SwiftData
|
||||
import UIKit
|
||||
import BackgroundTasks
|
||||
|
||||
// MARK: - Logo + splash
|
||||
|
||||
/// The three-bar logo that mirrors the app icon.
|
||||
struct JarvisLogoMark: View {
|
||||
var width: CGFloat = 180
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .center, spacing: 8) {
|
||||
// Orange (short) · White (longest) · Grey (medium) — same ratios as icon
|
||||
Capsule().fill(Palette.orange)
|
||||
.frame(width: width * 0.48, height: width * 0.075)
|
||||
.shadow(color: Palette.orange.opacity(0.55), radius: 10, y: 2)
|
||||
Capsule().fill(Color.white)
|
||||
.frame(width: width, height: width * 0.075)
|
||||
Capsule().fill(Color(hex: "888888"))
|
||||
.frame(width: width * 0.74, height: width * 0.075)
|
||||
}
|
||||
}
|
||||
}
|
||||
// MARK: - Splash
|
||||
|
||||
struct SplashView: View {
|
||||
var onDismiss: () -> Void
|
||||
|
||||
@State private var iconScale: CGFloat = 0.82
|
||||
@State private var iconOpacity: Double = 0
|
||||
@State private var markOpacity: Double = 0
|
||||
@State private var rootOpacity: Double = 1
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
Color(hex: "0A0A0A").ignoresSafeArea()
|
||||
VStack(spacing: 28) {
|
||||
JarvisLogoMark(width: 180)
|
||||
JarvisWordmark(size: 34)
|
||||
VStack(spacing: 22) {
|
||||
// App icon displayed as a circle
|
||||
Group {
|
||||
if let img = UIImage(named: "AppIcon") {
|
||||
Image(uiImage: img)
|
||||
.resizable()
|
||||
} else {
|
||||
Circle().fill(Palette.surface)
|
||||
}
|
||||
}
|
||||
.frame(width: 108, height: 108)
|
||||
.clipShape(Circle())
|
||||
.shadow(color: Color.black.opacity(0.4), radius: 20, y: 6)
|
||||
.scaleEffect(iconScale)
|
||||
.opacity(iconOpacity)
|
||||
|
||||
JarvisWordmark(size: 28)
|
||||
.opacity(markOpacity)
|
||||
}
|
||||
}
|
||||
.opacity(rootOpacity)
|
||||
.onAppear {
|
||||
withAnimation(.spring(response: 0.48, dampingFraction: 0.74).delay(0.08)) {
|
||||
iconScale = 1
|
||||
iconOpacity = 1
|
||||
}
|
||||
withAnimation(.easeOut(duration: 0.28).delay(0.32)) {
|
||||
markOpacity = 1
|
||||
}
|
||||
withAnimation(.easeIn(duration: 0.26).delay(1.6)) {
|
||||
rootOpacity = 0
|
||||
}
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1.9) {
|
||||
onDismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,7 +89,7 @@ struct JarvisApp: App {
|
||||
@StateObject private var connectivity = ConnectivitySettings.shared
|
||||
@StateObject private var connManager = ConnectivityManager.shared
|
||||
@StateObject private var notifications = NotificationManager.shared
|
||||
@State private var showSplash = true
|
||||
@State private var splashDone = false
|
||||
|
||||
// Single ModelContainer instance shared with BackgroundRefreshManager.
|
||||
private let container: ModelContainer = {
|
||||
@@ -81,10 +101,7 @@ struct JarvisApp: App {
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
ZStack {
|
||||
if showSplash {
|
||||
SplashView()
|
||||
.transition(.opacity)
|
||||
} else {
|
||||
// Main app always rendered underneath so it's ready when splash fades.
|
||||
Group {
|
||||
if settings.isConfigured {
|
||||
RootTabView()
|
||||
@@ -92,10 +109,11 @@ struct JarvisApp: App {
|
||||
OnboardingView()
|
||||
}
|
||||
}
|
||||
.transition(.opacity)
|
||||
|
||||
if !splashDone {
|
||||
SplashView { splashDone = true }
|
||||
}
|
||||
}
|
||||
.animation(.easeOut(duration: 0.5), value: showSplash)
|
||||
.preferredColorScheme(appearanceMode.colorScheme)
|
||||
.environmentObject(settings)
|
||||
.environmentObject(store)
|
||||
@@ -109,9 +127,6 @@ struct JarvisApp: App {
|
||||
connManager.start()
|
||||
await connManager.resolveAndActivate()
|
||||
await notifications.bootstrap()
|
||||
// Hold splash until setup is done, minimum 1.3 s for legibility.
|
||||
try? await Task.sleep(nanoseconds: 1_300_000_000)
|
||||
showSplash = false
|
||||
}
|
||||
}
|
||||
.modelContainer(container)
|
||||
|
||||
Reference in New Issue
Block a user