mirror of
				https://github.com/SuperBFG7/ympd
				synced 2025-10-30 21:33:00 +00:00 
			
		
		
		
	Improved page navigation for queue view and queue search
This commit is contained in:
		| @@ -71,7 +71,9 @@ | |||||||
|     </nav> |     </nav> | ||||||
|   </header> |   </header> | ||||||
|   <main role="main" class="container"> |   <main role="main" class="container"> | ||||||
|  |     <noscript> | ||||||
|  |       <div class="alert alert-danger" role="alert">JavaScript is disabled!</div> | ||||||
|  |     </noscript> | ||||||
|     <div class="card" id="cardPlayback"> |     <div class="card" id="cardPlayback"> | ||||||
|       <div class="card-header">Now playing</div> |       <div class="card-header">Now playing</div> | ||||||
|       <div class="card-body"> |       <div class="card-body"> | ||||||
| @@ -93,11 +95,11 @@ | |||||||
|      |      | ||||||
|     <div class="card hide" id="cardQueue"> |     <div class="card hide" id="cardQueue"> | ||||||
|       <div class="card-header"> |       <div class="card-header"> | ||||||
|         <span>Queue</span> |         <a href="#" data-toggle="collapse" data-target="#queue-buttons" style="color:black;">Queue</a> | ||||||
|         <span id="panel-heading-queue" class="text pull-right"></span> |         <span id="panel-heading-queue" class="text pull-right"></span> | ||||||
|       </div> |       </div> | ||||||
|       <div class="card-body"> |       <div class="card-body"> | ||||||
|         <div class="btn-toolbar" id="queue-buttons" role="toolbar"> |         <div class="btn-toolbar collapse show" id="queue-buttons" role="toolbar"> | ||||||
|           <div id="trashmode" class="btn-group mr-2"> |           <div id="trashmode" class="btn-group mr-2"> | ||||||
|             <button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown"><span class="material-icons">delete</span></button> |             <button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown"><span class="material-icons">delete</span></button> | ||||||
|             <div class="dropdown-menu bg-dark px-2" id="trashmodebtns"> |             <div class="dropdown-menu bg-dark px-2" id="trashmodebtns"> | ||||||
| @@ -131,7 +133,7 @@ | |||||||
|             <div class="input-group mr-2"> |             <div class="input-group mr-2"> | ||||||
|               <input type="text" class="form-control" placeholder="Search Queue" id="searchqueuestr"/> |               <input type="text" class="form-control" placeholder="Search Queue" id="searchqueuestr"/> | ||||||
|               <div class="input-group-append"> |               <div class="input-group-append"> | ||||||
|                 <button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown"><span class="material-icons">search</span></button> |                 <button title="Select tags to search" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown"><span class="material-icons">search</span></button> | ||||||
|                 <div class="dropdown-menu bg-dark dropdown-menu-right px-2" id="searchqueuetag"> |                 <div class="dropdown-menu bg-dark dropdown-menu-right px-2" id="searchqueuetag"> | ||||||
|                   <h6 class="dropdown-header text-light">Search in Tag</h6> |                   <h6 class="dropdown-header text-light">Search in Tag</h6> | ||||||
|                   <button type="button" class="btn btn-success btn-block">Any Tag</button> |                   <button type="button" class="btn btn-success btn-block">Any Tag</button> | ||||||
| @@ -142,6 +144,15 @@ | |||||||
|               </div> |               </div> | ||||||
|             </div> |             </div> | ||||||
|           </form> |           </form> | ||||||
|  |           <div id="queuePaginationTop" class="btn-group mr-2"> | ||||||
|  |             <button onclick="gotoPage('prev',this,event)" id="queuePaginationTopPrev" title="Previous Page" type="button" class="btn btn-secondary">«</button> | ||||||
|  |               <div class="input-group-append"> | ||||||
|  |                 <button id="queuePaginationTopPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">Page 1 / 1</button> | ||||||
|  |                 <div class="dropdown-menu bg-dark px-2" id="queuePaginationTopPages"> | ||||||
|  |                 </div> | ||||||
|  |               </div>             | ||||||
|  |             <button onclick="gotoPage('next',this,event)" id="queuePaginationTopNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">»</button> | ||||||
|  |           </div> | ||||||
|         </div> |         </div> | ||||||
|  |  | ||||||
|         <div class="table-responsive-md"> |         <div class="table-responsive-md"> | ||||||
| @@ -166,10 +177,23 @@ | |||||||
|             </tbody> |             </tbody> | ||||||
|           </table> |           </table> | ||||||
|         </div> |         </div> | ||||||
|         <ul id="queuePagination" class="pagination justify-content-center hide"> |         <div class="btn-toolbar" id="queueButtonsBottom" role="toolbar"> | ||||||
|           <li id="queuePrev" class="page-item disabled"><a class="page-link text-secondary" href="">Previous</a></li> |           <div class="btn-group mr-2"> | ||||||
|           <li id="queueNext" class="page-item disabled"><a class="page-link text-secondary" href="">Next</a></li> |             <button type="button" class="btn btn-secondary" onclick="scrollToTop()" title="To top"> | ||||||
|         </ul> |               <span class="material-icons">keyboard_arrow_up</span> | ||||||
|  |             </button> | ||||||
|  |           </div>         | ||||||
|  |           <div id="queuePaginationBottom" class="btn-group mr-2 dropup"> | ||||||
|  |             <button onclick="gotoPage('prev',this,event)" id="queuePaginationBottomPrev" title="Previous Page" type="button" class="btn btn-secondary">«</button> | ||||||
|  |               <div class="input-group-append"> | ||||||
|  |                 <button id="queuePaginationBottomPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">Page 1 / 1</button> | ||||||
|  |                 <div class="dropdown-menu bg-dark px-2" id="queuePaginationBottomPages"> | ||||||
|  |                 </div> | ||||||
|  |               </div>             | ||||||
|  |             <button onclick="gotoPage('next',this,event)" id="queuePaginationBottomNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">»</button> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |          | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|      |      | ||||||
|   | |||||||
| @@ -30,7 +30,7 @@ var pagination = 0; | |||||||
| var browsepath = ""; | var browsepath = ""; | ||||||
| var lastSongTitle = ""; | var lastSongTitle = ""; | ||||||
| var current_song = new Object(); | var current_song = new Object(); | ||||||
| var MAX_ELEMENTS_PER_PAGE = 100; | var MAX_ELEMENTS_PER_PAGE = 5; | ||||||
| var isTouch = Modernizr.touch ? 1 : 0; | var isTouch = Modernizr.touch ? 1 : 0; | ||||||
| var filter = ""; | var filter = ""; | ||||||
| var playstate = ""; | var playstate = ""; | ||||||
| @@ -229,15 +229,6 @@ function webSocketConnect() { | |||||||
|                     var nrItems=0; |                     var nrItems=0; | ||||||
|                     for (var song in obj.data) { |                     for (var song in obj.data) { | ||||||
|                         nrItems++; |                         nrItems++; | ||||||
|                         if (obj.data[song].type == 'wrap') { |  | ||||||
|                             $('#queueList > tbody').append( |  | ||||||
|                                  "<tr><td><span class=\"material-icons\">error_outline</span></td>" + |  | ||||||
|                                  "<td colspan=\"3\">Too many results, please refine your search!</td>" + |  | ||||||
|                                  "<td></td><td></td></tr>" |  | ||||||
|                             ); |  | ||||||
|                             continue; |  | ||||||
|                         } |  | ||||||
|                      |  | ||||||
|                         var minutes = Math.floor(obj.data[song].duration / 60); |                         var minutes = Math.floor(obj.data[song].duration / 60); | ||||||
|                         var seconds = obj.data[song].duration - minutes * 60; |                         var seconds = obj.data[song].duration - minutes * 60; | ||||||
|  |  | ||||||
| @@ -256,17 +247,36 @@ function webSocketConnect() { | |||||||
|                                "<td></td><td></td></tr>" |                                "<td></td><td></td></tr>" | ||||||
|                         ); |                         ); | ||||||
|                     } |                     } | ||||||
|                     if (obj.type == 'queue') { |                     totalPages=Math.ceil(obj.totalSongs / MAX_ELEMENTS_PER_PAGE); | ||||||
|                         if(obj.data.length && obj.data[obj.data.length-1].pos + 1 >= pagination + MAX_ELEMENTS_PER_PAGE) { |                     if (totalPages==0) { totalPages=1; } | ||||||
|                             $('#queueNext').removeClass('disabled'); |                     $('#queuePaginationTopPage').text('Page '+(pagination / MAX_ELEMENTS_PER_PAGE + 1)+' / '+totalPages); | ||||||
|                             $('#queuePagination').removeClass('hide'); |                     $('#queuePaginationBottomPage').text('Page '+(pagination / MAX_ELEMENTS_PER_PAGE + 1)+' / '+totalPages); | ||||||
|                         } |                     if (totalPages > 1) { | ||||||
|                         if(pagination > 0) { |                         $('#queuePaginationTopPage').removeClass('disabled'); | ||||||
|                             $('#queuePrev').removeClass('disabled'); |                         $('#queuePaginationBottomPage').removeClass('disabled'); | ||||||
|                             $('#queuePagination').removeClass('hide'); |                         $('#queuePaginationTopPages').empty(); | ||||||
|  |                         $('#queuePaginationBottomPages').empty(); | ||||||
|  |                         for (var i=0;i<totalPages;i++) { | ||||||
|  |                             $('#queuePaginationTopPages').append('<button onclick="gotoPage('+(i * MAX_ELEMENTS_PER_PAGE)+',this,event)" type="button" class="mr-1 mb-1 btn btn-secondary">'+(i+1)+'</button>'); | ||||||
|  |                             $('#queuePaginationBottomPages').append('<button onclick="gotoPage('+(i * MAX_ELEMENTS_PER_PAGE)+',this,event)" type="button" class="mr-1 mb-1 btn btn-secondary">'+(i+1)+'</button>'); | ||||||
|                         } |                         } | ||||||
|                     } else { |                     } else { | ||||||
|                         $('#queuePagination').addClass('hide'); |                         $('#queuePaginationTopPage').addClass('disabled'); | ||||||
|  |                         $('#queuePaginationBottomPage').addClass('disabled'); | ||||||
|  |                     } | ||||||
|  |                     if(obj.totalSongs > pagination + MAX_ELEMENTS_PER_PAGE) { | ||||||
|  |                         $('#queuePaginationTopNext').removeClass('disabled'); | ||||||
|  |                         $('#queuePaginationBottomNext').removeClass('disabled'); | ||||||
|  |                     } else { | ||||||
|  |                         $('#queuePaginationTopNext').addClass('disabled'); | ||||||
|  |                         $('#queuePaginationBottomNext').addClass('disabled');                             | ||||||
|  |                     } | ||||||
|  |                     if(pagination > 0) { | ||||||
|  |                         $('#queuePaginationTopPrev').removeClass('disabled'); | ||||||
|  |                         $('#queuePaginationBottomPrev').removeClass('disabled'); | ||||||
|  |                     } else { | ||||||
|  |                         $('#queuePaginationTopPrev').addClass('disabled'); | ||||||
|  |                         $('#queuePaginationBottomPrev').addClass('disabled'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if ( isTouch ) { |                     if ( isTouch ) { | ||||||
| @@ -756,6 +766,7 @@ $('#search').submit(function () { | |||||||
| }); | }); | ||||||
|  |  | ||||||
| $('#searchqueuestr').keyup(function (event) { | $('#searchqueuestr').keyup(function (event) { | ||||||
|  |   pagination=0; | ||||||
|   doQueueSearch(); |   doQueueSearch(); | ||||||
| }); | }); | ||||||
|  |  | ||||||
| @@ -773,7 +784,7 @@ function doQueueSearch() { | |||||||
|    }); |    }); | ||||||
|     |     | ||||||
|    if (searchstr.length >= 3) { |    if (searchstr.length >= 3) { | ||||||
|       socket.send('MPD_API_SEARCH_QUEUE,' + mpdtag + ',' + searchstr); |       socket.send('MPD_API_SEARCH_QUEUE,' + mpdtag + ','+pagination+',' + searchstr); | ||||||
|    } |    } | ||||||
|    if (searchstr.length == 0) { |    if (searchstr.length == 0) { | ||||||
|      socket.send('MPD_API_GET_QUEUE,0'); |      socket.send('MPD_API_GET_QUEUE,0'); | ||||||
| @@ -808,6 +819,44 @@ $('.page-link').on('click', function (e) { | |||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | function scrollToTop() { | ||||||
|  |     document.body.scrollTop = 0; // For Safari | ||||||
|  |     document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function gotoPage(x,element,event) { | ||||||
|  |     if ($(element).hasClass('disabled')) { | ||||||
|  |         event.preventDefault(); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     switch (x) { | ||||||
|  |         case "next": | ||||||
|  |             pagination += MAX_ELEMENTS_PER_PAGE; | ||||||
|  |             break; | ||||||
|  |         case "prev": | ||||||
|  |             pagination -= MAX_ELEMENTS_PER_PAGE; | ||||||
|  |             if(pagination <= 0) | ||||||
|  |                pagination = 0; | ||||||
|  |             break; | ||||||
|  |         default: | ||||||
|  |             pagination = x; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     switch(current_app) { | ||||||
|  |         case "queue": | ||||||
|  |             if ($('#searchqueuestr').val().length >=3) { | ||||||
|  |               doQueueSearch(); | ||||||
|  |             } else { | ||||||
|  |               app.setLocation('#/queue/'+pagination); | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         case "browse": | ||||||
|  |             app.setLocation('#/browse/'+pagination+'/'+browsepath); | ||||||
|  |             break; | ||||||
|  |     } | ||||||
|  |     event.preventDefault(); | ||||||
|  | } | ||||||
|  |  | ||||||
| function addStream() { | function addStream() { | ||||||
|     if($('#streamurl').val().length > 0) { |     if($('#streamurl').val().length > 0) { | ||||||
|         socket.send('MPD_API_ADD_TRACK,'+$('#streamurl').val()); |         socket.send('MPD_API_ADD_TRACK,'+$('#streamurl').val()); | ||||||
|   | |||||||
| @@ -245,6 +245,8 @@ out_save_queue: | |||||||
|                 mpdtagtype = strdup(token); |                 mpdtagtype = strdup(token); | ||||||
|             } |             } | ||||||
|              |              | ||||||
|  |             uint_buf = strtoul(strtok(NULL, ","), NULL, 10); | ||||||
|  |              | ||||||
|             if((token = strtok(NULL, ",")) == NULL) { |             if((token = strtok(NULL, ",")) == NULL) { | ||||||
|                 free(mpdtagtype); |                 free(mpdtagtype); | ||||||
|                 goto out_search; |                 goto out_search; | ||||||
| @@ -254,7 +256,7 @@ out_save_queue: | |||||||
|  |  | ||||||
| 	    //free(p_charbuf); | 	    //free(p_charbuf); | ||||||
|             //p_charbuf = strdup(c->content); |             //p_charbuf = strdup(c->content); | ||||||
|             n = mpd_search_queue(mpd.buf, mpdtagtype, searchstr); |             n = mpd_search_queue(mpd.buf, mpdtagtype, uint_buf, searchstr); | ||||||
|             free(searchstr); |             free(searchstr); | ||||||
| out_search_queue: | out_search_queue: | ||||||
|             free(p_charbuf); |             free(p_charbuf); | ||||||
| @@ -811,7 +813,7 @@ int mpd_search(char *buffer, char *searchstr) | |||||||
|     return cur - buffer; |     return cur - buffer; | ||||||
| } | } | ||||||
|  |  | ||||||
| int mpd_search_queue(char *buffer, char *mpdtagtype, char *searchstr) | int mpd_search_queue(char *buffer, char *mpdtagtype, unsigned int offset, char *searchstr) | ||||||
| { | { | ||||||
|     char *cur = buffer; |     char *cur = buffer; | ||||||
|     const char *end = buffer + MAX_SIZE; |     const char *end = buffer + MAX_SIZE; | ||||||
| @@ -838,7 +840,7 @@ int mpd_search_queue(char *buffer, char *mpdtagtype, char *searchstr) | |||||||
|  |  | ||||||
|         while((song = mpd_recv_song(mpd.conn)) != NULL) { |         while((song = mpd_recv_song(mpd.conn)) != NULL) { | ||||||
|           totalSongs ++; |           totalSongs ++; | ||||||
|           if(totalSongs <= 100) { |           if(totalSongs > offset && totalSongs <= offset+MAX_ELEMENTS_PER_PAGE) { | ||||||
|             cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"song\""); |             cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"song\""); | ||||||
| //            cur += json_emit_raw_str(cur, end - cur, ",\"uri\":"); | //            cur += json_emit_raw_str(cur, end - cur, ",\"uri\":"); | ||||||
| //            cur += json_emit_quoted_str(cur, end - cur, mpd_song_get_uri(song)); | //            cur += json_emit_quoted_str(cur, end - cur, mpd_song_get_uri(song)); | ||||||
| @@ -861,9 +863,10 @@ int mpd_search_queue(char *buffer, char *mpdtagtype, char *searchstr) | |||||||
|           } |           } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|         if (totalSongs > 100) { | /*        if (totalSongs > 100) { | ||||||
|           cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"wrap\"},"); |           cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"wrap\"},"); | ||||||
|         } |         } | ||||||
|  | */         | ||||||
|         cur--; |         cur--; | ||||||
|  |  | ||||||
|         cur += json_emit_raw_str(cur, end - cur, "]"); |         cur += json_emit_raw_str(cur, end - cur, "]"); | ||||||
|   | |||||||
| @@ -37,8 +37,8 @@ | |||||||
| } while(0) | } while(0) | ||||||
|  |  | ||||||
|  |  | ||||||
| #define MAX_SIZE 1024 * 100 | #define MAX_SIZE 1024 * 5 | ||||||
| #define MAX_ELEMENTS_PER_PAGE 100 | #define MAX_ELEMENTS_PER_PAGE 5 | ||||||
|  |  | ||||||
| #define GEN_ENUM(X) X, | #define GEN_ENUM(X) X, | ||||||
| #define GEN_STR(X) #X, | #define GEN_STR(X) #X, | ||||||
| @@ -122,7 +122,7 @@ int mpd_put_current_song(char *buffer); | |||||||
| int mpd_put_queue(char *buffer, unsigned int offset); | int mpd_put_queue(char *buffer, unsigned int offset); | ||||||
| int mpd_put_browse(char *buffer, char *path, unsigned int offset); | int mpd_put_browse(char *buffer, char *path, unsigned int offset); | ||||||
| int mpd_search(char *buffer, char *searchstr); | int mpd_search(char *buffer, char *searchstr); | ||||||
| int mpd_search_queue(char *buffer, char *mpdtagtype, char *searchstr); | int mpd_search_queue(char *buffer, char *mpdtagtype, unsigned int offset,  char *searchstr); | ||||||
| void mpd_disconnect(); | void mpd_disconnect(); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 jcorporation
					jcorporation