a simple web player for subsonic tinysub.devins.page
subsonic navidrome javascript
9
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: ratings

+24 -2
+19
src/js/contextmenu.js
··· 212 212 }; 213 213 } 214 214 215 + // get rating menu items 216 + function getRatingMenuItems(selectedIndices) { 217 + const items = {}; 218 + for (let rating = 0; rating <= 5; rating++) { 219 + const label = "★".repeat(rating) + "☆".repeat(5 - rating); 220 + items[label] = async () => { 221 + await Promise.all( 222 + selectedIndices.map((i) => setSongRating(state.queue[i], rating)), 223 + ); 224 + updateQueueDisplay(); 225 + }; 226 + } 227 + return items; 228 + } 229 + 215 230 // show queue context menu 216 231 function showQueueContextMenu(x, y, selectedIndices) { 217 232 showContextMenu(x, y, { ··· 244 259 selectedIndices.map((i) => setFavoriteSong(state.queue[i], false)), 245 260 ); 246 261 updateQueueDisplay(); 262 + }, 263 + [STRINGS.CONTEXT_RATING]: () => { 264 + showContextMenu(x, y, getRatingMenuItems(selectedIndices)); 265 + return false; // prevent cleanup, keep submenu open 247 266 }, 248 267 [STRINGS.CONTEXT_MOVE_UP]: () => { 249 268 const firstIdx = Math.min(...selectedIndices);
+4 -2
src/js/player.js
··· 109 109 } 110 110 }; 111 111 112 - // set song rating (1-5) 112 + // set song rating (0-5) 113 113 const setSongRating = async (song, rating) => { 114 114 if (!song || !state.api || !state.settings.enableRatings) return; 115 115 if (rating < 0 || rating > 5) return; 116 + 117 + await state.api.setRating(song.id, rating); 118 + 116 119 if (rating === 0) { 117 120 state.ratings.delete(song.id); 118 121 } else { 119 - await state.api.setRating(song.id, rating); 120 122 state.ratings.set(song.id, rating); 121 123 } 122 124 };
+1
src/js/strings/en.js
··· 15 15 CONTEXT_MOVE_UP: "move up", 16 16 CONTEXT_PLAY_NEXT: "play next", 17 17 CONTEXT_PLAY: "play", 18 + CONTEXT_RATING: "rating", 18 19 CONTEXT_SORT: "sort", 19 20 CONTEXT_UNFAVORITE: "unfavorite", 20 21 // context menu - sort