From 177cd191e3cf194a70d3ae65a4d17ed1884f76d4 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Tue, 30 Sep 2025 21:29:23 -0400 Subject: [PATCH] Simplify watch history controls and add loading spinners --- css/style.css | 22 +++-- js/historyView.js | 215 ++++++++++++---------------------------------- 2 files changed, 69 insertions(+), 168 deletions(-) diff --git a/css/style.css b/css/style.css index cdabeb25..65cdbe6c 100644 --- a/css/style.css +++ b/css/style.css @@ -360,12 +360,6 @@ header img { border-color: #991b1b; } -.watch-history-card__menus { - display: flex; - align-items: center; - gap: 0.5rem; -} - @media (max-width: 1024px) { .watch-history-card__meta { flex: 1 1 18rem; @@ -1129,6 +1123,22 @@ button:not(.icon-button):focus { display: flex; } +.watch-history-status { + display: inline-flex; + align-items: center; + gap: 0.5rem; +} + +.status-spinner--inline { + animation: spin 1s linear infinite; + border: 0.125rem solid rgba(96, 165, 250, 0.35); + border-radius: 9999px; + border-top-color: #60a5fa; + display: inline-block; + height: 1rem; + width: 1rem; +} + .status-banner { align-items: center; background-color: rgba(31, 41, 55, 0.9); diff --git a/js/historyView.js b/js/historyView.js index 4c6f5af7..13fa4ff5 100644 --- a/js/historyView.js +++ b/js/historyView.js @@ -234,105 +234,6 @@ function renderWatchHistoryGrid(videos, containerOrElement) { } } - let hasOlder = false; - if (canEdit && video.videoRootId && window.app?.hasOlderVersion) { - hasOlder = window.app.hasOlderVersion(video, fullAllEventsArray); - } - - const revertButton = hasOlder - ? ` - - ` - : ""; - - const gearMenu = canEdit - ? ` -
- - -
- ` - : ""; - - const moreMenu = ` -
- - -
- `; - - const cardControls = ` -
- ${moreMenu}${gearMenu} -
- `; - const safeTitle = window.app?.escapeHTML(video.title) || "Untitled"; const safeThumb = window.app?.escapeHTML(video.thumbnail) || ""; const playbackUrl = typeof video.url === "string" ? video.url : ""; @@ -432,7 +333,6 @@ function renderWatchHistoryGrid(videos, containerOrElement) { > Remove - ${cardControls} @@ -480,66 +380,6 @@ function renderWatchHistoryGrid(videos, containerOrElement) { const lazyEls = container.querySelectorAll("[data-lazy]"); lazyEls.forEach((el) => window.app?.mediaLoader.observe(el)); - window.app?.attachMoreMenuHandlers?.(container); - - const gearButtons = container.querySelectorAll("[data-settings-dropdown]"); - gearButtons.forEach((btn) => { - btn.addEventListener("click", (ev) => { - ev.stopPropagation(); - const idx = btn.getAttribute("data-settings-dropdown"); - const dropdown = document.getElementById(`settingsDropdown-${idx}`); - if (dropdown) dropdown.classList.toggle("hidden"); - }); - }); - - const editButtons = container.querySelectorAll("[data-edit-index]"); - editButtons.forEach((btn) => { - btn.addEventListener("click", (ev) => { - ev.stopPropagation(); - const idxAttr = btn.getAttribute("data-edit-index"); - const idx = Number.parseInt(idxAttr, 10); - const dropdown = document.getElementById(`settingsDropdown-${idxAttr}`); - if (dropdown) dropdown.classList.add("hidden"); - const eventId = btn.getAttribute("data-edit-event-id") || ""; - window.app?.handleEditVideo({ - eventId, - index: Number.isNaN(idx) ? null : idx, - }); - }); - }); - - const revertButtons = container.querySelectorAll("[data-revert-index]"); - revertButtons.forEach((btn) => { - btn.addEventListener("click", (ev) => { - ev.stopPropagation(); - const idxAttr = btn.getAttribute("data-revert-index"); - const idx = Number.parseInt(idxAttr, 10); - const dropdown = document.getElementById(`settingsDropdown-${idxAttr}`); - if (dropdown) dropdown.classList.add("hidden"); - const eventId = btn.getAttribute("data-revert-event-id") || ""; - window.app?.handleRevertVideo({ - eventId, - index: Number.isNaN(idx) ? null : idx, - }); - }); - }); - - const deleteAllButtons = container.querySelectorAll("[data-delete-all-index]"); - deleteAllButtons.forEach((btn) => { - btn.addEventListener("click", (ev) => { - ev.stopPropagation(); - const idxAttr = btn.getAttribute("data-delete-all-index"); - const idx = Number.parseInt(idxAttr, 10); - const dd = document.getElementById(`settingsDropdown-${idxAttr}`); - if (dd) dd.classList.add("hidden"); - const eventId = btn.getAttribute("data-delete-all-event-id") || ""; - window.app?.handleFullDeleteVideo({ - eventId, - index: Number.isNaN(idx) ? null : idx, - }); - }); - }); - const authorPics = container.querySelectorAll(".author-pic"); const authorNames = container.querySelectorAll(".author-name"); const creatorButtons = container.querySelectorAll( @@ -790,10 +630,18 @@ export function createWatchHistoryRenderer(config = {}) { const nextMessage = typeof message === "string" ? message.trim() : ""; if (nextMessage) { - statusEl.textContent = nextMessage; + if (nextMessage === WATCH_HISTORY_LOADING_STATUS) { + statusEl.innerHTML = + '' + + WATCH_HISTORY_LOADING_STATUS + + ""; + } else { + statusEl.textContent = nextMessage; + } statusEl.classList.remove("hidden"); } else { statusEl.textContent = ""; + statusEl.innerHTML = ""; statusEl.classList.add("hidden"); } }; @@ -945,6 +793,45 @@ export function createWatchHistoryRenderer(config = {}) { return; } + const showRemoveSpinner = (button) => { + if (!button || !button.dataset) { + return; + } + + if (button.dataset.originalHtml === undefined) { + button.dataset.originalHtml = button.innerHTML; + } + + if (button.dataset.originalAriaLabel === undefined) { + button.dataset.originalAriaLabel = button.getAttribute("aria-label") || ""; + } + + button.innerHTML = + ''; + button.setAttribute("aria-label", "Removing from watch history"); + }; + + const restoreRemoveButton = (button) => { + if (!button || !button.dataset) { + return; + } + + const originalHtml = button.dataset.originalHtml; + if (typeof originalHtml === "string") { + button.innerHTML = originalHtml; + } + + const originalAria = button.dataset.originalAriaLabel || ""; + if (originalAria) { + button.setAttribute("aria-label", originalAria); + } else { + button.removeAttribute("aria-label"); + } + + delete button.dataset.originalHtml; + delete button.dataset.originalAriaLabel; + }; + const handler = async (event) => { const removeTrigger = event.target.closest( "[data-history-remove-key]" @@ -971,6 +858,7 @@ export function createWatchHistoryRenderer(config = {}) { removeTrigger.disabled = true; removeTrigger.setAttribute("aria-busy", "true"); + showRemoveSpinner(removeTrigger); try { const result = await nostrClient.removeWatchHistoryItem(targetKey); @@ -1008,7 +896,10 @@ export function createWatchHistoryRenderer(config = {}) { "Failed to remove this video from watch history." ); } finally { - removeTrigger.removeAttribute("aria-busy"); + if (removeTrigger.isConnected) { + restoreRemoveButton(removeTrigger); + removeTrigger.removeAttribute("aria-busy"); + } } return;