partial download support for stream caching, better error handling

This commit is contained in:
2026-09-02 18:23:16 +02:00
parent 62af3683a4
commit d7999785c8
4 changed files with 230 additions and 63 deletions
+26 -5
View File
@@ -54,7 +54,9 @@
<TagSelect bind:listOpen bind:checked={filteredTags} {remainingTags} />
<button
onclick={() => (cachedOnly = !cachedOnly)}
class="material-icons filter-download {cachedOnly ? 'select-faves-star' : 'unselect-faves-star'}">file_download</button
class="material-icons filter-download {cachedOnly
? 'select-faves-star'
: 'unselect-faves-star'}">file_download</button
>
<button
onclick={() => (favoritesOnly = !favoritesOnly)}
@@ -68,7 +70,9 @@
{@const isCached = streamCache.cached.has(stream.id)}
{@const current = ctx.current?.id === stream.id}
<li
hidden={!displayedStreams.includes(stream) || (favoritesOnly && !favorited) || (cachedOnly && !isCached)}
hidden={!displayedStreams.includes(stream) ||
(favoritesOnly && !favorited) ||
(cachedOnly && !isCached)}
class="stream-item {current ? 'current-stream' : ''}"
id="stream-{stream.id}"
>
@@ -102,13 +106,25 @@
<span class="stream-item-cached">{streamCache.downloading.get(stream.id)}%</span>
{:else if isCached}
<button
onclick={(e) => { e.stopPropagation(); streamCache.remove(stream.id); }}
onclick={(e) => {
e.stopPropagation();
streamCache.remove(stream.id);
}}
class="material-icons stream-item-cached stream-item-cached-btn">delete</button
>
{:else}
{@const partial = streamCache.partials.get(stream.id)}
<button
onclick={(e) => { e.stopPropagation(); streamCache.download(stream); }}
class="material-icons filter-download stream-item-cached stream-item-cached-btn">file_download</button
onclick={(e) => {
e.stopPropagation();
streamCache.download(stream);
}}
title={partial
? `Partially downloaded (${Math.round((partial.received / partial.total) * 100)}%). Click to resume.`
: undefined}
class="material-icons filter-download stream-item-cached stream-item-cached-btn {partial
? 'stream-item-partial'
: ''}">file_download</button
>
{/if}
</li>
@@ -241,6 +257,11 @@
opacity: 1;
}
.stream-item-cached.stream-item-partial {
color: #c8a415;
opacity: 0.75;
}
.material-icons::-moz-focus-inner {
border: 0;
}
@@ -15,13 +15,18 @@
const stream = data.stream;
ctx.setCurrent(stream);
playerSrc = null;
let objectUrl: string | null = null;
if (streamCache.cached.has(stream.id)) {
streamCache.getUrl(stream.id).then((url) => {
objectUrl = url;
playerSrc = url ?? `/media/tracks/${stream.filename}`;
});
} else {
playerSrc = `/media/tracks/${stream.filename}`;
}
return () => {
if (objectUrl) URL.revokeObjectURL(objectUrl);
};
});
</script>