Playlist downloading and offline hardlinks
This commit is contained in:
66
src/main.rs
66
src/main.rs
@@ -1076,19 +1076,17 @@ fn handle_key(app: &mut App, code: KeyCode) {
|
|||||||
None => { app.status = "No user_id (login first)".into(); return; }
|
None => { app.status = "No user_id (login first)".into(); return; }
|
||||||
};
|
};
|
||||||
|
|
||||||
let (it, playlist_name, playlist_index) = match app.current_view() {
|
let (selected_item, playlist_ctx, selected_index) = match app.current_view() {
|
||||||
View::Library { items, selected, playlist_ctx, .. } if !items.is_empty() => {
|
View::Library { items, selected, playlist_ctx, .. } if !items.is_empty() => {
|
||||||
let it = items[*selected].clone();
|
(items[*selected].clone(), playlist_ctx.clone(), *selected)
|
||||||
let pname = playlist_ctx.as_ref().map(|p| p.name.clone());
|
|
||||||
(it, pname, *selected)
|
|
||||||
}
|
}
|
||||||
_ => { app.status = "Nothing to download here".into(); return; }
|
_ => { app.status = "Nothing to download here".into(); return; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ensure DM
|
||||||
let dm = match &app.downloads {
|
let dm = match &app.downloads {
|
||||||
Some(dm) => dm,
|
Some(dm) => dm,
|
||||||
None => {
|
None => {
|
||||||
// try start downloads now if we have a token
|
|
||||||
if cfg.access_token.is_some() {
|
if cfg.access_token.is_some() {
|
||||||
app.downloads = Some(downloads::DownloadManager::start(cfg.clone()));
|
app.downloads = Some(downloads::DownloadManager::start(cfg.clone()));
|
||||||
app.downloads.as_ref().unwrap()
|
app.downloads.as_ref().unwrap()
|
||||||
@@ -1099,14 +1097,17 @@ fn handle_key(app: &mut App, code: KeyCode) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let jf = match core::jellyfin::JellyfinClient::from_config(&cfg) {
|
let client = match core::jellyfin::JellyfinClient::from_config(&cfg) {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(e) => { app.status = format!("downloads: {e}"); return; }
|
Err(e) => { app.status = format!("downloads: {e}"); return; }
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(pname) = playlist_name {
|
let ty = selected_item.item_type.as_deref().unwrap_or("");
|
||||||
// only allow direct playables from playlists
|
|
||||||
let ty = it.item_type.as_deref().unwrap_or("");
|
// -------------------------
|
||||||
|
// CASE 1: We are INSIDE a playlist view (already works)
|
||||||
|
// -------------------------
|
||||||
|
if let Some(pctx) = playlist_ctx {
|
||||||
let playable = matches!(ty, "Movie" | "Episode" | "Audio");
|
let playable = matches!(ty, "Movie" | "Episode" | "Audio");
|
||||||
if !playable {
|
if !playable {
|
||||||
app.status = "Playlist downloads only support Movie/Episode/Audio".into();
|
app.status = "Playlist downloads only support Movie/Episode/Audio".into();
|
||||||
@@ -1114,15 +1115,53 @@ fn handle_key(app: &mut App, code: KeyCode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dm.send(downloads::DownloadCommand::EnqueuePlaylistItem {
|
dm.send(downloads::DownloadCommand::EnqueuePlaylistItem {
|
||||||
item: it,
|
item: selected_item,
|
||||||
playlist_name: pname,
|
playlist_name: pctx.name,
|
||||||
playlist_index,
|
playlist_index: selected_index,
|
||||||
});
|
});
|
||||||
app.status = "queued 1 (playlist)".into();
|
app.status = "queued 1 (playlist)".into();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match downloads::expand_for_enqueue(&jf, user_id, &it) {
|
// -------------------------
|
||||||
|
// CASE 2: We are on the PLAYLIST LIST and selected item IS a playlist
|
||||||
|
// -> enqueue via playlist-aware path so we get hardlinks/order
|
||||||
|
// -------------------------
|
||||||
|
if ty == "Playlist" {
|
||||||
|
app.status = format!("Fetching playlist… {}", selected_item.name);
|
||||||
|
|
||||||
|
match client.playlist_items(user_id, &selected_item.id, 0, 200) {
|
||||||
|
Ok(page) => {
|
||||||
|
let pname = selected_item.name.clone();
|
||||||
|
let mut n = 0usize;
|
||||||
|
|
||||||
|
for (i, it) in page.items.into_iter().enumerate() {
|
||||||
|
let it_ty = it.item_type.as_deref().unwrap_or("");
|
||||||
|
let playable = matches!(it_ty, "Movie" | "Episode" | "Audio");
|
||||||
|
if !playable { continue; }
|
||||||
|
|
||||||
|
dm.send(downloads::DownloadCommand::EnqueuePlaylistItem {
|
||||||
|
item: it,
|
||||||
|
playlist_name: pname.clone(),
|
||||||
|
playlist_index: i,
|
||||||
|
});
|
||||||
|
n += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
app.status = format!("queued {n} (playlist)");
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
app.status = format!("Playlist load failed: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------
|
||||||
|
// CASE 3: Normal (non-playlist-container) download behavior
|
||||||
|
// -------------------------
|
||||||
|
match downloads::expand_for_enqueue(&client, user_id, &selected_item) {
|
||||||
Ok(items) => {
|
Ok(items) => {
|
||||||
let n = items.len();
|
let n = items.len();
|
||||||
dm.send(downloads::DownloadCommand::Enqueue(items));
|
dm.send(downloads::DownloadCommand::Enqueue(items));
|
||||||
@@ -1133,6 +1172,7 @@ fn handle_key(app: &mut App, code: KeyCode) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
KeyCode::Char('q') => app.should_exit = true,
|
KeyCode::Char('q') => app.should_exit = true,
|
||||||
|
|
||||||
//Enter code Block
|
//Enter code Block
|
||||||
|
|||||||
Reference in New Issue
Block a user