[READ-ONLY] Mirror of https://github.com/probablykasper/ferrum. Music library app for Mac, Linux and Windows ferrum.kasper.space
electron linux macos music music-library music-player napi windows
0

Configure Feed

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

Add "All Songs" playlist

Kasper (Mar 5, 2026, 5:06 PM +0100) 27441702 d509d68b

+41 -3
+41 -3
mobile/src/routes/Library.svelte
··· 54 54 return get_folder(folder_id)?.children ?? [] 55 55 } 56 56 57 - function node_name(id: string): string { 57 + function node_name(id: string, context?: 'browser' | 'tracks'): string { 58 + if (id === 'root' && context === 'tracks') return 'All Songs' 58 59 const tl = get_tracklist(id) 59 60 if (!tl) return 'Unknown' 60 61 if (tl.type === 'special') return 'Library' ··· 91 92 // in Rust serializes them back to track ID strings over the wire. 92 93 const playlist_tracks = $derived.by(() => { 93 94 if (view.kind !== 'tracks') return [] 95 + // Fake "All Songs" playlist — aggregate every track in the library 96 + if (view.playlist_id === 'root') { 97 + return Object.values(library?.tracks ?? {}) as Track[] 98 + } 94 99 const playlist = get_playlist(view.playlist_id) 95 100 if (!playlist) { 96 101 console.error('[Library] no playlist found for id', view.playlist_id) ··· 195 200 <div class="min-w-0 flex-1"> 196 201 {#if view.kind === 'browser'} 197 202 <p class="truncate leading-tight font-semibold text-neutral-900 dark:text-neutral-100"> 198 - {node_name(view.folder_id)} 203 + {node_name(view.folder_id, 'browser')} 199 204 </p> 200 205 {:else if view.kind === 'tracks'} 201 206 <p class="truncate leading-tight font-semibold text-neutral-900 dark:text-neutral-100"> 202 - {node_name(view.playlist_id)} 207 + {node_name(view.playlist_id, 'tracks')} 203 208 </p> 204 209 {/if} 205 210 </div> ··· 220 225 <div class="flex-1 overflow-y-auto"> 221 226 {#if current_children.length > 0} 222 227 <ul class="divide-y divide-neutral-200 dark:divide-neutral-900"> 228 + {#if view.folder_id === 'root'} 229 + <li> 230 + <button 231 + type="button" 232 + onclick={() => open_playlist('root')} 233 + class="flex w-full items-center gap-3 px-4 py-3.5 text-left transition-colors hover:bg-neutral-100/50 active:bg-neutral-100 dark:hover:bg-neutral-800/50 dark:active:bg-neutral-800" 234 + > 235 + <span class="w-7 shrink-0 text-center text-neutral-500 select-none"> 236 + <svg 237 + style="transform: translateX(2px)" 238 + xmlns="http://www.w3.org/2000/svg" 239 + height="24px" 240 + viewBox="0 0 24 24" 241 + width="24px" 242 + fill="currentColor" 243 + ><path 244 + d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z" 245 + /></svg 246 + > 247 + </span> 248 + <div class="min-w-0 flex-1"> 249 + <p class="truncate font-medium text-neutral-900 dark:text-neutral-100"> 250 + All Songs 251 + </p> 252 + <p class="mt-0.5 text-xs text-neutral-500"> 253 + {Object.keys(library?.tracks ?? {}).length} 254 + {Object.keys(library?.tracks ?? {}).length === 1 ? 'track' : 'tracks'} 255 + </p> 256 + </div> 257 + <span class="text-lg text-neutral-400 select-none dark:text-neutral-700">›</span> 258 + </button> 259 + </li> 260 + {/if} 223 261 {#each current_children as child_id} 224 262 {@const tl = get_tracklist(child_id)} 225 263 {#if tl?.type === 'folder'}