Skip to content

Make PlayableActionSheet actions list scroll on small screens#178

Closed
phanan wants to merge 1 commit into
masterfrom
fix/playable-action-sheet-overflow
Closed

Make PlayableActionSheet actions list scroll on small screens#178
phanan wants to merge 1 commit into
masterfrom
fix/playable-action-sheet-overflow

Conversation

@phanan
Copy link
Copy Markdown
Member

@phanan phanan commented Apr 25, 2026

Summary

The previous PR (#176) added a Download/Remove Download item to the song action sheet. On smaller screens (iPhone SE / X) the new item pushes total content past the available height, and because the inner `ListView` had `NeverScrollableScrollPhysics()` and `shrinkWrap: true`, the parent `Column` overflowed instead of letting the list scroll.

This wraps the `ListView` in `Flexible` and drops the never-scrollable physics. When content fits, the sheet looks identical (spaceBetween still pins the action list to the bottom). When content overflows, the action list scrolls within its allotment instead of throwing a render error.

Test plan

  • New widget test mounts the sheet at iPhone SE size (320×568) and asserts no exception
  • Existing tests still pass (full suite green: 233/233)
  • Smoke test on a small device or simulator after merge to confirm scrolling feels right

Summary by CodeRabbit

  • Bug Fixes

    • Improved action sheet layout handling on smaller viewports to prevent overflow issues and better utilize available space.
  • Tests

    • Added test coverage for action sheet behavior on small screens (320x568 resolution).

Wrap the inner ListView in Flexible and drop NeverScrollableScrollPhysics
so the action list scrolls within the available height when content
exceeds it, instead of overflowing the Column. The sheet's spaceBetween
visual is preserved when content fits.

Adds a regression test that mounts the sheet at iPhone SE size (320x568)
and asserts no exception is raised.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 25, 2026

📝 Walkthrough

Walkthrough

The PlayableActionSheet widget's action list layout is refactored from a directly-sized ListView to a Flexible-wrapped ListView to improve layout behavior on constrained viewports. Tests are enhanced with configurable surface sizing and a new small-viewport verification case.

Changes

Cohort / File(s) Summary
PlayableActionSheet layout adjustment
lib/ui/screens/playable_action_sheet.dart
Wraps the action buttons ListView in a Flexible widget to allow responsive sizing within the parent Column, replacing the previous direct ListView approach.
Test infrastructure and coverage
test/ui/screens/playable_action_sheet_test.dart
Adds optional surfaceSize parameter to _mountSheet helper method and introduces a new test case verifying overflow-free layout behavior on a small viewport (320x568).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

Poem

🐰 A ListView once rigid and tight,
Now wrapped in Flexible—quite the delight!
On small screens it bends, never breaks,
Layout that flexes, no action forsakes. ✨

🚥 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 and concisely describes the main change: wrapping the actions list in Flexible to enable scrolling on small screens, which directly addresses the overflow problem identified in the PR objectives.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/playable-action-sheet-overflow

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
test/ui/screens/playable_action_sheet_test.dart (1)

116-127: Optional: strengthen the small-screen assertion.

tester.takeException() only catches errors that have already been reported (e.g. RenderFlex overflowed) at pump time. It will pass even if a regression silently clips actions off-screen without throwing. Consider also asserting that an action item near the end of the list is present (and optionally reachable via scroll) so the test fails on hidden/clipped content as well.

♻️ Suggested stronger assertion
       await _mountSheet(
         tester,
         downloaded: true,
         surfaceSize: const Size(320, 568),
       );

       expect(tester.takeException(), isNull);
+      // The last action should still be present (and scrollable into view) on small screens.
+      final addToPlaylist = find.text('Add to a Playlist…');
+      expect(addToPlaylist, findsOneWidget);
+      await tester.ensureVisible(addToPlaylist);
     },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/ui/screens/playable_action_sheet_test.dart` around lines 116 - 127, The
test currently only calls tester.takeException() which misses silent clipping;
update the 'lays out without overflow on small screens (iPhone SE)' test (the
testWidgets block that calls _mountSheet) to also assert that a known action
item near the end of the list is present and visible: use a stable identifier
from the sheet (e.g., the final action's text or Key used by the action widget)
with expect(find.text('<LAST_ACTION_LABEL>') or
find.byKey(ValueKey('<LAST_ACTION_KEY>')), findsOneWidget) and if it might be
offscreen use tester.scrollUntilVisible or tester.ensureVisible on that finder
before asserting to fail the test if the item is clipped or unreachable.
lib/ui/screens/playable_action_sheet.dart (1)

94-273: LGTM — Flexible-wrapped scrolling ListView resolves the overflow correctly.

With the modal opened via isScrollControlled: true, the outer Column receives a bounded max height, so Flexible (loose fit) + shrinkWrap: true does the right thing in both cases:

  • Content fits: ListView shrink-wraps to its intrinsic height, and MainAxisAlignment.spaceBetween still pins the actions to the bottom (behavior preserved).
  • Content overflows (small screens): ListView is capped at the remaining height and scrolls with default physics.

Nit/optional: on small screens there's no affordance hinting that the actions are scrollable. Wrapping the ListView in a Scrollbar (and giving the ListView a ScrollController) would make overflow discoverable to users on iPhone SE-class viewports.

♻️ Optional: add a Scrollbar for discoverability
-            Flexible(
-              child: ListView(
-                shrinkWrap: true,
-                children: <Widget>[
+            Flexible(
+              child: Scrollbar(
+                child: ListView(
+                  shrinkWrap: true,
+                  children: <Widget>[
                   ...
-              ],
-              ),
-            ),
+                  ],
+                ),
+              ),
+            ),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/ui/screens/playable_action_sheet.dart` around lines 94 - 273, The
ListView inside Flexible correctly fixes the overflow; to add the optional
affordance, create a ScrollController (e.g., _actionsScrollController) and wrap
the ListView in a Scrollbar that uses that controller; update the ListView to
pass controller: _actionsScrollController (keeping shrinkWrap: true) and dispose
the controller in the widget's State disposal; reference PlayableActionButton,
Flexible, ListView, and shrinkWrap to locate where to wrap and wire the
controller.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@lib/ui/screens/playable_action_sheet.dart`:
- Around line 94-273: The ListView inside Flexible correctly fixes the overflow;
to add the optional affordance, create a ScrollController (e.g.,
_actionsScrollController) and wrap the ListView in a Scrollbar that uses that
controller; update the ListView to pass controller: _actionsScrollController
(keeping shrinkWrap: true) and dispose the controller in the widget's State
disposal; reference PlayableActionButton, Flexible, ListView, and shrinkWrap to
locate where to wrap and wire the controller.

In `@test/ui/screens/playable_action_sheet_test.dart`:
- Around line 116-127: The test currently only calls tester.takeException()
which misses silent clipping; update the 'lays out without overflow on small
screens (iPhone SE)' test (the testWidgets block that calls _mountSheet) to also
assert that a known action item near the end of the list is present and visible:
use a stable identifier from the sheet (e.g., the final action's text or Key
used by the action widget) with expect(find.text('<LAST_ACTION_LABEL>') or
find.byKey(ValueKey('<LAST_ACTION_KEY>')), findsOneWidget) and if it might be
offscreen use tester.scrollUntilVisible or tester.ensureVisible on that finder
before asserting to fail the test if the item is clipped or unreachable.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 20058c1e-c73a-406d-9db9-6738e69c6ca9

📥 Commits

Reviewing files that changed from the base of the PR and between 2c9aa84 and 22e5013.

📒 Files selected for processing (2)
  • lib/ui/screens/playable_action_sheet.dart
  • test/ui/screens/playable_action_sheet_test.dart

@phanan
Copy link
Copy Markdown
Member Author

phanan commented Apr 25, 2026

Closing — the Flexible+scrollable wrap fixes the overflow but breaks drag-to-dismiss on the action list (the inner scrollable captures vertical drags even when content fits). PR #177's test surface bump remains the workaround for CI; the production sheet stays as it was. A proper fix would require DraggableScrollableSheet, which is a larger refactor of how the modal is shown.

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