Much improved search UI, fallbacks for images.

This commit is contained in:
Violet 2023-10-29 00:01:40 -05:00
parent 00eb2b5979
commit 9126a9f1c3
7 changed files with 69 additions and 33 deletions

View file

@ -54,24 +54,28 @@ app.get("/search", async (req, res) => {
for (let index = 0; index < videos.length; index++) { for (let index = 0; index < videos.length; index++) {
const result = videos[index]; const result = videos[index];
addedHTML += ` addedHTML += `
<div class="videoResult container row"> <div class="col-xxl-4 col-lg-6 col-md-12 col-sm-6 resultContainer">
<div class="col-md-4 col-sm-6"> <div class="videoResult container-fluid row">
<div class="col-md-4 col-lg-6 thumbparent">
<a class="videoLink" href="/watch?q=${result.id}"> <a class="videoLink" href="/watch?q=${result.id}">
<img src="${result.thumbnail}"> <img class="thumbnail" src="${result.thumbnail}; /Images/UnknownVideo.jpg">
</a> </a>
</div> </div>
<div class="col-md-8 col-sm-6"> <div class="col-md-8 col-lg-6">
<a class="videoLink" href="/watch?q=${result.id}"> <a class="videoLink" href="/watch?q=${result.id}">
<h3>${result.title}</h3> <p style="font-size: 1.25rem;">${result.title || "No Title Found"}</p>
<p>${result.description}</p><br> <p class="resultDescription">${result.description.substring(0, 75) + "..." || "No Description"}</p>
<img src="${result.channel.thumbnail}" class="minipfp"> </a>
<a style="color: white; class="videoLink" href="${result.channel.link}">${result.channel.name}</a> </div>
<div style="display: block; width: 100%; ">
<a style="color: white; margin: 10px; display: inline-block;" href="${result.channel.link}">
<img src="${result.channel.thumbnail}; /Images/UnknownPFP.jpg" class="minipfp">
${result.channel.name}
</a> </a>
</div> </div>
</div> </div>
</div>
` `
console.log(result)
} }
res.send(html.replace("{RESULTS}", addedHTML)) res.send(html.replace("{RESULTS}", addedHTML))
@ -136,9 +140,9 @@ app.get("/video", async (req, res) => {
var debounce = true var debounce = true
var dp = 0 var dp = 0
ytdl(id, { filter: "videoandaudio", quality: "highest", format: 'mp4' }) ytdl(id, { filter: 'videoandaudio', quality: "highest", format: 'mp4' })
.on("progress", (chunk, ct, et) => { .on("progress", (chunk, ct, et) => {
if (debounce) { if (debounce && ct > Math.min(et, 5000000)) {
debounce = false debounce = false
videoCache[id] = { videoCache[id] = {
"path": vidpath, "path": vidpath,
@ -149,7 +153,7 @@ app.get("/video", async (req, res) => {
ready(vidpath, fs.readFileSync(vidpath)) ready(vidpath, fs.readFileSync(vidpath))
} }
var percent = Math.round(ct / et * 100) var percent = Math.round(ct / et * 100)
if (percent > dp) { if (!debounce && percent > dp) {
dp = percent dp = percent
videoCache[id]["download%"] = dp videoCache[id]["download%"] = dp
} }
@ -206,7 +210,7 @@ app.get("/watch", async (req, res) => {
if (!(id in videoCache && videoCache[id]["downloaded"] == true)) { if (!(id in videoCache && videoCache[id]["downloaded"] == true)) {
html = html.replace("{CACHE_WARNING}", ` html = html.replace("{CACHE_WARNING}", `
<p style="color: lightgray">Please note that this video has not been fully cached, and may have trouble loading! <p style="color: lightgray">Please note that this video has not been fully cached, and may have trouble loading!
<br>{DOWNLOAD_PERCENT}% cached (as of page load).</p> <br>{DOWNLOAD_PERCENT}% cached as of page load. If content fails to load after a minute, reload the page!</p>
`) `)
if (id in videoCache && "download%" in videoCache[id]) { if (id in videoCache && "download%" in videoCache[id]) {
html = html.replace("{DOWNLOAD_PERCENT}", videoCache[id]["download%"]) html = html.replace("{DOWNLOAD_PERCENT}", videoCache[id]["download%"])

View file

@ -32,10 +32,10 @@
<hr> <hr>
<main> <main>
<h2 id="title">{VIDEO_TITLE}</h2> <h2 id="title">{VIDEO_TITLE}</h2>
{CACHE_WARNING}
<div id="description"> <div id="description">
{CACHE_WARNING}
<h2>Description: <br></h2> <h2>Description: <br></h2>
<p id="description">{VIDEO_DESCRIPTION}</p> <p>{VIDEO_DESCRIPTION}</p>
</div> </div>
</main> </main>
</body> </body>

View file

@ -14,10 +14,10 @@
<body> <body>
<div id="titleBar" class="row container-fluid"> <div id="titleBar" class="row container-fluid">
<div class="col-sm-5"> <div class="col-5">
<h1><a href="/">Simpletube</a></h1> <h1><a href="/">Simpletube</a></h1>
</div> </div>
<div class="col-sm-7"> <div class="col-7">
<form action="/search"> <form action="/search">
<input type="text" placeholder="Search" name="q" value="{SEARCH}"> <input type="text" placeholder="Search" name="q" value="{SEARCH}">
</form> </form>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -13,7 +13,7 @@
</head> </head>
<body> <body>
<div id="titleBar" class="row container"> <div id="titleBar" class="row container-fluid">
<div class="col-sm-5"> <div class="col-sm-5">
<h1><a href="/">Simpletube</a></h1> <h1><a href="/">Simpletube</a></h1>
</div> </div>

View file

@ -17,7 +17,7 @@ body, html {
} */ } */
a:not(h1 > a):not(.videoLink) { a:not(h1 > a):not(.videoLink) {
font-size: 1.5rem; font-size: 1.25rem;
background-color: black; background-color: black;
padding: 8px; padding: 8px;
margin: 5px; margin: 5px;
@ -25,6 +25,7 @@ a:not(h1 > a):not(.videoLink) {
border-radius: 15px; border-radius: 15px;
color: rgb(240, 220, 255); color: rgb(240, 220, 255);
text-decoration: none; text-decoration: none;
display: inline;
} }
.videoLink { .videoLink {
@ -42,7 +43,7 @@ a:not(h1 > a):not(.videoLink) {
} }
#titleBar { #titleBar {
width: 100vw; width: 100%;
background-color: rgb(5, 0, 10); background-color: rgb(5, 0, 10);
/* border: 0px; */ /* border: 0px; */
border: 2px transparent solid; border: 2px transparent solid;
@ -50,7 +51,7 @@ a:not(h1 > a):not(.videoLink) {
position: sticky; position: sticky;
top: 0px; top: 0px;
margin: 0; margin: 0;
padding: 0; padding: 10px;
} }
#titleBar > div > * { #titleBar > div > * {
@ -109,22 +110,52 @@ a:not(h1 > a):not(.videoLink) {
} }
p { p {
padding: 5px; padding: 2px;
} }
.videoResult { .videoResult {
background-color: black; background-color: black;
border: 2px gray solid; border: 2px gray solid;
border-radius: 10px; border-radius: 10px;
padding: 10px; padding: 3px;
margin: 10px; margin: auto;
text-align: left; text-align: left;
height: 100%;
} }
img { @media (max-width: 768px) {
width: 70%; .resultContainer {
max-width: 450px;
}
} }
.resultContainer {
margin: 5px auto;
}
.thumbnail {
width: 100%;
margin: auto;
border-radius: 20px;
aspect-ratio: 16/9;
object-fit: cover;
border: 2px white solid;
margin: 5px auto;
}
.thumbparent {
justify-content: center;
align-items: center;
display: flex;
}
/* @media (max-width: 1200px) and (min-width: 992px) {
.resultDescription {
display: none;
}
} */
.minipfp { .minipfp {
width: 60px; width: 60px;
height: 60px; height: 60px;
@ -132,4 +163,5 @@ img {
border-radius: 50%; border-radius: 50%;
padding: 0; padding: 0;
margin: 0; margin: 0;
display: inline-block;
} }