Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions src/renderer/logic/MediaSource/JellyfinMediaSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export class JellyfinMediaSource extends MediaSource {
this.accessToken = cache.accessToken;
this.userId = cache.userId;
this.lastSyncedAt = cache.lastSyncedAt;
this.hydrateFromCache(cache.items);
await this.hydrateFromCache(cache.items);

if (await this.verifySession()) {
this.isConnected.value = true;
Expand Down Expand Up @@ -452,8 +452,14 @@ export class JellyfinMediaSource extends MediaSource {
this.isSyncing.value = false;
}

private hydrateFromCache(items: JellyfinItem[]) {
items.forEach((item) => this.amethyst.player.queue.add(this.createTrackFromJellyfinItem(item)));
// Batches and yields between chunks so hydrating a large cached library doesn't
// freeze the renderer's main thread for the whole loop in one synchronous turn
private async hydrateFromCache(items: JellyfinItem[]) {
for (let i = 0; i < items.length; i += PAGE_SIZE) {
const chunk = items.slice(i, i + PAGE_SIZE).map((item) => this.createTrackFromJellyfinItem(item));
await this.amethyst.player.queue.add(chunk);
await new Promise((resolve) => setTimeout(resolve, 0));
}
}

private upsertTrack(item: JellyfinItem, existingById: Map<string, Track>) {
Expand Down
20 changes: 12 additions & 8 deletions src/renderer/logic/queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ export class Queue {
public constructor(private amethyst: Amethyst, paths?: string[]) {
if (paths) this.add(paths);
else {
// load saved queue from local storage
this.savedQueue.value.forEach((item) => {
// load saved queue from local storage, built up front and added in one batch so
// restoring a large queue doesn't re-serialize the whole list to storage per track
const tracks = this.savedQueue.value.map((item) => {
const track = new Track(this.amethyst, item.path);

if (item.type == MediaSourceType.Subsonic) {
Expand All @@ -71,8 +72,10 @@ export class Queue {
track.sourceType = MediaSourceType.Jellyfin;
}

this.add(track);
return track;
});

this.add(tracks);
}
}

Expand Down Expand Up @@ -151,16 +154,17 @@ export class Queue {
}

/**
* Adds a track to the queue
* @param item A filepath to the track
* Adds a track, or a batch of filepaths/tracks under a single localStorage sync, to the queue
* @param item A filepath, a track, or an array of either
*/
public async add(item: (string | string[]) | Track) {
public async add(item: (string | string[]) | Track | Track[]) {
if (item instanceof Track) {
this.list.value.set(item.path, item);
}
else if (item instanceof Array) {
const paths = Array.from(item);
paths.forEach((path) => this.list.value.set(path, new Track(this.amethyst, path)));
item.forEach((entry) => entry instanceof Track
? this.list.value.set(entry.path, entry)
: this.list.value.set(entry, new Track(this.amethyst, entry)));
}
else if (typeof item === "string") {
this.list.value.set(item, new Track(this.amethyst, item));
Expand Down
Loading