mirror of
				https://github.com/SuperBFG7/ympd
				synced 2025-10-31 13:53:00 +00:00 
			
		
		
		
	Feat: enable smart playlist editing #38
This commit is contained in:
		| @@ -656,11 +656,55 @@ | |||||||
|         </div> |         </div> | ||||||
|         <div class="modal-body"> |         <div class="modal-body"> | ||||||
|           <form class="needs-validation" id="saveSmartPlaylistFrm" novalidate> |           <form class="needs-validation" id="saveSmartPlaylistFrm" novalidate> | ||||||
|             <div class="form-group"> |             <div class="row"> | ||||||
|  |               <div class="form-group col-md-6">           | ||||||
|                 <label for="saveSmartPlaylistName">Name</label> |                 <label for="saveSmartPlaylistName">Name</label> | ||||||
|                 <input type="text" class="form-control" id="saveSmartPlaylistName"/> |                 <input type="text" class="form-control" id="saveSmartPlaylistName"/> | ||||||
|                 <div class="invalid-feedback">Invalid filename.</div> |                 <div class="invalid-feedback">Invalid filename.</div> | ||||||
|               </div>             |               </div>             | ||||||
|  |               <div class="form-group col-md-6"> | ||||||
|  |                 <label for="saveSmartPlaylistType">Type</label> | ||||||
|  |                 <input type="text" class="form-control" id="saveSmartPlaylistType" readonly/> | ||||||
|  |                 <div class="invalid-feedback">Invalid type.</div> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |             <hr/> | ||||||
|  |             <div class="row" id="saveSmartPlaylistSearch" class="hide"> | ||||||
|  |               <div class="form-group col-md-6">           | ||||||
|  |                 <label for="selectSaveSmartPlaylistTag">Tag</label> | ||||||
|  |                 <select id="selectSaveSmartPlaylistTag" class="form-control custom-select"></select> | ||||||
|  |               </div>             | ||||||
|  |               <div class="form-group col-md-6"> | ||||||
|  |                 <label for="inputSaveSmartPlaylistSearchstr">Search</label> | ||||||
|  |                 <input type="text" class="form-control" id="inputSaveSmartPlaylistSearchstr"/> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |             <div class="row" id="saveSmartPlaylistSticker" class="hide"> | ||||||
|  |               <div class="form-group col-md-6">           | ||||||
|  |                 <label for="selectSaveSmartPlaylistSticker">Sticker</label> | ||||||
|  |                 <select id="selectSaveSmartPlaylistSticker" class="form-control custom-select"> | ||||||
|  |                   <option value="like">Like</option> | ||||||
|  |                   <option value="playCount">playCount</option> | ||||||
|  |                 </select> | ||||||
|  |               </div>             | ||||||
|  |               <div class="form-group col-md-6"> | ||||||
|  |                 <label for="inputSaveSmartPlaylistStickerMaxentries">Max. entries</label> | ||||||
|  |                 <input type="text" class="form-control" id="inputSaveSmartPlaylistStickerMaxentries"/> | ||||||
|  |                 <div class="invalid-feedback">Must be a number.</div> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |             <div class="row" id="saveSmartPlaylistNewest" class="hide"> | ||||||
|  |               <div class="form-group col-md-6"> | ||||||
|  |                 <label for="inputSaveSmartPlaylistNewestTimerange">Timerange (days)</label> | ||||||
|  |                 <input type="text" class="form-control" id="inputSaveSmartPlaylistNewestTimerange"/> | ||||||
|  |                 <div class="invalid-feedback">Must be a number.</div> | ||||||
|  |               </div>             | ||||||
|  |               <div class="form-group col-md-6"> | ||||||
|  |                 <label for="inputSaveSmartPlaylistNewestMaxentries">Max. entries</label> | ||||||
|  |                 <input type="text" class="form-control" id="inputSaveSmartPlaylistNewestMaxentries"/> | ||||||
|  |                 <div class="invalid-feedback">Must be a number.</div> | ||||||
|  |               </div> | ||||||
|  |             </div>             | ||||||
|           </form> |           </form> | ||||||
|         </div> |         </div> | ||||||
|         <div class="modal-footer"> |         <div class="modal-footer"> | ||||||
|   | |||||||
| @@ -503,7 +503,7 @@ function appInit() { | |||||||
|                 showAddToPlaylist('SEARCH');                 |                 showAddToPlaylist('SEARCH');                 | ||||||
|             } |             } | ||||||
|             else if (event.target.innerText == 'Save as smart playlist') { |             else if (event.target.innerText == 'Save as smart playlist') { | ||||||
|                 showSaveSmartPlaylist(); |                 saveSearchAsSmartPlaylist(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     }, false); |     }, false); | ||||||
| @@ -1635,26 +1635,98 @@ function toggleAddToPlaylistFrm() { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| function showSaveSmartPlaylist() { | function saveSearchAsSmartPlaylist() { | ||||||
|  |     parseSmartPlaylist({"type": "smartpls", "data": {"playlist": "", "type": "search", "tag": app.current.filter, "searchstr": app.current.search}}); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function parseSmartPlaylist(obj) { | ||||||
|     var nameEl = document.getElementById('saveSmartPlaylistName'); |     var nameEl = document.getElementById('saveSmartPlaylistName'); | ||||||
|     nameEl.value = ''; |     nameEl.value = obj.data.playlist; | ||||||
|     nameEl.classList.remove('is-invalid'); |     nameEl.classList.remove('is-invalid'); | ||||||
|  |     document.getElementById('saveSmartPlaylistType').value = obj.data.type; | ||||||
|     document.getElementById('saveSmartPlaylistFrm').classList.remove('was-validated'); |     document.getElementById('saveSmartPlaylistFrm').classList.remove('was-validated'); | ||||||
|  |     document.getElementById('saveSmartPlaylistSearch').classList.add('hide'); | ||||||
|  |     document.getElementById('saveSmartPlaylistSticker').classList.add('hide'); | ||||||
|  |     document.getElementById('saveSmartPlaylistNewest').classList.add('hide'); | ||||||
|  |     var tagList = '<option value="any">Any Tag</option>'; | ||||||
|  |     for (var key in settings.tags) { | ||||||
|  |         if (settings.tags[key] == true && key != 'Track') { | ||||||
|  |             tagList += '<option value="' + key + '">' + key + '</option>'; | ||||||
|  |         } | ||||||
|  |     }     | ||||||
|  |     document.getElementById('selectSaveSmartPlaylistTag').innerHTML = tagList; | ||||||
|  |     if (obj.data.type == 'search') { | ||||||
|  |         document.getElementById('saveSmartPlaylistSearch').classList.remove('hide'); | ||||||
|  |         document.getElementById('selectSaveSmartPlaylistTag').value = obj.data.tag; | ||||||
|  |         document.getElementById('inputSaveSmartPlaylistSearchstr').value = obj.data.searchstr; | ||||||
|  |     } | ||||||
|  |     else if (obj.data.type == 'sticker') { | ||||||
|  |         document.getElementById('saveSmartPlaylistSticker').classList.remove('hide'); | ||||||
|  |         document.getElementById('selectSaveSmartPlaylistSticker').value = obj.data.sticker; | ||||||
|  |         document.getElementById('inputSaveSmartPlaylistStickerMaxentries').value = obj.data.maxentries; | ||||||
|  |     } | ||||||
|  |     else if (obj.data.type == 'newest') { | ||||||
|  |         document.getElementById('saveSmartPlaylistNewest').classList.remove('hide'); | ||||||
|  |         var timerange = obj.data.timerange / 24 / 60 / 60; | ||||||
|  |         document.getElementById('inputSaveSmartPlaylistNewestTimerange').value = timerange; | ||||||
|  |         document.getElementById('inputSaveSmartPlaylistNewestMaxentries').value = obj.data.maxentries; | ||||||
|  |     } | ||||||
|     modalSaveSmartPlaylist.show(); |     modalSaveSmartPlaylist.show(); | ||||||
|     nameEl.focus(); |     nameEl.focus(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function chkInt(el, frm) { | ||||||
|  |     var value = el.value.replace(/\d/g,''); | ||||||
|  |     if (value != '') { | ||||||
|  |         el.classList.add('is-invalid'); | ||||||
|  |         frm.classList.add('was-validated'); | ||||||
|  |         return false; | ||||||
|  |     } else { | ||||||
|  |         el.classList.remove('is-invalid'); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| function saveSmartPlaylist() { | function saveSmartPlaylist() { | ||||||
|     var value = document.getElementById('saveSmartPlaylistName').value; |     var name = document.getElementById('saveSmartPlaylistName').value; | ||||||
|     var valid = value.replace(/[\w\-]/g, ''); |     var type = document.getElementById('saveSmartPlaylistType').value; | ||||||
|     if (value != '' && valid == '') { |     var valid = name.replace(/[\w\-]/g, ''); | ||||||
|         sendAPI({"cmd": "MPD_API_SMARTPLS_SAVE", "data": {"type": "search", "playlist": value, "tag": app.current.filter, "searchstr": app.current.search}}); |     var frm = document.getElementById('saveSmartPlaylistFrm'); | ||||||
|  |     if (name != '' && valid == '') { | ||||||
|  |         if (type == 'search') { | ||||||
|  |             var tagEl = document.getElementById('selectSaveSmartPlaylistTag'); | ||||||
|  |             var tag = tagEl.options[tagEl.selectedIndex].value; | ||||||
|  |             var searchstr = document.getElementById('inputSaveSmartPlaylistSearchstr').value; | ||||||
|  |             sendAPI({"cmd": "MPD_API_SMARTPLS_SAVE", "data": {"type": type, "playlist": name, "tag": tag, "searchstr": searchstr}}); | ||||||
|  |         } else if (type == 'sticker') { | ||||||
|  |             var stickerEl = document.getElementById('selectSaveSmartPlaylistSticker'); | ||||||
|  |             var sticker = stickerEl.options[stickerEl.selectedIndex].value; | ||||||
|  |             var maxentriesEl = document.getElementById('inputSaveSmartPlaylistStickerMaxentries'); | ||||||
|  |             if (!chkInt(maxentriesEl, frm)) | ||||||
|  |                 return; | ||||||
|  |             var maxentries = maxentriesEl.value; | ||||||
|  |             sendAPI({"cmd": "MPD_API_SMARTPLS_SAVE", "data": {"type": type, "playlist": name, "sticker": sticker, "maxentries": maxentries}}); | ||||||
|  |         } else if (type == 'newest') { | ||||||
|  |             var timerangeEl = document.getElementById('inputSaveSmartPlaylistNewestTimerange'); | ||||||
|  |             if (!chkInt(timerangeEl, frm)) | ||||||
|  |                 return; | ||||||
|  |             var timerange = parseInt(timerangeEl.value) * 60 * 60 * 24; | ||||||
|  |             var maxentriesEl = document.getElementById('inputSaveSmartPlaylistNewestMaxentries'); | ||||||
|  |             if (!chkInt(maxentriesEl, frm)) | ||||||
|  |                 return; | ||||||
|  |             var maxentries = maxentriesEl.value; | ||||||
|  |             sendAPI({"cmd": "MPD_API_SMARTPLS_SAVE", "data": {"type": type, "playlist": name, "timerange": timerange, "maxentries": maxentries}}); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             document.getElementById('saveSmartPlaylistType').classList.add('is-invalid'); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|         modalSaveSmartPlaylist.hide(); |         modalSaveSmartPlaylist.hide(); | ||||||
|         showNotification('Saved smart playlist ' + value, '', '', 'success'); |         showNotification('Saved smart playlist ' + name, '', '', 'success'); | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|         document.getElementById('saveSmartPlaylistName').classList.add('is-invalid'); |         document.getElementById('saveSmartPlaylistName').classList.add('is-invalid'); | ||||||
|         document.getElementById('saveSmartPlaylistFrm').classList.add('was-validated'); |         frm.classList.add('was-validated'); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1763,6 +1835,10 @@ function renamePlaylist() { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function showSmartPlaylist(playlist) { | ||||||
|  |     sendAPI({"cmd": "MPD_API_SMARTPLS_GET", "data": {"playlist": playlist}}, parseSmartPlaylist); | ||||||
|  | } | ||||||
|  |  | ||||||
| function dirname(uri) { | function dirname(uri) { | ||||||
|     return uri.replace(/\/[^\/]*$/, ''); |     return uri.replace(/\/[^\/]*$/, ''); | ||||||
| } | } | ||||||
| @@ -1840,6 +1916,7 @@ function showMenu(el, event) { | |||||||
|         menu += addMenuItem({"cmd": "appendQueue", "options": [type, uri, name]}, 'Append to queue') + |         menu += addMenuItem({"cmd": "appendQueue", "options": [type, uri, name]}, 'Append to queue') + | ||||||
|             addMenuItem({"cmd": "replaceQueue", "options": [type, uri, name]},'Replace queue') + |             addMenuItem({"cmd": "replaceQueue", "options": [type, uri, name]},'Replace queue') + | ||||||
|             (type == 'smartpls' ? addMenuItem({"cmd": "playlistDetails", "options": [uri]}, 'View playlist') : addMenuItem({"cmd": "playlistDetails", "options": [uri]}, 'Edit playlist'))+ |             (type == 'smartpls' ? addMenuItem({"cmd": "playlistDetails", "options": [uri]}, 'View playlist') : addMenuItem({"cmd": "playlistDetails", "options": [uri]}, 'Edit playlist'))+ | ||||||
|  |             (type == 'smartpls' ? addMenuItem({"cmd": "showSmartPlaylist", "options": [uri]}, 'Edit smart playlist') : '') + | ||||||
|             (uri.indexOf('myMPDsmart') != 0 ? |             (uri.indexOf('myMPDsmart') != 0 ? | ||||||
|                 addMenuItem({"cmd": "showRenamePlaylist", "options": [uri]}, 'Rename playlist') +  |                 addMenuItem({"cmd": "showRenamePlaylist", "options": [uri]}, 'Rename playlist') +  | ||||||
|                 addMenuItem({"cmd": "delPlaylist", "options": [uri]}, 'Delete playlist') : ''); |                 addMenuItem({"cmd": "delPlaylist", "options": [uri]}, 'Delete playlist') : ''); | ||||||
|   | |||||||
| @@ -196,7 +196,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|                 n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Smart Playlists update failed\"}"); |                 n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Smart Playlists update failed\"}"); | ||||||
|             break; |             break; | ||||||
|         case MPD_API_SMARTPLS_SAVE: |         case MPD_API_SMARTPLS_SAVE: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {type: %Q}}", p_charbuf1); |             je = json_scanf(msg.p, msg.len, "{data: {type: %Q}}", &p_charbuf1); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 if (strcmp(p_charbuf1, "sticker") == 0) { |                 if (strcmp(p_charbuf1, "sticker") == 0) { | ||||||
|                     je = json_scanf(msg.p, msg.len, "{data: {playlist: %Q, sticker: %Q, maxentries: %d}}", &p_charbuf2, &p_charbuf3, &int_buf1); |                     je = json_scanf(msg.p, msg.len, "{data: {playlist: %Q, sticker: %Q, maxentries: %d}}", &p_charbuf2, &p_charbuf3, &int_buf1); | ||||||
| @@ -2006,7 +2006,8 @@ int mympd_smartpls_put(char *buffer, char *playlist) { | |||||||
|         if (strcmp(smartpltype, "sticker") == 0) { |         if (strcmp(smartpltype, "sticker") == 0) { | ||||||
|             je = json_scanf(content, strlen(content), "{sticker: %Q, maxentries: %d}", &p_charbuf1, &int_buf1); |             je = json_scanf(content, strlen(content), "{sticker: %Q, maxentries: %d}", &p_charbuf1, &int_buf1); | ||||||
|             if (je == 2) { |             if (je == 2) { | ||||||
|                 len = json_printf(&out, "{type: smartpls, data: {type: %Q, sticker: %Q, maxentries: %d}", |                 len = json_printf(&out, "{type: smartpls, data: {playlist: %Q, type: %Q, sticker: %Q, maxentries: %d}}", | ||||||
|  |                     playlist, | ||||||
|                     smartpltype, |                     smartpltype, | ||||||
|                     p_charbuf1, |                     p_charbuf1, | ||||||
|                     int_buf1); |                     int_buf1); | ||||||
| @@ -2016,7 +2017,8 @@ int mympd_smartpls_put(char *buffer, char *playlist) { | |||||||
|         else if (strcmp(smartpltype, "newest") == 0) { |         else if (strcmp(smartpltype, "newest") == 0) { | ||||||
|             je = json_scanf(content, strlen(content), "{timerange: %d, maxentries: %d}", &int_buf1, &int_buf2); |             je = json_scanf(content, strlen(content), "{timerange: %d, maxentries: %d}", &int_buf1, &int_buf2); | ||||||
|             if (je == 2) { |             if (je == 2) { | ||||||
|                 len = json_printf(&out, "{type: smartpls, data: {type: %Q, timerange: %d, maxentries: %d}", |                 len = json_printf(&out, "{type: smartpls, data: {playlist: %Q, type: %Q, timerange: %d, maxentries: %d}}", | ||||||
|  |                     playlist, | ||||||
|                     smartpltype, |                     smartpltype, | ||||||
|                     int_buf1, |                     int_buf1, | ||||||
|                     int_buf2); |                     int_buf2); | ||||||
| @@ -2025,7 +2027,8 @@ int mympd_smartpls_put(char *buffer, char *playlist) { | |||||||
|         else if (strcmp(smartpltype, "search") == 0) { |         else if (strcmp(smartpltype, "search") == 0) { | ||||||
|             je = json_scanf(content, strlen(content), "{tag: %Q, searchstr: %Q}", &p_charbuf1, &p_charbuf2); |             je = json_scanf(content, strlen(content), "{tag: %Q, searchstr: %Q}", &p_charbuf1, &p_charbuf2); | ||||||
|             if (je == 2) { |             if (je == 2) { | ||||||
|                 len = json_printf(&out, "{type: smartpls, data: {type: %Q, tag: %d, searchstr: %d}", |                 len = json_printf(&out, "{type: smartpls, data: {playlist: %Q, type: %Q, tag: %Q, searchstr: %Q}}", | ||||||
|  |                     playlist, | ||||||
|                     smartpltype, |                     smartpltype, | ||||||
|                     p_charbuf1, |                     p_charbuf1, | ||||||
|                     p_charbuf2); |                     p_charbuf2); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 jcorporation
					jcorporation