mirror of
https://github.com/YGGverse/Yoda.git
synced 2026-03-31 16:45:27 +00:00
211 lines
6.2 KiB
Rust
211 lines
6.2 KiB
Rust
mod directory;
|
|
mod image;
|
|
mod status;
|
|
mod text;
|
|
|
|
use directory::Directory;
|
|
use image::Image;
|
|
use text::Text;
|
|
|
|
use crate::{app::browser::window::tab::item::page::Page, profile::Profile};
|
|
|
|
use super::{ItemAction, TabAction, WindowAction};
|
|
use adw::StatusPage;
|
|
use gtk::{
|
|
Box, Orientation,
|
|
gdk::Paintable,
|
|
gio::{Cancellable, File},
|
|
glib::Uri,
|
|
prelude::{BoxExt, IsA, WidgetExt},
|
|
};
|
|
use std::{rc::Rc, time::Duration};
|
|
|
|
pub struct Content {
|
|
window_action: Rc<WindowAction>,
|
|
item_action: Rc<ItemAction>,
|
|
tab_action: Rc<TabAction>,
|
|
pub g_box: Box,
|
|
}
|
|
|
|
impl Content {
|
|
// Construct
|
|
|
|
/// Create new container for different components
|
|
pub fn build(
|
|
(window_action, tab_action, item_action): (
|
|
&Rc<WindowAction>,
|
|
&Rc<TabAction>,
|
|
&Rc<ItemAction>,
|
|
),
|
|
) -> Self {
|
|
Self {
|
|
g_box: Box::builder().orientation(Orientation::Vertical).build(),
|
|
window_action: window_action.clone(),
|
|
item_action: item_action.clone(),
|
|
tab_action: tab_action.clone(),
|
|
}
|
|
}
|
|
|
|
// Actions
|
|
|
|
/// Set new `content::Image` component for `Self`
|
|
///
|
|
/// * action removes previous children component from `Self`
|
|
pub fn to_image(&self, paintable: &impl IsA<Paintable>) -> Image {
|
|
self.clean();
|
|
let i = Image::new_from_paintable(paintable);
|
|
self.g_box.append(&i.picture);
|
|
i
|
|
}
|
|
|
|
/// Set new `content::Status` component for `Self` with new `status::Download` preset
|
|
///
|
|
/// * action removes previous children component from `Self`
|
|
pub fn to_status_download(
|
|
&self,
|
|
initial_filename: &str,
|
|
cancellable: &Cancellable,
|
|
on_choose: impl Fn(File, Rc<status::download::Action>) + 'static,
|
|
) -> StatusPage {
|
|
self.clean();
|
|
let s = status::download::build(initial_filename, cancellable, on_choose);
|
|
self.g_box.append(&s);
|
|
s
|
|
}
|
|
|
|
/// Set new `content::Status` component for `Self` with new `status::Failure` preset
|
|
///
|
|
/// * action removes previous children component from `Self`
|
|
pub fn to_status_failure(&self) -> StatusPage {
|
|
self.clean();
|
|
let s = status::failure::new();
|
|
self.g_box.append(&s);
|
|
s
|
|
}
|
|
|
|
/// Set new `content::Status` component for `Self` with new `status::Tofu` preset
|
|
///
|
|
/// * action removes previous children component from `Self`
|
|
pub fn to_status_tofu(&self, on_accept: impl Fn() + 'static) -> StatusPage {
|
|
self.clean();
|
|
let s = status::tofu::build(on_accept);
|
|
self.g_box.append(&s);
|
|
s
|
|
}
|
|
|
|
/// Set new `content::Status` component for `Self` with new `status::Mime` issue preset
|
|
///
|
|
/// * action removes previous children component from `Self`
|
|
pub fn to_status_mime(
|
|
&self,
|
|
mime: &str,
|
|
download: Option<(&Rc<ItemAction>, &Uri)>,
|
|
) -> StatusPage {
|
|
self.clean();
|
|
let s = status::mime::build(mime, download);
|
|
self.g_box.append(&s);
|
|
s
|
|
}
|
|
|
|
/// Set new `content::Status` component for `Self` with new `status::Identity` preset
|
|
///
|
|
/// * action removes previous children component from `Self`
|
|
pub fn to_status_identity(&self) -> StatusPage {
|
|
self.clean();
|
|
let s = status::identity::build((&self.tab_action, &self.item_action));
|
|
self.g_box.append(&s);
|
|
s
|
|
}
|
|
|
|
/// Set new `content::Status` component for `Self` with new `status::Loading` preset
|
|
///
|
|
/// * action removes previous children component from `Self`
|
|
pub fn to_status_loading(&self, show_with_delay: Option<Duration>) -> StatusPage {
|
|
self.clean();
|
|
let s = status::loading::build(show_with_delay);
|
|
self.g_box.append(&s);
|
|
s
|
|
}
|
|
|
|
/// `text/gemini`
|
|
pub fn to_text_gemini(&self, profile: &Rc<Profile>, base: &Uri, data: &str) -> Text {
|
|
self.clean();
|
|
match Text::gemini(
|
|
(&self.window_action, &self.item_action),
|
|
profile,
|
|
base,
|
|
data,
|
|
) {
|
|
Ok(text) => {
|
|
self.g_box.append(&text.scrolled_window);
|
|
text
|
|
}
|
|
Err((message, text)) => {
|
|
self.g_box.append(&{
|
|
let banner = adw::Banner::builder()
|
|
.title(message)
|
|
.revealed(true)
|
|
.button_label("Ok")
|
|
.build();
|
|
banner.connect_button_clicked(|this| this.set_revealed(false));
|
|
banner
|
|
});
|
|
match text {
|
|
Some(text) => {
|
|
self.g_box.append(&text.scrolled_window);
|
|
text
|
|
}
|
|
None => todo!(),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// `text/markdown`
|
|
pub fn to_text_markdown(&self, page: &Rc<Page>, base: &Uri, data: &str) -> Text {
|
|
self.clean();
|
|
let m = Text::markdown((&self.window_action, &self.item_action), page, base, data);
|
|
self.g_box.append(&m.scrolled_window);
|
|
m
|
|
}
|
|
|
|
/// `text/plain`
|
|
pub fn to_text_plain(&self, data: &str) -> Text {
|
|
self.clean();
|
|
let t = Text::plain(data);
|
|
self.g_box.append(&t.scrolled_window);
|
|
t
|
|
}
|
|
|
|
/// [text/nex](https://nightfall.city/nex/info/specification.txt)
|
|
pub fn to_text_nex(&self, base: &Uri, data: &str) -> Text {
|
|
self.clean();
|
|
let t = Text::nex((&self.window_action, &self.item_action), base, data);
|
|
self.g_box.append(&t.scrolled_window);
|
|
t
|
|
}
|
|
|
|
pub fn to_directory(
|
|
&self,
|
|
file: &File,
|
|
callback: (impl Fn() + 'static, impl Fn(&File) + 'static),
|
|
) {
|
|
self.clean();
|
|
self.g_box.append(&Directory::for_file(file, callback))
|
|
}
|
|
|
|
/// * system `source:`
|
|
pub fn to_text_source(&self, data: &str) -> Text {
|
|
self.clean();
|
|
let t = Text::source(data);
|
|
self.g_box.append(&t.scrolled_window);
|
|
t
|
|
}
|
|
|
|
/// Remove all children components from `Self`
|
|
pub fn clean(&self) {
|
|
while let Some(child) = self.g_box.last_child() {
|
|
self.g_box.remove(&child);
|
|
}
|
|
}
|
|
}
|