1use std::sync::Arc;
2
3use tokio::sync::mpsc::UnboundedSender;
4use tracing::error;
5use wiki_api::{
6 languages::Language,
7 page::{LanguageLink, Link, Page, Property},
8 search::SearchResult,
9 Endpoint,
10};
11
12use crate::{
13 action::{Action, PageViewerAction},
14 config::Config,
15};
16
17pub struct PageLoader {
19 config: Arc<Config>,
20 action_tx: UnboundedSender<Action>,
21}
22
23impl PageLoader {
24 pub fn new(config: Arc<Config>, action_tx: UnboundedSender<Action>) -> Self {
25 Self { config, action_tx }
26 }
27
28 pub fn load_search_result(&self, result: SearchResult) {
29 self.load_page_custom(result.endpoint, result.language, result.title);
30 }
31
32 pub fn load_link(&self, link: Link) {
33 let link_data = match link {
34 Link::Internal(data) => data,
35 _ => return,
36 };
37
38 self.load_page_custom(link_data.endpoint, link_data.language, link_data.page);
39 }
40
41 pub fn load_language_link(&self, link: LanguageLink) {
42 self.load_page_custom(link.endpoint, link.language, link.title);
43 }
44
45 fn load_page_custom(&self, endpoint: Endpoint, language: Language, title: String) {
46 let page_request = Page::builder()
47 .page(title)
48 .properties(vec![
49 Property::Text,
50 Property::Sections,
51 Property::LangLinks,
52 ])
53 .endpoint(endpoint)
54 .language(language)
55 .redirects(self.config.api.page_redirects);
56
57 let tx = self.action_tx.clone();
58 tokio::spawn(async move {
59 tx.send(Action::SwitchContextPage).unwrap();
60 tx.send(Action::EnterProcessing).unwrap();
61
62 match page_request.fetch().await {
63 Ok(page) => tx
64 .send(Action::PageViewer(PageViewerAction::DisplayPage(page)))
65 .unwrap(),
66 Err(error) => {
67 let error = error.context("Unable to fetch the page");
68 tx.send(Action::PageViewer(PageViewerAction::ExitLoading))
69 .unwrap();
70 tx.send(Action::PopupError(error.to_string())).unwrap();
71 error!("{:?}", error);
72 }
73 };
74
75 tx.send(Action::EnterNormal).unwrap();
76 });
77 }
78}