Skip to content

fix(node): restore view-tree owners on map dispose so node-list popups aren't invisible#5699

Merged
jamesarich merged 1 commit into
mainfrom
fix/node-detail-map-lifecycle-owner-leak
Jun 1, 2026
Merged

fix(node): restore view-tree owners on map dispose so node-list popups aren't invisible#5699
jamesarich merged 1 commit into
mainfrom
fix/node-detail-map-lifecycle-owner-leak

Conversation

@jamesarich

Copy link
Copy Markdown
Collaborator

Problem

On the Nodes list, all popups — the sort/filter menus and the long-press NodeContextMenu — stopped appearing after navigating into a node detail and back. The popup window was created (and even grabbed focus) but its content measured to 0×0 (dumpsys windowmAttrs={(0,0)(0x0)}), so nothing drew.

Root cause

InlineMap (rendered inside the node-detail screen) and NodeClusterMarkers (Map screen) set the activity root view's ViewTreeLifecycleOwner / ViewTreeSavedStateRegistryOwner to work around a maps-compose MarkerComposable crash — but with an empty onDispose {}:

view.rootView.setViewTreeLifecycleOwner(lifecycleOwner)   // activity ROOT view
...
onDispose {}                                              // never restored

lifecycleOwner is the host screen's NavEntry-scoped, transient lifecycle. Visiting a node detail with a location attaches that owner to the activity root view; navigating back destroys the lifecycle but leaves it on the root view. Every Popup/DropdownMenu opened afterward inherits its lifecycle from the root view → gets a DESTROYED lifecycle → its content never composes → 0×0 invisible window.

This explains why it affected all popups, any popup type, only after a detail visit, and was unaffected by Compose-level changes. Regression from #5684 (bisected on-device: good through internal.111, bad at HEAD).

Fix

Capture the previous owners (findViewTreeLifecycleOwner() / findViewTreeSavedStateRegistryOwner()) before overwriting and restore them in onDispose, in both InlineMap.kt and NodeClusterMarkers.kt. The maps crash workaround stays intact; we just no longer leak a destroyed lifecycle onto the root view.

Verification

Built and run on an emulator. After repeated node detail → back round-trips:

  • Sort/filter menu renders (576×1952)
  • Long-press context menu renders (531×692)

🤖 Generated with Claude Code

…dering invisible

InlineMap (and NodeClusterMarkers) set the activity root view's
ViewTreeLifecycleOwner / SavedStateRegistryOwner to work around a
maps-compose MarkerComposable crash, but used an empty `onDispose {}`.

The owner is the host screen's NavEntry-scoped lifecycle. Visiting a node
detail with a location attaches that transient owner to the activity root
view; navigating back destroys the lifecycle but leaves it on the root view.
Every Popup/DropdownMenu opened afterward (node-list sort/filter menus,
long-press context menu) inherits the destroyed lifecycle from the root view,
so its content never composes and the popup window is measured at 0x0 —
invisible.

Capture the previous owners and restore them in onDispose, keeping the maps
crash workaround intact while no longer leaking a destroyed lifecycle onto the
root view.

Regression from #5684. Verified on-device: sort/filter and long-press menus
render correctly across repeated node detail round-trips.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added the bugfix PR tag label Jun 1, 2026
@jamesarich jamesarich enabled auto-merge June 1, 2026 12:23
@jamesarich jamesarich disabled auto-merge June 1, 2026 12:26
@jamesarich jamesarich added this pull request to the merge queue Jun 1, 2026
Merged via the queue into main with commit 63ff12d Jun 1, 2026
18 checks passed
@jamesarich jamesarich deleted the fix/node-detail-map-lifecycle-owner-leak branch June 1, 2026 12:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix PR tag

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant