Skip to content

feat #142: create button builder callback to replace the submit button#174

Merged
koukibadr merged 2 commits into
mainfrom
feat#142-create-button-builder
Jul 5, 2026
Merged

feat #142: create button builder callback to replace the submit button#174
koukibadr merged 2 commits into
mainfrom
feat#142-create-button-builder

Conversation

@koukibadr

@koukibadr koukibadr commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added a buttonBuilder option to fully customize the submit button in bottom pickers.
    • Range time pickers can now close automatically when submitting.
  • Changes

    • Deprecated the legacy submit-button configuration options in favor of buttonBuilder.
    • Updated sample picker setup to use the new custom submit button behavior.
    • Improved modal dismissal handling with a dedicated dismiss() method and safer lifecycle tracking.
  • Tests

    • Added widget tests covering default vs custom submit button rendering.

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds buttonBuilder to BottomPicker, introduces dismiss() and widget-level disposal tracking, deprecates legacy submit-button APIs and BottomPickerButton, and updates the example plus widget coverage.

Changes

buttonBuilder feature

Layer / File(s) Summary
Deprecation annotations and buttonBuilder wiring across constructors
lib/bottom_picker.dart
Updates constructors and related fields to accept buttonBuilder and marks legacy submit-button parameters and onSubmit/closeOnSubmit paths deprecated.
buttonBuilder property, dismiss and lifecycle state
lib/bottom_picker.dart
Adds buttonBuilder rendering, stores the show context, adds dismiss(), marks the widget disposed during teardown, and updates keyboard dismissal guards.
Deprecate BottomPickerButton
lib/widgets/bottom_picker_button.dart
Marks BottomPickerButton with @Deprecated, directing users to BottomPicker.
Example usage update and widget tests
example/lib/main.dart, test/button_builder_test.dart, analysis_options.yaml
Updates the example to use buttonBuilder and closeOnSubmit, adds widget tests for buttonBuilder and displaySubmitButton combinations, and excludes generated/example files from analysis.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant BottomPicker
  participant BottomPickerState
  participant Navigator

  User->>BottomPicker: buttonBuilder(instance, context)
  BottomPicker->>BottomPicker: dismiss()
  BottomPicker->>Navigator: pop() if mounted and canPop
  BottomPickerState->>BottomPicker: dispose() sets disposed = true
Loading

Possibly related PRs

  • koukibadr/Bottom-Picker#172 — touches the same BottomPicker submit-button API surface and deprecated constructor attributes.
  • The current PR — adds buttonBuilder, dismiss(), and updated example/tests around the same widget flow.

Poem

