|
137 | 137 | let libraryConfigured = $state(false); |
138 | 138 | let jellyfinUrl = $state(''); |
139 | 139 | let cacheUsage = $state<{ usedBytes: string; quotaBytes: string; percentage: number } | null>(null); |
| 140 | + let libraryUsage = $state<{ video: { usedBytes: string; count: number } | null; music: { usedBytes: string; count: number } | null } | null>(null); |
140 | 141 | let clearingCache = $state(false); |
141 | 142 |
|
142 | 143 | function buildOptionsFlags(opts: { sponsorblock: boolean; subtitles: boolean; metadata: boolean }, saveToLibrary = false): string[] { |
|
249 | 250 | try { |
250 | 251 | const res = await fetch('/api/library/usage'); |
251 | 252 | if (res.ok) { |
252 | | - cacheUsage = await res.json(); |
| 253 | + const data = await res.json(); |
| 254 | + cacheUsage = data.cache; |
| 255 | + libraryUsage = data.library; |
253 | 256 | } |
254 | 257 | } catch (e) { |
255 | | - console.error('Failed to load cache usage:', e); |
| 258 | + console.error('Failed to load usage:', e); |
256 | 259 | } |
257 | 260 | } |
258 | 261 |
|
|
734 | 737 | </div> |
735 | 738 | </div> |
736 | 739 |
|
737 | | - {#if cacheUsage} |
738 | | - <div class="cache-usage"> |
739 | | - <div class="cache-usage-header"> |
740 | | - <div class="cache-usage-left"> |
741 | | - <span class="cache-usage-label">Cache Usage</span> |
742 | | - <span class="cache-usage-tooltip" data-tooltip="Downloads are stored in a temporary cache. When the cache fills up, the oldest downloads are automatically removed to free space. Save to Library to keep downloads permanently.">?</span> |
| 740 | + {#if cacheUsage || libraryUsage} |
| 741 | + <div class="storage-row"> |
| 742 | + {#if cacheUsage} |
| 743 | + <div class="storage-box"> |
| 744 | + <div class="cache-usage-header"> |
| 745 | + <div class="cache-usage-left"> |
| 746 | + <span class="cache-usage-label">Cache</span> |
| 747 | + <span class="cache-usage-tooltip" data-tooltip="Downloads are stored in a temporary cache. When the cache fills up, the oldest downloads are automatically removed to free space. Save to Library to keep downloads permanently.">?</span> |
| 748 | + </div> |
| 749 | + <div class="cache-usage-right"> |
| 750 | + <span class="cache-usage-value">{formatBytes(cacheUsage.usedBytes)} / {formatBytes(cacheUsage.quotaBytes)}</span> |
| 751 | + {#if Number(cacheUsage.usedBytes) > 0} |
| 752 | + <button class="btn btn-sm btn-secondary cache-clear-btn" onclick={clearCache} disabled={clearingCache}> |
| 753 | + {clearingCache ? 'Clearing...' : 'Clear'} |
| 754 | + </button> |
| 755 | + {/if} |
| 756 | + </div> |
| 757 | + </div> |
| 758 | + <div class="cache-usage-bar"> |
| 759 | + <div class="cache-usage-fill" class:warning={cacheUsage.percentage > 80} class:critical={cacheUsage.percentage > 95} style="width: max({cacheUsage.percentage}%, {cacheUsage.percentage > 0 ? '4px' : '0px'})"></div> |
| 760 | + </div> |
743 | 761 | </div> |
744 | | - <div class="cache-usage-right"> |
745 | | - <span class="cache-usage-value">{formatBytes(cacheUsage.usedBytes)} / {formatBytes(cacheUsage.quotaBytes)}</span> |
746 | | - {#if Number(cacheUsage.usedBytes) > 0} |
747 | | - <button class="btn btn-sm btn-secondary cache-clear-btn" onclick={clearCache} disabled={clearingCache}> |
748 | | - {clearingCache ? 'Clearing...' : 'Clear'} |
749 | | - </button> |
750 | | - {/if} |
| 762 | + {/if} |
| 763 | + {#if libraryUsage?.video} |
| 764 | + <div class="storage-box"> |
| 765 | + <div class="cache-usage-header"> |
| 766 | + <div class="cache-usage-left"> |
| 767 | + <span class="cache-usage-label">Video Library</span> |
| 768 | + </div> |
| 769 | + <div class="cache-usage-right"> |
| 770 | + <span class="cache-usage-value">{formatBytes(libraryUsage.video.usedBytes)}</span> |
| 771 | + <span class="storage-count">{libraryUsage.video.count} file{libraryUsage.video.count !== 1 ? 's' : ''}</span> |
| 772 | + </div> |
| 773 | + </div> |
751 | 774 | </div> |
752 | | - </div> |
753 | | - <div class="cache-usage-bar"> |
754 | | - <div class="cache-usage-fill" class:warning={cacheUsage.percentage > 80} class:critical={cacheUsage.percentage > 95} style="width: max({cacheUsage.percentage}%, {cacheUsage.percentage > 0 ? '4px' : '0px'})"></div> |
755 | | - </div> |
| 775 | + {/if} |
| 776 | + {#if libraryUsage?.music} |
| 777 | + <div class="storage-box"> |
| 778 | + <div class="cache-usage-header"> |
| 779 | + <div class="cache-usage-left"> |
| 780 | + <span class="cache-usage-label">Music Library</span> |
| 781 | + </div> |
| 782 | + <div class="cache-usage-right"> |
| 783 | + <span class="cache-usage-value">{formatBytes(libraryUsage.music.usedBytes)}</span> |
| 784 | + <span class="storage-count">{libraryUsage.music.count} file{libraryUsage.music.count !== 1 ? 's' : ''}</span> |
| 785 | + </div> |
| 786 | + </div> |
| 787 | + </div> |
| 788 | + {/if} |
756 | 789 | </div> |
757 | 790 | {/if} |
758 | 791 |
|
|
1933 | 1966 | margin-bottom: var(--spacing-lg); |
1934 | 1967 | } |
1935 | 1968 |
|
1936 | | - .cache-usage { |
| 1969 | + .storage-row { |
| 1970 | + display: flex; |
| 1971 | + gap: var(--spacing-md); |
| 1972 | + margin-bottom: var(--spacing-lg); |
| 1973 | + } |
| 1974 | +
|
| 1975 | + .storage-box { |
1937 | 1976 | background: var(--bg-secondary); |
1938 | 1977 | border: 1px solid var(--border); |
1939 | 1978 | border-radius: var(--radius-lg); |
1940 | 1979 | padding: var(--spacing-md) var(--spacing-lg); |
1941 | | - margin-bottom: var(--spacing-lg); |
| 1980 | + flex: 1; |
| 1981 | + min-width: 0; |
| 1982 | + } |
| 1983 | +
|
| 1984 | + .storage-count { |
| 1985 | + font-size: 0.75rem; |
| 1986 | + color: var(--text-tertiary); |
1942 | 1987 | } |
1943 | 1988 |
|
1944 | 1989 | .cache-usage-header { |
|
2145 | 2190 | width: 100%; |
2146 | 2191 | } |
2147 | 2192 |
|
| 2193 | + .storage-row { |
| 2194 | + flex-direction: column; |
| 2195 | + } |
| 2196 | +
|
2148 | 2197 | .downloads-layout { |
2149 | 2198 | grid-template-columns: 1fr; |
2150 | 2199 | gap: var(--spacing-lg); |
|
0 commit comments