a simple web player for subsonic tinysub.devins.page
subsonic navidrome javascript
11
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: dynamic context menu positioning

+8 -10
+8 -10
src/js/contextmenu.js
··· 23 23 24 24 contextMenuEl = createElement("div", { 25 25 className: CLASSES.CONTEXT_MENU, 26 - attributes: { 27 - style: `left: ${Math.min(x, window.innerWidth - 200)}px; top: ${Math.min(y, window.innerHeight - 200)}px;`, 28 - }, 29 26 }); 30 27 31 28 Object.entries(items).forEach(([label, handler]) => { ··· 38 35 }); 39 36 40 37 document.body.appendChild(contextMenuEl); 38 + 39 + // position menu 40 + const rect = contextMenuEl.getBoundingClientRect(); 41 + contextMenuEl.style.left = `${Math.max(0, Math.min(x, window.innerWidth - rect.width))}px`; 42 + contextMenuEl.style.top = `${Math.max(0, Math.min(y, window.innerHeight - rect.height))}px`; 41 43 42 44 currentHideMenuHandler = cleanupContextMenu; 43 45 ··· 75 77 selectedIndices.map((i) => setFavoriteSong(state.queue[i], true)), 76 78 ); 77 79 updateQueueDisplay(); 80 + cleanupContextMenu(); 78 81 }, 79 82 Unfavorite: async () => { 80 83 await Promise.all( 81 84 selectedIndices.map((i) => setFavoriteSong(state.queue[i], false)), 82 85 ); 83 86 updateQueueDisplay(); 87 + cleanupContextMenu(); 84 88 }, 85 89 "Move Up": () => { 86 90 const firstIdx = Math.min(...selectedIndices); ··· 113 117 (e) => { 114 118 const isQueueTable = e.target.closest(`#${DOM_IDS.QUEUE_TABLE}`); 115 119 116 - if (contextMenuEl && isQueueTable) { 117 - contextMenuEl.remove(); 118 - contextMenuEl = null; 119 - return; 120 - } 121 - 122 - if (!isQueueTable || contextMenuEl) { 120 + if (!isQueueTable && contextMenuEl) { 123 121 e.preventDefault(); 124 122 e.stopImmediatePropagation(); 125 123 }