mirror of
https://github.com/YGGverse/Yoda.git
synced 2026-03-31 16:45:27 +00:00
implement Redirect struct as the redirection wrapper with additional API features
This commit is contained in:
parent
0a5e837140
commit
a832936054
5 changed files with 111 additions and 18 deletions
|
|
@ -566,7 +566,10 @@ fn handle(
|
|||
.set_size(None)
|
||||
.commit();
|
||||
|
||||
page.navigation.request.info.replace(i.into_redirect());
|
||||
page.navigation.request.info.replace(match redirect {
|
||||
Redirect::Permanent { .. } => i.into_permanent_redirect(),
|
||||
Redirect::Temporary { .. } => i.into_temporary_redirect(),
|
||||
});
|
||||
}
|
||||
page.item_action.load.activate(Some(&t), false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
mod dialog;
|
||||
mod event;
|
||||
mod redirect;
|
||||
mod socket;
|
||||
|
||||
use super::Profile;
|
||||
use dialog::Dialog;
|
||||
use event::Event;
|
||||
use gtk::{gio::SocketAddress, prelude::IsA};
|
||||
use redirect::Redirect;
|
||||
use socket::Socket;
|
||||
|
||||
/// Common, shared `Page` information holder
|
||||
|
|
@ -24,7 +26,7 @@ pub struct Info {
|
|||
mime: Option<String>,
|
||||
/// Hold redirections chain with handled details
|
||||
/// * the `referrer` member name is reserved for other protocols
|
||||
redirect: Option<Box<Self>>,
|
||||
redirect: Option<Box<Redirect>>,
|
||||
/// Key to relate data collected with the specific request
|
||||
request: Option<String>,
|
||||
/// Hold size info
|
||||
|
|
@ -74,13 +76,20 @@ impl Info {
|
|||
|
||||
/// Take `Self`, convert it into the redirect member,
|
||||
/// then, return new `Self` back
|
||||
/// * tip: use on driver redirection events
|
||||
pub fn into_redirect(self) -> Self {
|
||||
pub fn into_redirect(self, method: redirect::Method) -> Self {
|
||||
let mut this = Self::new();
|
||||
this.redirect = Some(Box::new(self));
|
||||
this.redirect = Some(Box::new(Redirect { info: self, method }));
|
||||
this
|
||||
}
|
||||
|
||||
pub fn into_permanent_redirect(self) -> Self {
|
||||
self.into_redirect(redirect::Method::Permanent)
|
||||
}
|
||||
|
||||
pub fn into_temporary_redirect(self) -> Self {
|
||||
self.into_redirect(redirect::Method::Temporary)
|
||||
}
|
||||
|
||||
pub fn add_event(&mut self, name: String) -> &mut Self {
|
||||
self.event.push(Event::now(name));
|
||||
self
|
||||
|
|
|
|||
|
|
@ -185,36 +185,60 @@ impl Dialog for PreferencesDialog {
|
|||
.icon_name("insert-link-symbolic")
|
||||
.build();
|
||||
p.add(&{
|
||||
// Collect redirections into the buffer,
|
||||
// to reverse chain before add its members to widget
|
||||
// * capacity optimized for Gemini protocol (as default)
|
||||
let mut b = Vec::with_capacity(5);
|
||||
use gtk::Button;
|
||||
/// Common suffix widget pattern
|
||||
fn suffix(
|
||||
icon_name: impl Into<GString>,
|
||||
tooltip_text: impl Into<GString>,
|
||||
) -> Button {
|
||||
Button::builder()
|
||||
.css_classes(["flat"])
|
||||
.icon_name(icon_name)
|
||||
.tooltip_text(tooltip_text)
|
||||
.sensitive(false)
|
||||
.valign(Align::Center)
|
||||
.halign(Align::Center)
|
||||
.build()
|
||||
}
|
||||
/// Recursively collect redirection members into the given vector
|
||||
fn chain<'a>(b: &mut Vec<&'a Info>, i: &'a Info) {
|
||||
b.push(i);
|
||||
if let Some(ref r) = i.redirect {
|
||||
chain(b, r)
|
||||
chain(b, &r.info)
|
||||
}
|
||||
}
|
||||
// Collect redirections into the buffer,
|
||||
// to reverse chain before add its members to widget
|
||||
// * capacity optimized for Gemini protocol (as default)
|
||||
let mut b = Vec::with_capacity(5);
|
||||
chain(&mut b, info);
|
||||
b.reverse();
|
||||
let l = b.len(); // calculate once
|
||||
let t = b[0].event[0].time(); // first event time to count from
|
||||
for (i, r) in b.iter().enumerate() {
|
||||
g.add(&{
|
||||
let is_external = r
|
||||
.redirect
|
||||
.as_ref()
|
||||
.is_some_and(|this| this.is_external(r).is_some_and(|v| v));
|
||||
let a = ActionRow::builder()
|
||||
.css_classes(["property"])
|
||||
.subtitle_selectable(true)
|
||||
.title_selectable(true)
|
||||
.title(r.request().unwrap())
|
||||
.build();
|
||||
// show redirections counter
|
||||
a.add_prefix(&{
|
||||
let c = i + 1;
|
||||
gtk::Button::builder()
|
||||
Button::builder()
|
||||
.css_classes([
|
||||
"circular",
|
||||
if c == l { "success" } else { "accent" },
|
||||
if is_external {
|
||||
"warning"
|
||||
} else if c == l {
|
||||
"success"
|
||||
} else {
|
||||
"accent"
|
||||
},
|
||||
])
|
||||
.label(c.to_string())
|
||||
.sensitive(false)
|
||||
|
|
@ -222,6 +246,15 @@ impl Dialog for PreferencesDialog {
|
|||
.halign(Align::Center)
|
||||
.build()
|
||||
});
|
||||
if let Some(ref redirect) = r.redirect {
|
||||
a.add_suffix(&suffix(
|
||||
redirect.method.icon_name(),
|
||||
redirect.method.to_string(),
|
||||
))
|
||||
}
|
||||
if is_external {
|
||||
a.add_suffix(&suffix("application-exit-symbolic", "External")) // @TODO links contain ⇖ text label indication
|
||||
}
|
||||
// show total redirection time in ms
|
||||
a.set_subtitle(&if i == 0 {
|
||||
t.format_iso8601().unwrap()
|
||||
|
|
@ -237,7 +270,7 @@ impl Dialog for PreferencesDialog {
|
|||
)
|
||||
});
|
||||
a
|
||||
});
|
||||
})
|
||||
}
|
||||
g
|
||||
});
|
||||
|
|
@ -266,10 +299,7 @@ impl Dialog for PreferencesDialog {
|
|||
);
|
||||
a.add_suffix(
|
||||
&Label::builder()
|
||||
.css_classes([
|
||||
"flat",
|
||||
if c == 0 { "success" } else { "warning" },
|
||||
])
|
||||
.css_classes([if c == 0 { "success" } else { "warning" }])
|
||||
.halign(Align::End)
|
||||
.label(if c > 0 {
|
||||
format!("+{c} ms")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
pub mod method;
|
||||
pub use method::Method;
|
||||
|
||||
use super::Info;
|
||||
|
||||
/// Unified redirection info wrapper for the application page
|
||||
pub struct Redirect {
|
||||
pub info: Info,
|
||||
pub method: Method,
|
||||
}
|
||||
|
||||
impl Redirect {
|
||||
// Getters
|
||||
|
||||
/// Check redirection has external target
|
||||
/// * return `None` when at least one request value could not be parsed to
|
||||
/// the valid [Uri](https://docs.gtk.org/glib/struct.Uri.html) host
|
||||
pub fn is_external(&self, cmp: &Info) -> Option<bool> {
|
||||
fn parse(info: &Info) -> Option<gtk::glib::GString> {
|
||||
gtk::glib::Uri::parse(info.request.as_ref()?, gtk::glib::UriFlags::NONE)
|
||||
.ok()?
|
||||
.host()
|
||||
}
|
||||
Some(parse(&self.info)? != parse(cmp)?)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/// Common redirection type enumeration for different protocol drivers
|
||||
pub enum Method {
|
||||
Permanent,
|
||||
Temporary,
|
||||
}
|
||||
|
||||
impl Method {
|
||||
pub fn icon_name(&self) -> &str {
|
||||
match self {
|
||||
Self::Permanent => "network-transmit-symbolic",
|
||||
Self::Temporary => "network-transmit-receive-symbolic",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Method {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Permanent => write!(f, "Permanent"),
|
||||
Self::Temporary => {
|
||||
write!(f, "Temporary")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue