mirror of
https://github.com/YGGverse/Yoda.git
synced 2025-03-13 06:01:21 +00:00
delegate history_snap action to protocol driver implementation
This commit is contained in:
parent
68b3119bb1
commit
33d5d414ac
@ -93,16 +93,12 @@ impl Window {
|
||||
|
||||
action.history_back.connect_activate({
|
||||
let tab = tab.clone();
|
||||
move |position| {
|
||||
tab.history_back(position);
|
||||
}
|
||||
move |position| tab.history_back(position)
|
||||
});
|
||||
|
||||
action.history_forward.connect_activate({
|
||||
let tab = tab.clone();
|
||||
move |position| {
|
||||
tab.history_forward(position);
|
||||
}
|
||||
move |position| tab.history_forward(position)
|
||||
});
|
||||
|
||||
action.load.on_activate({
|
||||
@ -114,9 +110,7 @@ impl Window {
|
||||
|
||||
action.open.on_activate({
|
||||
let tab = tab.clone();
|
||||
move |position, request| {
|
||||
tab.open(position, request, true);
|
||||
}
|
||||
move |position, request| tab.open(position, request)
|
||||
});
|
||||
|
||||
// Init struct
|
||||
|
@ -284,13 +284,13 @@ impl Tab {
|
||||
/// Reload page at `i32` position or selected page on `None` given
|
||||
pub fn reload(&self, page_position: Option<i32>) {
|
||||
if let Some(item) = self.item(page_position) {
|
||||
item.client.handle(&item.page.navigation.request(), true);
|
||||
item.client.handle(&item.page.navigation.request());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open(&self, page_position: Option<i32>, request: &str, is_snap_history: bool) {
|
||||
pub fn open(&self, page_position: Option<i32>, request: &str) {
|
||||
if let Some(item) = self.item(page_position) {
|
||||
item.action.load.activate(Some(request), is_snap_history);
|
||||
item.action.load.activate(Some(request));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ impl Item {
|
||||
if let Some(uri) = page.navigation.home() {
|
||||
let request = uri.to_string();
|
||||
page.navigation.set_request(&request);
|
||||
client.handle(&request, true);
|
||||
client.handle(&request);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -98,10 +98,10 @@ impl Item {
|
||||
action.load.connect_activate({
|
||||
let page = page.clone();
|
||||
let client = client.clone();
|
||||
move |request, is_history| {
|
||||
if let Some(text) = request {
|
||||
page.navigation.set_request(&text);
|
||||
client.handle(&text, is_history);
|
||||
move |request| {
|
||||
if let Some(request) = request {
|
||||
page.navigation.set_request(&request);
|
||||
client.handle(&request);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -114,9 +114,7 @@ impl Item {
|
||||
action.reload.connect_activate({
|
||||
let page = page.clone();
|
||||
let client = client.clone();
|
||||
move |_, _| {
|
||||
client.handle(&page.navigation.request(), true);
|
||||
}
|
||||
move |_, _| client.handle(&page.navigation.request())
|
||||
});
|
||||
|
||||
action.reload.connect_enabled_notify({
|
||||
@ -150,10 +148,10 @@ impl Item {
|
||||
});
|
||||
|
||||
// Handle immediately on request
|
||||
if let Some(text) = request {
|
||||
page.navigation.set_request(text);
|
||||
if let Some(request) = request {
|
||||
page.navigation.set_request(request);
|
||||
if is_load {
|
||||
client.handle(text, true);
|
||||
client.handle(request)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ impl Action {
|
||||
|
||||
let history = Rc::new(History::build({
|
||||
let load = load.clone();
|
||||
move |request| load.activate(Some(&request), false)
|
||||
move |request| load.activate(Some(&request))
|
||||
}));
|
||||
|
||||
Self {
|
||||
|
@ -32,30 +32,25 @@ impl Load {
|
||||
|
||||
/// Emit [activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal
|
||||
/// with formatted for this action [Variant](https://docs.gtk.org/glib/struct.Variant.html) value
|
||||
pub fn activate(&self, request: Option<&str>, is_history: bool) {
|
||||
self.simple_action.activate(Some(
|
||||
&(request.unwrap_or_default(), is_history).to_variant(),
|
||||
));
|
||||
pub fn activate(&self, request: Option<&str>) {
|
||||
self.simple_action
|
||||
.activate(Some(&(request.unwrap_or_default()).to_variant()));
|
||||
}
|
||||
|
||||
// Events
|
||||
|
||||
/// Define callback function for
|
||||
/// [SimpleAction::activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal
|
||||
pub fn connect_activate(&self, callback: impl Fn(Option<GString>, bool) + 'static) {
|
||||
pub fn connect_activate(&self, callback: impl Fn(Option<GString>) + 'static) {
|
||||
self.simple_action.connect_activate(move |_, this| {
|
||||
let (request, is_history) = this
|
||||
.expect("Expected (`request`,`is_history`) variant")
|
||||
.get::<(String, bool)>()
|
||||
.expect("Parameter type does not match (`String`,`bool`) tuple");
|
||||
|
||||
callback(
|
||||
match request.is_empty() {
|
||||
true => None,
|
||||
false => Some(request.into()),
|
||||
},
|
||||
is_history,
|
||||
)
|
||||
let request = this
|
||||
.expect("Expected `request` variant")
|
||||
.get::<String>()
|
||||
.expect("Parameter type does not match `String`");
|
||||
callback(match request.is_empty() {
|
||||
true => None,
|
||||
false => Some(request.into()),
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ impl Client {
|
||||
|
||||
/// Route tab item `request` to protocol driver
|
||||
/// * or `navigation` entry if the value not provided
|
||||
pub fn handle(&self, request: &str, is_snap_history: bool) {
|
||||
pub fn handle(&self, request: &str) {
|
||||
// Move focus out from navigation entry @TODO
|
||||
self.page.browser_action.escape.activate(None);
|
||||
|
||||
@ -61,18 +61,8 @@ impl Client {
|
||||
match result {
|
||||
// route by scheme
|
||||
Ok(uri) => match uri.scheme().as_str() {
|
||||
"file" => {
|
||||
if is_snap_history {
|
||||
snap_history(&page);
|
||||
}
|
||||
driver.file.handle(uri, feature, cancellable)
|
||||
}
|
||||
"gemini" | "titan" => {
|
||||
if is_snap_history {
|
||||
snap_history(&page);
|
||||
}
|
||||
driver.gemini.handle(uri, feature, cancellable)
|
||||
}
|
||||
"file" => driver.file.handle(uri, feature, cancellable),
|
||||
"gemini" | "titan" => driver.gemini.handle(uri, feature, cancellable),
|
||||
scheme => {
|
||||
// no scheme match driver, complete with failure message
|
||||
let status = page.content.to_status_failure();
|
||||
@ -84,10 +74,7 @@ impl Client {
|
||||
}
|
||||
},
|
||||
// begin redirection to new address suggested
|
||||
Err(query) => page
|
||||
.item_action
|
||||
.load
|
||||
.activate(Some(&query), is_snap_history),
|
||||
Err(query) => page.item_action.load.activate(Some(&query)),
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -199,13 +186,3 @@ fn search(profile: &Profile, query: &str) -> Uri {
|
||||
)
|
||||
.unwrap() // @TODO handle or skip extra URI parse by String return
|
||||
}
|
||||
|
||||
/// Make new history record in related components
|
||||
fn snap_history(page: &Page) {
|
||||
page.item_action
|
||||
.history
|
||||
.add(page.navigation.request(), true);
|
||||
page.profile
|
||||
.history
|
||||
.open(page.navigation.request(), Some(page.title()))
|
||||
}
|
||||
|
@ -20,18 +20,16 @@ impl Directory {
|
||||
{
|
||||
let page = page.clone();
|
||||
move |file| {
|
||||
page.item_action.load.activate(
|
||||
Some(&format!(
|
||||
"file://{}",
|
||||
file.path().unwrap().to_str().unwrap()
|
||||
)),
|
||||
true,
|
||||
)
|
||||
page.item_action.load.activate(Some(&format!(
|
||||
"file://{}",
|
||||
file.path().unwrap().to_str().unwrap()
|
||||
)))
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
page.set_title(&self.file.parse_name());
|
||||
page.snap_history();
|
||||
page.window_action.find.simple_action.set_enabled(false);
|
||||
page.window_action.save_as.simple_action.set_enabled(false);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ impl Image {
|
||||
};
|
||||
page.set_title(&crate::tool::uri_to_title(uri));
|
||||
page.set_progress(0.0);
|
||||
page.snap_history();
|
||||
page.window_action.find.simple_action.set_enabled(false);
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ impl Status {
|
||||
widget.set_description(Some(message));
|
||||
page.set_title(&widget.title());
|
||||
page.set_progress(0.0);
|
||||
page.snap_history();
|
||||
page.window_action.find.simple_action.set_enabled(false);
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ impl Text {
|
||||
None => crate::tool::uri_to_title(uri),
|
||||
});
|
||||
page.set_progress(0.0);
|
||||
page.snap_history();
|
||||
page.window_action.find.simple_action.set_enabled(true);
|
||||
}
|
||||
}
|
||||
|
@ -102,6 +102,7 @@ impl Gemini {
|
||||
});
|
||||
self.page.set_title("Titan input");
|
||||
self.page.set_progress(0.0);
|
||||
//self.page.snap_history();
|
||||
}
|
||||
_ => panic!(), // unexpected
|
||||
}
|
||||
@ -145,6 +146,7 @@ fn handle(
|
||||
let title = input.to_string();
|
||||
page.set_progress(0.0);
|
||||
page.set_title(&title);
|
||||
page.snap_history();
|
||||
redirects.replace(0); // reset
|
||||
match input {
|
||||
// https://geminiprotocol.net/docs/protocol-specification.gmi#status-10
|
||||
@ -174,62 +176,61 @@ fn handle(
|
||||
{
|
||||
let cancellable = cancellable.clone();
|
||||
let stream = connection.stream();
|
||||
move |file, action| {
|
||||
match file.replace(
|
||||
None,
|
||||
false,
|
||||
gtk::gio::FileCreateFlags::NONE,
|
||||
Some(&cancellable),
|
||||
) {
|
||||
Ok(file_output_stream) => {
|
||||
use crate::tool::Format;
|
||||
// Asynchronously read [IOStream](https://docs.gtk.org/gio/class.IOStream.html)
|
||||
// to local [MemoryInputStream](https://docs.gtk.org/gio/class.MemoryInputStream.html)
|
||||
// show bytes count in loading widget, validate max size for incoming data
|
||||
// * no dependency of Gemini library here, feel free to use any other `IOStream` processor
|
||||
file_output_stream::from_stream_async(
|
||||
stream.clone(),
|
||||
file_output_stream,
|
||||
cancellable.clone(),
|
||||
Priority::DEFAULT,
|
||||
(
|
||||
0x100000, // 1M bytes per chunk
|
||||
None, // unlimited
|
||||
0, // initial totals
|
||||
),
|
||||
(
|
||||
// on chunk
|
||||
{
|
||||
let action = action.clone();
|
||||
move |_, total| action.update.activate(&format!(
|
||||
"Received {}...",
|
||||
total.bytes()
|
||||
))
|
||||
},
|
||||
// on complete
|
||||
{
|
||||
let action = action.clone();
|
||||
move |result| match result {
|
||||
Ok((_, total)) => {
|
||||
action.complete.activate(&format!(
|
||||
"Saved to {} ({} total)",
|
||||
file.parse_name(),
|
||||
total.bytes()
|
||||
))
|
||||
}
|
||||
Err(e) => action.cancel.activate(&e.to_string())
|
||||
move |file, action| match file.replace(
|
||||
None,
|
||||
false,
|
||||
gtk::gio::FileCreateFlags::NONE,
|
||||
Some(&cancellable),
|
||||
) {
|
||||
Ok(file_output_stream) => {
|
||||
use crate::tool::Format;
|
||||
// Asynchronously read [IOStream](https://docs.gtk.org/gio/class.IOStream.html)
|
||||
// to local [MemoryInputStream](https://docs.gtk.org/gio/class.MemoryInputStream.html)
|
||||
// show bytes count in loading widget, validate max size for incoming data
|
||||
// * no dependency of Gemini library here, feel free to use any other `IOStream` processor
|
||||
file_output_stream::from_stream_async(
|
||||
stream.clone(),
|
||||
file_output_stream,
|
||||
cancellable.clone(),
|
||||
Priority::DEFAULT,
|
||||
(
|
||||
0x100000, // 1M bytes per chunk
|
||||
None, // unlimited
|
||||
0, // initial totals
|
||||
),
|
||||
(
|
||||
// on chunk
|
||||
{
|
||||
let action = action.clone();
|
||||
move |_, total| action.update.activate(&format!(
|
||||
"Received {}...",
|
||||
total.bytes()
|
||||
))
|
||||
},
|
||||
// on complete
|
||||
{
|
||||
let action = action.clone();
|
||||
move |result| match result {
|
||||
Ok((_, total)) => {
|
||||
action.complete.activate(&format!(
|
||||
"Saved to {} ({} total)",
|
||||
file.parse_name(),
|
||||
total.bytes()
|
||||
))
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
Err(e) => action.cancel.activate(&e.to_string()),
|
||||
Err(e) => action.cancel.activate(&e.to_string())
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
Err(e) => action.cancel.activate(&e.to_string()),
|
||||
}
|
||||
},
|
||||
);
|
||||
page.set_progress(0.0);
|
||||
page.set_title(&status.title());
|
||||
page.snap_history();
|
||||
redirects.replace(0); // reset
|
||||
},
|
||||
_ => match success.mime() {
|
||||
@ -270,6 +271,7 @@ fn handle(
|
||||
.find
|
||||
.simple_action
|
||||
.set_enabled(true);
|
||||
page.snap_history();
|
||||
redirects.replace(0); // reset
|
||||
},
|
||||
Err(e) => {
|
||||
@ -277,6 +279,7 @@ fn handle(
|
||||
status.set_description(Some(&e.to_string()));
|
||||
page.set_progress(0.0);
|
||||
page.set_title(&status.title());
|
||||
page.snap_history();
|
||||
redirects.replace(0); // reset
|
||||
},
|
||||
},
|
||||
@ -285,6 +288,7 @@ fn handle(
|
||||
status.set_description(Some(&e.to_string()));
|
||||
page.set_progress(0.0);
|
||||
page.set_title(&status.title());
|
||||
page.snap_history();
|
||||
redirects.replace(0); // reset
|
||||
}
|
||||
}
|
||||
@ -294,6 +298,7 @@ fn handle(
|
||||
status.set_description(Some(&e.to_string()));
|
||||
page.set_progress(0.0);
|
||||
page.set_title(&status.title());
|
||||
page.snap_history();
|
||||
redirects.replace(0); // reset
|
||||
},
|
||||
}
|
||||
@ -320,7 +325,6 @@ fn handle(
|
||||
(
|
||||
move |_, total| status.set_description(Some(&format!("Download: {total} bytes"))),
|
||||
{
|
||||
//let page = page.clone();
|
||||
move | result | match result {
|
||||
Ok((memory_input_stream, _)) => {
|
||||
Pixbuf::from_stream_async(
|
||||
@ -339,6 +343,7 @@ fn handle(
|
||||
}
|
||||
}
|
||||
page.set_progress(0.0);
|
||||
page.snap_history();
|
||||
redirects.replace(0); // reset
|
||||
},
|
||||
)
|
||||
@ -348,6 +353,7 @@ fn handle(
|
||||
status.set_description(Some(&e.to_string()));
|
||||
page.set_progress(0.0);
|
||||
page.set_title(&status.title());
|
||||
page.snap_history();
|
||||
redirects.replace(0); // reset
|
||||
}
|
||||
}
|
||||
@ -362,6 +368,7 @@ fn handle(
|
||||
status.set_description(Some(&format!("Content type `{mime}` yet not supported")));
|
||||
page.set_progress(0.0);
|
||||
page.set_title(&status.title());
|
||||
page.snap_history();
|
||||
redirects.replace(0); // reset
|
||||
},
|
||||
}
|
||||
@ -397,7 +404,7 @@ fn handle(
|
||||
page.navigation.set_request(&target.to_string());
|
||||
}
|
||||
redirects.replace(total);
|
||||
page.item_action.load.activate(Some(&target.to_string()), false);
|
||||
page.item_action.load.activate(Some(&target.to_string()));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
@ -419,6 +426,7 @@ fn handle(
|
||||
status.set_description(Some(message.as_ref().unwrap_or(&certificate.to_string())));
|
||||
page.set_progress(0.0);
|
||||
page.set_title(&status.title());
|
||||
page.snap_history();
|
||||
redirects.replace(0); // reset
|
||||
}
|
||||
}
|
||||
@ -433,6 +441,7 @@ fn handle(
|
||||
status.set_description(Some(message.as_ref().unwrap_or(&temporary.to_string())));
|
||||
page.set_progress(0.0);
|
||||
page.set_title(&status.title());
|
||||
page.snap_history();
|
||||
redirects.replace(0); // reset
|
||||
if let Some(callback) = on_failure {
|
||||
callback()
|
||||
@ -449,6 +458,7 @@ fn handle(
|
||||
status.set_description(Some(message.as_ref().unwrap_or(&permanent.to_string())));
|
||||
page.set_progress(0.0);
|
||||
page.set_title(&status.title());
|
||||
page.snap_history();
|
||||
redirects.replace(0); // reset
|
||||
if let Some(callback) = on_failure {
|
||||
callback()
|
||||
@ -462,6 +472,7 @@ fn handle(
|
||||
status.set_description(Some(&e.to_string()));
|
||||
page.set_progress(0.0);
|
||||
page.set_title(&status.title());
|
||||
page.snap_history();
|
||||
redirects.replace(0); // reset
|
||||
}
|
||||
}
|
||||
|
@ -93,6 +93,16 @@ impl Page {
|
||||
self.search.show()
|
||||
}
|
||||
|
||||
/// Make new history record in related components
|
||||
pub fn snap_history(&self) {
|
||||
self.item_action
|
||||
.history
|
||||
.add(self.navigation.request(), true);
|
||||
self.profile
|
||||
.history
|
||||
.open(self.navigation.request(), Some(self.title()))
|
||||
}
|
||||
|
||||
/// Cleanup session for `Self`
|
||||
pub fn clean(
|
||||
&self,
|
||||
|
@ -24,9 +24,7 @@ pub fn build(mime: &str, download: Option<(&Rc<ItemAction>, &Uri)>) -> StatusPag
|
||||
let action = action.clone();
|
||||
let request = request.clone();
|
||||
move |_| {
|
||||
action
|
||||
.load
|
||||
.activate(Some(&format!("download:{}", request)), true);
|
||||
action.load.activate(Some(&format!("download:{}", request)));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -388,8 +388,7 @@ impl Gemini {
|
||||
// Select link handler by scheme
|
||||
return match uri.scheme().as_str() {
|
||||
"gemini" | "titan" => {
|
||||
// Open new page in browser
|
||||
item_action.load.activate(Some(&uri.to_str()), true);
|
||||
item_action.load.activate(Some(&uri.to_str()))
|
||||
}
|
||||
// Scheme not supported, delegate
|
||||
_ => UriLauncher::new(&uri.to_str()).launch(
|
||||
|
@ -81,14 +81,11 @@ impl Response for Box {
|
||||
action_send.connect_activate({
|
||||
let form = form.clone();
|
||||
move |_, _| {
|
||||
item_action.load.activate(
|
||||
Some(&format!(
|
||||
"{}?{}",
|
||||
base.to_string_partial(UriHideFlags::QUERY),
|
||||
Uri::escape_string(&form.text(), None, false),
|
||||
)),
|
||||
false, // prevent re-send on history navigation
|
||||
);
|
||||
item_action.load.activate(Some(&format!(
|
||||
"{}?{}",
|
||||
base.to_string_partial(UriHideFlags::QUERY),
|
||||
Uri::escape_string(&form.text(), None, false),
|
||||
)))
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -59,14 +59,11 @@ impl Sensitive for Box {
|
||||
action_send.connect_activate({
|
||||
let form = form.clone();
|
||||
move |_, _| {
|
||||
item_action.load.activate(
|
||||
Some(&format!(
|
||||
"{}?{}",
|
||||
base.to_string_partial(UriHideFlags::QUERY),
|
||||
Uri::escape_string(&form.password_entry_row.text(), None, false),
|
||||
)),
|
||||
false, // prevent re-send on history navigation
|
||||
);
|
||||
item_action.load.activate(Some(&format!(
|
||||
"{}?{}",
|
||||
base.to_string_partial(UriHideFlags::QUERY),
|
||||
Uri::escape_string(&form.password_entry_row.text(), None, false),
|
||||
)))
|
||||
}
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user