fix video switching errors

fixed errors that break video playback when switching between videos or loading in the same video again on firefox and chrome
This commit is contained in:
Keep Creating Online
2025-01-26 08:53:34 -05:00
parent c0617891d2
commit 9445180f2a

View File

@@ -334,6 +334,12 @@ class bitvidApp {
window.addEventListener("beforeunload", async () => { window.addEventListener("beforeunload", async () => {
await this.cleanup(); await this.cleanup();
}); });
// Popstate event for back/forward navigation
window.addEventListener("popstate", async (event) => {
console.log("[popstate] Back or forward button detected. Cleaning up...");
await this.hideModal();
});
} }
login(pubkey, saveToStorage = true) { login(pubkey, saveToStorage = true) {
@@ -377,6 +383,12 @@ class bitvidApp {
await torrentClient.cleanup(); await torrentClient.cleanup();
} catch (error) { } catch (error) {
this.log("Cleanup error:", error); this.log("Cleanup error:", error);
} finally {
try {
await fetch("./webtorrent/cancel/");
} catch (err) {
console.error("Failed to cancel old WebTorrent request:", err);
}
} }
} }
@@ -393,9 +405,18 @@ class bitvidApp {
await this.cleanup(); await this.cleanup();
this.playerModal.style.display = "none"; this.playerModal.style.display = "none";
this.playerModal.classList.add("hidden"); this.playerModal.classList.add("hidden");
// Clear out the old magnet so "same video requested" doesn't block re-loading
this.currentMagnetUri = null;
// Reset back to original path (no query param) // Optionally revert the URL if you want to remove ?v=...
window.history.replaceState({}, "", window.location.pathname); window.history.replaceState({}, "", window.location.pathname);
// Cancel any lingering torrent requests again
try {
await fetch("./webtorrent/cancel/");
} catch (err) {
console.error("Failed to cancel old WebTorrent request:", err);
}
} }
async handleSubmit(e) { async handleSubmit(e) {
@@ -823,19 +844,23 @@ class bitvidApp {
return; return;
} }
// Decode in case the magnet was URI-encoded
const decodedMagnet = decodeURIComponent(magnetURI); const decodedMagnet = decodeURIComponent(magnetURI);
// Prevent re-invoking the same video // Prevent re-invoking the exact same magnet link if it's already in use
// (Note: We set this.currentMagnetUri = null in hideModal() and popstate logic,
// so that returning here won't block re-loading the same magnet after a back button press.)
if (this.currentMagnetUri === decodedMagnet) { if (this.currentMagnetUri === decodedMagnet) {
this.log("Same video requested - already playing"); this.log("Same video requested - already playing");
return; return;
} }
this.currentMagnetUri = decodedMagnet; this.currentMagnetUri = decodedMagnet;
// Show the modal
this.playerModal.style.display = "flex"; this.playerModal.style.display = "flex";
this.playerModal.classList.remove("hidden"); this.playerModal.classList.remove("hidden");
// Re-fetch the latest from relays // Fetch (or re-fetch) videos from relays
const videos = await nostrClient.fetchVideos(); const videos = await nostrClient.fetchVideos();
const video = videos.find((v) => v.magnet === decodedMagnet); const video = videos.find((v) => v.magnet === decodedMagnet);
if (!video) { if (!video) {
@@ -843,10 +868,10 @@ class bitvidApp {
return; return;
} }
// store the full video object so we can reference it in share // Keep a reference to the current video
this.currentVideo = video; this.currentVideo = video;
// Decrypt only once if user owns it // If the user owns a private video, decrypt it just once
if ( if (
video.isPrivate && video.isPrivate &&
video.pubkey === this.pubkey && video.pubkey === this.pubkey &&
@@ -859,9 +884,7 @@ class bitvidApp {
const finalMagnet = video.magnet; const finalMagnet = video.magnet;
// Generate the nevent from video.id // Update the URL so the service worker has a consistent scope
// - We keep the same PATH (window.location.pathname),
// just adding ?v=... so the service worker scope is consistent
try { try {
const nevent = window.NostrTools.nip19.neventEncode({ id: video.id }); const nevent = window.NostrTools.nip19.neventEncode({ id: video.id });
const newUrl = const newUrl =
@@ -871,17 +894,14 @@ class bitvidApp {
console.error("Error pushing new URL state:", err); console.error("Error pushing new URL state:", err);
} }
// Fetch creator profile
let creatorProfile = { let creatorProfile = {
name: "Unknown", name: "Unknown",
picture: `https://robohash.org/${video.pubkey}`, picture: `https://robohash.org/${video.pubkey}`,
}; };
try { try {
const userEvents = await nostrClient.pool.list(nostrClient.relays, [ const userEvents = await nostrClient.pool.list(nostrClient.relays, [
{ { kinds: [0], authors: [video.pubkey], limit: 1 },
kinds: [0],
authors: [video.pubkey],
limit: 1,
},
]); ]);
if (userEvents.length > 0 && userEvents[0]?.content) { if (userEvents.length > 0 && userEvents[0]?.content) {
const profile = JSON.parse(userEvents[0].content); const profile = JSON.parse(userEvents[0].content);
@@ -894,6 +914,7 @@ class bitvidApp {
this.log("Error fetching creator profile:", error); this.log("Error fetching creator profile:", error);
} }
// Derive a short display of the pubkey
let creatorNpub = "Unknown"; let creatorNpub = "Unknown";
try { try {
creatorNpub = window.NostrTools.nip19.npubEncode(video.pubkey); creatorNpub = window.NostrTools.nip19.npubEncode(video.pubkey);
@@ -902,6 +923,7 @@ class bitvidApp {
creatorNpub = video.pubkey; creatorNpub = video.pubkey;
} }
// Populate modal fields
this.videoTitle.textContent = video.title || "Untitled"; this.videoTitle.textContent = video.title || "Untitled";
this.videoDescription.textContent = this.videoDescription.textContent =
video.description || "No description available."; video.description || "No description available.";
@@ -915,9 +937,11 @@ class bitvidApp {
this.creatorAvatar.src = creatorProfile.picture; this.creatorAvatar.src = creatorProfile.picture;
this.creatorAvatar.alt = creatorProfile.name; this.creatorAvatar.alt = creatorProfile.name;
// Start streaming
this.log("Starting video stream with:", finalMagnet); this.log("Starting video stream with:", finalMagnet);
await torrentClient.streamVideo(finalMagnet, this.modalVideo); await torrentClient.streamVideo(finalMagnet, this.modalVideo);
// Periodically mirror main player stats into the modal
const updateInterval = setInterval(() => { const updateInterval = setInterval(() => {
if (!document.body.contains(this.modalVideo)) { if (!document.body.contains(this.modalVideo)) {
clearInterval(updateInterval); clearInterval(updateInterval);
@@ -934,8 +958,9 @@ class bitvidApp {
if (progress) this.modalProgress.style.width = progress.style.width; if (progress) this.modalProgress.style.width = progress.style.width;
if (peers) this.modalPeers.textContent = peers.textContent; if (peers) this.modalPeers.textContent = peers.textContent;
if (speed) this.modalSpeed.textContent = speed.textContent; if (speed) this.modalSpeed.textContent = speed.textContent;
if (downloaded) if (downloaded) {
this.modalDownloaded.textContent = downloaded.textContent; this.modalDownloaded.textContent = downloaded.textContent;
}
}, 1000); }, 1000);
} catch (error) { } catch (error) {
this.log("Error in playVideo:", error); this.log("Error in playVideo:", error);