A rabbit tapped a shiny new way,
With buttonBuilder hopping in play.
Old buttons snoozed, deprecated and neat,
While dismiss() made the landing complete.
Tests gave a cheerful little cheer —
🐇 the picker’s new path is clear.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding a button builder callback to replace the existing submit button.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/bottom_picker.dart`:
- Around line 798-799: Consolidate the picker lifecycle into a single disposed
flag because BottomPicker and BottomPickerState currently maintain separate
disposed states that can drift apart. Update the dismissal and disposal flow in
BottomPickerState, including dismiss(), dispose(), and _onKeyPressed, to read
and write one source of truth instead of mixing widget.disposed and the State’s
own disposed field. Remove the redundant flag or delegate all checks to the same
field so escape-key dismissal, manual dismissals, and State.dispose() all
observe the same lifecycle state.
- Around line 827-834: The dismiss() method in BottomPicker is using a stored
_context without verifying it is still mounted before calling
Navigator.of(_context!).canPop(), which can crash if the context is stale.
Update dismiss() to first guard against _context being null and unmounted by
checking _context!.mounted before any Navigator lookup, then keep the existing
canPop() and disposed checks in place. Use the dismiss() method and the _context
field in BottomPicker to locate the fix.
- Around line 366-373: Update BottomPicker.range() so the submit validation no
longer always requires onRangeDateSubmitPressed when buttonBuilder is supplied;
adjust the assert in the BottomPicker constructor/initializer path to allow a
custom button to replace the default submit button, matching the existing
buttonBuilder callback flow. Use the BottomPicker.range() setup and the
assert(buttonBuilder != null || onRangeDateSubmitPressed != null) behavior as
the reference point, and keep the deprecated onRangeDateSubmitPressed
requirement only when no custom button is provided.
- Around line 798-804: The `_context` field in `BottomPicker` should not be a
late stored caller `BuildContext`, because `dismiss()` may access it before
`show()` initializes it and a retained external context can become invalid.
Update the `show()`/`dismiss()` flow to avoid holding `_context` directly in
`BottomPicker`; instead keep a navigator/route reference or add
mounted/unmounted guards around the `Navigator.of(...)` usage so dismissal does
not depend on a stale context.

In `@test/button_builder_test.dart`:
- Around line 1-117: Add coverage for the new BottomPicker lifecycle behavior in
the button builder test suite by creating tests around the
BottomPicker.dismiss() and disposed flow. Verify that calling dismiss() on an
active BottomPicker pops the route, and that calling it again after the picker
has already been dismissed does nothing/error-free. Use the existing
BottomPicker test setup as the entry point and reference the
BottomPicker.dismiss method and disposed state to locate the new assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 445c476e-ddb5-45da-8413-d73873a8eada

📥 Commits

Reviewing files that changed from the base of the PR and between 3ebcd67 and bfe5d6e.

📒 Files selected for processing (4)
  • example/lib/main.dart
  • lib/bottom_picker.dart
  • lib/widgets/bottom_picker_button.dart
  • test/button_builder_test.dart

Comment thread lib/bottom_picker.dart
Comment thread lib/bottom_picker.dart Outdated
Comment thread lib/bottom_picker.dart Outdated
Comment thread lib/bottom_picker.dart
Comment thread test/button_builder_test.dart

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
lib/bottom_picker.dart (2)

738-744: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

buttonBuilder loses generic type info for consumers.

The field is typed Widget Function(BottomPicker instance, BuildContext context)?; bare BottomPicker resolves to BottomPicker<dynamic>, so callback consumers get an untyped instance instead of BottomPicker<T>.

♻️ Proposed fix
-  final Widget Function(BottomPicker instance, BuildContext context)?
+  final Widget Function(BottomPicker<T> instance, BuildContext context)?
       buttonBuilder;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/bottom_picker.dart` around lines 738 - 744, The buttonBuilder callback is
losing the picker’s generic type because its first parameter is declared as a
bare BottomPicker, which erases T for consumers. Update the buttonBuilder field
type so the instance parameter preserves the generic form used throughout
BottomPicker<T>, and ensure any related callback signatures or uses of
buttonBuilder reference the generic BottomPicker<T> consistently.

426-483: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Same assert issue in BottomPicker.rangeTime().

assert(onRangeTimeSubmitPressed != null); at line 475 has the identical problem flagged for BottomPicker.range(): it forces the deprecated onRangeTimeSubmitPressed callback to be non-null even when buttonBuilder is provided to fully replace the submit button.

🐛 Proposed fix
-    assert(onRangeTimeSubmitPressed != null);
+    assert(buttonBuilder != null || onRangeTimeSubmitPressed != null);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/bottom_picker.dart` around lines 426 - 483, The same deprecated-callback
assertion issue exists in BottomPicker.rangeTime(): the constructor currently
requires onRangeTimeSubmitPressed even when buttonBuilder is used to fully
handle submit actions. Update BottomPicker.rangeTime so the validation only
enforces the deprecated callback when buttonBuilder is not provided, matching
the behavior of the submit button replacement path and keeping the range-time
API consistent with BottomPicker.range.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@lib/bottom_picker.dart`:
- Around line 738-744: The buttonBuilder callback is losing the picker’s generic
type because its first parameter is declared as a bare BottomPicker, which
erases T for consumers. Update the buttonBuilder field type so the instance
parameter preserves the generic form used throughout BottomPicker<T>, and ensure
any related callback signatures or uses of buttonBuilder reference the generic
BottomPicker<T> consistently.
- Around line 426-483: The same deprecated-callback assertion issue exists in
BottomPicker.rangeTime(): the constructor currently requires
onRangeTimeSubmitPressed even when buttonBuilder is used to fully handle submit
actions. Update BottomPicker.rangeTime so the validation only enforces the
deprecated callback when buttonBuilder is not provided, matching the behavior of
the submit button replacement path and keeping the range-time API consistent
with BottomPicker.range.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1c619cb9-179c-409a-a17b-5de9428c3d98

📥 Commits

Reviewing files that changed from the base of the PR and between bfe5d6e and e457e80.

📒 Files selected for processing (2)
  • analysis_options.yaml
  • lib/bottom_picker.dart

@koukibadr koukibadr merged commit 043a1f2 into main Jul 5, 2026
5 checks passed
@koukibadr koukibadr deleted the feat#142-create-button-builder branch July 5, 2026 05:12
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.

1 participant