-
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
Conversation
Add LaunchScreen.storyboard with: - Centered V2er logo (100x100) - SplashBackground color (white/dark gray for light/dark mode) - SplashLogoColor for logo tint (matches Android implementation) Colors match Android app: - Light mode: white background (#FFFFFF), dark logo (#111214) - Dark mode: dark background (#111214), white logo (#FFFFFF) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
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.
Pull request overview
This PR adds a native iOS splash screen (launch screen) to the V2er app with a centered logo that adapts to light and dark mode appearances. The implementation uses a LaunchScreen.storyboard with proper Auto Layout constraints and named color assets for theme support.
Key changes:
- New LaunchScreen.storyboard with centered 100x100pt logo using Auto Layout
- Two named color sets (SplashBackground and SplashLogoColor) with light/dark mode variants
- SplashLogo image asset configured as a template for tinting
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| V2er/LaunchScreen.storyboard | New launch screen storyboard with centered imageView using Auto Layout constraints and named color references |
| V2er/Assets.xcassets/SplashLogo.imageset/Contents.json | Image asset configuration with template rendering and vector preservation properties |
| V2er/Assets.xcassets/SplashLogo.imageset/splash_logo.png | 1024x1024px PNG logo image (binary file) |
| V2er/Assets.xcassets/Colors/SplashLogoColor.colorset/Contents.json | Logo tint color: dark gray (light mode) / white (dark mode) |
| V2er/Assets.xcassets/Colors/SplashBackground.colorset/Contents.json | Background color: white (light mode) / dark gray (dark mode) |
| V2er.xcodeproj/project.pbxproj | Xcode project file updates to include LaunchScreen.storyboard in resources |
V2er/LaunchScreen.storyboard
Outdated
| <namedColor name="SplashBackground"> | ||
| <color red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> | ||
| </namedColor> | ||
| <namedColor name="SplashLogoColor"> | ||
| <color red="0.066999999999999993" green="0.070999999999999994" blue="0.078" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> | ||
| </namedColor> |
Copilot
AI
Dec 1, 2025
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.
The storyboard includes hardcoded RGB color values in the resources section (lines 44-49) that duplicate the color definitions from the named color sets. This creates a discrepancy where:
- The view references named colors
SplashBackgroundandSplashLogoColor(lines 22, 30) which support light/dark mode - But the
<resources>section defines fallback RGB values that only represent the light mode colors
This inconsistency could cause issues if the named color assets are not found. Consider removing the hardcoded RGB values from the resources section and relying solely on the named colors, or ensure the fallback values accurately represent both appearance modes.
| <namedColor name="SplashBackground"> | |
| <color red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> | |
| </namedColor> | |
| <namedColor name="SplashLogoColor"> | |
| <color red="0.066999999999999993" green="0.070999999999999994" blue="0.078" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> | |
| </namedColor> |
V2er/LaunchScreen.storyboard
Outdated
| </scene> | ||
| </scenes> | ||
| <resources> | ||
| <image name="SplashLogo" width="1024" height="1024"/> |
Copilot
AI
Dec 1, 2025
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.
The storyboard hardcodes the image dimensions as 1024x1024 in the resources section (line 43), but the imageView is constrained to 100x100 points (lines 24-25). While Auto Layout will handle the scaling at runtime using the scaleAspectFit content mode (line 20), the hardcoded dimensions in the resources section are merely informational for Interface Builder.
This is acceptable, but be aware that providing a 1024x1024 PNG for display at 100x100 points means:
- On 1x devices: The image is scaled down 10.24x
- On 2x devices: The image is scaled down 5.12x
- On 3x devices: The image is scaled down 3.41x
This is inefficient in terms of bundle size. Consider using appropriately sized assets or a vector PDF to optimize the app bundle.
| <image name="SplashLogo" width="1024" height="1024"/> | |
| <image name="SplashLogo" width="100" height="100"/> |
| "filename" : "splash_logo.png", | ||
| "idiom" : "universal", | ||
| "scale" : "1x" | ||
| }, | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "2x" | ||
| }, | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "3x" |
Copilot
AI
Dec 1, 2025
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.
The image asset is configured to use only a 1x image (splash_logo.png at 1024x1024) without providing 2x and 3x variants. While the preserves-vector-representation property is set to true (suggesting vector/PDF support), the actual asset is a PNG file, not a vector format.
For optimal display quality on all iOS devices, consider either:
- Providing @2x and @3x PNG variants (2048x2048 and 3072x3072), or
- Using a PDF vector format with
preserves-vector-representation: trueto automatically scale to all resolutions
Since the logo is used as a template (for tinting), a PDF vector would be the preferred approach for best quality and smaller bundle size.
| "filename" : "splash_logo.png", | |
| "idiom" : "universal", | |
| "scale" : "1x" | |
| }, | |
| { | |
| "idiom" : "universal", | |
| "scale" : "2x" | |
| }, | |
| { | |
| "idiom" : "universal", | |
| "scale" : "3x" | |
| "filename" : "splash_logo.pdf", | |
| "idiom" : "universal" |
V2er/LaunchScreen.storyboard
Outdated
| @@ -0,0 +1,51 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> | |||
| <device id="retina6_12" orientation="portrait" appearance="light"/> | |||
Copilot
AI
Dec 1, 2025
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.
[nitpick] The storyboard references a hardcoded device size (retina6_12 with 393x852 dimensions) which represents iPhone 14 Pro. While Auto Layout constraints are used (which is good), the hardcoded device reference in line 3 is just for Interface Builder preview purposes and won't affect runtime behavior on different devices.
However, it would be better practice to test on multiple device sizes to ensure the constraints work as expected across all supported iOS devices.
| <device id="retina6_12" orientation="portrait" appearance="light"/> |
Code Coverage Report ❌Current coverage: 29.73% |
- Remove hardcoded RGB color values from storyboard resources section - Use named color references only (SplashBackground, SplashLogoColor) - Update image resource dimensions to match display size (100x100) - Simplify image asset configuration (single universal image) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Code Coverage Report ❌Current coverage: 24.53% |
- Replace LaunchScreen.storyboard with SwiftUI SplashView - Add vector PDF logo from Android project for better scaling - Support light/dark mode with adaptive colors - Add TypewriterView with ease-out animation for slogan - Slogan: "Way to explore" with monospaced font - Logo size: 200x200, centered with slogan below 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
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.
Pull request overview
Copilot reviewed 7 out of 8 changed files in this pull request and generated 3 comments.
| var easeIn: Bool = true | ||
|
|
||
| @State private var animatedText: AttributedString = "" | ||
| @State private var typingTask: Task<Void, Error>? |
Copilot
AI
Dec 1, 2025
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.
The task is typed as Task<Void, Error>? but never throws errors. Consider using Task<Void, Never>? to accurately reflect that this task doesn't throw, or add proper error handling for the async operations.
| @State private var typingTask: Task<Void, Error>? | |
| @State private var typingTask: Task<Void, Never>? |
V2er/View/Splash/SplashView.swift
Outdated
| 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 | ||
| } | ||
| } |
Copilot
AI
Dec 1, 2025
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 of DispatchQueue.main.asyncAfter for consistency with the rest of the codebase. This pattern is used throughout the project (e.g., in Utils.swift, SearchPage.swift, Toast.swift).
V2er/View/Splash/SplashView.swift
Outdated
| DispatchQueue.main.asyncAfter(deadline: .now() + 1.2) { | ||
| withAnimation(.easeOut(duration: 0.3)) { | ||
| store.appState.globalState.launchFinished = true | ||
| } | ||
| } |
Copilot
AI
Dec 1, 2025
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.
Direct mutation of global state violates the Redux-like architecture pattern described in the project guidelines. State updates should be dispatched through actions and processed by reducers. Consider creating a GlobalActions.LaunchFinished action and dispatching it via the store instead.
Code Coverage Report ❌Current coverage: 31.45% |
- Use runInMain utility instead of DispatchQueue.main.asyncAfter - Use LaunchFinishedAction and Redux pattern instead of direct state mutation - Change TypewriterView Task type from Task<Void, Error>? to Task<Void, Never>? since the task doesn't throw errors 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Code Coverage Report ❌Current coverage: 30.3% |
Summary
Test plan
🤖 Generated with Claude Code