full playlist integration almost complete

This commit is contained in:
2026-02-16 20:24:47 -06:00
parent 1d2a7d5268
commit 7dc15dae1b
2 changed files with 178 additions and 4 deletions

View File

@@ -47,6 +47,7 @@ enum View {
total: usize,
page_size: usize,
loading: bool,
playlist_ctx: Option<PlaylistCtx>,
},
OfflineLibrary {
title: String,
@@ -57,6 +58,11 @@ enum View {
Login,
}
#[derive(Clone)]
struct PlaylistCtx {
name: String,
}
#[derive(Clone, Debug, Default)]
struct MpvState {
eof: bool,
@@ -496,6 +502,7 @@ fn handle_key(app: &mut App, code: KeyCode) {
total: page.total,
page_size: PAGE_SIZE,
loading: false,
playlist_ctx: None,
});
app.status = "Search loaded".into();
}
@@ -1018,6 +1025,7 @@ fn handle_key(app: &mut App, code: KeyCode) {
// downloads focus overrides normal navigation
// downloads focus overrides normal navigation
/* //come back
let mut handled_by_downloads = false;
if app.downloads_focus {
@@ -1055,6 +1063,7 @@ fn handle_key(app: &mut App, code: KeyCode) {
if handled_by_downloads {
return;
}
*/
match code {
KeyCode::Char('d') => {
@@ -1067,8 +1076,12 @@ fn handle_key(app: &mut App, code: KeyCode) {
None => { app.status = "No user_id (login first)".into(); return; }
};
let (it) = match app.current_view() {
View::Library { items, selected, .. } if !items.is_empty() => items[*selected].clone(),
let (it, playlist_name, playlist_index) = match app.current_view() {
View::Library { items, selected, playlist_ctx, .. } if !items.is_empty() => {
let it = items[*selected].clone();
let pname = playlist_ctx.as_ref().map(|p| p.name.clone());
(it, pname, *selected)
}
_ => { app.status = "Nothing to download here".into(); return; }
};
@@ -1091,6 +1104,24 @@ fn handle_key(app: &mut App, code: KeyCode) {
Err(e) => { app.status = format!("downloads: {e}"); return; }
};
if let Some(pname) = playlist_name {
// only allow direct playables from playlists
let ty = it.item_type.as_deref().unwrap_or("");
let playable = matches!(ty, "Movie" | "Episode" | "Audio");
if !playable {
app.status = "Playlist downloads only support Movie/Episode/Audio".into();
return;
}
dm.send(downloads::DownloadCommand::EnqueuePlaylistItem {
item: it,
playlist_name: pname,
playlist_index,
});
app.status = "queued 1 (playlist)".into();
return;
}
match downloads::expand_for_enqueue(&jf, user_id, &it) {
Ok(items) => {
let n = items.len();
@@ -1166,6 +1197,7 @@ fn handle_key(app: &mut App, code: KeyCode) {
total, // cheap total for UI
page_size: PAGE_SIZE,
loading: false,
playlist_ctx: None,
});
app.status = "Loaded".into();
}
@@ -1212,6 +1244,7 @@ fn handle_key(app: &mut App, code: KeyCode) {
total: page.total,
page_size: PAGE_SIZE,
loading: false,
playlist_ctx: None,
});
app.status = "$".into();
}
@@ -1292,6 +1325,7 @@ fn handle_key(app: &mut App, code: KeyCode) {
total: page.total,
page_size: PAGE_SIZE,
loading: false,
playlist_ctx: Some(PlaylistCtx { name: it.name.clone() }),
});
app.status = "$".into();
}
@@ -2006,6 +2040,7 @@ fn open_children(app: &mut App, title: String, query: core::jellyfin::LibraryQue
total: page.total,
page_size: PAGE_SIZE,
loading: false,
playlist_ctx: None,
});
app.status = "$".into();
}