use crate::api::explore::{Topic, Topics};
use crate::api::insights::{
Activity, Author, Counted, Counter, Dependencies, Dependency, Manifest, Popular, Traffic,
};
use crate::api::lists::{ListPage, Mine, MyLists, StarList};
use crate::api::model::{Capped, NodeId, RepoId};
use crate::api::packages::{Kind, Package, PackageDetail, PackageList, PackageRef, Version};
use crate::api::replies::SavedReply;
pub const START: u64 = 1_775_952_000;
pub fn activity() -> Activity {
let alice: Vec<u32> = (0..26).map(|w| [3, 0, 5, 8, 1, 0, 2][w % 7]).collect();
let bob: Vec<u32> = (0..26).map(|w| u32::from(w % 4 == 0)).collect();
let carol: Vec<u32> = (0..26).map(|w| u32::from(w >= 20) * 4).collect();
let weeks: Vec<u32> = (0..26)
.map(|w| alice.get(w).unwrap_or(&0) + bob.get(w).unwrap_or(&0) + carol.get(w).unwrap_or(&0))
.collect();
let sum = |w: &[u32]| w.iter().map(|&n| u64::from(n)).sum::<u64>();
let author = |name: &str, login: Option<&str>, weeks: Vec<u32>| Author {
name: name.into(),
login: login.map(str::to_owned),
commits: sum(&weeks),
weeks,
};
Activity {
start: START,
total: sum(&weeks),
weeks,
weekdays: [4, 20, 25, 18, 22, 9, 2],
authors: vec![
author("Alice Liddell", Some("alice"), alice),
author("carol", Some("carol"), carol),
author("Bob Builder", None, bob),
],
authors_left_out: 0,
cut: None,
by: Counter::Git,
}
}
pub fn traffic() -> Traffic {
let day = |d: u32, n: u64, u: u64| (format!("2026-10-{d:02}T00:00:00Z"), n, u);
Traffic {
views: Counted {
count: 54,
uniques: 12,
days: vec![day(8, 10, 3), day(9, 40, 8), day(10, 4, 1)],
},
clones: Counted {
count: 7,
uniques: 2,
days: vec![day(9, 6, 1), day(10, 1, 1)],
},
referrers: vec![Popular {
name: "news.ycombinator.com".into(),
title: None,
count: 30,
uniques: 9,
}],
paths: vec![Popular {
name: "/gold-silver-copper/ghtui".into(),
title: Some("A keyboard-driven terminal client for GitHub".into()),
count: 41,
uniques: 11,
}],
}
}
pub fn dependencies() -> Dependencies {
let dep = |package: &str, requirements: &str, repo: Option<&str>| Dependency {
package: package.into(),
manager: "RUST".into(),
requirements: requirements.into(),
repo: repo.and_then(RepoId::parse),
};
Dependencies {
manifests: Capped::new(
vec![
Manifest {
path: "Cargo.lock".into(),
dependencies: Capped::new(
vec![
dep("ratatui", "= 0.30.0", Some("ratatui/ratatui")),
dep("tokio", "= 1.47.1", Some("tokio-rs/tokio")),
],
212,
),
..Default::default()
},
Manifest {
path: "xtask/Cargo.toml".into(),
dependencies: Capped::new(vec![dep("duct", ">= 1.0.0, < 2.0.0", None)], 1),
..Default::default()
},
],
2,
),
}
}
fn topic(name: &str, title: &str, about: &str) -> Topic {
Topic {
name: name.into(),
display_name: Some(title.into()),
short_description: Some(about.into()),
featured: true,
curated: true,
..Topic::default()
}
}
pub fn featured() -> Topics {
Topics {
topics: vec![
topic("rust", "Rust", "Rust is a systems programming language."),
topic("terminal", "Terminal", "Programs that run in a terminal."),
],
total: 2,
}
}
pub fn rust() -> Topic {
Topic {
description: Some("Rust is a systems programming language created by Mozilla.".into()),
created_by: Some("Graydon Hoare".into()),
released: Some("July 7, 2010".into()),
stars: Some(1200),
related: vec!["cargo".into(), "webassembly".into()],
..topic("rust", "Rust", "Rust is a systems programming language.")
}
}
fn list(name: &str, slug: &str, count: u64, private: bool) -> StarList {
StarList {
id: NodeId::new(format!("UL_{slug}")),
name: name.into(),
slug: slug.into(),
description: (!private).then(|| "Tools I use every day".to_owned()),
private,
count,
last_added: Some("2026-10-01T10:00:00Z".into()),
}
}
pub fn star_lists() -> Capped<StarList> {
Capped::new(
vec![
list("Terminal tools", "terminal-tools", 2, false),
list("To read", "to-read", 0, true),
],
2,
)
}
pub fn list_page() -> ListPage {
let mut repos = crate::fixtures::profile_repos();
repos.items.truncate(2);
repos.total = 2;
repos.next = None;
ListPage {
list: list("Terminal tools", "terminal-tools", 2, false),
repos,
}
}
pub fn my_lists() -> MyLists {
let mine = |name: &str, slug: &str, has| Mine {
id: NodeId::new(format!("UL_{slug}")),
name: name.into(),
private: false,
count: 2,
has: Some(has),
};
MyLists {
repo: NodeId::new("R_ghtui"),
starred: true,
viewer: "octocat".into(),
lists: Capped::new(
vec![
mine("Terminal tools", "terminal-tools", true),
mine("To read", "to-read", false),
],
2,
),
}
}
pub fn package_ref() -> PackageRef {
PackageRef {
owner: "gold-silver-copper".into(),
kind: Kind::Container,
name: "ghtui".into(),
}
}
fn package() -> Package {
Package {
at: package_ref(),
repo: RepoId::parse("gold-silver-copper/ghtui"),
visibility: "public".into(),
versions: 2,
updated_at: Some("2026-10-01T10:00:00Z".into()),
}
}
pub fn packages() -> PackageList {
PackageList {
items: vec![
package(),
Package {
at: PackageRef {
kind: Kind::Npm,
name: "ghtui-theme".into(),
..package_ref()
},
visibility: "private".into(),
versions: 5,
..package()
},
],
cut: Vec::new(),
}
}
pub fn package_detail() -> PackageDetail {
let version = |id, name: &str, tags: &[&str]| Version {
id,
name: name.into(),
tags: tags.iter().map(|t| (*t).to_owned()).collect(),
created_at: Some("2026-10-01T10:00:00Z".into()),
};
PackageDetail {
package: package(),
versions: crate::fixtures::page(
2,
vec![
version(102, "sha256:9f1c0d2e", &["latest", "0.2.0"]),
version(101, "sha256:3a7b55e1", &[]),
],
None,
),
}
}
pub fn saved_replies() -> Capped<SavedReply> {
Capped::from(vec![SavedReply {
title: "Thanks".into(),
body: "Thanks for the report!".into(),
}])
}