mod gemini; mod markdown; mod nex; mod plain; mod source; use crate::{app::browser::window::tab::item::page::Page, profile::Profile}; use super::{ItemAction, WindowAction}; use adw::ClampScrollable; use gemini::Gemini; use gtk::{ScrolledWindow, TextView, glib::Uri}; use markdown::Markdown; use nex::Nex; use plain::Plain; use source::Source; use std::rc::Rc; pub struct Meta { pub title: Option, } // @TODO move to separated mod pub struct Text { pub meta: Meta, pub scrolled_window: ScrolledWindow, pub text_view: TextView, } impl Text { pub fn gemini( actions: (&Rc, &Rc), profile: &Rc, base: &Uri, gemtext: &str, ) -> Result)> { match Gemini::build(actions, profile, base, gemtext) { Ok(widget) => Ok(Self { scrolled_window: reader(&widget.text_view), text_view: widget.text_view, meta: Meta { title: widget.title, }, }), Err(e) => match e { gemini::Error::Markup(message, widget) => Err(( message, Some(Self { scrolled_window: reader(&widget.text_view), text_view: widget.text_view, meta: Meta { title: widget.title, }, }), )), }, } } pub fn markdown( actions: (&Rc, &Rc), page: &Rc, base: &Uri, gemtext: &str, ) -> Self { let markdown = Markdown::build(actions, page, base, gemtext); Self { scrolled_window: reader(&markdown.text_view), text_view: markdown.text_view, meta: Meta { title: markdown.title, }, } } pub fn plain(data: &str) -> Self { let text_view = TextView::plain(data); Self { scrolled_window: reader(&text_view), text_view, meta: Meta { title: None }, } } pub fn nex(actions: (&Rc, &Rc), base: &Uri, data: &str) -> Self { let mut title = None; let text_view = TextView::nex(actions, base, data, &mut title); Self { scrolled_window: reader(&text_view), text_view, meta: Meta { title }, } } pub fn source(data: &str) -> Self { let source = sourceview::View::source(data); Self { scrolled_window: ScrolledWindow::builder().child(&source).build(), text_view: source.into_text_view(), meta: Meta { title: None }, } } } // Tools // Grab focus into the `TextView` on click empty `ClampScrollable` area fn grab_focus_patch(clamp_scrollable: &ClampScrollable, text_view: &TextView) { use gtk::{GestureClick, prelude::WidgetExt}; let controller = GestureClick::new(); controller.connect_pressed({ let text_view = text_view.clone(); move |_, _, _, _| { text_view.grab_focus(); } }); clamp_scrollable.add_controller(controller); } fn reader(text_view: &TextView) -> ScrolledWindow { let clamp_scrollable = ClampScrollable::builder() .child(text_view) .css_classes(["view"]) .maximum_size(800) .build(); grab_focus_patch(&clamp_scrollable, text_view); ScrolledWindow::builder().child(&clamp_scrollable).build() }