-
Notifications
You must be signed in to change notification settings - Fork 0
Splash画面にアニメーションを入れました #868
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
WalkthroughRemoves the platform splash bitmap layers, disables fullscreen/system-bar-drawing in Android launch themes, adjusts iOS launch image size, adds a Motor-driven branding overlay and navigation timing to the Flutter splash screen, and updates pubspec splash configuration and dependencies. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20–25 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
lib/ui/screen/splash/splash_screen.dart (1)
36-47: Addmountedcheck after async gap to prevent crashes.After
await Future.delayed(...), the widget may have been disposed. CallingsetStateor navigating without checkingmountedcan cause exceptions like "setState() called after dispose()".Future<void> redirect(BuildContext context, WidgetRef ref) async { await Future<void>.delayed(const Duration(seconds: 2)); + if (!mounted) return; ref.read(currentUserProvider.notifier).update(); setState(() { showBranding = false; }); + if (!mounted) return; if (await ref.read(accountServiceProvider).isUserRegistered()) { + if (!mounted) return; context.pushReplacementNamed(RouterPath.tab); } else { + if (!mounted) return; context.pushReplacementNamed(RouterPath.newAccount); } }
🧹 Nitpick comments (2)
lib/ui/screen/splash/splash_screen.dart (2)
22-34: Callsuper.initState()before other initialization logic.The Dart/Flutter convention is to call
super.initState()at the beginning of the method, not at the end.@override void initState() { + super.initState(); redirect(context, ref); // 1フレーム後に 0→1 へ更新して文字を順次表示 WidgetsBinding.instance.addPostFrameCallback((_) { if (!mounted) { return; } setState(() { titleProgress = 1.0; }); }); - super.initState(); }
91-93: Consider extracting layout constants.The
leftPadding,iconWidth, andgapvalues are defined inside the builder callback and recreated on every animation frame. Moving them to class-level constants or outside the builder would be marginally cleaner.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (19)
android/app/src/main/res/drawable-hdpi/android12splash.pngis excluded by!**/*.pngandroid/app/src/main/res/drawable-hdpi/splash.pngis excluded by!**/*.pngandroid/app/src/main/res/drawable-mdpi/android12splash.pngis excluded by!**/*.pngandroid/app/src/main/res/drawable-mdpi/splash.pngis excluded by!**/*.pngandroid/app/src/main/res/drawable-night-hdpi/android12splash.pngis excluded by!**/*.pngandroid/app/src/main/res/drawable-night-mdpi/android12splash.pngis excluded by!**/*.pngandroid/app/src/main/res/drawable-night-xhdpi/android12splash.pngis excluded by!**/*.pngandroid/app/src/main/res/drawable-night-xxhdpi/android12splash.pngis excluded by!**/*.pngandroid/app/src/main/res/drawable-night-xxxhdpi/android12splash.pngis excluded by!**/*.pngandroid/app/src/main/res/drawable-xhdpi/android12splash.pngis excluded by!**/*.pngandroid/app/src/main/res/drawable-xhdpi/splash.pngis excluded by!**/*.pngandroid/app/src/main/res/drawable-xxhdpi/android12splash.pngis excluded by!**/*.pngandroid/app/src/main/res/drawable-xxhdpi/splash.pngis excluded by!**/*.pngandroid/app/src/main/res/drawable-xxxhdpi/android12splash.pngis excluded by!**/*.pngandroid/app/src/main/res/drawable-xxxhdpi/splash.pngis excluded by!**/*.pngios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.pngis excluded by!**/*.pngios/Runner/Assets.xcassets/LaunchImage.imageset/[email protected]is excluded by!**/*.pngios/Runner/Assets.xcassets/LaunchImage.imageset/[email protected]is excluded by!**/*.pngpubspec.lockis excluded by!**/*.lock
📒 Files selected for processing (10)
android/app/src/main/res/drawable-v21/launch_background.xml(0 hunks)android/app/src/main/res/drawable/launch_background.xml(0 hunks)android/app/src/main/res/values-night-v31/styles.xml(1 hunks)android/app/src/main/res/values-night/styles.xml(1 hunks)android/app/src/main/res/values-v31/styles.xml(1 hunks)android/app/src/main/res/values/styles.xml(1 hunks)ios/Runner/Base.lproj/LaunchScreen.storyboard(1 hunks)ios/Runner/Info.plist(1 hunks)lib/ui/screen/splash/splash_screen.dart(3 hunks)pubspec.yaml(2 hunks)
💤 Files with no reviewable changes (2)
- android/app/src/main/res/drawable-v21/launch_background.xml
- android/app/src/main/res/drawable/launch_background.xml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (9)
ios/Runner/Info.plist (1)
4-287: Formatting-only changes acknowledged.The diff shows re-indentation of the plist structure with no functional changes to keys or values.
ios/Runner/Base.lproj/LaunchScreen.storyboard (1)
41-41: LaunchImage dimension change acknowledged.The image size reduction from 1300×1300 to 168×185 aligns with the PR's approach of delegating the animated branding to the Flutter layer while keeping the native launch screen minimal.
pubspec.yaml (2)
95-100: Native splash configuration simplified correctly.The configuration properly sets up a white background for both platforms and includes the
android_12block required for Android 12+ splash screen API compatibility.
53-53: New dependency for animation is valid.The
motorpackage (version 1.1.0 published on pub.dev) provides theSingleMotionBuilderused for the text reveal animation in the splash screen. The version constraint is appropriate.lib/ui/screen/splash/splash_screen.dart (1)
82-120: Text reveal animation implementation looks well-crafted.The
SingleMotionBuilderapproach with gradual character reveal, scale, and letter-spacing transitions creates a polished effect. The animation parameters (1800ms duration, easeOutCubic curve) provide smooth visual feedback.android/app/src/main/res/values-night-v31/styles.xml (1)
6-7: Launch theme changes align with the new splash approach.Disabling fullscreen mode and system bar background drawing during launch is appropriate since the animated branding is now handled at the Flutter layer. The system bars will remain visible during the brief native splash phase.
android/app/src/main/res/values/styles.xml (1)
9-10: Consistent with v31 variant changes—fullscreen disabled in default light theme.The same fullscreen and system bar background changes applied to the default light theme. Consistency across all variants is maintained.
android/app/src/main/res/values-night/styles.xml (1)
9-10: Consistent with other variants—fullscreen disabled in dark theme.The changes are identical to the light and v31 variants, maintaining consistency across all theme configurations for the splash screen startup behavior.
android/app/src/main/res/values-v31/styles.xml (1)
6-7: Fullscreen and system bar changes consistently applied across all style variants.These changes disable fullscreen mode and prevent the app from drawing system bar backgrounds during splash, allowing system UI to remain visible. The settings are consistently applied across all four style variants (values, values-v31, values-night, and values-night-v31) and align with the animation-focused splash screen redesign.
The custom Flutter animation implementation in
splash_screen.dartproperly replaces the removedandroid:windowSplashScreenAnimatedIcon, using motor package and standard Flutter AnimatedBuilder with titleProgress animation to handle the splash screen animation sequence.
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.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
lib/ui/screen/splash/splash_screen.dart (1)
35-45: Guard asyncredirectwithmountedchecks to avoidsetState/ navigation after dispose.Because
redirectawaits a delay andisUserRegistered(), theSplashScreenStatemight be disposed before those futures complete (e.g., user backs out quickly). In that casesetStateorpushReplacementNamedcan throw.Add
mounted/context.mountedguards around the async boundaries:Future<void> redirect(BuildContext context, WidgetRef ref) async { - await Future<void>.delayed(const Duration(seconds: 2)); - ref.read(currentUserProvider.notifier).update(); - setState(() { - showBranding = false; - }); - if (await ref.read(accountServiceProvider).isUserRegistered()) { - context.pushReplacementNamed(RouterPath.tab); - } else { - context.pushReplacementNamed(RouterPath.newAccount); - } + await Future<void>.delayed(const Duration(seconds: 2)); + if (!mounted) { + return; + } + + ref.read(currentUserProvider.notifier).update(); + + setState(() { + showBranding = false; + }); + + final isRegistered = + await ref.read(accountServiceProvider).isUserRegistered(); + if (!mounted || !context.mounted) { + return; + } + + if (isRegistered) { + context.pushReplacementNamed(RouterPath.tab); + } else { + context.pushReplacementNamed(RouterPath.newAccount); + } }Optionally, if you want the fade‑out animation to complete before navigation, you could also
await Future<void>.delayed(const Duration(milliseconds: 300));after togglingshowBrandingand before checkingisUserRegistered()/ navigating.
🧹 Nitpick comments (2)
lib/ui/screen/splash/splash_screen.dart (2)
22-33: Callsuper.initState()first to follow Flutter/Riverpod conventions.
super.initState()should run before doing work like kicking off redirects or scheduling post‑frame callbacks. This avoids surprises if the superclass (orConsumerState) ever relies on its own initialization happening first.You can simplify
initStatelike this:@override void initState() { - redirect(context, ref); - WidgetsBinding.instance.addPostFrameCallback((_) { - if (!mounted) { - return; - } - setState(() { - titleProgress = 1.0; - }); - }); - super.initState(); + super.initState(); + + redirect(context, ref); + + WidgetsBinding.instance.addPostFrameCallback((_) { + if (!mounted) { + return; + } + setState(() { + titleProgress = 1.0; + }); + }); }
52-121: Branding overlay and Motor animation look good; consider de‑duplicating icon sizing.The layered
Stack+AnimatedOpacityandSingleMotionBuilderusage is coherent and should give a nice branding effect.One small nit: the icon is rendered at
width: 90, height: 90, but the text offset assumesiconWidth = 80. To avoid subtle misalignment if the icon size changes later, you could share a single constant:- child: - Assets.image.appIcon.image(width: 90, height: 90), + const double iconSize = 90; + child: Assets.image.appIcon.image( + width: iconSize, + height: iconSize, + ), ... - const double iconWidth = 80; + const double iconWidth = iconSize;(or hoist
iconSizeas astatic conston the state class if you prefer).Purely a maintainability/layout consistency tweak; the current code is functionally fine.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
lib/ui/screen/splash/splash_screen.dart(3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (2)
lib/ui/screen/splash/splash_screen.dart (2)
8-8: Motor import looks appropriate; just confirm dependency wiring.The extra
motorimport matches the new animation usage below and is fine. Please just double‑check thatpubspec.yamldeclares a compatiblemotorversion so this stays in sync with your dependency graph.
18-20: State flags for animation and branding are clear and reasonable.
titleProgressstarting at0andshowBrandingattruematch the intended “animate in, then fade branding out” flow. No changes needed here.
iseruuuuu
left a comment
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.
Issue
概要
追加したPackage
- motor
Screenshot
RPReplay_Final1765107868.mov
備考
Summary by CodeRabbit
New Features
Style
Chores
✏️ Tip: You can customize this high-level summary in your review settings.