fix(13-02): defer virtualizer event delegation until element exists
- Event delegation handlers were attached in firstUpdated(), but the virtualizer is conditionally rendered (hidden when tracks empty/loading) - On first render, tracks are [] so virtualizer doesn't exist, and firstUpdated() never fires again — delegation was never attached - Move delegation to a guarded helper called from both firstUpdated() and updated(), so it attaches as soon as the virtualizer appears - Fixes click, multi-select, context menu, double-click, and drag in both track-list and queue-panel components
This commit is contained in:
@@ -204,6 +204,9 @@ export class TrackList extends LitElement implements SelectionHost, ContextMenuH
|
||||
@query('#sort-dropdown')
|
||||
private sortDropdownPopup!: WaPopup;
|
||||
|
||||
/** Whether delegated event handlers have been attached to the virtualizer. */
|
||||
private delegationAttached = false;
|
||||
|
||||
private resizingColumn: number | null = null;
|
||||
private resizeStartX = 0;
|
||||
private resizeStartWidths: number[] = [];
|
||||
@@ -1084,6 +1087,7 @@ export class TrackList extends LitElement implements SelectionHost, ContextMenuH
|
||||
virt.removeEventListener('dragstart', this.onDelegatedDragStart);
|
||||
virt.removeEventListener('dragend', this.onTrackDragEnd);
|
||||
}
|
||||
this.delegationAttached = false;
|
||||
|
||||
this.virtualizer?.removeEventListener(
|
||||
'visibilityChanged',
|
||||
@@ -1121,20 +1125,35 @@ export class TrackList extends LitElement implements SelectionHost, ContextMenuH
|
||||
|
||||
override firstUpdated() {
|
||||
this.initColumnWidths();
|
||||
this.attachDelegation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach delegated event handlers to the virtualizer.
|
||||
* The virtualizer may not exist on first render (tracks
|
||||
* still loading), so this is called from both
|
||||
* firstUpdated() and updated() — guarded by a flag.
|
||||
*/
|
||||
private attachDelegation() {
|
||||
if (this.delegationAttached) return;
|
||||
|
||||
// Event delegation: attach stable handlers to the virtualizer
|
||||
// so renderTrackRow creates zero per-item closures.
|
||||
const virt = this.virtualizer;
|
||||
if (virt) {
|
||||
virt.addEventListener('click', this.onDelegatedClick);
|
||||
virt.addEventListener('dblclick', this.onDelegatedDblClick);
|
||||
virt.addEventListener('contextmenu', this.onDelegatedContextMenu);
|
||||
virt.addEventListener('dragstart', this.onDelegatedDragStart);
|
||||
virt.addEventListener('dragend', this.onTrackDragEnd);
|
||||
}
|
||||
|
||||
if (!virt) return;
|
||||
|
||||
virt.addEventListener('click', this.onDelegatedClick);
|
||||
virt.addEventListener('dblclick', this.onDelegatedDblClick);
|
||||
virt.addEventListener('contextmenu', this.onDelegatedContextMenu);
|
||||
virt.addEventListener('dragstart', this.onDelegatedDragStart);
|
||||
virt.addEventListener('dragend', this.onTrackDragEnd);
|
||||
this.delegationAttached = true;
|
||||
}
|
||||
|
||||
override updated(changed: Map<string, unknown>) {
|
||||
// The virtualizer may not exist on first render
|
||||
// (tracks still loading). Retry delegation here.
|
||||
this.attachDelegation();
|
||||
|
||||
// Recompute widths when the column config changes.
|
||||
const colKey = this.trackListCtrl.columnIds.join(
|
||||
',',
|
||||
|
||||
Reference in New Issue
Block a user