mod parser; use parser::header::Header; use parser::link::Link; use parser::plain::Plain; use gtk::{ gio::SimpleAction, glib::{GString, Propagation, Uri, UriFlags}, prelude::{ActionExt, StyleContextExt, ToVariant, WidgetExt}, Align, CssProvider, Label, STYLE_PROVIDER_PRIORITY_APPLICATION, }; use std::sync::Arc; pub struct Reader { title: Option, // css: CssProvider, widget: Label, } impl Reader { // Construct pub fn new(gemtext: &str, base: &Uri, action_page_open: Arc) -> Self { // Init title let mut title = None; // Init markup let mut markup = String::new(); for line in gemtext.lines() { // Is header if let Some(header) = Header::from(line) { // Format markup.push_str(header.markup()); // Set title from first document header tag if title == None { title = Some(header.text().clone()); } continue; } // Is link if let Some(link) = Link::from(line, base) { // Format markup.push_str(link.markup()); continue; } // Nothing match, escape string just markup.push_str(Plain::from(line).markup()) } // Init CSS let css = CssProvider::new(); /* @TODO Theme parser error: css.load_from_path( "src/browser/main/tab/page/content/text/gemini/reader/default.css" ); */ css.load_from_data("label{caret-color: transparent;}"); // Init widget let widget = Label::builder() .halign(Align::Fill) .valign(Align::Fill) .hexpand(true) .vexpand(true) .xalign(0.0) .yalign(0.0) .margin_start(8) .margin_end(8) .wrap(true) .selectable(true) .use_markup(true) .label(markup) .build(); widget .style_context() .add_provider(&css, STYLE_PROVIDER_PRIORITY_APPLICATION); // Connect actions widget.connect_activate_link(move |_, href| { // Detect requested protocol if let Ok(uri) = Uri::parse(&href, UriFlags::NONE) { return match uri.scheme().as_str() { "gemini" => { // Open new page action_page_open.activate(Some(&uri.to_str().to_variant())); // Prevent link open in external application Propagation::Stop } // Protocol not supported _ => Propagation::Proceed, }; } // Delegate unparsable Propagation::Proceed }); // Result Self { title, // css, widget, } } // Getters pub fn title(&self) -> &Option { &self.title } pub fn widget(&self) -> &Label { &self.widget } }