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,16 +236,28 @@ 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(),
Priority::DEFAULT,
(
0x400, // 1024 chunk
0xfffff, // 1M limit
),
(
|_, _| {}, // on chunk (maybe nothing to count yet @TODO)
move |result| match result { // on complete
Ok((memory_input_stream, total)) => memory_input_stream.read_all_async(
vec![0;total],
Priority::DEFAULT,
Some(&cancellable),
move |result| match result { move |result| match result {
Ok(text) => { Ok((buffer, _ ,_)) => match std::str::from_utf8(&buffer) {
Ok(data) => {
let widget = if matches!(*feature, Feature::Source) { let widget = if matches!(*feature, Feature::Source) {
page.content.to_text_source(&text.to_string()) page.content.to_text_source(&data.to_string())
} else { } else {
page.content.to_text_gemini(&uri, &text.to_string()) page.content.to_text_gemini(&uri, &data.to_string())
}; };
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 {
@ -254,7 +270,7 @@ fn handle(
.simple_action .simple_action
.set_enabled(true); .set_enabled(true);
redirects.replace(0); // reset redirects.replace(0); // reset
} },
Err(e) => { Err(e) => {
let status = page.content.to_status_failure(); let status = page.content.to_status_failure();
status.set_description(Some(&e.to_string())); status.set_description(Some(&e.to_string()));
@ -263,6 +279,24 @@ fn handle(
redirects.replace(0); // reset 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,17 +308,19 @@ 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 0x400, // 1024 bytes per chunk, optional step for images download tracking
0xA00000, // 10M bytes max to prevent memory overflow if server play with promises 0xA00000 // 10M bytes max to prevent memory overflow if server play with promises
move |_, total| ),
status.set_description(Some(&format!("Download: {total} bytes"))), (
move |_, total| status.set_description(Some(&format!("Download: {total} bytes"))),
{ {
let page = page.clone(); //let page = page.clone();
move |result| match result { move | result | match result {
Ok((memory_input_stream, _)) => { Ok((memory_input_stream, _)) => {
Pixbuf::from_stream_async( Pixbuf::from_stream_async(
&memory_input_stream, &memory_input_stream,
@ -314,7 +350,8 @@ fn handle(
redirects.replace(0); // reset redirects.replace(0); // reset
} }
} }
}, }
),
) )
} }
mime => { mime => {