Bug Description
FaroUserInteractionWidget incorrectly identifies tapped elements when the app uses a Navigator. The widget tree traversal in _findElementTapped performs a depth-first search from the root and returns the first widget whose paint bounds contain the tap position. Since Flutter's Navigator keeps previous routes mounted in the widget tree, the traversal can match an interactive widget (e.g., InkWell, ButtonStyleButton) from a background page instead of the currently visible foreground page.
This results in user_interaction events being sent with an incorrect element_description (and potentially wrong element_type) -- the description comes from a widget the user never actually interacted with.
Steps to Reproduce
- Run the SDK example app (
example/)
- From the Features (home) page, navigate to the User Actions page
- Tap the "Idle (→ cancel)" button
- Check the generated
user_interaction event in Grafana Cloud (or your collector)
Expected Behavior
The element_description attribute should be "Idle (→ cancel)" -- the label of the button that was tapped.
Actual Behavior
The element_description attribute is "Session: Sampled" -- text from the Sampling Settings card on the Features (home) page, which is still mounted in the widget tree behind the current page.
Code Sample
The issue is in lib/src/faro_user_interaction_widget.dart, specifically in _findElementTapped:
rootElement.visitChildElements(elementFind);
This visits all children from the root without awareness of the navigation stack, so background route widgets are checked before foreground route widgets.
Additional Context
Potential fix approaches:
- Use Flutter's
HitTestResult from the GestureBinding to identify only the topmost widget at the tap position
- Filter out elements that belong to non-active routes (e.g., check
ModalRoute.of(context)?.isCurrent)
- Reverse the traversal order or use a last-match-wins strategy instead of first-match-wins
Bug Description
FaroUserInteractionWidgetincorrectly identifies tapped elements when the app uses aNavigator. The widget tree traversal in_findElementTappedperforms a depth-first search from the root and returns the first widget whose paint bounds contain the tap position. Since Flutter'sNavigatorkeeps previous routes mounted in the widget tree, the traversal can match an interactive widget (e.g.,InkWell,ButtonStyleButton) from a background page instead of the currently visible foreground page.This results in
user_interactionevents being sent with an incorrectelement_description(and potentially wrongelement_type) -- the description comes from a widget the user never actually interacted with.Steps to Reproduce
example/)user_interactionevent in Grafana Cloud (or your collector)Expected Behavior
The
element_descriptionattribute should be"Idle (→ cancel)"-- the label of the button that was tapped.Actual Behavior
The
element_descriptionattribute is"Session: Sampled"-- text from the Sampling Settings card on the Features (home) page, which is still mounted in the widget tree behind the current page.Code Sample
The issue is in
lib/src/faro_user_interaction_widget.dart, specifically in_findElementTapped:rootElement.visitChildElements(elementFind);This visits all children from the root without awareness of the navigation stack, so background route widgets are checked before foreground route widgets.
Additional Context
Potential fix approaches:
HitTestResultfrom theGestureBindingto identify only the topmost widget at the tap positionModalRoute.of(context)?.isCurrent)