2020-03-10 05:24:31 +08:00
|
|
|
import * as html from "../html.js";
|
|
|
|
import * as conf from "../conf.js";
|
2020-03-13 06:03:26 +08:00
|
|
|
import { escape } from "../mpd.js";
|
2020-03-10 05:24:31 +08:00
|
|
|
import Component from "../component.js";
|
2020-03-17 05:57:13 +08:00
|
|
|
import Search from "./search.js";
|
|
|
|
import Result from "./yt-result.js";
|
2020-03-09 21:26:39 +08:00
|
|
|
|
|
|
|
|
2019-04-15 00:09:42 +08:00
|
|
|
const decoder = new TextDecoder("utf-8");
|
|
|
|
|
|
|
|
function decodeChunk(byteArray) {
|
2019-04-15 03:02:21 +08:00
|
|
|
// \r => \n
|
|
|
|
return decoder.decode(byteArray).replace(/\u000d/g, "\n");
|
2019-04-15 00:09:42 +08:00
|
|
|
}
|
2019-03-29 04:43:18 +08:00
|
|
|
|
2020-03-09 21:26:39 +08:00
|
|
|
class YT extends Component {
|
2020-03-17 05:57:13 +08:00
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
this._search = new Search();
|
|
|
|
|
|
|
|
this._search.onSubmit = _ => {
|
|
|
|
let query = this._search.value;
|
|
|
|
query && this._doSearch(query);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-16 06:14:55 +08:00
|
|
|
connectedCallback() {
|
|
|
|
super.connectedCallback();
|
|
|
|
|
2020-03-17 05:57:13 +08:00
|
|
|
this._clear();
|
2020-03-09 21:26:39 +08:00
|
|
|
}
|
2019-03-31 05:05:33 +08:00
|
|
|
|
2020-03-17 05:57:13 +08:00
|
|
|
_clear() {
|
2020-03-16 06:14:55 +08:00
|
|
|
html.clear(this);
|
2020-03-17 05:57:13 +08:00
|
|
|
this.appendChild(this._search);
|
2020-03-16 06:14:55 +08:00
|
|
|
}
|
|
|
|
|
2020-03-17 05:57:13 +08:00
|
|
|
async _doSearch(query) {
|
|
|
|
this._clear();
|
|
|
|
this._search.pending(true);
|
2020-03-16 06:14:55 +08:00
|
|
|
|
2020-03-18 05:02:12 +08:00
|
|
|
let url = `/youtube?q=${encodeURIComponent(query)}&limit=${encodeURIComponent(conf.ytLimit)}`;
|
|
|
|
let response = await fetch(url);
|
2020-06-24 19:40:29 +08:00
|
|
|
if (response.status == 200) {
|
|
|
|
let results = await response.json();
|
|
|
|
results.forEach(result => {
|
|
|
|
let node = new Result(result.title);
|
|
|
|
this.appendChild(node);
|
|
|
|
node.addButton("download", () => this._download(result.id));
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
let text = await response.text();
|
|
|
|
alert(text);
|
|
|
|
}
|
2019-03-31 05:05:33 +08:00
|
|
|
|
2020-03-17 05:57:13 +08:00
|
|
|
this._search.pending(false);
|
2019-03-31 05:05:33 +08:00
|
|
|
}
|
2019-03-29 04:43:18 +08:00
|
|
|
|
2019-04-15 03:02:21 +08:00
|
|
|
|
2020-03-17 05:57:13 +08:00
|
|
|
async _download(id) {
|
|
|
|
this._clear();
|
2019-04-15 03:02:21 +08:00
|
|
|
|
2020-03-17 05:57:13 +08:00
|
|
|
let pre = html.node("pre", {}, "", this);
|
|
|
|
this._search.pending(true);
|
2019-04-15 03:02:21 +08:00
|
|
|
|
2020-03-09 21:26:39 +08:00
|
|
|
let body = new URLSearchParams();
|
2020-03-17 05:57:13 +08:00
|
|
|
body.set("id", id);
|
2020-03-09 21:26:39 +08:00
|
|
|
let response = await fetch("/youtube", {method:"POST", body});
|
2019-04-15 03:02:21 +08:00
|
|
|
|
2020-03-09 21:26:39 +08:00
|
|
|
let reader = response.body.getReader();
|
|
|
|
while (true) {
|
|
|
|
let { done, value } = await reader.read();
|
|
|
|
if (done) { break; }
|
|
|
|
pre.textContent += decodeChunk(value);
|
|
|
|
pre.scrollTop = pre.scrollHeight;
|
|
|
|
}
|
|
|
|
reader.releaseLock();
|
2019-03-29 04:43:18 +08:00
|
|
|
|
2020-03-17 05:57:13 +08:00
|
|
|
this._search.pending(false);
|
2020-03-09 21:26:39 +08:00
|
|
|
|
|
|
|
if (response.status == 200) {
|
2020-03-13 06:03:26 +08:00
|
|
|
this._mpd.command(`update ${escape(conf.ytPath)}`);
|
2020-03-09 21:26:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_onComponentChange(c, isThis) {
|
2020-03-17 05:57:13 +08:00
|
|
|
const wasHidden = this.hidden;
|
2020-03-09 21:26:39 +08:00
|
|
|
this.hidden = !isThis;
|
2020-03-17 05:57:13 +08:00
|
|
|
|
2020-06-24 19:40:29 +08:00
|
|
|
if (!wasHidden && isThis) { this._clear(); }
|
2020-03-09 21:26:39 +08:00
|
|
|
}
|
2019-03-29 04:43:18 +08:00
|
|
|
}
|
2020-03-09 21:26:39 +08:00
|
|
|
|
|
|
|
customElements.define("cyp-yt", YT);
|