Skip to content

Dev#17

Merged
pckimlong merged 8 commits into
mainfrom
dev
Dec 7, 2025
Merged

Dev#17
pckimlong merged 8 commits into
mainfrom
dev

Conversation

@pckimlong
Copy link
Copy Markdown
Owner

No description provided.

…cessary rebuilds

Replace Set/Map-based state tracking with fixed-size lists for O(1) access. Add counters to cache loading state instead of iterating collections. Minimize setState calls by checking if state actually changed before updating. Cache SplashTaskError string representation. Add early returns in providers when no tasks exist. Use eagerError in Future.wait for faster failure detection. Make oneTimeTasks and reactiveTasks
perf(splash): optimize reactive task state management and reduce unnecessary rebuilds
Copilot AI review requested due to automatic review settings December 6, 2025 07:00
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @pckimlong, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request focuses on optimizing the performance and enhancing the reliability of the splash screen system. It introduces a more efficient state management approach within the "SplashBuilder" and refines the task execution and error reporting mechanisms. A comprehensive suite of new tests has been added to validate these improvements and ensure the system's robustness, alongside routine dependency updates.

Highlights

  • Performance Optimization: Refactored internal state management in "SplashBuilder" from "Set"/"Map" to "List" with explicit counters, significantly improving performance for tracking splash task loading states by enabling O(1) access.
  • Enhanced Task Execution & Error Handling: Improved the logic for one-time and reactive splash tasks, including conditional "Stopwatch" usage, "Future.wait" with "eagerError: true", and a more robust "SplashTaskError.toString()" method with caching and limited stack trace output.
  • Expanded Test Coverage: Added extensive unit and widget tests across various components ("SplashConfig", "SplashTaskError", "oneTimeSplashTasksProvider", "reactiveSplashTasksProvider", "SplashBuilder", "task() helper") to ensure the reliability and correctness of the splash screen system.
  • Dependency Updates & Version Bump: Updated "flutter_riverpod" and "riverpod" dependencies in the example project to "3.0.3" and incremented the package version to "0.0.2".
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces significant performance optimizations and greatly expands the test suite, which is fantastic. The move from Maps/Sets to Lists with counters for state tracking in SplashBuilder is a smart way to reduce overhead and prevent unnecessary rebuilds. The optimizations in _oneTimeSplashTasksProvider and SplashTaskError are also valuable. The new tests are comprehensive and cover many edge cases, which significantly improves the robustness of the library. I have one minor suggestion regarding a comment in lib/src/splash_task.dart to ensure it aligns perfectly with the code's implementation. Overall, this is an excellent contribution.

Comment thread lib/src/splash_task.dart Outdated
Comment on lines +22 to +26
// Use more efficient Future.wait with growable: false
await Future.wait(
[for (final task in tasks) task(ref)],
eagerError: true,
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Great job on the performance optimizations in this file!

I noticed a small discrepancy between the comment and the code here. The comment mentions using a list with growable: false for efficiency, but the list comprehension [for ...] actually creates a growable list.

To align the code with the comment's intent and potentially gain a minor performance improvement, you could use .map with toList(growable: false).

Suggested change
// Use more efficient Future.wait with growable: false
await Future.wait(
[for (final task in tasks) task(ref)],
eagerError: true,
);
// Use more efficient Future.wait with a fixed-length list
await Future.wait(
tasks.map((task) => task(ref)).toList(growable: false),
eagerError: true,
);

Copy link
Copy Markdown
Contributor

Copilot AI left a 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 prepares version 0.0.2 of the Riverboot package, primarily focusing on internal improvements, test coverage expansion, and performance optimizations. The changes include comprehensive test suite expansion, state management optimizations in SplashBuilder, and performance improvements in task execution logic.

Key changes:

  • Expanded test suite from 2 to 30+ tests covering all major functionality
  • Performance optimizations using Lists instead of Sets/Maps and counter-based tracking
  • Added immutability guarantees for SplashConfig task lists with string caching for error messages

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
test/splash_task_test.dart Comprehensive test suite expansion covering SplashConfig, SplashTaskError, providers, and SplashBuilder widget
lib/src/splash_task.dart Performance optimizations (early returns, conditional stopwatch), string caching for SplashTaskError, and code formatting
lib/src/splash_builder.dart Replaced Set/Map-based tracking with List-based tracking and counters for O(1) access and reduced setState calls
example/lib/main.dart Code formatting changes (line consolidation)
example/pubspec.lock Updated flutter_riverpod from 3.0.0 to 3.0.3 and version reference to 0.0.2
pubspec.yaml Version bump from 0.0.1 to 0.0.2
CHANGELOG.md Added version 0.0.2 entry with brief description

final future = container.read(oneTimeSplashTasksProvider.future);

// Allow tasks to start
await Future.delayed(const Duration(milliseconds: 10));
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] This test relies on a 10ms delay to ensure both tasks have started, which could be flaky on slow CI systems or under heavy load. Consider using a more deterministic synchronization mechanism, such as having each task signal when it has started (e.g., via additional Completers), rather than relying on timing.

