aidoku/structs/
home.rs

1use super::{Chapter, FilterValue, Listing, Manga};
2use serde::{Deserialize, Serialize};
3
4extern crate alloc;
5use alloc::{string::String, vec::Vec};
6
7/// A partial result for the home page.
8///
9/// This should only be used with [send_partial_result](crate::imports::std::send_partial_result)
10/// in the [get_home](super::Home::get_home) function.
11#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
12pub enum HomePartialResult {
13	Layout(HomeLayout),
14	Component(HomeComponent),
15}
16
17/// A home layout for a source.
18#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize)]
19pub struct HomeLayout {
20	/// The components of the layout.
21	pub components: Vec<HomeComponent>,
22}
23
24/// A component for a home layout.
25#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
26pub struct HomeComponent {
27	/// The title of the component.
28	pub title: Option<String>,
29	/// The subtitle of the component.
30	pub subtitle: Option<String>,
31	/// The component value.
32	pub value: HomeComponentValue,
33}
34
35impl Default for HomeComponent {
36	fn default() -> Self {
37		Self {
38			title: None,
39			subtitle: None,
40			value: HomeComponentValue::empty_scroller(),
41		}
42	}
43}
44
45/// The value of a component for a home layout.
46#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
47pub enum HomeComponentValue {
48	/// A horizontal scroller of images.
49	///
50	/// Only the image urls and values of the provided links are used.
51	ImageScroller {
52		links: Vec<Link>,
53		auto_scroll_interval: Option<f32>,
54		width: Option<i32>,
55		height: Option<i32>,
56	},
57	/// A large scroller of manga.
58	///
59	/// This component displays the title, author, cover image, description,
60	/// content rating and tags of the provided manga entries.
61	BigScroller {
62		entries: Vec<Manga>,
63		auto_scroll_interval: Option<f32>,
64	},
65	/// A small scroller of manga.
66	///
67	/// The subtitles of the provided links are not used.
68	Scroller {
69		entries: Vec<Link>,
70		listing: Option<Listing>,
71	},
72	/// A list of manga.
73	MangaList {
74		/// If the list should be displayed with ranking numbers.
75		ranking: bool,
76		page_size: Option<i32>,
77		entries: Vec<Link>,
78		listing: Option<Listing>,
79	},
80	/// A list of manga chapters.
81	///
82	/// The relative time to the chapter's date uploaded is displayed if provided.
83	MangaChapterList {
84		page_size: Option<i32>,
85		entries: Vec<MangaWithChapter>,
86		listing: Option<Listing>,
87	},
88	/// A collection of links to filtered listings.
89	Filters(Vec<FilterItem>),
90	/// A list of links.
91	///
92	/// Only the link title and values are used.
93	Links(Vec<Link>),
94}
95
96impl HomeComponentValue {
97	/// Creates an empty image scroller component.
98	pub fn empty_image_scroller() -> Self {
99		Self::ImageScroller {
100			links: Vec::new(),
101			auto_scroll_interval: None,
102			width: None,
103			height: None,
104		}
105	}
106
107	/// Creates an empty big scroller component.
108	pub fn empty_big_scroller() -> Self {
109		Self::BigScroller {
110			entries: Vec::new(),
111			auto_scroll_interval: None,
112		}
113	}
114
115	/// Creates an empty scroller component.
116	pub fn empty_scroller() -> Self {
117		Self::Scroller {
118			entries: Vec::new(),
119			listing: None,
120		}
121	}
122
123	/// Creates an empty manga list component.
124	pub fn empty_manga_list() -> Self {
125		Self::MangaList {
126			ranking: false,
127			page_size: None,
128			entries: Vec::new(),
129			listing: None,
130		}
131	}
132
133	/// Creates an empty manga chapter list component.
134	pub fn empty_manga_chapter_list() -> Self {
135		Self::MangaChapterList {
136			page_size: None,
137			entries: Vec::new(),
138			listing: None,
139		}
140	}
141
142	/// Creates an empty filters component.
143	pub fn empty_filters() -> Self {
144		Self::Filters(Vec::new())
145	}
146
147	/// Creates an empty links component.
148	pub fn empty_links() -> Self {
149		Self::Links(Vec::new())
150	}
151}
152
153/// A paired manga and chapter.
154#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
155pub struct MangaWithChapter {
156	pub manga: Manga,
157	pub chapter: Chapter,
158}
159
160/// A link to a listing that uses the provided filters.
161#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
162pub struct FilterItem {
163	pub title: String,
164	pub values: Option<Vec<FilterValue>>,
165}
166
167impl From<String> for FilterItem {
168	fn from(title: String) -> Self {
169		Self {
170			title,
171			values: None,
172		}
173	}
174}
175
176impl From<&str> for FilterItem {
177	fn from(title: &str) -> Self {
178		Self {
179			title: String::from(title),
180			values: None,
181		}
182	}
183}
184
185/// A link used in home components.
186#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
187pub struct Link {
188	pub title: String,
189	pub subtitle: Option<String>,
190	pub image_url: Option<String>,
191	pub value: Option<LinkValue>,
192}
193
194/// A link value that can be opened by the Aidoku app.
195#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
196pub enum LinkValue {
197	Url(String),
198	Listing(Listing),
199	Manga(Manga),
200}
201
202impl Default for LinkValue {
203	fn default() -> Self {
204		Self::Url(String::new())
205	}
206}
207
208impl From<Manga> for Link {
209	fn from(value: Manga) -> Self {
210		Link {
211			title: value.title.clone(),
212			subtitle: value
213				.authors
214				.as_ref()
215				.map(|a| a.join(", "))
216				.or(value.description.clone()),
217			image_url: value.cover.clone(),
218			value: Some(LinkValue::Manga(value)),
219		}
220	}
221}