mirror of
https://github.com/YGGverse/Yoda.git
synced 2026-04-02 17:45:28 +00:00
update gemtext error handler
This commit is contained in:
parent
c8607e151a
commit
33943d37f1
9 changed files with 64 additions and 108 deletions
|
|
@ -63,7 +63,6 @@ impl Item {
|
||||||
));
|
));
|
||||||
|
|
||||||
target_child.append(&page.navigation.g_box);
|
target_child.append(&page.navigation.g_box);
|
||||||
target_child.append(&page.notice.banner);
|
|
||||||
target_child.append(&page.content.g_box);
|
target_child.append(&page.content.g_box);
|
||||||
target_child.append(&page.search.g_box);
|
target_child.append(&page.search.g_box);
|
||||||
target_child.append(&page.input.clamp);
|
target_child.append(&page.input.clamp);
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,6 @@ impl Client {
|
||||||
|
|
||||||
// Reset widgets
|
// Reset widgets
|
||||||
self.page.input.unset();
|
self.page.input.unset();
|
||||||
self.page.notice.unset();
|
|
||||||
self.page.search.unset();
|
self.page.search.unset();
|
||||||
self.page.set_title("Loading..");
|
self.page.set_title("Loading..");
|
||||||
self.page.set_progress(0.1);
|
self.page.set_progress(0.1);
|
||||||
|
|
|
||||||
|
|
@ -260,9 +260,6 @@ fn handle(
|
||||||
_ => panic!() // unexpected
|
_ => panic!() // unexpected
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(notice) = widget.meta.notice {
|
|
||||||
page.notice(¬ice)
|
|
||||||
}
|
|
||||||
page.search.set(Some(widget.text_view));
|
page.search.set(Some(widget.text_view));
|
||||||
page.set_title(&match widget.meta.title {
|
page.set_title(&match widget.meta.title {
|
||||||
Some(title) => title.into(), // @TODO
|
Some(title) => title.into(), // @TODO
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ mod database;
|
||||||
mod error;
|
mod error;
|
||||||
mod input;
|
mod input;
|
||||||
mod navigation;
|
mod navigation;
|
||||||
mod notice;
|
|
||||||
mod search;
|
mod search;
|
||||||
|
|
||||||
use super::{Action as ItemAction, BrowserAction, Profile, TabAction, WindowAction};
|
use super::{Action as ItemAction, BrowserAction, Profile, TabAction, WindowAction};
|
||||||
|
|
@ -12,7 +11,6 @@ use content::Content;
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use input::Input;
|
use input::Input;
|
||||||
use navigation::Navigation;
|
use navigation::Navigation;
|
||||||
use notice::Notice;
|
|
||||||
use search::Search;
|
use search::Search;
|
||||||
use sqlite::Transaction;
|
use sqlite::Transaction;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
@ -27,7 +25,6 @@ pub struct Page {
|
||||||
pub content: Rc<Content>,
|
pub content: Rc<Content>,
|
||||||
pub input: Rc<Input>,
|
pub input: Rc<Input>,
|
||||||
pub navigation: Rc<Navigation>,
|
pub navigation: Rc<Navigation>,
|
||||||
pub notice: Rc<Notice>,
|
|
||||||
pub search: Rc<Search>,
|
pub search: Rc<Search>,
|
||||||
// System
|
// System
|
||||||
/// Reference to [TabPage](https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.TabPage.html)
|
/// Reference to [TabPage](https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.TabPage.html)
|
||||||
|
|
@ -59,7 +56,6 @@ impl Page {
|
||||||
(window_action, tab_action, item_action),
|
(window_action, tab_action, item_action),
|
||||||
));
|
));
|
||||||
let input = Rc::new(Input::new());
|
let input = Rc::new(Input::new());
|
||||||
let notice = Rc::new(Notice::new());
|
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
Self {
|
Self {
|
||||||
|
|
@ -73,7 +69,6 @@ impl Page {
|
||||||
content,
|
content,
|
||||||
input,
|
input,
|
||||||
navigation,
|
navigation,
|
||||||
notice,
|
|
||||||
search,
|
search,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -104,11 +99,6 @@ impl Page {
|
||||||
self.search.show()
|
self.search.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Toggle `Notice` widget
|
|
||||||
pub fn notice(&self, title: &str) {
|
|
||||||
self.notice.show(title)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Cleanup session for `Self`
|
/// Cleanup session for `Self`
|
||||||
pub fn clean(
|
pub fn clean(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
||||||
|
|
@ -118,10 +118,31 @@ impl Content {
|
||||||
/// `text/gemini`
|
/// `text/gemini`
|
||||||
pub fn to_text_gemini(&self, base: &Uri, data: &str) -> Text {
|
pub fn to_text_gemini(&self, base: &Uri, data: &str) -> Text {
|
||||||
self.clean();
|
self.clean();
|
||||||
let text = Text::gemini((&self.window_action, &self.item_action), base, data);
|
match Text::gemini((&self.window_action, &self.item_action), base, data) {
|
||||||
|
Ok(text) => {
|
||||||
self.g_box.append(&text.scrolled_window);
|
self.g_box.append(&text.scrolled_window);
|
||||||
text
|
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/plain`
|
/// `text/plain`
|
||||||
pub fn to_text_plain(&self, data: &str) -> Text {
|
pub fn to_text_plain(&self, data: &str) -> Text {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ use std::rc::Rc;
|
||||||
|
|
||||||
pub struct Meta {
|
pub struct Meta {
|
||||||
pub title: Option<String>,
|
pub title: Option<String>,
|
||||||
pub notice: Option<String>,
|
|
||||||
} // @TODO move to separated mod
|
} // @TODO move to separated mod
|
||||||
|
|
||||||
pub struct Text {
|
pub struct Text {
|
||||||
|
|
@ -26,54 +25,36 @@ impl Text {
|
||||||
actions: (&Rc<WindowAction>, &Rc<ItemAction>),
|
actions: (&Rc<WindowAction>, &Rc<ItemAction>),
|
||||||
base: &Uri,
|
base: &Uri,
|
||||||
gemtext: &str,
|
gemtext: &str,
|
||||||
) -> Self {
|
) -> Result<Self, (String, Option<Self>)> {
|
||||||
// Init gemtext reader
|
match Gemini::build(actions, base, gemtext) {
|
||||||
let (gemini, notice) = match Gemini::build(actions, base, gemtext) {
|
Ok(widget) => Ok(Self {
|
||||||
Ok(gemini) => (gemini, None),
|
scrolled_window: reader(&widget.text_view),
|
||||||
Err(e) => {
|
text_view: widget.text_view,
|
||||||
let notice = e.message();
|
|
||||||
match e {
|
|
||||||
gemini::Error::Multiline(gemini) => (gemini, Some(notice)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Init container widget
|
|
||||||
let clamp_scrollable = ClampScrollable::builder()
|
|
||||||
.child(&gemini.text_view)
|
|
||||||
.css_classes(["view"])
|
|
||||||
.maximum_size(800)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
grab_focus_patch(&clamp_scrollable, &gemini.text_view);
|
|
||||||
|
|
||||||
Self {
|
|
||||||
text_view: gemini.text_view,
|
|
||||||
meta: Meta {
|
meta: Meta {
|
||||||
title: gemini.title,
|
title: widget.title,
|
||||||
notice,
|
},
|
||||||
|
}),
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)),
|
||||||
},
|
},
|
||||||
scrolled_window: ScrolledWindow::builder().child(&clamp_scrollable).build(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn plain(data: &str) -> Self {
|
pub fn plain(data: &str) -> Self {
|
||||||
let text_view = TextView::plain(data);
|
let text_view = TextView::plain(data);
|
||||||
let clamp_scrollable = ClampScrollable::builder()
|
|
||||||
.child(&text_view)
|
|
||||||
.css_classes(["view"])
|
|
||||||
.maximum_size(800) // @TODO auto-expand
|
|
||||||
.build();
|
|
||||||
|
|
||||||
grab_focus_patch(&clamp_scrollable, &text_view);
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
scrolled_window: ScrolledWindow::builder().child(&clamp_scrollable).build(),
|
scrolled_window: reader(&text_view),
|
||||||
text_view,
|
text_view,
|
||||||
meta: Meta {
|
meta: Meta { title: None },
|
||||||
title: None,
|
|
||||||
notice: None,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,10 +63,7 @@ impl Text {
|
||||||
Self {
|
Self {
|
||||||
scrolled_window: ScrolledWindow::builder().child(&source).build(),
|
scrolled_window: ScrolledWindow::builder().child(&source).build(),
|
||||||
text_view: source.into_text_view(),
|
text_view: source.into_text_view(),
|
||||||
meta: Meta {
|
meta: Meta { title: None },
|
||||||
title: None,
|
|
||||||
notice: None,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -106,3 +84,15 @@ fn grab_focus_patch(clamp_scrollable: &ClampScrollable, text_view: &TextView) {
|
||||||
|
|
||||||
clamp_scrollable.add_controller(controller);
|
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()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -506,7 +506,10 @@ impl Gemini {
|
||||||
if is_multiline_enabled {
|
if is_multiline_enabled {
|
||||||
Ok(Self { text_view, title })
|
Ok(Self { text_view, title })
|
||||||
} else {
|
} else {
|
||||||
Err(Error::Multiline(Self { text_view, title }))
|
Err(Error::Markup(
|
||||||
|
"Invalid multiline markup! Gemtext format partially ignored.".to_string(),
|
||||||
|
Self { text_view, title },
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,3 @@
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
Multiline(super::Gemini),
|
Markup(String, super::Gemini),
|
||||||
}
|
|
||||||
|
|
||||||
impl Error {
|
|
||||||
pub fn message(&self) -> String {
|
|
||||||
match self {
|
|
||||||
Self::Multiline(_) => {
|
|
||||||
"Invalid multiline markup! Gemtext format partially ignored.".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
use adw::Banner;
|
|
||||||
|
|
||||||
pub struct Notice {
|
|
||||||
pub banner: Banner,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Notice {
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
/// Create new `Self`
|
|
||||||
pub fn new() -> Self {
|
|
||||||
let banner = Banner::builder().button_label("Ok").build();
|
|
||||||
banner.connect_button_clicked(|this| this.set_revealed(false));
|
|
||||||
Self { banner }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actions
|
|
||||||
|
|
||||||
pub fn show(&self, title: &str) {
|
|
||||||
self.banner.set_title(title);
|
|
||||||
self.banner.set_revealed(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unset(&self) {
|
|
||||||
self.banner.set_revealed(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Notice {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue