Skip to content

Commit cc334a5

Browse files
committed
feat(network): implement background prefetching for saved tracks and playlists to enhance playback performance
1 parent 7653a29 commit cc334a5

1 file changed

Lines changed: 45 additions & 23 deletions

File tree

‎src/network.rs‎

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -337,10 +337,23 @@ impl Network {
337337
self.start_collection_playback(offset).await;
338338
}
339339
IoEvent::PreFetchAllSavedTracks => {
340-
self.prefetch_all_saved_tracks().await;
340+
// Spawn prefetch as a separate task to avoid blocking playback
341+
let spotify = self.spotify.clone();
342+
let app = self.app.clone();
343+
let large_search_limit = self.large_search_limit;
344+
tokio::spawn(async move {
345+
Self::prefetch_all_saved_tracks_task(spotify, app, large_search_limit).await;
346+
});
341347
}
342348
IoEvent::PreFetchAllPlaylistTracks(playlist_id) => {
343-
self.prefetch_all_playlist_tracks(playlist_id).await;
349+
// Spawn prefetch as a separate task to avoid blocking playback
350+
let spotify = self.spotify.clone();
351+
let app = self.app.clone();
352+
let large_search_limit = self.large_search_limit;
353+
tokio::spawn(async move {
354+
Self::prefetch_all_playlist_tracks_task(spotify, app, large_search_limit, playlist_id)
355+
.await;
356+
});
344357
}
345358
};
346359

@@ -1133,10 +1146,15 @@ impl Network {
11331146

11341147
/// Pre-fetch all saved tracks pages in background for seamless playback
11351148
/// This loads all remaining pages that haven't been loaded yet
1136-
async fn prefetch_all_saved_tracks(&mut self) {
1149+
/// Runs as a separate async task to avoid blocking other operations
1150+
async fn prefetch_all_saved_tracks_task(
1151+
spotify: AuthCodeSpotify,
1152+
app: Arc<Mutex<App>>,
1153+
large_search_limit: u32,
1154+
) {
11371155
// Get current state
11381156
let (current_total, pages_loaded) = {
1139-
let app = self.app.lock().await;
1157+
let app = app.lock().await;
11401158
if let Some(saved_tracks) = app.library.saved_tracks.get_results(Some(0)) {
11411159
(
11421160
saved_tracks.total,
@@ -1148,20 +1166,19 @@ impl Network {
11481166
};
11491167

11501168
// Calculate how many tracks we already have
1151-
let tracks_loaded = pages_loaded * self.large_search_limit;
1169+
let tracks_loaded = pages_loaded * large_search_limit;
11521170

11531171
// Fetch remaining pages (limit to reasonable amount to avoid memory issues)
11541172
let max_tracks_to_prefetch = 500; // ~10 pages
11551173
let mut offset = tracks_loaded;
11561174

11571175
while offset < current_total && offset < tracks_loaded + max_tracks_to_prefetch {
1158-
match self
1159-
.spotify
1160-
.current_user_saved_tracks_manual(None, Some(self.large_search_limit), Some(offset))
1176+
match spotify
1177+
.current_user_saved_tracks_manual(None, Some(large_search_limit), Some(offset))
11611178
.await
11621179
{
11631180
Ok(saved_tracks) => {
1164-
let mut app = self.app.lock().await;
1181+
let mut app = app.lock().await;
11651182
// Add liked song IDs to the set
11661183
saved_tracks.items.iter().for_each(|item| {
11671184
if let Some(track_id) = &item.track.id {
@@ -1171,20 +1188,26 @@ impl Network {
11711188
// Add page to the saved tracks
11721189
app.library.saved_tracks.pages.push(saved_tracks);
11731190
}
1174-
Err(e) => {
1175-
self.handle_error(anyhow!(e)).await;
1191+
Err(_e) => {
1192+
// Silently fail in background task - don't show errors to user
11761193
break;
11771194
}
11781195
}
1179-
offset += self.large_search_limit;
1196+
offset += large_search_limit;
11801197
}
11811198
}
11821199

11831200
/// Pre-fetch all tracks from a playlist in background
1184-
async fn prefetch_all_playlist_tracks(&mut self, playlist_id: PlaylistId<'static>) {
1201+
/// Runs as a separate async task to avoid blocking other operations
1202+
async fn prefetch_all_playlist_tracks_task(
1203+
spotify: AuthCodeSpotify,
1204+
app: Arc<Mutex<App>>,
1205+
large_search_limit: u32,
1206+
playlist_id: PlaylistId<'static>,
1207+
) {
11851208
// Get current playlist state
11861209
let current_total = {
1187-
let app = self.app.lock().await;
1210+
let app = app.lock().await;
11881211
if let Some(playlist_tracks) = &app.playlist_tracks {
11891212
playlist_tracks.total
11901213
} else {
@@ -1194,41 +1217,40 @@ impl Network {
11941217

11951218
// Get current offset
11961219
let current_offset = {
1197-
let app = self.app.lock().await;
1220+
let app = app.lock().await;
11981221
app.playlist_offset
11991222
};
12001223

12011224
// Fetch remaining pages (limit to avoid memory issues)
12021225
let max_tracks_to_prefetch = 500; // ~10 pages
1203-
let mut offset = current_offset + self.large_search_limit;
1226+
let mut offset = current_offset + large_search_limit;
12041227

12051228
while offset < current_total && offset < current_offset + max_tracks_to_prefetch {
1206-
match self
1207-
.spotify
1229+
match spotify
12081230
.playlist_items_manual(
12091231
playlist_id.clone(),
12101232
None,
12111233
None,
1212-
Some(self.large_search_limit),
1234+
Some(large_search_limit),
12131235
Some(offset),
12141236
)
12151237
.await
12161238
{
12171239
Ok(playlist_page) => {
12181240
// Store the fetched tracks
1219-
let mut app = self.app.lock().await;
1241+
let mut app = app.lock().await;
12201242
// Extend playlist tracks items
12211243
if let Some(ref mut existing) = app.playlist_tracks {
12221244
existing.items.extend(playlist_page.items);
12231245
existing.total = playlist_page.total; // Update total in case it changed
12241246
}
12251247
}
1226-
Err(e) => {
1227-
self.handle_error(anyhow!(e)).await;
1248+
Err(_e) => {
1249+
// Silently fail in background task - don't show errors to user
12281250
break;
12291251
}
12301252
}
1231-
offset += self.large_search_limit;
1253+
offset += large_search_limit;
12321254
}
12331255
}
12341256

0 commit comments

Comments
 (0)