SplashView.swift 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import SwiftUI
  2. /// Keeps the static system launch screen visually continuous, then presents
  3. /// the selected 星痕 brand artwork before revealing the app.
  4. struct LaunchRootView: View {
  5. @State private var isShowingSplash = true
  6. var body: some View {
  7. ZStack {
  8. ContentView()
  9. if isShowingSplash {
  10. SplashView {
  11. withAnimation(.easeInOut(duration: 0.45)) {
  12. isShowingSplash = false
  13. }
  14. }
  15. .transition(.opacity)
  16. .zIndex(1)
  17. }
  18. }
  19. }
  20. }
  21. struct SplashView: View {
  22. @Environment(\.accessibilityReduceMotion) private var reduceMotion
  23. @State private var artworkOpacity = 0.0
  24. @State private var artworkScale = 1.008
  25. @State private var hasStarted = false
  26. let onFinished: () -> Void
  27. var body: some View {
  28. ZStack {
  29. Color("LaunchBackground")
  30. .ignoresSafeArea()
  31. Image("SplashArtwork")
  32. .resizable()
  33. .scaledToFill()
  34. .frame(maxWidth: .infinity, maxHeight: .infinity)
  35. .clipped()
  36. .opacity(artworkOpacity)
  37. .scaleEffect(artworkScale)
  38. .ignoresSafeArea()
  39. }
  40. .statusBarHidden(true)
  41. .task {
  42. guard !hasStarted else { return }
  43. hasStarted = true
  44. await playEntrance()
  45. }
  46. .accessibilityElement(children: .ignore)
  47. .accessibilityLabel("星痕。倾听,然后深刻。纯粹星辰出品。")
  48. }
  49. @MainActor
  50. private func playEntrance() async {
  51. if reduceMotion {
  52. artworkOpacity = 1
  53. artworkScale = 1
  54. try? await Task.sleep(for: .seconds(1.2))
  55. onFinished()
  56. return
  57. }
  58. withAnimation(.easeOut(duration: 0.65)) {
  59. artworkOpacity = 1
  60. artworkScale = 1
  61. }
  62. let holdDuration: Duration = ProcessInfo.processInfo.environment["XINGHEN_SPLASH_QA"] == "1"
  63. ? .seconds(30)
  64. : .seconds(2.05)
  65. try? await Task.sleep(for: holdDuration)
  66. onFinished()
  67. }
  68. }
  69. #Preview("星痕开屏") {
  70. SplashView(onFinished: {})
  71. }