update ggemini api

This commit is contained in:
yggverse 2025-02-03 13:41:31 +02:00
parent 63b3c3852a
commit 1a7424f623

View File

@ -3,7 +3,10 @@ use ggemini::client::connection::response::{
failure::{Permanent, Temporary}, failure::{Permanent, Temporary},
Certificate, Failure, Input, Redirect, Certificate, Failure, Input, Redirect,
}; };
use ggemini::client::{connection::response::data::Text, Client, Request, Response}; use ggemini::{
client::{Client, Request, Response},
gio::memory_input_stream::from_stream_async,
};
use gtk::glib::Bytes; use gtk::glib::Bytes;
use gtk::glib::GString; use gtk::glib::GString;
use gtk::{ use gtk::{
@ -13,6 +16,7 @@ use gtk::{
glib::{Priority, Uri}, glib::{Priority, Uri},
prelude::{FileExt, SocketClientExt}, prelude::{FileExt, SocketClientExt},
}; };
use sourceview::prelude::InputStreamExtManual;
use std::{cell::Cell, path::MAIN_SEPARATOR, rc::Rc, time::Duration}; use std::{cell::Cell, path::MAIN_SEPARATOR, rc::Rc, time::Duration};
/// Multi-protocol client API for `Page` object /// Multi-protocol client API for `Page` object
@ -232,37 +236,67 @@ fn handle(
redirects.replace(0); // reset redirects.replace(0); // reset
}, },
_ => match success.mime() { _ => match success.mime() {
"text/gemini" => Text::from_stream_async( "text/gemini" => from_stream_async(
connection.stream(), connection.stream(),
Priority::DEFAULT,
cancellable.clone(), cancellable.clone(),
move |result| match result { Priority::DEFAULT,
Ok(text) => { (
let widget = if matches!(*feature, Feature::Source) { 0x400, // 1024 chunk
page.content.to_text_source(&text.to_string()) 0xfffff, // 1M limit
} else { ),
page.content.to_text_gemini(&uri, &text.to_string()) (
}; |_, _| {}, // on chunk (maybe nothing to count yet @TODO)
page.search.set(Some(widget.text_view)); move |result| match result { // on complete
page.set_title(&match widget.meta.title { Ok((memory_input_stream, total)) => memory_input_stream.read_all_async(
Some(title) => title.into(), // @TODO vec![0;total],
None => uri_to_title(&uri), Priority::DEFAULT,
}); Some(&cancellable),
page.set_progress(0.0); move |result| match result {
page.window_action Ok((buffer, _ ,_)) => match std::str::from_utf8(&buffer) {
.find Ok(data) => {
.simple_action let widget = if matches!(*feature, Feature::Source) {
.set_enabled(true); page.content.to_text_source(&data.to_string())
redirects.replace(0); // reset } else {
page.content.to_text_gemini(&uri, &data.to_string())
};
page.search.set(Some(widget.text_view));
page.set_title(&match widget.meta.title {
Some(title) => title.into(), // @TODO
None => uri_to_title(&uri),
});
page.set_progress(0.0);
page.window_action
.find
.simple_action
.set_enabled(true);
redirects.replace(0); // reset
},
Err(e) => {
let status = page.content.to_status_failure();
status.set_description(Some(&e.to_string()));
page.set_progress(0.0);
page.set_title(&status.title());
redirects.replace(0); // reset
},
},
Err((_, e)) => {
let status = page.content.to_status_failure();
status.set_description(Some(&e.to_string()));
page.set_progress(0.0);
page.set_title(&status.title());
redirects.replace(0); // reset
}
}
),
Err(e) => {
let status = page.content.to_status_failure();
status.set_description(Some(&e.to_string()));
page.set_progress(0.0);
page.set_title(&status.title());
redirects.replace(0); // reset
},
} }
Err(e) => { )
let status = page.content.to_status_failure();
status.set_description(Some(&e.to_string()));
page.set_progress(0.0);
page.set_title(&status.title());
redirects.replace(0); // reset
},
},
), ),
"image/png" | "image/gif" | "image/jpeg" | "image/webp" => { "image/png" | "image/gif" | "image/jpeg" | "image/webp" => {
// Final image size unknown, show loading widget // Final image size unknown, show loading widget
@ -274,47 +308,50 @@ fn handle(
// to local [MemoryInputStream](https://docs.gtk.org/gio/class.MemoryInputStream.html) // to local [MemoryInputStream](https://docs.gtk.org/gio/class.MemoryInputStream.html)
// show bytes count in loading widget, validate max size for incoming data // 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 // * no dependency of Gemini library here, feel free to use any other `IOStream` processor
ggemini::gio::memory_input_stream::from_stream_async( from_stream_async(
connection.stream(), connection.stream(),
cancellable.clone(), cancellable.clone(),
Priority::DEFAULT, Priority::DEFAULT,
0x400, // 1024 bytes per chunk, optional step for images download tracking (
0xA00000, // 10M bytes max to prevent memory overflow if server play with promises 0x400, // 1024 bytes per chunk, optional step for images download tracking
move |_, total| 0xA00000 // 10M bytes max to prevent memory overflow if server play with promises
status.set_description(Some(&format!("Download: {total} bytes"))), ),
{ (
let page = page.clone(); move |_, total| status.set_description(Some(&format!("Download: {total} bytes"))),
move |result| match result { {
Ok((memory_input_stream, _)) => { //let page = page.clone();
Pixbuf::from_stream_async( move | result | match result {
&memory_input_stream, Ok((memory_input_stream, _)) => {
Some(&cancellable), Pixbuf::from_stream_async(
move |result| { &memory_input_stream,
match result { Some(&cancellable),
Ok(buffer) => { move |result| {
page.set_title(&uri_to_title(&uri)); match result {
page.content.to_image(&Texture::for_pixbuf(&buffer)); Ok(buffer) => {
page.set_title(&uri_to_title(&uri));
page.content.to_image(&Texture::for_pixbuf(&buffer));
}
Err(e) => {
let status = page.content.to_status_failure();
status.set_description(Some(e.message()));
page.set_title(&status.title());
}
} }
Err(e) => { page.set_progress(0.0);
let status = page.content.to_status_failure(); redirects.replace(0); // reset
status.set_description(Some(e.message())); },
page.set_title(&status.title()); )
} }
} Err(e) => {
page.set_progress(0.0); let status = page.content.to_status_failure();
redirects.replace(0); // reset status.set_description(Some(&e.to_string()));
}, page.set_progress(0.0);
) page.set_title(&status.title());
} redirects.replace(0); // reset
Err(e) => { }
let status = page.content.to_status_failure();
status.set_description(Some(&e.to_string()));
page.set_progress(0.0);
page.set_title(&status.title());
redirects.replace(0); // reset
} }
} }
}, ),
) )
} }
mime => { mime => {