diff --git a/js/app.js b/js/app.js
index 839d0e59..e861eef4 100644
--- a/js/app.js
+++ b/js/app.js
@@ -2395,6 +2395,7 @@ class bitvidApp {
@@ -2423,6 +2424,7 @@ class bitvidApp {
@@ -2430,6 +2432,7 @@ class bitvidApp {
@@ -2687,6 +2690,10 @@ class bitvidApp {
}
}
}
+ if (video && video.id) {
+ this.videosMap.set(video.id, video);
+ }
+
fragment.appendChild(cardEl);
this.renderedVideoIds.add(video.id);
});
@@ -2723,10 +2730,15 @@ class bitvidApp {
const editButtons = this.videoList.querySelectorAll("[data-edit-index]");
editButtons.forEach((button) => {
button.addEventListener("click", () => {
- const index = button.getAttribute("data-edit-index");
- const dropdown = document.getElementById(`settingsDropdown-${index}`);
+ const indexAttr = button.getAttribute("data-edit-index");
+ const eventId = button.getAttribute("data-edit-event-id") || "";
+ const index = Number.parseInt(indexAttr, 10);
+ const dropdown = document.getElementById(`settingsDropdown-${indexAttr}`);
if (dropdown) dropdown.classList.add("hidden");
- this.handleEditVideo(index);
+ this.handleEditVideo({
+ eventId,
+ index: Number.isNaN(index) ? null : index,
+ });
});
});
@@ -2736,10 +2748,15 @@ class bitvidApp {
);
revertButtons.forEach((button) => {
button.addEventListener("click", () => {
- const index = button.getAttribute("data-revert-index");
- const dropdown = document.getElementById(`settingsDropdown-${index}`);
+ const indexAttr = button.getAttribute("data-revert-index");
+ const eventId = button.getAttribute("data-revert-event-id") || "";
+ const index = Number.parseInt(indexAttr, 10);
+ const dropdown = document.getElementById(`settingsDropdown-${indexAttr}`);
if (dropdown) dropdown.classList.add("hidden");
- this.handleRevertVideo(index);
+ this.handleRevertVideo({
+ eventId,
+ index: Number.isNaN(index) ? null : index,
+ });
});
});
@@ -2749,10 +2766,15 @@ class bitvidApp {
);
deleteAllButtons.forEach((button) => {
button.addEventListener("click", () => {
- const index = button.getAttribute("data-delete-all-index");
- const dropdown = document.getElementById(`settingsDropdown-${index}`);
+ const indexAttr = button.getAttribute("data-delete-all-index");
+ const eventId = button.getAttribute("data-delete-all-event-id") || "";
+ const index = Number.parseInt(indexAttr, 10);
+ const dropdown = document.getElementById(`settingsDropdown-${indexAttr}`);
if (dropdown) dropdown.classList.add("hidden");
- this.handleFullDeleteVideo(index);
+ this.handleFullDeleteVideo({
+ eventId,
+ index: Number.isNaN(index) ? null : index,
+ });
});
});
@@ -2934,21 +2956,137 @@ class bitvidApp {
}
}
+ normalizeActionTarget(target) {
+ if (target && typeof target === "object") {
+ const eventId =
+ typeof target.eventId === "string" ? target.eventId.trim() : "";
+ let index = null;
+ if (typeof target.index === "number" && Number.isInteger(target.index)) {
+ index = target.index;
+ } else if (
+ typeof target.index === "string" && target.index.trim().length > 0
+ ) {
+ const parsed = Number.parseInt(target.index.trim(), 10);
+ index = Number.isNaN(parsed) ? null : parsed;
+ }
+ return { eventId, index };
+ }
+
+ if (typeof target === "string") {
+ const trimmed = target.trim();
+ if (!trimmed) {
+ return { eventId: "", index: null };
+ }
+ if (/^-?\d+$/.test(trimmed)) {
+ const parsed = Number.parseInt(trimmed, 10);
+ return { eventId: "", index: Number.isNaN(parsed) ? null : parsed };
+ }
+ return { eventId: trimmed, index: null };
+ }
+
+ if (typeof target === "number" && Number.isInteger(target)) {
+ return { eventId: "", index: target };
+ }
+
+ return { eventId: "", index: null };
+ }
+
+ async resolveVideoActionTarget({
+ eventId = "",
+ index = null,
+ preloadedList,
+ } = {}) {
+ const trimmedEventId = typeof eventId === "string" ? eventId.trim() : "";
+ const normalizedIndex =
+ typeof index === "number" && Number.isInteger(index) && index >= 0
+ ? index
+ : null;
+
+ const candidateLists = Array.isArray(preloadedList)
+ ? [preloadedList]
+ : [];
+
+ for (const list of candidateLists) {
+ if (trimmedEventId) {
+ const match = list.find((video) => video?.id === trimmedEventId);
+ if (match) {
+ this.videosMap.set(match.id, match);
+ return match;
+ }
+ }
+ if (
+ normalizedIndex !== null &&
+ normalizedIndex >= 0 &&
+ normalizedIndex < list.length
+ ) {
+ const match = list[normalizedIndex];
+ if (match) {
+ this.videosMap.set(match.id, match);
+ return match;
+ }
+ }
+ }
+
+ if (trimmedEventId) {
+ const fromMap = this.videosMap.get(trimmedEventId);
+ if (fromMap) {
+ return fromMap;
+ }
+
+ const activeVideos = nostrClient.getActiveVideos();
+ const fromActive = activeVideos.find((video) => video.id === trimmedEventId);
+ if (fromActive) {
+ this.videosMap.set(fromActive.id, fromActive);
+ return fromActive;
+ }
+
+ const fromAll = nostrClient.allEvents.get(trimmedEventId);
+ if (fromAll) {
+ this.videosMap.set(fromAll.id, fromAll);
+ return fromAll;
+ }
+
+ const fetched = await nostrClient.getEventById(trimmedEventId);
+ if (fetched) {
+ this.videosMap.set(fetched.id, fetched);
+ return fetched;
+ }
+ }
+
+ if (normalizedIndex !== null) {
+ const activeVideos = nostrClient.getActiveVideos();
+ if (normalizedIndex >= 0 && normalizedIndex < activeVideos.length) {
+ const candidate = activeVideos[normalizedIndex];
+ if (candidate) {
+ this.videosMap.set(candidate.id, candidate);
+ return candidate;
+ }
+ }
+ }
+
+ return null;
+ }
+
/**
* Handle "Edit Video" from gear menu.
*/
- async handleEditVideo(index) {
+ async handleEditVideo(target) {
try {
- // 1) Fetch the current list of videos (the newest versions)
- const all = await nostrClient.fetchVideos();
- const video = all[index];
+ const normalizedTarget = this.normalizeActionTarget(target);
+ const latestVideos = await nostrClient.fetchVideos();
+ const video = await this.resolveVideoActionTarget({
+ ...normalizedTarget,
+ preloadedList: latestVideos,
+ });
// 2) Basic ownership checks
if (!this.pubkey) {
this.showError("Please login to edit videos.");
return;
}
- if (!video || video.pubkey !== this.pubkey) {
+ const userPubkey = (this.pubkey || "").toLowerCase();
+ const videoPubkey = (video?.pubkey || "").toLowerCase();
+ if (!video || !videoPubkey || videoPubkey !== userPubkey) {
this.showError("You do not own this video.");
return;
}
@@ -3022,17 +3160,22 @@ class bitvidApp {
}
}
- async handleRevertVideo(index) {
+ async handleRevertVideo(target) {
try {
- // 1) Still use fetchVideos to get the video in question
+ const normalizedTarget = this.normalizeActionTarget(target);
const activeVideos = await nostrClient.fetchVideos();
- const video = activeVideos[index];
+ const video = await this.resolveVideoActionTarget({
+ ...normalizedTarget,
+ preloadedList: activeVideos,
+ });
if (!this.pubkey) {
this.showError("Please login to revert.");
return;
}
- if (!video || video.pubkey !== this.pubkey) {
+ const userPubkey = (this.pubkey || "").toLowerCase();
+ const videoPubkey = (video?.pubkey || "").toLowerCase();
+ if (!video || !videoPubkey || videoPubkey !== userPubkey) {
this.showError("You do not own this video.");
return;
}
@@ -3070,16 +3213,22 @@ class bitvidApp {
/**
* Handle "Delete Video" from gear menu.
*/
- async handleFullDeleteVideo(index) {
+ async handleFullDeleteVideo(target) {
try {
+ const normalizedTarget = this.normalizeActionTarget(target);
const all = await nostrClient.fetchVideos();
- const video = all[index];
+ const video = await this.resolveVideoActionTarget({
+ ...normalizedTarget,
+ preloadedList: all,
+ });
if (!this.pubkey) {
this.showError("Please login to delete videos.");
return;
}
- if (!video || video.pubkey !== this.pubkey) {
+ const userPubkey = (this.pubkey || "").toLowerCase();
+ const videoPubkey = (video?.pubkey || "").toLowerCase();
+ if (!video || !videoPubkey || videoPubkey !== userPubkey) {
this.showError("You do not own this video.");
return;
}
diff --git a/js/channelProfile.js b/js/channelProfile.js
index cac4fee2..aa552426 100644
--- a/js/channelProfile.js
+++ b/js/channelProfile.js
@@ -271,6 +271,7 @@ async function loadUserVideos(pubkey) {
class="block w-full text-left px-4 py-2 text-sm text-red-400
hover:bg-red-700 hover:text-white"
data-revert-index="${index}"
+ data-revert-event-id="${video.id}"
>
Revert
@@ -305,6 +306,7 @@ async function loadUserVideos(pubkey) {
class="block w-full text-left px-4 py-2 text-sm text-gray-100
hover:bg-gray-700"
data-edit-index="${index}"
+ data-edit-event-id="${video.id}"
>
Edit
@@ -313,6 +315,7 @@ async function loadUserVideos(pubkey) {
class="block w-full text-left px-4 py-2 text-sm text-red-400
hover:bg-red-700 hover:text-white"
data-delete-all-index="${index}"
+ data-delete-all-event-id="${video.id}"
>
Delete All
@@ -446,10 +449,15 @@ async function loadUserVideos(pubkey) {
editBtns.forEach((btn) => {
btn.addEventListener("click", (ev) => {
ev.stopPropagation();
- const idx = parseInt(btn.getAttribute("data-edit-index"), 10);
- const dropdown = document.getElementById(`settingsDropdown-${idx}`);
+ 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");
- app.handleEditVideo(idx);
+ const eventId = btn.getAttribute("data-edit-event-id") || "";
+ app.handleEditVideo({
+ eventId,
+ index: Number.isNaN(idx) ? null : idx,
+ });
});
});
@@ -458,10 +466,15 @@ async function loadUserVideos(pubkey) {
revertBtns.forEach((btn) => {
btn.addEventListener("click", (ev) => {
ev.stopPropagation();
- const idx = parseInt(btn.getAttribute("data-revert-index"), 10);
- const dropdown = document.getElementById(`settingsDropdown-${idx}`);
+ 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");
- app.handleRevertVideo(idx);
+ const eventId = btn.getAttribute("data-revert-event-id") || "";
+ app.handleRevertVideo({
+ eventId,
+ index: Number.isNaN(idx) ? null : idx,
+ });
});
});
@@ -470,10 +483,15 @@ async function loadUserVideos(pubkey) {
deleteAllBtns.forEach((btn) => {
btn.addEventListener("click", (ev) => {
ev.stopPropagation();
- const idx = parseInt(btn.getAttribute("data-delete-all-index"), 10);
- const dropdown = document.getElementById(`settingsDropdown-${idx}`);
+ const idxAttr = btn.getAttribute("data-delete-all-index");
+ const idx = Number.parseInt(idxAttr, 10);
+ const dropdown = document.getElementById(`settingsDropdown-${idxAttr}`);
if (dropdown) dropdown.classList.add("hidden");
- app.handleFullDeleteVideo(idx);
+ const eventId = btn.getAttribute("data-delete-all-event-id") || "";
+ app.handleFullDeleteVideo({
+ eventId,
+ index: Number.isNaN(idx) ? null : idx,
+ });
});
});
} catch (err) {
diff --git a/js/subscriptions.js b/js/subscriptions.js
index f5e5db50..2ef66b04 100644
--- a/js/subscriptions.js
+++ b/js/subscriptions.js
@@ -328,6 +328,7 @@ class SubscriptionsManager {
@@ -356,6 +357,7 @@ class SubscriptionsManager {
@@ -363,6 +365,7 @@ class SubscriptionsManager {
@@ -500,10 +503,15 @@ class SubscriptionsManager {
editButtons.forEach((btn) => {
btn.addEventListener("click", (ev) => {
ev.stopPropagation();
- const idx = btn.getAttribute("data-edit-index");
- const dropdown = document.getElementById(`settingsDropdown-${idx}`);
+ 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");
- window.app?.handleEditVideo(idx);
+ const eventId = btn.getAttribute("data-edit-event-id") || "";
+ window.app?.handleEditVideo({
+ eventId,
+ index: Number.isNaN(idx) ? null : idx,
+ });
});
});
@@ -512,10 +520,15 @@ class SubscriptionsManager {
revertButtons.forEach((btn) => {
btn.addEventListener("click", (ev) => {
ev.stopPropagation();
- const idx = btn.getAttribute("data-revert-index");
- const dropdown = document.getElementById(`settingsDropdown-${idx}`);
+ 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");
- window.app?.handleRevertVideo(idx);
+ const eventId = btn.getAttribute("data-revert-event-id") || "";
+ window.app?.handleRevertVideo({
+ eventId,
+ index: Number.isNaN(idx) ? null : idx,
+ });
});
});
@@ -526,10 +539,15 @@ class SubscriptionsManager {
deleteAllButtons.forEach((btn) => {
btn.addEventListener("click", (ev) => {
ev.stopPropagation();
- const idx = btn.getAttribute("data-delete-all-index");
- const dd = document.getElementById(`settingsDropdown-${idx}`);
+ 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");
- window.app?.handleFullDeleteVideo(idx);
+ const eventId = btn.getAttribute("data-delete-all-event-id") || "";
+ window.app?.handleFullDeleteVideo({
+ eventId,
+ index: Number.isNaN(idx) ? null : idx,
+ });
});
});