mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2025-09-09 15:38:44 +00:00
added "copy magnet link" button so anyone can seed videos they like
added "copy magnet link" button so anyone can seed videos they like. Also, added non-functioning share button as placeholder.
This commit is contained in:
BIN
src/assets/gif/please-stand-by.gif
Normal file
BIN
src/assets/gif/please-stand-by.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 MiB |
1
src/assets/svg/copy-magnet.svg
Normal file
1
src/assets/svg/copy-magnet.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M17.374 20.235c2.444-2.981 6.626-8.157 6.626-8.157l-3.846-3.092s-2.857 3.523-6.571 8.097c-4.312 5.312-11.881-2.41-6.671-6.671 4.561-3.729 8.097-6.57 8.097-6.57l-3.092-3.842s-5.173 4.181-8.157 6.621c-2.662 2.175-3.76 4.749-3.76 7.24 0 5.254 4.867 10.139 10.121 10.139 2.487 0 5.064-1.095 7.253-3.765zm4.724-7.953l-1.699 2.111-1.74-1.397 1.701-2.114 1.738 1.4zm-10.386-10.385l1.4 1.738-2.113 1.701-1.397-1.74 2.11-1.699z"/></svg>
|
After Width: | Height: | Size: 519 B |
1
src/assets/svg/share-video.svg
Normal file
1
src/assets/svg/share-video.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M5 7c2.761 0 5 2.239 5 5s-2.239 5-5 5-5-2.239-5-5 2.239-5 5-5zm11.122 12.065c-.073.301-.122.611-.122.935 0 2.209 1.791 4 4 4s4-1.791 4-4-1.791-4-4-4c-1.165 0-2.204.506-2.935 1.301l-5.488-2.927c-.23.636-.549 1.229-.943 1.764l5.488 2.927zm7.878-15.065c0-2.209-1.791-4-4-4s-4 1.791-4 4c0 .324.049.634.122.935l-5.488 2.927c.395.535.713 1.127.943 1.764l5.488-2.927c.731.795 1.77 1.301 2.935 1.301 2.209 0 4-1.791 4-4z"/></svg>
|
After Width: | Height: | Size: 513 B |
@@ -14,7 +14,7 @@
|
||||
<div class="flex items-center px-6 py-4">
|
||||
<button
|
||||
id="closeModal"
|
||||
class="back-button flex items-center justify-center w-10 h-10 rounded-full bg-black/50 hover:bg-black/70 transition-all duration-200 backdrop-blur"
|
||||
class="back-button flex items-center justify-center w-10 h-10 rounded-full bg-black/50 hover:bg-black/70 transition-all duration-200 backdrop-blur focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-black focus:ring-blue-500"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@@ -39,9 +39,28 @@
|
||||
</div>
|
||||
|
||||
<div class="video-info p-6">
|
||||
<!-- Rest of the content stays the same -->
|
||||
<!-- Video Title -->
|
||||
<h2 id="videoTitle" class="text-2xl font-bold mb-2 text-white"></h2>
|
||||
<!-- Title and icons row -->
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<h2 id="videoTitle" class="text-2xl font-bold text-white"></h2>
|
||||
<div class="flex items-center space-x-2">
|
||||
<!-- Copy Magnet Button (circular) -->
|
||||
<button id="copyMagnetBtn" class="icon-button">
|
||||
<img
|
||||
src="assets/svg/copy-magnet.svg"
|
||||
alt="Copy Magnet"
|
||||
class="icon-image"
|
||||
/>
|
||||
</button>
|
||||
<!-- Share Button (circular) -->
|
||||
<button id="shareBtn" class="icon-button">
|
||||
<img
|
||||
src="assets/svg/share-video.svg"
|
||||
alt="Share Video"
|
||||
class="icon-image"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Video Timestamp -->
|
||||
<div
|
||||
|
@@ -1,5 +1,3 @@
|
||||
/* css/style.css */
|
||||
|
||||
:root {
|
||||
--color-bg: #0f172a;
|
||||
--color-card: #1e293b;
|
||||
@@ -93,12 +91,17 @@ header img {
|
||||
inset: 0;
|
||||
background-color: rgb(0 0 0 / 0.9);
|
||||
z-index: 50;
|
||||
display: flex;
|
||||
display: none; /* Hidden by default */
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
|
||||
/* If you ever want to show it, add ".flex" class dynamically */
|
||||
#playerModal.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* Modal Content Container */
|
||||
.modal-content {
|
||||
width: 100%;
|
||||
@@ -106,6 +109,18 @@ header img {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #0f172a;
|
||||
animation: fadeIn 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Video Container */
|
||||
@@ -214,8 +229,8 @@ textarea:focus {
|
||||
ring: 2px var(--color-primary);
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
button {
|
||||
/* Global button styles -- only apply to normal (non-icon) buttons */
|
||||
button:not(.icon-button) {
|
||||
padding: 0.75rem 1.5rem;
|
||||
background-color: var(--color-primary);
|
||||
color: white;
|
||||
@@ -224,12 +239,12 @@ button {
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
button:not(.icon-button):hover {
|
||||
background-color: var(--color-secondary);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
button:focus {
|
||||
button:not(.icon-button):focus {
|
||||
outline: none;
|
||||
ring: 2px var(--color-primary);
|
||||
}
|
||||
@@ -268,16 +283,6 @@ button:focus {
|
||||
border: 1px solid rgb(34 197 94 / 0.2);
|
||||
}
|
||||
|
||||
/* Modal Display */
|
||||
#playerSection,
|
||||
#playerModal {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#playerModal.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 640px) {
|
||||
#videoList {
|
||||
@@ -310,7 +315,7 @@ footer a:hover {
|
||||
inset: 0;
|
||||
background-color: rgb(0 0 0 / 0.9);
|
||||
z-index: 50;
|
||||
display: flex;
|
||||
display: none; /* hidden by default */
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
@@ -374,9 +379,7 @@ footer a:hover {
|
||||
}
|
||||
|
||||
#disclaimerModal .modal-scroll {
|
||||
max-height: calc(
|
||||
90vh - 5rem
|
||||
); /* Account for button container and padding */
|
||||
max-height: calc(90vh - 5rem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,3 +424,51 @@ footer a:hover {
|
||||
background-color: rgb(31 41 55 / 0.5);
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
|
||||
/* --- New Classes for Icon Buttons & Images --- */
|
||||
|
||||
/* Circular icon buttons */
|
||||
.icon-button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
/* Fixed width/height for a perfect circle */
|
||||
width: 2.5rem; /* 40px */
|
||||
height: 2.5rem; /* 40px */
|
||||
|
||||
line-height: 0;
|
||||
background-color: #3f3f46; /* Gray 700 */
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 9999px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
|
||||
/* Hover state: slightly lighter gray */
|
||||
.icon-button:hover {
|
||||
background-color: #52525b; /* Gray 600 */
|
||||
}
|
||||
|
||||
/* Focus/active states: red ring */
|
||||
.icon-button:focus,
|
||||
.icon-button:active {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.6); /* Red ring #dc2626 */
|
||||
}
|
||||
|
||||
/* Icon images (force white if originally black) */
|
||||
.icon-image {
|
||||
width: 1.25rem; /* 20px */
|
||||
height: 1.25rem; /* 20px */
|
||||
|
||||
/*
|
||||
If your icon is black and you want to invert it to white, use this:
|
||||
filter: brightness(0) invert(1);
|
||||
|
||||
If your icon is already white, keep it commented out or remove it.
|
||||
*/
|
||||
|
||||
pointer-events: none;
|
||||
}
|
||||
|
@@ -45,6 +45,10 @@ class bitvidApp {
|
||||
this.creatorName = null;
|
||||
this.creatorNpub = null;
|
||||
|
||||
// New buttons for magnet copy and share
|
||||
this.copyMagnetBtn = null;
|
||||
this.shareBtn = null;
|
||||
|
||||
// Notification Containers
|
||||
this.errorContainer = document.getElementById("errorContainer");
|
||||
this.successContainer = document.getElementById("successContainer");
|
||||
@@ -165,6 +169,10 @@ class bitvidApp {
|
||||
this.creatorName = document.getElementById("creatorName");
|
||||
this.creatorNpub = document.getElementById("creatorNpub");
|
||||
|
||||
// New icons for magnet copy and share
|
||||
this.copyMagnetBtn = document.getElementById("copyMagnetBtn");
|
||||
this.shareBtn = document.getElementById("shareBtn");
|
||||
|
||||
// Add scroll behavior for nav
|
||||
let lastScrollY = 0;
|
||||
const modalNav = document.getElementById("modalNav");
|
||||
@@ -283,6 +291,25 @@ class bitvidApp {
|
||||
});
|
||||
}
|
||||
|
||||
// Copy magnet link
|
||||
if (this.copyMagnetBtn) {
|
||||
this.copyMagnetBtn.addEventListener("click", () => {
|
||||
if (this.currentMagnetUri) {
|
||||
navigator.clipboard
|
||||
.writeText(this.currentMagnetUri)
|
||||
.then(() => this.showSuccess("Magnet link copied to clipboard!"))
|
||||
.catch(() => this.showError("Failed to copy magnet link."));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Share button (no action for now)
|
||||
if (this.shareBtn) {
|
||||
this.shareBtn.addEventListener("click", () => {
|
||||
this.log("Share button clicked (not implemented).");
|
||||
});
|
||||
}
|
||||
|
||||
// Cleanup on page unload
|
||||
window.addEventListener("beforeunload", async () => {
|
||||
await this.cleanup();
|
||||
@@ -804,6 +831,7 @@ class bitvidApp {
|
||||
|
||||
const decodedMagnet = decodeURIComponent(magnetURI);
|
||||
|
||||
// Prevent re-invoking the same video
|
||||
if (this.currentMagnetUri === decodedMagnet) {
|
||||
this.log("Same video requested - already playing");
|
||||
return;
|
||||
@@ -830,13 +858,11 @@ class bitvidApp {
|
||||
) {
|
||||
this.log("User owns a private video => decrypting magnet link...");
|
||||
video.magnet = fakeDecrypt(video.magnet);
|
||||
// Mark it so we don't do it again
|
||||
video.alreadyDecrypted = true;
|
||||
}
|
||||
|
||||
const finalMagnet = video.magnet;
|
||||
|
||||
// Profile fetch
|
||||
let creatorProfile = {
|
||||
name: "Unknown",
|
||||
picture: `https://robohash.org/${video.pubkey}`,
|
||||
@@ -849,8 +875,6 @@ class bitvidApp {
|
||||
limit: 1,
|
||||
},
|
||||
]);
|
||||
|
||||
// Ensure userEvents isn't empty before accessing [0]
|
||||
if (userEvents.length > 0 && userEvents[0]?.content) {
|
||||
const profile = JSON.parse(userEvents[0].content);
|
||||
creatorProfile = {
|
||||
|
Reference in New Issue
Block a user