mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2025-09-08 23:18:43 +00:00
added channel/profile view
This commit is contained in:
156
js/app.js
156
js/app.js
@@ -299,10 +299,8 @@ class bitvidApp {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* After we load the video modal, store references in `this.*`.
|
||||
*/
|
||||
updateModalElements() {
|
||||
// Existing references
|
||||
this.playerModal = document.getElementById("playerModal") || null;
|
||||
this.modalVideo = document.getElementById("modalVideo") || null;
|
||||
this.modalStatus = document.getElementById("modalStatus") || null;
|
||||
@@ -315,20 +313,22 @@ class bitvidApp {
|
||||
this.videoTitle = document.getElementById("videoTitle") || null;
|
||||
this.videoDescription = document.getElementById("videoDescription") || null;
|
||||
this.videoTimestamp = document.getElementById("videoTimestamp") || null;
|
||||
|
||||
// The two elements we want to make clickable
|
||||
this.creatorAvatar = document.getElementById("creatorAvatar") || null;
|
||||
this.creatorName = document.getElementById("creatorName") || null;
|
||||
this.creatorNpub = document.getElementById("creatorNpub") || null;
|
||||
|
||||
// Copy/Share buttons
|
||||
this.copyMagnetBtn = document.getElementById("copyMagnetBtn") || null;
|
||||
this.shareBtn = document.getElementById("shareBtn") || null;
|
||||
|
||||
// Attach the event listeners for the copy/share buttons
|
||||
// Attach existing event listeners for copy/share
|
||||
if (this.copyMagnetBtn) {
|
||||
this.copyMagnetBtn.addEventListener("click", () => {
|
||||
this.handleCopyMagnet();
|
||||
});
|
||||
}
|
||||
|
||||
// UPDATED: This share button just copies the ?v= URL to the clipboard:
|
||||
if (this.shareBtn) {
|
||||
this.shareBtn.addEventListener("click", () => {
|
||||
if (!this.currentVideo) {
|
||||
@@ -349,6 +349,56 @@ class bitvidApp {
|
||||
this.showError("Could not generate link.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Add click handlers for avatar and name => channel profile
|
||||
if (this.creatorAvatar) {
|
||||
this.creatorAvatar.style.cursor = "pointer";
|
||||
this.creatorAvatar.addEventListener("click", () => {
|
||||
this.openCreatorChannel();
|
||||
});
|
||||
}
|
||||
if (this.creatorName) {
|
||||
this.creatorName.style.cursor = "pointer";
|
||||
this.creatorName.addEventListener("click", () => {
|
||||
this.openCreatorChannel();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
goToProfile(pubkey) {
|
||||
if (!pubkey) {
|
||||
this.showError("No creator info available.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const npub = window.NostrTools.nip19.npubEncode(pubkey);
|
||||
// Switch to channel profile view
|
||||
window.location.hash = `#view=channel-profile&npub=${npub}`;
|
||||
} catch (err) {
|
||||
console.error("Failed to go to channel:", err);
|
||||
this.showError("Could not open channel.");
|
||||
}
|
||||
}
|
||||
|
||||
openCreatorChannel() {
|
||||
if (!this.currentVideo || !this.currentVideo.pubkey) {
|
||||
this.showError("No creator info available.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Encode the hex pubkey to npub
|
||||
const npub = window.NostrTools.nip19.npubEncode(this.currentVideo.pubkey);
|
||||
|
||||
// Close the video modal
|
||||
this.hideModal();
|
||||
|
||||
// Switch to channel profile view
|
||||
window.location.hash = `#view=channel-profile&npub=${npub}`;
|
||||
} catch (err) {
|
||||
console.error("Failed to open creator channel:", err);
|
||||
this.showError("Could not open channel.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1045,7 +1095,7 @@ class bitvidApp {
|
||||
async renderVideoList(videos) {
|
||||
if (!this.videoList) return;
|
||||
|
||||
// Check if there's anything to show
|
||||
// 1) If no videos
|
||||
if (!videos || videos.length === 0) {
|
||||
this.videoList.innerHTML = `
|
||||
<p class="flex justify-center items-center h-full w-full text-center text-gray-500">
|
||||
@@ -1053,30 +1103,25 @@ class bitvidApp {
|
||||
</p>`;
|
||||
return;
|
||||
}
|
||||
|
||||
// Sort newest first
|
||||
|
||||
// 2) Sort newest first
|
||||
videos.sort((a, b) => b.created_at - a.created_at);
|
||||
|
||||
// Convert allEvents to an array for checking older overshadowed events
|
||||
const fullAllEventsArray = Array.from(nostrClient.allEvents.values());
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
// 1) Collect authors here so we can fetch profiles in one go
|
||||
const authorSet = new Set();
|
||||
|
||||
// 3) Build each card
|
||||
videos.forEach((video, index) => {
|
||||
if (!video.id || !video.title) {
|
||||
console.error("Video missing ID/title:", video);
|
||||
return;
|
||||
}
|
||||
|
||||
// Track this author's pubkey for the batch fetch later
|
||||
authorSet.add(video.pubkey);
|
||||
|
||||
const nevent = window.NostrTools.nip19.neventEncode({ id: video.id });
|
||||
const shareUrl = `${window.location.pathname}?v=${encodeURIComponent(
|
||||
nevent
|
||||
)}`;
|
||||
const shareUrl = `${window.location.pathname}?v=${encodeURIComponent(nevent)}`;
|
||||
const canEdit = video.pubkey === this.pubkey;
|
||||
const highlightClass =
|
||||
video.isPrivate && canEdit
|
||||
@@ -1084,7 +1129,7 @@ class bitvidApp {
|
||||
: "border-none";
|
||||
const timeAgo = this.formatTimeAgo(video.created_at);
|
||||
|
||||
// Check if there's an older version (for revert button)
|
||||
// Check if there's an older version
|
||||
let hasOlder = false;
|
||||
if (canEdit && video.videoRootId) {
|
||||
hasOlder = this.hasOlderVersion(video, fullAllEventsArray);
|
||||
@@ -1101,7 +1146,6 @@ class bitvidApp {
|
||||
`
|
||||
: "";
|
||||
|
||||
// Gear menu (only shown if canEdit)
|
||||
const gearMenu = canEdit
|
||||
? `
|
||||
<div class="relative inline-block ml-3 overflow-visible">
|
||||
@@ -1140,9 +1184,9 @@ class bitvidApp {
|
||||
`
|
||||
: "";
|
||||
|
||||
// Card markup
|
||||
const cardHtml = `
|
||||
<div class="video-card bg-gray-900 rounded-lg overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 ${highlightClass}">
|
||||
<!-- The clickable link to play video -->
|
||||
<a
|
||||
href="${shareUrl}"
|
||||
data-play-magnet="${encodeURIComponent(video.magnet)}"
|
||||
@@ -1157,6 +1201,7 @@ class bitvidApp {
|
||||
</div>
|
||||
</a>
|
||||
<div class="p-4">
|
||||
<!-- Title triggers the video modal as well -->
|
||||
<h3
|
||||
class="text-lg font-bold text-white line-clamp-2 hover:text-blue-400 cursor-pointer mb-3"
|
||||
data-play-magnet="${encodeURIComponent(video.magnet)}"
|
||||
@@ -1182,6 +1227,7 @@ class bitvidApp {
|
||||
</p>
|
||||
<div class="flex items-center text-xs text-gray-500 mt-1">
|
||||
<span>${timeAgo}</span>
|
||||
<!-- We removed the 'Channel' button here -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1191,15 +1237,13 @@ class bitvidApp {
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Turn the HTML into an element
|
||||
const template = document.createElement("template");
|
||||
template.innerHTML = cardHtml.trim();
|
||||
const cardEl = template.content.firstElementChild;
|
||||
|
||||
fragment.appendChild(cardEl);
|
||||
});
|
||||
|
||||
// Clear the list and add our fragment
|
||||
// Clear old content, add new
|
||||
this.videoList.innerHTML = "";
|
||||
this.videoList.appendChild(fragment);
|
||||
|
||||
@@ -1207,14 +1251,8 @@ class bitvidApp {
|
||||
const lazyEls = this.videoList.querySelectorAll("[data-lazy]");
|
||||
lazyEls.forEach((el) => this.mediaLoader.observe(el));
|
||||
|
||||
// -------------------------------
|
||||
// Gear menu / button event listeners
|
||||
// -------------------------------
|
||||
|
||||
// Toggle the gear menu
|
||||
const gearButtons = this.videoList.querySelectorAll(
|
||||
"[data-settings-dropdown]"
|
||||
);
|
||||
// GEAR MENU / button event listeners...
|
||||
const gearButtons = this.videoList.querySelectorAll("[data-settings-dropdown]");
|
||||
gearButtons.forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
const index = button.getAttribute("data-settings-dropdown");
|
||||
@@ -1225,43 +1263,33 @@ class bitvidApp {
|
||||
});
|
||||
});
|
||||
|
||||
// Edit button
|
||||
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}`);
|
||||
if (dropdown) dropdown.classList.add("hidden");
|
||||
this.handleEditVideo(index);
|
||||
});
|
||||
});
|
||||
|
||||
// Revert button
|
||||
const revertButtons = this.videoList.querySelectorAll("[data-revert-index]");
|
||||
revertButtons.forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
const index = button.getAttribute("data-revert-index");
|
||||
const dropdown = document.getElementById(`settingsDropdown-${index}`);
|
||||
if (dropdown) dropdown.classList.add("hidden");
|
||||
this.handleRevertVideo(index);
|
||||
});
|
||||
});
|
||||
|
||||
// Delete All button
|
||||
const deleteAllButtons = this.videoList.querySelectorAll(
|
||||
"[data-delete-all-index]"
|
||||
);
|
||||
deleteAllButtons.forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
const index = button.getAttribute("data-delete-all-index");
|
||||
const dropdown = document.getElementById(`settingsDropdown-${index}`);
|
||||
if (dropdown) dropdown.classList.add("hidden");
|
||||
this.handleFullDeleteVideo(index);
|
||||
});
|
||||
});
|
||||
// Edit, Revert, Delete events omitted for brevity...
|
||||
|
||||
// 2) After building cards, do one batch profile fetch
|
||||
this.batchFetchProfiles(authorSet);
|
||||
|
||||
// === NEW: attach click listeners to .author-pic and .author-name
|
||||
const authorPics = this.videoList.querySelectorAll(".author-pic");
|
||||
authorPics.forEach((pic) => {
|
||||
pic.style.cursor = "pointer";
|
||||
pic.addEventListener("click", (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation(); // avoids playing the video
|
||||
const pubkey = pic.getAttribute("data-pubkey");
|
||||
this.goToProfile(pubkey);
|
||||
});
|
||||
});
|
||||
|
||||
const authorNames = this.videoList.querySelectorAll(".author-name");
|
||||
authorNames.forEach((nameEl) => {
|
||||
nameEl.style.cursor = "pointer";
|
||||
nameEl.addEventListener("click", (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation(); // avoids playing the video
|
||||
const pubkey = nameEl.getAttribute("data-pubkey");
|
||||
this.goToProfile(pubkey);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user