Skip to content

inspect/tap skip FilledButton and CheckboxListTile; callback fallback no-ops when hittable is false #68

Open

Description

@JohnGalt1717

Summary

inspect does not list Material 3 FilledButton or CheckboxListTile as interactive widgets. tap by ValueKey finds those widgets, but when hittable is false (debug overlay / modal scrim covering the app) _tryInvokeCallback no-ops for both types, so the CLI reports Tapped and the UI does not change.

set_checkbox already understands CheckboxListTile (_getCheckboxState), then calls _performTapWithDetails, which hits the same no-op.

Published 0.9.37 (c31a08ead80e) is GitHub main. Re-activating dart pub global activate flutter_skill and flutter pub upgrade flutter_skill cannot pick up a newer release.

Environment

  • flutter_skill 0.9.37 (app FlutterSkillBinding + dart pub global activate flutter_skill)
  • Flutter 3.47.x / Dart 3.13.x
  • Android emulator (Pixel 10 Pro XL, 1344×2992) with ISpect overlay (--dart-define=ISPECT_ENABLED=true)
  • Modal showModalBottomSheet containing CheckboxListTile + FilledButton with ValueKeys

Repro

showModalBottomSheet<void>(
  context: context,
  builder: (context) => Column(
    mainAxisSize: MainAxisSize.min,
    children: [
      CheckboxListTile(
        key: const ValueKey('appointment-consent-treatment'),
        value: false,
        onChanged: (_) {},
        title: const Text('Treatment'),
      ),
      FilledButton(
        key: const ValueKey('appointment-consent-grant'),
        onPressed: () {},
        child: const Text('Grant'),
      ),
    ],
  ),
);
dart run flutter_skill inspect --output=json "ws://127.0.0.1:<vm>/ws"
dart run flutter_skill act "ws://…" find_element appointment-consent-grant
dart run flutter_skill act "ws://…" tap appointment-consent-grant

Actual

inspect (28 elements on a live VitalForge consumer sheet):

  • 27 hittable: false (home chrome under the scrim, close IconButton, chips)
  • 1 hittable: true — ISpect floating pill GestureDetector (~40×40)
  • No FilledButton, no CheckboxListTile, no appointment-consent-* keys
  • Close control appears as type: Button, widgetType: IconButton, key: null even though the widget has ValueKey('appointment-detail-close')

find_element appointment-consent-grant → not found while the form is hidden (granted state). While the form is showing, tap appointment-consent-treatment prints Tapped and either does nothing or the pointer hits the modal barrier and dismisses the sheet.

Expected

  1. inspect lists FilledButton / ButtonStyleButton with the ValueKey (and Semantics.identifier when set).
  2. inspect lists CheckboxListTile (or the keyed parent) with value / enabled, not only an inner key-less Checkbox.
  3. When hittable is false, tap / set_checkbox invoke FilledButton.onPressed and CheckboxListTile.onChanged (same as ElevatedButton / IconButton / GestureDetector today).
  4. Overlay-route widgets (modal sheet) are listed even when a debug pill is the only hittable hit-test target.

Source (0.9.37 lib/flutter_skill.dart)

Allowlist — no FilledButton, no CheckboxListTile:

static bool _isInteractiveWidget(Widget widget) {
  return widget is ElevatedButton ||
      widget is TextButton ||
      widget is OutlinedButton ||
      widget is IconButton ||
      widget is FloatingActionButton ||
      widget is TextField ||
      widget is TextFormField ||
      widget is Checkbox ||
      widget is Switch ||
      widget is Slider ||
      widget is DropdownButton ||
      (widget is InkWell && widget.onTap != null) ||
      (widget is GestureDetector && widget.onTap != null) ||
      widget is ListTile;
}

Same gap in _findInteractiveElements / _findInteractiveElementsStructured and SemanticRefGenerator._getSemanticRole.

Tap path:

if (_isHittableAt(element, center)) {
  await _dispatchTap(center);
} else {
  _tryInvokeCallback(element); // Elevated/Text/Outlined/IconButton/FAB/InkWell/GestureDetector only
}

_getCheckboxState already handles CheckboxListTile / SwitchListTile; _tryInvokeCallback does not call onChanged.

Suggested fix

  • Treat ButtonStyleButton (covers FilledButton, ElevatedButton, OutlinedButton, TextButton) in inspect, semantic refs, and _tryInvokeCallback.
  • Treat CheckboxListTile / SwitchListTile / RadioListTile the same way; invoke onChanged?.call(!(value ?? false)).
  • Emit Semantics.identifier on inspect entries and resolve tap / set_checkbox / find_element by identifier as well as ValueKey.
  • When an overlay route is current, prefer its interactive (and keyed) widgets even if a debug overlay makes hittable false.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions