yt tuning

This commit is contained in:
Ondrej Zara 2019-04-14 21:02:21 +02:00
parent 0e339fc88d
commit e0ab191d72
6 changed files with 85 additions and 74 deletions

View file

@ -38,6 +38,7 @@ button {
flex-direction: row;
align-items: center;
display: inline-flex;
white-space: nowrap;
background-color: transparent;
padding: 0;
border: none;
@ -576,8 +577,6 @@ nav ul li.active {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
#yt header {
display: flex;
@ -632,36 +631,32 @@ nav ul li.active {
#yt li:nth-child(odd) {
background-color: var(--bg-alt);
}
#yt .go {
width: 96px;
height: 96px;
justify-content: center;
#yt header {
border-bottom: 1px solid var(--fg);
}
#yt .go:disabled {
position: relative;
#yt header button + button {
margin-left: 16px;
}
#yt .go:disabled::before {
content: "";
display: block;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
border-top: 3px solid var(--primary);
border-radius: 50%;
animation: rotate linear 3s infinite;
#yt .clear {
margin-left: auto;
}
#yt p {
margin: 16px 8px;
#yt pre {
flex-grow: 1;
overflow: auto;
white-space: pre-wrap;
}
@keyframes rotate {
#yt.pending header {
background-image: linear-gradient(var(--primary), var(--primary));
background-repeat: no-repeat;
background-size: 25% 4px;
animation: bar ease-in-out 3s alternate infinite;
}
@keyframes bar {
0% {
transform: rotate(0deg);
background-position: 0 100%;
}
100% {
transform: rotate(360deg);
background-position: 100% 100%;
}
}
#settings {

View file

@ -35,6 +35,7 @@ button {
.flex-row;
display: inline-flex;
white-space: nowrap;
background-color: transparent;
padding: 0;

View file

@ -1,39 +1,33 @@
#yt {
.component;
align-items: center;
justify-content: center;
header {
border-bottom: 1px solid var(--fg);
.go {
width: 96px;
height: 96px;
justify-content: center;
&:disabled {
position: relative;
&::before {
content: "";
display: block;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
border-top: 3px solid var(--primary);
border-radius: 50%;
animation: rotate linear 3s infinite;
}
button + button {
margin-left: 16px;
}
}
p {
margin: 16px 8px;
.clear {
margin-left: auto;
}
pre {
flex-grow: 1;
overflow: auto;
white-space: pre-wrap;
}
&.pending header {
background-image: linear-gradient(var(--primary), var(--primary));
background-repeat: no-repeat;
background-size: 25% 4px;
animation: bar ease-in-out 3s alternate infinite;
}
}
@keyframes rotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
@keyframes bar {
0% { background-position: 0 100%; }
100% { background-position: 100% 100%; }
}

View file

@ -57,8 +57,12 @@
<ul></ul>
</section>
<section id="yt">
<button class="go" data-icon="download">Go!</button>
<p></p>
<header>
<button class="download" data-icon="download">Download</button>
<button class="search-download" data-icon="magnify">Search &amp; Download</button>
<button class="clear" data-icon="close">Clear</button>
</header>
<pre></pre>
</section>
<section id="settings">
<dl>

View file

@ -8,41 +8,58 @@ let node;
const decoder = new TextDecoder("utf-8");
function decodeChunk(byteArray) {
return decoder.decode(byteArray);
// \r => \n
return decoder.decode(byteArray).replace(/\u000d/g, "\n");
}
async function onClick(e) {
let url = prompt("Please enter a YouTube URL:");
if (!url) { return; }
async function post(q) {
let pre = node.querySelector("pre");
html.clear(pre);
let button = e.target;
button.disabled = true;
let p = node.querySelector("p");
p.textContent = "";
node.classList.add("pending");
let body = new URLSearchParams();
body.set("url", url);
body.set("q", q);
let response = await fetch("/youtube", {method:"POST", body});
let reader = response.body.getReader();
while (true) {
let { done, value } = await reader.read();
if (done) { break; }
p.textContent += decodeChunk(value);
pre.textContent += decodeChunk(value);
pre.scrollTop = pre.scrollHeight;
}
reader.releaseLock();
button.disabled = false;
node.classList.remove("pending");
if (response.status == 200) {
mpd.command(`update ${mpd.escape(conf.ytPath)}`);
}
}
function download() {
let url = prompt("Please enter a YouTube URL:");
if (!url) { return; }
post(url);
}
function search() {
let q = prompt("Please enter a search string:");
if (!q) { return; }
post(`ytsearch:${q}`);
}
function clear() {
html.clear(node.querySelector("pre"));
}
export async function activate() {}
export function init(n) {
node = n;
let button = node.querySelector(".go").addEventListener("click", onClick);
node.querySelector(".download").addEventListener("click", e => download());
node.querySelector(".search-download").addEventListener("click", e => search());
node.querySelector(".clear").addEventListener("click", e => clear());
}

View file

@ -5,16 +5,16 @@ const port = Number(process.argv[2]) || 8080;
const cmd = "youtube-dl";
//const cmd = "./test.sh";
function downloadYoutube(url, response) {
function downloadYoutube(q, response) {
response.setHeader("Content-Type", "text/plain"); // necessary for firefox to read by chunks
// response.setHeader("Content-Type", "text/plain; charset=utf-8");
// FIXME create directory
console.log("YouTube downloading", url);
console.log("YouTube downloading", q);
let args = [
"-f", "bestaudio",
"-o", `${__dirname}/_youtube/%(title)s-%(id)s.%(ext)s`,
url
q
]
let child = require("child_process").spawn(cmd, args);
@ -39,9 +39,9 @@ function handleYoutube(request, response) {
request.setEncoding("utf8");
request.on("data", chunk => str += chunk);
request.on("end", () => {
let url = require("querystring").parse(str)["url"];
if (url) {
downloadYoutube(url, response);
let q = require("querystring").parse(str)["q"];
if (q) {
downloadYoutube(q, response);
} else {
response.writeHead(404);
response.end();