Files
brittle/brittle-ui/src/pub_list.rs

83 lines
3.7 KiB
Rust

//! Publication list: centre pane showing filtered references.
use leptos::prelude::*;
use brittle_model::ReferenceSummary;
use crate::lib_tab::Pane;
/// Centre pane: a scrollable list of publication summaries.
///
/// `cursor` tracks which row is selected; clicking a row updates it.
/// Items are draggable — dropping onto a library tree node calls
/// `add_to_library` via the Tauri IPC.
#[component]
pub fn PubList(
items: RwSignal<Vec<ReferenceSummary>>,
cursor: RwSignal<usize>,
focused: RwSignal<Pane>,
) -> impl IntoView {
use leptos::either::Either;
let open_pdf_ctx = use_context::<crate::OpenPdfContext>();
view! {
<div class="pub-list-pane" class:pane-focused=move || focused.get() == Pane::List>
{move || {
let list = items.get();
if list.is_empty() {
Either::Left(view! {
<div class="empty-state">"No publications"</div>
})
} else {
let cursor_pos = cursor.get();
Either::Right(view! {
<ul class="pub-list">
{list.into_iter().enumerate().map(|(i, item)| {
let is_cursor = i == cursor_pos;
let title = item.title_display().to_owned();
let authors = item.author_display();
let year = item.year.clone().unwrap_or_default();
let kind = item.entry_type.to_string();
let ref_id = item.id.to_string();
let cite_key = item.cite_key.clone();
let ref_id_for_dblclick = ref_id.clone();
view! {
<li
class="pub-item"
class:pub-cursor=is_cursor
draggable="true"
on:dragstart=move |ev| {
let ev: &web_sys::DragEvent = &ev;
if let Some(dt) = ev.data_transfer() {
let _ = dt.set_data(
"application/brittle-ref-id",
&ref_id,
);
}
}
on:click=move |_| cursor.set(i)
on:dblclick=move |_| {
cursor.set(i);
if let Some(ctx) = open_pdf_ctx {
ctx.0.set(Some(crate::PdfOpenRequest {
ref_id: ref_id_for_dblclick.clone(),
title: cite_key.clone(),
}));
}
}
>
<span class="pub-type">{kind}</span>
<span class="pub-title">{title}</span>
<span class="pub-meta">{authors}{" "}{year}</span>
</li>
}
}).collect::<Vec<_>>()}
</ul>
})
}
}}
</div>
}
}