mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2025-09-10 07:58:47 +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">
|
<div class="flex items-center px-6 py-4">
|
||||||
<button
|
<button
|
||||||
id="closeModal"
|
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
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
@@ -39,9 +39,28 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="video-info p-6">
|
<div class="video-info p-6">
|
||||||
<!-- Rest of the content stays the same -->
|
<!-- Title and icons row -->
|
||||||
<!-- Video Title -->
|
<div class="flex items-center justify-between mb-2">
|
||||||
<h2 id="videoTitle" class="text-2xl font-bold mb-2 text-white"></h2>
|
<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 -->
|
<!-- Video Timestamp -->
|
||||||
<div
|
<div
|
||||||
|
@@ -1,5 +1,3 @@
|
|||||||
/* css/style.css */
|
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--color-bg: #0f172a;
|
--color-bg: #0f172a;
|
||||||
--color-card: #1e293b;
|
--color-card: #1e293b;
|
||||||
@@ -93,12 +91,17 @@ header img {
|
|||||||
inset: 0;
|
inset: 0;
|
||||||
background-color: rgb(0 0 0 / 0.9);
|
background-color: rgb(0 0 0 / 0.9);
|
||||||
z-index: 50;
|
z-index: 50;
|
||||||
display: flex;
|
display: none; /* Hidden by default */
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overscroll-behavior: contain;
|
overscroll-behavior: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If you ever want to show it, add ".flex" class dynamically */
|
||||||
|
#playerModal.flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
/* Modal Content Container */
|
/* Modal Content Container */
|
||||||
.modal-content {
|
.modal-content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -106,6 +109,18 @@ header img {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background-color: #0f172a;
|
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 */
|
/* Video Container */
|
||||||
@@ -214,8 +229,8 @@ textarea:focus {
|
|||||||
ring: 2px var(--color-primary);
|
ring: 2px var(--color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Buttons */
|
/* Global button styles -- only apply to normal (non-icon) buttons */
|
||||||
button {
|
button:not(.icon-button) {
|
||||||
padding: 0.75rem 1.5rem;
|
padding: 0.75rem 1.5rem;
|
||||||
background-color: var(--color-primary);
|
background-color: var(--color-primary);
|
||||||
color: white;
|
color: white;
|
||||||
@@ -224,12 +239,12 @@ button {
|
|||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
button:hover {
|
button:not(.icon-button):hover {
|
||||||
background-color: var(--color-secondary);
|
background-color: var(--color-secondary);
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
button:focus {
|
button:not(.icon-button):focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
ring: 2px var(--color-primary);
|
ring: 2px var(--color-primary);
|
||||||
}
|
}
|
||||||
@@ -268,16 +283,6 @@ button:focus {
|
|||||||
border: 1px solid rgb(34 197 94 / 0.2);
|
border: 1px solid rgb(34 197 94 / 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Modal Display */
|
|
||||||
#playerSection,
|
|
||||||
#playerModal {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#playerModal.flex {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Responsive Design */
|
/* Responsive Design */
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
#videoList {
|
#videoList {
|
||||||
@@ -310,7 +315,7 @@ footer a:hover {
|
|||||||
inset: 0;
|
inset: 0;
|
||||||
background-color: rgb(0 0 0 / 0.9);
|
background-color: rgb(0 0 0 / 0.9);
|
||||||
z-index: 50;
|
z-index: 50;
|
||||||
display: flex;
|
display: none; /* hidden by default */
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overscroll-behavior: contain;
|
overscroll-behavior: contain;
|
||||||
@@ -374,9 +379,7 @@ footer a:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#disclaimerModal .modal-scroll {
|
#disclaimerModal .modal-scroll {
|
||||||
max-height: calc(
|
max-height: calc(90vh - 5rem);
|
||||||
90vh - 5rem
|
|
||||||
); /* Account for button container and padding */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,3 +424,51 @@ footer a:hover {
|
|||||||
background-color: rgb(31 41 55 / 0.5);
|
background-color: rgb(31 41 55 / 0.5);
|
||||||
backdrop-filter: blur(4px);
|
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.creatorName = null;
|
||||||
this.creatorNpub = null;
|
this.creatorNpub = null;
|
||||||
|
|
||||||
|
// New buttons for magnet copy and share
|
||||||
|
this.copyMagnetBtn = null;
|
||||||
|
this.shareBtn = null;
|
||||||
|
|
||||||
// Notification Containers
|
// Notification Containers
|
||||||
this.errorContainer = document.getElementById("errorContainer");
|
this.errorContainer = document.getElementById("errorContainer");
|
||||||
this.successContainer = document.getElementById("successContainer");
|
this.successContainer = document.getElementById("successContainer");
|
||||||
@@ -165,6 +169,10 @@ class bitvidApp {
|
|||||||
this.creatorName = document.getElementById("creatorName");
|
this.creatorName = document.getElementById("creatorName");
|
||||||
this.creatorNpub = document.getElementById("creatorNpub");
|
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
|
// Add scroll behavior for nav
|
||||||
let lastScrollY = 0;
|
let lastScrollY = 0;
|
||||||
const modalNav = document.getElementById("modalNav");
|
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
|
// Cleanup on page unload
|
||||||
window.addEventListener("beforeunload", async () => {
|
window.addEventListener("beforeunload", async () => {
|
||||||
await this.cleanup();
|
await this.cleanup();
|
||||||
@@ -804,6 +831,7 @@ class bitvidApp {
|
|||||||
|
|
||||||
const decodedMagnet = decodeURIComponent(magnetURI);
|
const decodedMagnet = decodeURIComponent(magnetURI);
|
||||||
|
|
||||||
|
// Prevent re-invoking the same video
|
||||||
if (this.currentMagnetUri === decodedMagnet) {
|
if (this.currentMagnetUri === decodedMagnet) {
|
||||||
this.log("Same video requested - already playing");
|
this.log("Same video requested - already playing");
|
||||||
return;
|
return;
|
||||||
@@ -830,13 +858,11 @@ class bitvidApp {
|
|||||||
) {
|
) {
|
||||||
this.log("User owns a private video => decrypting magnet link...");
|
this.log("User owns a private video => decrypting magnet link...");
|
||||||
video.magnet = fakeDecrypt(video.magnet);
|
video.magnet = fakeDecrypt(video.magnet);
|
||||||
// Mark it so we don't do it again
|
|
||||||
video.alreadyDecrypted = true;
|
video.alreadyDecrypted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const finalMagnet = video.magnet;
|
const finalMagnet = video.magnet;
|
||||||
|
|
||||||
// Profile fetch
|
|
||||||
let creatorProfile = {
|
let creatorProfile = {
|
||||||
name: "Unknown",
|
name: "Unknown",
|
||||||
picture: `https://robohash.org/${video.pubkey}`,
|
picture: `https://robohash.org/${video.pubkey}`,
|
||||||
@@ -849,8 +875,6 @@ class bitvidApp {
|
|||||||
limit: 1,
|
limit: 1,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Ensure userEvents isn't empty before accessing [0]
|
|
||||||
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);
|
||||||
creatorProfile = {
|
creatorProfile = {
|
||||||
|
Reference in New Issue
Block a user