diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js
index 98883e23..9655ea27 100644
--- a/copyparty/web/browser.js
+++ b/copyparty/web/browser.js
@@ -305,6 +305,7 @@ var Ls = {
"mb_play": "play",
"mm_hashplay": "play this audio file?",
+ "mm_m3u": "press Enter/OK
to Play\npress ESC/Cancel
to Edit",
"mp_breq": "need firefox 82+ or chrome 73+ or iOS 15+",
"mm_bload": "now loading...",
"mm_bconv": "converting to {0}, please wait...",
@@ -911,6 +912,7 @@ var Ls = {
"mb_play": "lytt",
"mm_hashplay": "spill denne sangen?",
+ "mm_m3u": "trykk Enter/OK
for å spille\ntrykk ESC/Avbryt
for å redigere",
"mp_breq": "krever firefox 82+, chrome 73+, eller iOS 15+",
"mm_bload": "laster inn...",
"mm_bconv": "konverterer til {0}, vent litt...",
@@ -2630,6 +2632,7 @@ if (can_owa && APPLE && / OS ([1-9]|1[0-7])_/.test(UA))
mpl.init_ac2();
+var re_m3u = /\.(m3u8?)$/i;
var re_au_native = (can_ogg || have_acode) ? /\.(aac|flac|m4a|mp3|ogg|opus|wav)$/i : /\.(aac|flac|m4a|mp3|wav)$/i,
re_au_all = /\.(aac|ac3|aif|aiff|alac|alaw|amr|ape|au|dfpwm|dts|flac|gsm|it|itgz|itxz|itz|m4a|mdgz|mdxz|mdz|mo3|mod|mp2|mp3|mpc|mptm|mt2|mulaw|ogg|okt|opus|ra|s3m|s3gz|s3xz|s3z|tak|tta|ulaw|wav|wma|wv|xm|xmgz|xmxz|xmz|xpk|3gp|asf|avi|flv|m4v|mkv|mov|mp4|mpeg|mpeg2|mpegts|mpg|mpg2|nut|ogm|ogv|rm|ts|vob|webm|wmv)$/i;
@@ -2656,9 +2659,9 @@ function MPlayer() {
link = link[link.length - 1];
var url = link.getAttribute('href'),
- m = re_audio.exec(url.split('?')[0]);
+ fn = url.split('?')[0];
- if (m) {
+ if (re_audio.exec(fn)) {
var tid = link.getAttribute('id');
r.order.push(tid);
r.tracks[tid] = url;
@@ -2666,6 +2669,11 @@ function MPlayer() {
ebi('a' + tid).onclick = ev_play;
clmod(trs[a], 'au', 1);
}
+ else if (re_m3u.exec(fn)) {
+ var tid = link.getAttribute('id');
+ tds[0].innerHTML = '' + L.mb_play + '';
+ ebi('a' + tid).onclick = ev_load_m3u;
+ }
}
r.vol = clamp(fcfg_get('vol', IPHONE ? 1 : dvol / 100), 0, 1);
@@ -4395,6 +4403,11 @@ function eval_hash() {
goto(v.slice(3));
return;
}
+
+ if (v.startsWith("#m3u=")) {
+ load_m3u(v.slice(5));
+ return;
+ }
}
@@ -6900,7 +6913,7 @@ var ahotkeys = function (e) {
// search
-(function () {
+var search_ui = (function () {
var sconf = [
[
L.s_sz,
@@ -6935,7 +6948,8 @@ var ahotkeys = function (e) {
]
];
- var trs = [],
+ var r = {},
+ trs = [],
orig_url = null,
orig_html = null,
cap = 125;
@@ -7142,13 +7156,19 @@ var ahotkeys = function (e) {
search_in_progress = 0;
srch_msg(false, '');
- var res = JSON.parse(this.responseText),
- tagord = res.tag_order;
+ var res = JSON.parse(this.responseText);
+ r.render(res, this, true);
+ }
- sortfiles(res.hits);
+ r.render = function (res, xhr, sort) {
+ var tagord = res.tag_order;
+
+ srch_msg(false, '');
+ if (sort)
+ sortfiles(res.hits);
var ofiles = ebi('files');
- if (ofiles.getAttribute('ts') > this.ts)
+ if (xhr && ofiles.getAttribute('ts') > xhr.ts)
return;
treectl.hide();
@@ -7200,19 +7220,21 @@ var ahotkeys = function (e) {
}
ofiles = set_files_html(html.join('\n'));
- ofiles.setAttribute("ts", this.ts);
- ofiles.setAttribute("q_raw", this.q_raw);
+ ofiles.setAttribute("ts", xhr ? xhr.ts : 1);
+ ofiles.setAttribute("q_raw", xhr ? xhr.q_raw : 'playlist');
set_vq();
mukey.render();
reload_browser();
filecols.set_style(['File Name']);
- sethash('q=' + uricom_enc(this.q_raw));
+ if (xhr)
+ sethash('q=' + uricom_enc(xhr.q_raw));
+
ebi('unsearch').onclick = unsearch;
var m = ebi('moar');
if (m)
m.onclick = moar;
- }
+ };
function unsearch(e) {
ev(e);
@@ -7229,9 +7251,93 @@ var ahotkeys = function (e) {
cap *= 2;
do_search();
}
+
+ return r;
})();
+function ev_load_m3u(e) {
+ ev(e);
+ var id = this.getAttribute('id').slice(1),
+ url = ebi(id).getAttribute('href').split('?')[0];
+
+ modal.confirm(L.mm_m3u,
+ function () { load_m3u(url); },
+ function () { window.location = url + '?edit'}
+ );
+ return false;
+}
+function load_m3u(url) {
+ var xhr = new XHR();
+ xhr.open('GET', url, true);
+ xhr.onload = render_m3u;
+ xhr.url = url;
+ xhr.send();
+ return false;
+}
+function render_m3u() {
+ if (!xhrchk(this, L.tv_xe1, L.tv_xe2))
+ return;
+
+ var evp = get_evpath(),
+ m3u = this.responseText,
+ xtd = m3u.slice(0, 12).indexOf('#EXTM3U') + 1,
+ lines = m3u.replace(/\r/g, '\n').split('\n'),
+ dur = 1,
+ artist = '',
+ title = '',
+ ret = {'hits': [], 'tag_order': ['artist', 'title', '.dur'], 'trunc': false};
+
+ for (var a = 0; a < lines.length; a++) {
+ var ln = lines[a].trim();
+ if (xtd && ln.startsWith('#')) {
+ var m = /^#EXTINF:([0-9]+)[, ](.*)/.exec(ln);
+ if (m) {
+ dur = m[1];
+ title = m[2];
+ var ofs = title.indexOf(' - ');
+ if (ofs > 0) {
+ artist = title.slice(0, ofs);
+ title = title.slice(ofs + 3);
+ }
+ }
+ continue;
+ }
+ if (ln.indexOf('.') < 0)
+ continue;
+
+ var n = ret.hits.length + 1,
+ url = ln;
+
+ if (url.indexOf(':\\')) // C:\
+ url = url.split(/\\/g).pop();
+
+ url = url.replace(/\\/g, '/');
+ url = uricom_enc(url).replace(/%2f/gi, '/')
+
+ if (!url.startsWith('/'))
+ url = vjoin(evp, url);
+
+ ret.hits.push({
+ "ts": 946684800 + n,
+ "sz": 100000 + n,
+ "rp": url,
+ "tags": {".dur": dur, "artist": artist, "title": title}
+ });
+ dur = 1;
+ artist = title = '';
+ }
+
+ search_ui.render(ret, null, false);
+ sethash('m3u=' + this.url.split('?')[0].split('/').pop());
+ goto();
+
+ var el = QS('#files>tbody>tr.au>td>a.play');
+ if (el)
+ el.click();
+}
+
+
function aligngriditems() {
if (!treectl)
return;