a simple web player for subsonic tinysub.devins.page
subsonic navidrome javascript
at main 303 lines 9.2 kB view raw
1<!doctype html> 2<html lang="en"> 3 <head> 4 <meta charset="UTF-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 <title>tinysub</title> 7 <link rel="manifest" href="manifest.json" /> 8 <link rel="icon" href="static/tinysub.svg" type="image/svg+xml" /> 9 <link rel="stylesheet" href="css/base.css" /> 10 <link rel="stylesheet" href="css/components.css" /> 11 </head> 12 <body> 13 <!-- icons cache --> 14 <!-- this serves as a lookup table for the build process, which inlines the imgs into a single html --> 15 <div id="icon-cache" style="display: none"> 16 <img id="icon-play" src="static/famfamfam-silk/control_play_blue.png" /> 17 <img id="icon-pause" src="static/famfamfam-silk/control_pause_blue.png" /> 18 <img 19 id="icon-play-next" 20 src="static/famfamfam-silk/control_fastforward_blue.png" 21 /> 22 <img id="icon-add" src="static/famfamfam-silk/add.png" /> 23 <img id="icon-favorite" src="static/famfamfam-silk/heart.png" /> 24 <img id="icon-move-up" src="static/famfamfam-silk/arrow_up.png" /> 25 <img id="icon-move-down" src="static/famfamfam-silk/arrow_down.png" /> 26 <img id="icon-remove" src="static/famfamfam-silk/cross.png" /> 27 <img id="icon-tinysub" src="static/tinysub.svg" /> 28 </div> 29 <!-- auth modal --> 30 <div id="auth-modal" class="modal hidden"> 31 <div class="modal-content"> 32 <h2>tinysub</h2> 33 <form id="login-form"> 34 <div class="form-group"> 35 <label for="server">server URL:</label> 36 <input 37 type="url" 38 id="server" 39 placeholder="http://localhost:4040" 40 required 41 /> 42 </div> 43 <div class="form-group"> 44 <label for="username">username:</label> 45 <input id="username" autocomplete="username" required /> 46 </div> 47 <div class="form-group"> 48 <label for="password">password:</label> 49 <input 50 type="password" 51 id="password" 52 autocomplete="current-password" 53 required 54 /> 55 </div> 56 <p> 57 <a href="https://tangled.org/devins.page/tinysub">source code</a> 58 </p> 59 <p id="auth-error" class="danger"></p> 60 <div class="modal-actions"> 61 <button type="submit">connect</button> 62 </div> 63 </form> 64 </div> 65 </div> 66 <!-- settings modal --> 67 <div id="settings-modal" class="modal hidden"> 68 <div class="modal-content"> 69 <h2>settings</h2> 70 <div class="form-group"> 71 <label> 72 <input type="checkbox" id="scrobbling-toggle" /> 73 scrobbling 74 </label> 75 </div> 76 <div class="form-group"> 77 <label> 78 <input type="checkbox" id="dynamic-favicon-toggle" /> 79 dynamic favicon 80 </label> 81 </div> 82 <div class="form-group"> 83 <label 84 >artist art size: <span id="artist-size-display">16</span>px</label 85 > 86 <input 87 type="range" 88 id="artist-size" 89 min="0" 90 max="256" 91 step="4" 92 value="16" 93 /> 94 </div> 95 <div class="form-group"> 96 <label 97 >album art size: <span id="album-size-display">32</span>px</label 98 > 99 <input 100 type="range" 101 id="album-size" 102 min="0" 103 max="256" 104 step="4" 105 value="32" 106 /> 107 </div> 108 <div class="form-group"> 109 <label>song art size: <span id="song-size-display">16</span>px</label> 110 <input 111 type="range" 112 id="song-size" 113 min="0" 114 max="256" 115 step="4" 116 value="16" 117 /> 118 </div> 119 <div class="form-group"> 120 <label 121 >now playing art size: 122 <span id="now-playing-size-display">128</span>px</label 123 > 124 <input 125 type="range" 126 id="now-playing-size" 127 min="0" 128 max="256" 129 step="32" 130 value="128" 131 /> 132 </div> 133 <div class="modal-actions"> 134 <button id="clear-db-settings-btn">clear dbs</button> 135 <button id="logout-settings-btn" class="danger">logout</button> 136 <button id="close-settings-btn">close</button> 137 </div> 138 </div> 139 </div> 140 <!-- keyboard help modal --> 141 <div id="keyboard-help-modal" class="modal hidden"> 142 <div class="modal-content"> 143 <h2>keyboard help</h2> 144 <div class="shortcuts-grid"> 145 <div class="shortcut-section-group"> 146 <h3>general</h3> 147 <div class="shortcuts-items-grid"> 148 <kbd>Ctrl+,</kbd><span>open settings</span> <kbd>?</kbd 149 ><span>open keyboard help</span> 150 </div> 151 </div> 152 <div class="shortcut-section-group"> 153 <h3>playback</h3> 154 <div class="shortcuts-items-grid"> 155 <kbd>Space</kbd><span>play/pause</span> <kbd>J / L</kbd 156 ><span>seek ±10s</span> <kbd>Alt+J / Alt+L</kbd 157 ><span>previous / next</span> <kbd>Shift+R</kbd 158 ><span>toggle loop</span> 159 </div> 160 </div> 161 <div class="shortcut-section-group"> 162 <h3>library</h3> 163 <div class="shortcuts-items-grid"> 164 <kbd>↑ / ↓</kbd><span>navigate rows</span> <kbd>Home / End</kbd 165 ><span>first / last row</span> <kbd>Page Up / Page Down</kbd 166 ><span>jump ±10 rows</span> <kbd>Enter</kbd 167 ><span>expand/collapse</span> <kbd>P</kbd 168 ><span>add to queue</span> <kbd>Alt+P</kbd><span>play next</span> 169 <kbd>Esc</kbd><span>clear selection</span> 170 </div> 171 </div> 172 <div class="shortcut-section-group"> 173 <h3>queue</h3> 174 <div class="shortcuts-items-grid"> 175 <kbd>↑ / ↓</kbd><span>navigate rows</span> <kbd>Home / End</kbd 176 ><span>first / last row</span> <kbd>Page Up / Page Down</kbd 177 ><span>jump ±10 rows</span> <kbd>Alt + ↑ / ↓</kbd 178 ><span>move selected rows</span> <kbd>Enter</kbd 179 ><span>play selected row</span> <kbd>Delete</kbd 180 ><span>remove selected</span> <kbd>Menu</kbd 181 ><span>context menu</span><kbd>Ctrl+A</kbd><span>select all</span 182 ><kbd>Shift + ↑ / ↓</kbd><span>extend selection</span> 183 <kbd>Esc</kbd><span>clear selection</span> 184 </div> 185 </div> 186 </div> 187 <div class="modal-actions"> 188 <button id="close-keyboard-help-btn">close</button> 189 </div> 190 </div> 191 </div> 192 193 <header id="playback"> 194 <audio id="player" crossorigin="anonymous"></audio> 195 <button id="prev-btn" aria-label="previous"> 196 <img 197 src="static/famfamfam-silk/control_rewind_blue.png" 198 alt="previous" 199 /> 200 </button> 201 <button id="play-btn" aria-label="play"> 202 <img src="static/famfamfam-silk/control_play_blue.png" alt="play" /> 203 </button> 204 <button id="next-btn" aria-label="next"> 205 <img 206 src="static/famfamfam-silk/control_fastforward_blue.png" 207 alt="next" 208 /> 209 </button> 210 <button id="loop-btn" aria-label="loop"> 211 <img src="static/famfamfam-silk/control_repeat.png" alt="loop" /> 212 </button> 213 <input type="range" id="progress" min="0" max="100" value="0" /> 214 <span id="time-display">0:00 / 0:00</span> 215 </header> 216 217 <aside id="sidebar"> 218 <div id="library"> 219 <h2> 220 <a class="section-toggle" data-section="artists">▸ artists</a> 221 </h2> 222 <div id="artists-tree"></div> 223 <h2> 224 <a class="section-toggle" data-section="playlists">▸ playlists</a> 225 </h2> 226 <div id="playlists-tree"></div> 227 </div> 228 <div id="now-playing"> 229 <img 230 id="cover-art" 231 src="static/tinysub.svg" 232 alt="cover" 233 loading="lazy" 234 /> 235 <div id="track-info"> 236 <div id="track-title">no track playing</div> 237 <div id="track-artist"></div> 238 <div id="track-lyric"></div> 239 </div> 240 </div> 241 </aside> 242 243 <main id="queue"> 244 <table id="queue-table"> 245 <thead> 246 <tr> 247 <th></th> 248 <th>title</th> 249 <th>artist</th> 250 <th>album</th> 251 <th>duration</th> 252 <th><span id="queue-count">0</span> songs</th> 253 </tr> 254 </thead> 255 <tbody id="queue-list"></tbody> 256 </table> 257 </main> 258 259 <footer id="footer"> 260 <span 261 ><a href="https://tangled.org/devins.page/tinysub">tinysub</a> 262 1.8.3</span 263 > 264 <div id="actions"> 265 <button id="clear-btn" aria-label="clear"> 266 <img src="static/famfamfam-silk/cross.png" alt="clear" /> 267 <span>clear</span> 268 </button> 269 <button id="sort-btn" aria-label="sort"> 270 <img src="static/famfamfam-silk/arrow_switch.png" alt="sort" /> 271 <span>sort</span> 272 </button> 273 <button id="settings-btn" aria-label="settings"> 274 <img src="static/famfamfam-silk/cog.png" alt="settings" /> 275 <span>settings</span> 276 </button> 277 </div> 278 </footer> 279 280 <script src="js/strings/en.js"></script> 281 <script src="js/constants.js"></script> 282 <script src="js/validation.js"></script> 283 <script src="js/selection.js"></script> 284 <script src="js/api.js"></script> 285 <script src="js/state.js"></script> 286 <script src="js/image-cache.js"></script> 287 <script src="js/queue-storage.js"></script> 288 <script src="js/virtual-scroll.js"></script> 289 <script src="js/queue.js"></script> 290 <script src="js/library.js"></script> 291 <script src="js/modal.js"></script> 292 <script src="js/input.js"></script> 293 <script src="js/contextmenu.js"></script> 294 <script src="js/ui.js"></script> 295 <script src="js/settings.js"></script> 296 <script src="js/auth.js"></script> 297 <script src="js/spark-md5.js"></script> 298 <script src="js/player.js"></script> 299 <script src="js/draggable.js"></script> 300 <script src="js/lyrics.js"></script> 301 <script src="js/events.js"></script> 302 </body> 303</html>