fix(offline): one server-only rule for both library views
Two defects with one cause: "server only" was a private $derived inside MediaCard. The list view (what LibraryGrid renders when the stored view preference is list) had no notion of it at all, so a library browsed as a list offline showed every revealed item as an ordinary tappable row that plays nothing, with no way to queue it. And the rule asked the downloads store whether *this item id* was downloaded — but only a playable leaf (Audio, Movie, Episode) ever has a download row. An album's tracks carry them, the album does not, so a fully downloaded album greyed itself out and offered to queue what was already on the device. The rule moves to the pure $lib/utils/serverOnly and both views call it. The container half is answered by the backend rather than guessed at: get_download_disk_usage().sizes already carries container subtotals beside leaf sizes (DR-085), so deviceContentIds is membership in a Rust-computed map, not a frontend list of which item types are containers. That map was loaded only by the Downloads page, so the shell primes it at startup and re-reads it whenever the offline gate settles. Queueing is shared too, since the list view had no copy to diverge from. TRACES: UR-052, UR-055 | DR-292 | UT-257, UT-258
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Tests for the "server only" card rule shared by the grid and the list view.
|
||||
*
|
||||
* TRACES: UR-052 | DR-292 | UT-257
|
||||
*/
|
||||
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { isServerOnly, type ServerOnlyInput } from "./serverOnly";
|
||||
|
||||
const offlineReveal: ServerOnlyInput = {
|
||||
isMediaItem: true,
|
||||
isConnected: false,
|
||||
revealServerCatalog: true,
|
||||
isDownloaded: false,
|
||||
isActivelyDownloading: false,
|
||||
hasDeviceContent: false,
|
||||
};
|
||||
|
||||
describe("isServerOnly", () => {
|
||||
it("is true only offline, with the reveal on, for an item with nothing on the device", () => {
|
||||
expect(isServerOnly(offlineReveal)).toBe(true);
|
||||
expect(isServerOnly({ ...offlineReveal, isConnected: true })).toBe(false);
|
||||
expect(isServerOnly({ ...offlineReveal, revealServerCatalog: false })).toBe(false);
|
||||
});
|
||||
|
||||
it("never greys a library tile: there is nothing to queue", () => {
|
||||
expect(isServerOnly({ ...offlineReveal, isMediaItem: false })).toBe(false);
|
||||
});
|
||||
|
||||
it("does not grey the item's own completed or in-flight download", () => {
|
||||
expect(isServerOnly({ ...offlineReveal, isDownloaded: true })).toBe(false);
|
||||
expect(isServerOnly({ ...offlineReveal, isActivelyDownloading: true })).toBe(false);
|
||||
});
|
||||
|
||||
it("does not grey a container whose children are on the device", () => {
|
||||
// The regression: an album has no download row of its own — its *tracks*
|
||||
// do — so a fully downloaded album greyed itself out and offered to queue
|
||||
// what was already there.
|
||||
expect(isServerOnly({ ...offlineReveal, hasDeviceContent: true })).toBe(false);
|
||||
});
|
||||
|
||||
it("still greys a container with nothing downloaded under it", () => {
|
||||
expect(isServerOnly({ ...offlineReveal, hasDeviceContent: false })).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user