177 lines
6.9 KiB
Rust
177 lines
6.9 KiB
Rust
//! The library organizer (name + kind of each top-level pool folder) and the
|
||
//! choice of libraries feeding miniDLNA generation.
|
||
|
||
use std::collections::HashSet;
|
||
use std::fs;
|
||
|
||
use super::{DialogState, Env, Event, modal, ok_cancel_row};
|
||
use crate::core::file_manager::{FileManager, Library, LibraryKind};
|
||
use crate::ui::common::{GREY, RED};
|
||
|
||
pub struct LibraryOrganizerDialog {
|
||
rows: Vec<(String, LibraryKind)>,
|
||
selected: Option<usize>,
|
||
}
|
||
|
||
impl LibraryOrganizerDialog {
|
||
pub fn new(fm: &FileManager) -> Self {
|
||
Self {
|
||
rows: fm
|
||
.libraries()
|
||
.into_iter()
|
||
.map(|l| (l.name, l.kind))
|
||
.collect(),
|
||
selected: None,
|
||
}
|
||
}
|
||
|
||
pub fn show(&mut self, ctx: &egui::Context, env: &mut Env) -> DialogState {
|
||
let mut ok = None;
|
||
let (_, close) = modal(ctx, "libraries", "Knihovny poolu", 560.0, |ui| {
|
||
ui.label("Knihovny = složky v kořeni poolu, každá je jedna knihovna v Jellyfinu.\nTyp určuje, jak Curator složku zpracuje.");
|
||
ui.add_space(6.0);
|
||
egui::Grid::new("lib_rows")
|
||
.striped(true)
|
||
.num_columns(3)
|
||
.show(ui, |ui| {
|
||
ui.strong("");
|
||
ui.strong("Název složky");
|
||
ui.strong("Typ");
|
||
ui.end_row();
|
||
for (i, (name, kind)) in self.rows.iter_mut().enumerate() {
|
||
ui.radio_value(&mut self.selected, Some(i), "");
|
||
crate::ui::common::sized(ui, 240.0, egui::TextEdit::singleline(name));
|
||
egui::ComboBox::from_id_salt(("kind", i))
|
||
.selected_text(kind.label())
|
||
.show_ui(ui, |ui| {
|
||
for k in LibraryKind::ALL {
|
||
ui.selectable_value(kind, k, k.label());
|
||
}
|
||
});
|
||
ui.end_row();
|
||
}
|
||
});
|
||
ui.horizontal(|ui| {
|
||
if ui.button("➕ Přidat knihovnu").clicked() {
|
||
self.rows.push((String::new(), LibraryKind::Movie));
|
||
}
|
||
if ui.button("➖ Odebrat").clicked()
|
||
&& let Some(i) = self.selected.take().filter(|i| *i < self.rows.len())
|
||
{
|
||
self.rows.remove(i);
|
||
}
|
||
});
|
||
ui.add(egui::Label::new(egui::RichText::new(
|
||
"Pozn.: „Mix“ zpracuje filmy (v kořeni) i seriály (v podsložkách); „Domácí videa“ se do miniDLNA zrcadlí celé. Po uložení nabídnu smazání prázdných složek, které už nejsou knihovnou (s obsahem nechám být).",
|
||
).color(GREY)).wrap());
|
||
ok = ok_cancel_row(ui);
|
||
});
|
||
match ok {
|
||
Some(true) => {
|
||
let specs: Vec<Library> = self
|
||
.rows
|
||
.iter()
|
||
.filter(|(n, _)| !n.trim().is_empty())
|
||
.map(|(n, k)| Library::new(n.trim(), *k))
|
||
.collect();
|
||
if let Err(e) = env.fm.set_libraries(specs) {
|
||
env.warn("Knihovny", e.to_string());
|
||
return DialogState::Open;
|
||
}
|
||
if let Some(pool) = env.fm.pool_dir() {
|
||
for lib in env.fm.libraries() {
|
||
let _ = fs::create_dir_all(pool.join(&lib.name));
|
||
}
|
||
}
|
||
let names: Vec<String> = env
|
||
.fm
|
||
.libraries()
|
||
.iter()
|
||
.map(|l| format!("{} ({})", l.name, l.kind.as_str()))
|
||
.collect();
|
||
env.events
|
||
.push(Event::Status(format!("Knihovny: {}", names.join(", "))));
|
||
env.events.push(Event::LibrariesChanged);
|
||
DialogState::Closed
|
||
}
|
||
Some(false) => DialogState::Closed,
|
||
None if close => DialogState::Closed,
|
||
None => DialogState::Open,
|
||
}
|
||
}
|
||
}
|
||
|
||
pub struct MinidlnaLibrariesDialog {
|
||
rows: Vec<(String, LibraryKind, bool)>,
|
||
}
|
||
|
||
impl MinidlnaLibrariesDialog {
|
||
pub fn new(fm: &FileManager) -> Self {
|
||
let chosen: Option<HashSet<String>> =
|
||
fm.minidlna_libraries().map(|v| v.into_iter().collect());
|
||
Self {
|
||
rows: fm
|
||
.libraries()
|
||
.into_iter()
|
||
.map(|l| {
|
||
let on = chosen.as_ref().is_none_or(|c| c.contains(&l.name));
|
||
(l.name, l.kind, on)
|
||
})
|
||
.collect(),
|
||
}
|
||
}
|
||
|
||
pub fn show(&mut self, ctx: &egui::Context, env: &mut Env) -> DialogState {
|
||
let mut ok = None;
|
||
let (_, close) = modal(
|
||
ctx,
|
||
"minidlna_libs",
|
||
"Knihovny pro generování miniDLNA",
|
||
440.0,
|
||
|ui| {
|
||
ui.add(egui::Label::new("Které knihovny se mají promítnout do miniDLNA stromu (žánry, Tipy dne, Nově přidané, zrcadlené seriály)?").wrap());
|
||
ui.add(egui::Label::new(egui::RichText::new("⚠ Odškrtnutá knihovna: její odkazy ve stromu se při dalším generování odeberou jako zastaralé, dokud ji znovu nezaškrtneš.").color(RED)).wrap());
|
||
ui.add_space(6.0);
|
||
for (name, kind, on) in &mut self.rows {
|
||
ui.checkbox(on, format!("{name} ({})", kind.as_str()));
|
||
}
|
||
ui.horizontal(|ui| {
|
||
if ui.button("Vše").clicked() {
|
||
self.rows.iter_mut().for_each(|r| r.2 = true);
|
||
}
|
||
if ui.button("Nic").clicked() {
|
||
self.rows.iter_mut().for_each(|r| r.2 = false);
|
||
}
|
||
});
|
||
ok = ok_cancel_row(ui);
|
||
},
|
||
);
|
||
match ok {
|
||
Some(true) => {
|
||
let chosen: Vec<String> = self
|
||
.rows
|
||
.iter()
|
||
.filter(|r| r.2)
|
||
.map(|r| r.0.clone())
|
||
.collect();
|
||
let all = chosen.len() == self.rows.len();
|
||
if let Err(e) =
|
||
env.fm
|
||
.set_minidlna_libraries(if all { None } else { Some(chosen.clone()) })
|
||
{
|
||
env.warn("miniDLNA", e.to_string());
|
||
}
|
||
env.events.push(Event::Status(format!(
|
||
"miniDLNA: {}/{} knihoven vybráno pro generování.",
|
||
chosen.len(),
|
||
self.rows.len()
|
||
)));
|
||
DialogState::Closed
|
||
}
|
||
Some(false) => DialogState::Closed,
|
||
None if close => DialogState::Closed,
|
||
None => DialogState::Open,
|
||
}
|
||
}
|
||
}
|