Copilot uses AI. Check for mistakes.
Comment thread lib/src/splash_builder.dart Outdated
Comment thread lib/src/splash_task.dart Outdated
if (tasks.isNotEmpty) {
if (config.runOneTimeTaskInParallel) {
await Future.wait([for (final task in tasks) task(ref)]);
// Use more efficient Future.wait with growable: false
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment states "Use more efficient Future.wait with growable: false" but growable is not a parameter of Future.wait. Only eagerError is specified. This comment is misleading and should be updated to accurately reflect the optimization being made (e.g., "Use eagerError: true to fail fast on the first error")

Suggested change
// Use more efficient Future.wait with growable: false
// Use Future.wait with eagerError: true to fail fast on the first error

Copilot uses AI. Check for mistakes.
Comment thread lib/src/splash_task.dart
Comment thread CHANGELOG.md Outdated
pckimlong and others added 5 commits December 6, 2025 14:46
Add retry parameter with exponential backoff strategy using retryCount-based Duration in seconds. This demonstrates the retry delay configuration feature in the example app.
…r` and `run`, add new tests, and update documentation.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings December 7, 2025 04:09
@pckimlong pckimlong merged commit c8d3887 into main Dec 7, 2025
5 of 6 checks passed
Copy link
Copy Markdown
Contributor

Copilot AI left a 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 11 out of 12 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.md
|---|---------|-----------------|
| **When** | Once at app start | When trigger changes |
| **Use for** | Init services, load config | User session data |
| **Shows splash** | Only on first run or manual retry | Every time trigger changes |
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing article: "Only on first run or manual retry" should be "Only on first run or on manual retry" for consistent parallelism in the phrase structure.

Suggested change
| **Shows splash** | Only on first run or manual retry | Every time trigger changes |
| **Shows splash** | Only on first run or on manual retry | Every time trigger changes |

Copilot uses AI. Check for mistakes.
Comment thread README.md
|---|---------|-----------------|
| **When** | Once at app start | When trigger changes |
| **Use for** | Init services, load config | User session data |
| **Shows splash** | Only on first run or manual retry | Every time trigger changes |
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing article: "Every time trigger changes" should be "Every time the trigger changes" for proper grammar.

Suggested change
| **Shows splash** | Only on first run or manual retry | Every time trigger changes |
| **Shows splash** | Only on first run or manual retry | Every time the trigger changes |

Copilot uses AI. Check for mistakes.
Comment thread lib/src/splash_task.dart
Comment on lines +196 to +197
/// The [run] function only receives [read] - no [watch] - to prevent
/// accidentally creating unwanted reactive dependencies.
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation states "The [run] function only receives [read] - no [watch]", but this is incorrect. The function signature shows Future<void> Function(Ref ref) run, which provides full Ref access including both ref.read() and ref.watch(). This is also confirmed by the tests and example code which use ref.watch() inside run.

Suggested change
/// The [run] function only receives [read] - no [watch] - to prevent
/// accidentally creating unwanted reactive dependencies.
/// The [run] function receives a full [Ref] object, allowing both [read] and [watch].
/// You may use [ref.read] or [ref.watch] as needed within [run].

Copilot uses AI. Check for mistakes.
Comment thread test/bootstrap_test.dart
tasks: [
for (var i = 0; i < 10; i++)
(ref) async {
await Future.delayed(Duration(milliseconds: (i + 1) * 5)); // Variable delays
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment states "Variable delays" but the actual implementation uses (i + 1) * 5 milliseconds, which creates delays of 5ms, 10ms, 15ms... 50ms. This pattern is actually consistent/predictable rather than variable. Consider either changing the comment to "Incremental delays" or using truly variable delays like Random().nextInt(50) + 1.

Copilot uses AI. Check for mistakes.
Comment thread pubspec.yaml
name: riverboot
description: "App bootstrap & splash task system for Flutter with Riverpod"
version: 0.0.1
version: 0.1.0
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Version inconsistency: pubspec.yaml shows version 0.1.0, but the CHANGELOG.md documents version 0.0.2, and example/pubspec.lock shows riverboot version 0.0.2. These versions should be consistent across the codebase.

Suggested change
version: 0.1.0
version: 0.0.2

Copilot uses AI. Check for mistakes.
// Ignoring=true allows taps to pass through to the app (if that's what you want)
// Ignoring=false blocks taps (if you want to freeze input during fade)
// Usually, during fade out, we want to BLOCK input until fully revealed:
ignoring: false, // Splash catches taps until it is removed
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment states "Ignoring=true allows taps to pass through to the app" and then "Ignoring=false blocks taps", but the code sets ignoring: false with the comment "Splash catches taps until it is removed". This is contradictory - if ignoring: false, then the widget is NOT ignoring pointer events, meaning it blocks/catches taps (which is the desired behavior). The inline comment should clarify this more clearly, e.g., "ignoring: false means IgnorePointer does NOT ignore - it blocks input on the splash".

Suggested change
ignoring: false, // Splash catches taps until it is removed
ignoring: false, // IgnorePointer does NOT ignore taps: it blocks input on the splash until it is removed

Copilot uses AI. Check for mistakes.
Comment thread README.md
),
```

**Key behavior:** Only `trigger` changes show splash. Using `ref.watch()` in `run` keeps providers alive and re-runs silently without splash.
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation states "Using ref.watch() in run keeps providers alive and re-runs silently without splash." This is misleading. According to the implementation in splash_builder.dart (lines 30-31), reactive task changes show splash when isRefreshing is true, but isReloading (when run's own dependencies change) does not show splash. This distinction should be clarified to accurately reflect the behavior.

Suggested change
**Key behavior:** Only `trigger` changes show splash. Using `ref.watch()` in `run` keeps providers alive and re-runs silently without splash.
**Key behavior:** Only changes to `trigger` show splash (when `isRefreshing` is true). Dependencies watched via `ref.watch()` inside `run` will re-run the task silently (when `isReloading` is true) without showing splash. This distinction ensures that splash only appears for trigger changes, not for internal dependency updates.

Copilot uses AI. Check for mistakes.
Comment thread README.md

| | `tasks` | `reactiveTask` |
|---|---------|-----------------|
| **When** | Once at app start | When trigger changes |
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing article: "When trigger changes" should be "When the trigger changes" for proper grammar.

Suggested change
| **When** | Once at app start | When trigger changes |
| **When** | Once at app start | When the trigger changes |

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants