From ad200f2b97d561f6a240d1bfca0d6cd2ed12ef1a Mon Sep 17 00:00:00 2001 From: ed Date: Sat, 26 Apr 2025 00:19:41 +0000 Subject: [PATCH] add ui for creating playlists --- README.md | 1 + copyparty/web/browser.css | 15 +++++++-- copyparty/web/browser.js | 69 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1742cdb0..48668b68 100644 --- a/README.md +++ b/README.md @@ -1044,6 +1044,7 @@ open the `[🎺]` media-player-settings tab to configure it, * `[full]` does a full preload by downloading the entire next file; good for unreliable connections, bad for slow connections * `[~s]` toggles the seekbar waveform display * `[/np]` enables buttons to copy the now-playing info as an irc message + * `[📻]` enables buttons to create an m3u playlist with the selected songs * `[os-ctl]` makes it possible to control audio playback from the lockscreen of your device (enables [mediasession](https://developer.mozilla.org/en-US/docs/Web/API/MediaSession)) * `[seek]` allows seeking with lockscreen controls (buggy on some devices) * `[art]` shows album art on the lockscreen diff --git a/copyparty/web/browser.css b/copyparty/web/browser.css index 14770e65..71fa8c17 100644 --- a/copyparty/web/browser.css +++ b/copyparty/web/browser.css @@ -1151,10 +1151,10 @@ html.y #widget.open { background: #fff; background: var(--bg-u3); } -#wfs, #wfm, #wzip, #wnp { +#wfs, #wfm, #wzip, #wnp, #wm3u { display: none; } -#wfs, #wzip, #wnp { +#wfs, #wzip, #wnp, #wm3u { margin-right: .2em; padding-right: .2em; border: 1px solid var(--bg-u5); @@ -1175,6 +1175,7 @@ html.y #widget.open { line-height: 1em; } #wtoggle.sel #wzip, +#wtoggle.m3u #wm3u, #wtoggle.np #wnp { display: inline-block; } @@ -1183,6 +1184,7 @@ html.y #widget.open { } #wfm a, #wnp a, +#wm3u a, #wzip a { font-size: .5em; padding: 0 .3em; @@ -1190,6 +1192,10 @@ html.y #widget.open { position: relative; display: inline-block; } +#wm3u a { + margin: -.2em .1em; + font-size: .45em; +} #wfs { font-size: .36em; text-align: right; @@ -1198,6 +1204,7 @@ html.y #widget.open { border-width: 0 .25em 0 0; } #wfm span, +#wm3u span, #wnp span { font-size: .6em; display: block; @@ -1205,6 +1212,10 @@ html.y #widget.open { #wnp span { font-size: .7em; } +#wm3u span { + font-size: .77em; + padding-top: .2em; +} #wfm a:not(.en) { opacity: .3; color: var(--fm-off); diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js index 9655ea27..af007753 100644 --- a/copyparty/web/browser.js +++ b/copyparty/web/browser.js @@ -144,6 +144,8 @@ var Ls = { "wt_seldl": "download selection as separate files$NHotkey: Y", "wt_npirc": "copy irc-formatted track info", "wt_nptxt": "copy plaintext track info", + "wt_m3ua": "add to m3u playlist (click 📻copy later)", + "wt_m3uc": "copy m3u playlist to clipboard", "wt_grid": "toggle grid / list view$NHotkey: G", "wt_prev": "previous track$NHotkey: J", "wt_play": "play / pause$NHotkey: P", @@ -280,6 +282,7 @@ var Ls = { "mt_fau": "on phones, prevent music from stopping if the next song doesn't preload fast enough (can make tags display glitchy)\">☕️", "mt_waves": "waveform seekbar:$Nshow audio amplitude in the scrubber\">~s", "mt_npclip": "show buttons for clipboarding the currently playing song\">/np", + "mt_m3u_c": "show buttons for clipboarding the$Nselected songs as m3u8 playlist entries\">📻", "mt_octl": "os integration (media hotkeys / osd)\">os-ctl", "mt_oseek": "allow seeking through os integration$N$Nnote: on some devices (iPhones),$Nthis replaces the next-song button\">seek", "mt_oscv": "show album cover in osd\">art", @@ -436,6 +439,10 @@ var Ls = { "tvt_sel": "select file   ( for cut / copy / delete / ... )$NHotkey: S\">sel", "tvt_edit": "open file in text editor$NHotkey: E\">✏️ edit", + "m3u_add1": "song added to m3u playlist", + "m3u_addn": "{0} songs added to m3u playlist", + "m3u_clip": "m3u playlist now copied to clipboard\n\nyou should create a new textfile named something.m3u and paste the playlist in that document; this will make it playable", + "gt_vau": "don't show videos, just play the audio\">🎧", "gt_msel": "enable file selection; ctrl-click a file to override$N$N<em>when active: doubleclick a file / folder to open it</em>$N$NHotkey: S\">multiselect", "gt_crop": "center-crop thumbnails\">crop", @@ -751,6 +758,8 @@ var Ls = { "wt_seldl": "last ned de valgte filene$NSnarvei: Y", "wt_npirc": "kopiér sang-info (irc-formatert)", "wt_nptxt": "kopiér sang-info", + "wt_m3ua": "legg til sang i m3u-spilleliste$N(husk å klikke på 📻copy senere)", + "wt_m3uc": "kopiér m3u-spillelisten til utklippstavlen", "wt_grid": "bytt mellom ikoner og listevisning$NSnarvei: G", "wt_prev": "forrige sang$NSnarvei: J", "wt_play": "play / pause$NSnarvei: P", @@ -887,6 +896,7 @@ var Ls = { "mt_fau": "for telefoner: forhindre at avspilling stopper hvis nettet er for tregt til å laste neste sang i tide. Hvis påskrudd, kan forårsake at sang-info ikke vises korrekt i OS'et\">☕️", "mt_waves": "waveform seekbar:$Nvis volumkurve i avspillingsfeltet\">~s", "mt_npclip": "vis knapper for å kopiere info om sangen du hører på\">/np", + "mt_m3u_c": "vis knapper for å kopiere de valgte$Nsangene som innslag i en m3u8 spilleliste\">📻", "mt_octl": "integrering med operativsystemet (fjernkontroll, info-skjerm)\">os-ctl", "mt_oseek": "tillat spoling med fjernkontroll$N$Nmerk: på noen enheter (iPhones) så vil$Ndette erstatte knappen for neste sang\">spoling", "mt_oscv": "vis album-cover på infoskjermen\">bilde", @@ -1043,6 +1053,10 @@ var Ls = { "tvt_sel": "markér filen   ( for utklipp / sletting / ... )$NSnarvei: S\">merk", "tvt_edit": "redigér filen$NSnarvei: E\">✏️ endre", + "m3u_add1": "sangen ble lagt til i m3u-spillelisten", + "m3u_addn": "{0} sanger ble lagt til i m3u-spillelisten", + "m3u_clip": "m3u-spillelisten ble kopiert til utklippstavlen\n\nneste steg er å opprette et tekstdokument med filnavn som slutter på .m3u og lime inn spillelisten der", + "gt_vau": "ikke vis videofiler, bare spill lyden\">🎧", "gt_msel": "markér filer istedenfor å åpne dem; ctrl-klikk filer for å overstyre$N$N<em>når aktiv: dobbelklikk en fil / mappe for å åpne</em>$N$NSnarvei: S\">markering", "gt_crop": "beskjær ikonene så de passer bedre\">✂", @@ -1893,6 +1907,9 @@ ebi('widget').innerHTML = ( '📋irc📋txt' + + '📻add📻copy' + '♫' + @@ -2308,6 +2325,7 @@ var mpl = (function () { ' 0) { + dur = dur.split(':'); + dur = 60 * parseInt(dur[0]) + parseInt(dur[1]); + } + else dur = parseInt(dur); + + mpl.m3ut += '#EXTINF:' + dur + ',' + tag + '\n' + uricom_dec(get_evpath()) + md.file + '\n'; + } + toast.ok(2, files.length == 1 ? L.m3u_add1 : L.m3u_addn.format(files.length), null, 'top'); + }; + m3uc.onclick = function (e) { + ev(e); + cliptxt(mpl.m3ut, function () { + toast.ok(15, L.m3u_clip, null, 'top'); + }); + }; r.set(sread('au_open') == 1); setTimeout(function () { clmod(widget, 'anim', 1); @@ -4129,6 +4196,7 @@ function play(tid, is_ev, seek) { clmod(ebi(oid), 'act', 1); clmod(ebi(oid).closest('tr'), 'play', 1); clmod(ebi('wtoggle'), 'np', mpl.clip); + clmod(ebi('wtoggle'), 'm3u', mpl.m3uen); if (thegrid) thegrid.loadsel(); @@ -4749,6 +4817,7 @@ var fileman = (function () { clmod(bshr, 'hide', hshr); clmod(ebi('wfm'), 'act', QS('#wfm a.en:not(.hide)')); + clmod(ebi('wtoggle'), 'm3u', mpl.m3uen && (nsel || (mp && mp.au))); var wfs = ebi('wfs'), h = ''; try {