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.

feat: animation/effect toggle

for pulse animation and context menu blur

+31 -2
+9 -2
src/css/components.css
··· 256 256 background: var(--bg-secondary); 257 257 } 258 258 259 + :not(.no-animations) #queue #queue-table tbody tr.currently-playing { 260 + animation: pulse 4s linear infinite; 261 + } 262 + 259 263 #queue #queue-table tbody tr.currently-playing { 260 264 background: var(--playing); 261 - animation: pulse 4s linear infinite; 262 265 } 263 266 264 267 #queue #queue-table tbody tr.dragging { ··· 344 347 #context-menu { 345 348 position: fixed; 346 349 background: var(--bg-context-menu); 347 - backdrop-filter: blur(16px); 348 350 border: 1px solid var(--border); 349 351 border-radius: 0.25rem; 350 352 box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25); 351 353 z-index: 1000; 352 354 min-width: 10rem; 355 + } 356 + 357 + :not(.no-animations) #context-menu { 358 + background: Menu; 359 + backdrop-filter: blur(16px); 353 360 } 354 361 355 362 #context-menu .context-menu-item {
+6
src/index.html
··· 114 114 </label> 115 115 </div> 116 116 <div class="form-group"> 117 + <label> 118 + <input type="checkbox" id="animations-toggle" /> 119 + enable animations/visual effects 120 + </label> 121 + </div> 122 + <div class="form-group"> 117 123 <label 118 124 >artist art size: <span id="artist-size-display">24</span>px</label 119 125 >
+15
src/js/settings.js
··· 31 31 ); 32 32 const favoritesToggle = document.getElementById("favorites-toggle"); 33 33 const ratingsToggle = document.getElementById("ratings-toggle"); 34 + const animationsToggle = document.getElementById("animations-toggle"); 34 35 35 36 // load and apply settings from localStorage 36 37 const saved = localStorage.getItem("tinysub_settings"); ··· 42 43 } 43 44 applySettings(); 44 45 46 + if (!state.settings.enableAnimations) { 47 + document.documentElement.classList.add("no-animations"); 48 + } 49 + 45 50 scrobbleToggle.checked = state.settings.scrobbling; 46 51 dynamicFaviconToggle.checked = state.settings.dynamicFavicon; 47 52 favoritesToggle.checked = state.settings.enableFavorites; 48 53 ratingsToggle.checked = state.settings.enableRatings; 54 + animationsToggle.checked = state.settings.enableAnimations; 49 55 50 56 // initialize sliders and setup listeners 51 57 Object.entries(ART_SETTINGS).forEach(([name, key]) => { ··· 109 115 state.settings.enableFavorites = favoritesToggle.checked; 110 116 localStorage.setItem("tinysub_settings", JSON.stringify(state.settings)); 111 117 updateQueueDisplay(); 118 + }); 119 + 120 + animationsToggle.addEventListener("change", () => { 121 + state.settings.enableAnimations = animationsToggle.checked; 122 + document.documentElement.classList.toggle( 123 + "no-animations", 124 + !animationsToggle.checked, 125 + ); 126 + localStorage.setItem("tinysub_settings", JSON.stringify(state.settings)); 112 127 }); 113 128 114 129 // logout button
+1
src/js/state.js
··· 21 21 dynamicFavicon: true, 22 22 enableFavorites: true, 23 23 enableRatings: false, 24 + enableAnimations: true, 24 25 artArtist: 24, 25 26 artAlbum: 32, 26 27 artSong: 16,