prehnite/app/window/main_window/
mod.rs

1mod book_opener;
2mod menubar;
3pub mod page;
4
5use crate::app::window::main_window::book_opener::book_opener_handler;
6use crate::app::window::main_window::menubar::{menubar, menubar_handler, MenuBarMessage};
7use crate::app::window::main_window::page::item_list::{ItemListActions, ItemListMessage};
8use crate::app::window::main_window::page::{MainWindowPage, MainWindowPageId};
9use crate::app::window::{Window, WindowMessage};
10use iced::futures::FutureExt;
11use iced::{window, Element, Task};
12use prehnite_core::db::{open_book_or_alert, DBType};
13use prehnite_core::i18n::i18n_w;
14use prehnite_core::settings::registry::SettingRegistry;
15use prehnite_core::settings::GlobalSettingKey;
16use prehnite_core::util::file_dialog::FileOpe;
17use tracing::error;
18
19impl Into<FileOpe> for BookOpenerMessage {
20    fn into(self) -> FileOpe {
21        match self {
22            BookOpenerMessage::New => FileOpe::New,
23            _ => FileOpe::Open,
24        }
25    }
26}
27
28#[derive(Clone, Debug)]
29pub enum BookOpenerMessage {
30    Open,
31    New,
32    Opened,
33    NotOpened,
34}
35
36#[derive(Clone, Debug)]
37pub enum MainWindowMessage {
38    BookOpener(BookOpenerMessage),
39    ChangePage(MainWindowPageId),
40    ItemList(ItemListMessage),
41    MenuBar(MenuBarMessage),
42    BookOpened,
43    OpenVersionInfoWindow,
44    OpenSettingWindow,
45    OpenLicenseInfoWindow,
46    OpenBackgroundInfoEditorWindow,
47    OpenBibliographyEditorWindow,
48    OpenEditorWindow(i64),
49    OpenNewItemPromptWindow
50}
51
52impl From<MainWindowMessage> for WindowMessage {
53    fn from(value: MainWindowMessage) -> Self {
54        Self::MainWindowMessage(value)
55    }
56}
57
58#[derive(Debug)]
59pub struct MainWindow {
60    page: MainWindowPage,
61    is_book_opened: bool,
62    window_id: Option<window::Id>,
63}
64
65impl MainWindow {
66    #[tracing::instrument]
67    async fn open_last_opened_book() -> MainWindowMessage {
68        let last_opened = SettingRegistry::get(&GlobalSettingKey::LastOpened.into());
69        fn return_err() -> MainWindowMessage {
70            MainWindowMessage::ChangePage(MainWindowPageId::BookNotOpened)
71        }
72        match last_opened
73            .and_then(|v| v.to_opt_string())
74            .and_then(|v| v.parse().ok())
75        {
76            None => return_err(),
77            Some(v) => {
78                if open_book_or_alert(v).await {
79                    MainWindowMessage::BookOpened
80                } else {
81                    return_err()
82                }
83            }
84        }
85    }
86
87    fn update_impl(&mut self, message: MainWindowMessage) -> Task<MainWindowMessage> {
88        match message {
89            MainWindowMessage::BookOpener(msg) => return book_opener_handler(self, msg),
90            MainWindowMessage::ItemList(msg) => {
91                if let MainWindowPage::ItemList(page) = &mut self.page {
92                    return match page.update(msg) {
93                        ItemListActions::Run(v) => v.map(MainWindowMessage::ItemList),
94                    };
95                }
96                error!("invalid message received.");
97            }
98            MainWindowMessage::ChangePage(page) => {
99                self.page = page.clone().into();
100                match page {
101                    MainWindowPageId::ItemList => {
102                        return Task::done(MainWindowMessage::ItemList(ItemListMessage::LoadItems));
103                    }
104                    _ => {}
105                }
106            }
107            MainWindowMessage::MenuBar(v) => return menubar_handler(self, v),
108            MainWindowMessage::BookOpened => {
109                self.is_book_opened = true;
110                return Task::future(async {
111                    SettingRegistry::load(DBType::PrehniteBook).await;
112                    MainWindowMessage::ChangePage(MainWindowPageId::ItemList)
113                });
114            }
115            MainWindowMessage::OpenVersionInfoWindow => { /* handled by daemon*/ }
116            MainWindowMessage::OpenSettingWindow => { /* handled by daemon*/ }
117            MainWindowMessage::OpenLicenseInfoWindow => { /* handled by daemon*/ }
118            MainWindowMessage::OpenBackgroundInfoEditorWindow => { /* handled by daemon*/ }
119            MainWindowMessage::OpenBibliographyEditorWindow => { /* handled by daemon*/ }
120            MainWindowMessage::OpenEditorWindow(_) => { /* handled by daemon*/ }
121            MainWindowMessage::OpenNewItemPromptWindow => {/* handled by daemon*/}
122        }
123        Task::none()
124    }
125
126    fn view_impl(&self) -> Element<'_, MainWindowMessage> {
127        Element::from(iced::widget::column![
128            menubar(self.is_book_opened).map(MainWindowMessage::MenuBar),
129            match &self.page {
130                MainWindowPage::NowLoading => i18n_w("now-loading").into(),
131                MainWindowPage::ItemList(v) => v.view().map(MainWindowMessage::ItemList),
132            }
133        ])
134    }
135}
136
137impl Window for MainWindow {
138    fn new() -> Self {
139        Self {
140            page: Default::default(),
141            is_book_opened: false,
142            window_id: None,
143        }
144    }
145
146    fn init_task() -> Task<WindowMessage> {
147        if SettingRegistry::get(&GlobalSettingKey::AutoOpenLastOpened.into())
148            .and_then(|v| v.get())
149            .unwrap_or(true)
150        {
151            Task::future(Self::open_last_opened_book().map(WindowMessage::MainWindowMessage))
152        } else {
153            Task::done(MainWindowMessage::ChangePage(MainWindowPageId::BookNotOpened).into())
154        }
155    }
156
157    #[tracing::instrument]
158    fn update(&mut self, message: WindowMessage) -> Task<WindowMessage> {
159        if let WindowMessage::MainWindowMessage(message) = message {
160            self.update_impl(message)
161                .map(WindowMessage::MainWindowMessage)
162        } else {
163            error!("Invalid message received.");
164            Task::none()
165        }
166    }
167
168    fn view(&'_ self) -> Element<'_, WindowMessage> {
169        self.view_impl().map(WindowMessage::MainWindowMessage)
170    }
171
172    fn title(&'_ self) -> String {
173        "Prehnite".into()
174    }
175
176    fn set_window_id(&mut self, window_id: window::Id) {
177        self.window_id = Some(window_id);
178    }
179}