Skip to main content

wiki_tui/
page_loader.rs

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
17/// Responsible for loading a page
18pub 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}