-
Notifications
You must be signed in to change notification settings - Fork 48
feat: add splash screen with centered logo #81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
5d25617
44c830c
6efdd2d
cffc8a2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| { | ||
| "colors" : [ | ||
| { | ||
| "color" : { | ||
| "color-space" : "srgb", | ||
| "components" : { | ||
| "alpha" : "1.000", | ||
| "blue" : "1.000", | ||
| "green" : "1.000", | ||
| "red" : "1.000" | ||
| } | ||
| }, | ||
| "idiom" : "universal" | ||
| }, | ||
| { | ||
| "appearances" : [ | ||
| { | ||
| "appearance" : "luminosity", | ||
| "value" : "dark" | ||
| } | ||
| ], | ||
| "color" : { | ||
| "color-space" : "srgb", | ||
| "components" : { | ||
| "alpha" : "1.000", | ||
| "blue" : "0.078", | ||
| "green" : "0.071", | ||
| "red" : "0.067" | ||
| } | ||
| }, | ||
| "idiom" : "universal" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| { | ||
| "images" : [ | ||
| { | ||
| "filename" : "splash_logo.pdf", | ||
| "idiom" : "universal" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| }, | ||
| "properties" : { | ||
| "preserves-vector-representation" : true, | ||
| "template-rendering-intent" : "template" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| // | ||
| // SplashView.swift | ||
| // V2er | ||
| // | ||
| // Created by Claude on 2024/12/1. | ||
| // | ||
|
|
||
| import SwiftUI | ||
|
|
||
| struct SplashView: View { | ||
| @EnvironmentObject private var store: Store | ||
| @Environment(\.colorScheme) private var colorScheme | ||
|
|
||
| @State private var showSlogan = false | ||
|
|
||
| private let slogan = "Way to explore" | ||
|
|
||
| // Logo color adapts to color scheme (matches Android) | ||
| private var logoColor: Color { | ||
| colorScheme == .dark ? .white : Color(red: 0.067, green: 0.071, blue: 0.078) | ||
| } | ||
|
|
||
| var body: some View { | ||
| ZStack { | ||
| // Background color - matches Android implementation | ||
| Color("SplashBackground") | ||
| .ignoresSafeArea() | ||
|
|
||
| // Logo - vector PDF with template rendering (fixed position) | ||
| Image("SplashLogo") | ||
| .renderingMode(.template) | ||
| .resizable() | ||
| .aspectRatio(contentMode: .fit) | ||
| .frame(width: 200, height: 200) | ||
| .foregroundColor(logoColor) | ||
|
|
||
| // Slogan with typewriter effect (fixed position below logo) | ||
| if showSlogan { | ||
| TypewriterView(text: slogan, typingDelay: .milliseconds(35)) | ||
| .font(.system(size: 17, weight: .semibold, design: .default)) | ||
| .foregroundColor(logoColor.opacity(0.85)) | ||
| .offset(y: 74) | ||
| } | ||
| } | ||
| .onAppear { | ||
| // Show slogan after a short delay | ||
| DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { | ||
| showSlogan = true | ||
| } | ||
|
|
||
| // Hide splash after animation completes | ||
| DispatchQueue.main.asyncAfter(deadline: .now() + 1.2) { | ||
| withAnimation(.easeOut(duration: 0.3)) { | ||
| store.appState.globalState.launchFinished = true | ||
| } | ||
| } | ||
|
||
| } | ||
| } | ||
| } | ||
|
|
||
| #Preview { | ||
| SplashView() | ||
| .environmentObject(Store.shared) | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,82 @@ | ||||||
| // | ||||||
| // TypewriterView.swift | ||||||
| // V2er | ||||||
| // | ||||||
| // Created by Claude on 2024/12/1. | ||||||
| // | ||||||
|
|
||||||
| import SwiftUI | ||||||
|
|
||||||
| struct TypewriterView: View { | ||||||
| var text: String | ||||||
| var typingDelay: Duration = .milliseconds(50) | ||||||
| var easeIn: Bool = true | ||||||
|
|
||||||
| @State private var animatedText: AttributedString = "" | ||||||
| @State private var typingTask: Task<Void, Error>? | ||||||
|
||||||
| @State private var typingTask: Task<Void, Error>? | |
| @State private var typingTask: Task<Void, Never>? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using the existing
runInMain(delay:execute:)utility function instead ofDispatchQueue.main.asyncAfterfor consistency with the rest of the codebase. This pattern is used throughout the project (e.g., in Utils.swift, SearchPage.swift, Toast.swift).