use super::*;
use crate::api::packages::{PackageDetail, PackageList, PackagesOf, install};
use std::fmt::Write as _;
fn visibility(v: &str) -> Option<Seg> {
match v {
"" | "public" => None,
v => Some(chip(capitalized(v), Bg::SecondaryContainer)),
}
}
pub fn packages(page: &mut Page, of: &PackagesOf, list: &PackageList, now: u64) {
let title = vec![strong(format!("Packages {}", list.items.len()))];
let empty = match of {
PackagesOf::Owner(_) => "No packages published.",
PackagesOf::Repo(_) => "This repository hasn't published packages.",
};
let items = Whole(&list.items);
list_box(page, title, Vec::new(), &items, empty, |page, p| {
item(page, url::package(&p.at, None), |page, link| {
let mut segs = vec![
Seg::linked(p.at.name.clone(), Role::Link, link),
space(),
chip(p.at.kind.name(), Bg::ContainerHigh),
];
if let Some(v) = visibility(&p.visibility) {
segs.extend([space(), v]);
}
page.box_line(segs, Vec::new(), 0);
let mut subline = plural(p.versions, "version");
if let Some(at) = &p.updated_at {
let _ = write!(subline, " · updated {}", time::ago_iso(at, now));
}
if let (Some(repo), PackagesOf::Owner(_)) = (&p.repo, of) {
let _ = write!(subline, " · {repo}");
}
body(page, vec![meta(subline)]);
});
});
if !list.cut.is_empty() {
let kinds: Vec<&str> = list.cut.iter().map(|k| k.name()).collect();
let kinds = kinds.join(", ");
let text = format!("Only the first 100 {kinds} packages are listed.");
say(page, text, Role::Meta);
}
}
pub fn package(
page: &mut Page,
d: &PackageDetail,
version: Option<u64>,
delete_key: &str,
now: u64,
) {
let p = &d.package;
let mut title = vec![
Seg::new(p.at.name.clone(), Role::Title),
space(),
chip(p.at.kind.name(), Bg::ContainerHigh),
];
if let Some(v) = visibility(&p.visibility) {
title.extend([space(), v]);
}
page.line(title);
let mut subline = vec![meta("By "), login_seg(page, &p.at.owner, Role::Link)];
if let Some(repo) = &p.repo {
subline.push(meta(" · from "));
let from = url::repo(repo);
subline.push(link_seg(page, repo.to_string(), from, Role::Link));
}
subline.push(meta(format!(" · {}", plural(p.versions, "version"))));
page.wrapped(subline, 0, Frame::None);
page.blank();
let shown = match version {
Some(id) => d.versions.items.iter().find(|v| v.id == id),
None => d.versions.items.first(),
};
if let Some(v) = shown {
let name = v.tags.first().unwrap_or(&v.name);
let title = vec![strong(format!("Install {name}"))];
page.box_top(title, Vec::new());
for line in install(&p.at, p.repo.as_ref(), v) {
page.wrapped(vec![Seg::new(line, Role::Code)], 0, Frame::Body);
}
page.box_bottom();
page.blank();
} else if let Some(id) = version {
let text = format!("Version {id} isn't among those loaded.");
say(page, text, Role::Meta);
page.blank();
}
let right = vec![meta(format!("{delete_key} deletes one"))];
let (versions, none) = (&d.versions, "No versions.");
counted_box(page, "Versions", right, versions, none, |page, v| {
item(page, url::package(&p.at, Some(v.id)), |page, link| {
let role = if shown.is_some_and(|s| s.id == v.id) {
Role::Strong
} else {
Role::Link
};
let mut segs = vec![Seg::linked(v.name.clone(), role, link)];
for t in &v.tags {
tag(&mut segs, t, Bg::TertiaryContainer);
}
page.box_line(segs, Vec::new(), 0);
if let Some(at) = &v.created_at {
let subline = format!("published {}", time::ago_iso(at, now));
body(page, vec![meta(subline)]);
}
});
});
}