Browse Source

draft new ggemini api version

master
yggverse 1 month ago
parent
commit
2cc69288fb
  1. 461
      src/app/browser/window/tab/item/page.rs

461
src/app/browser/window/tab/item/page.rs

@ -14,15 +14,12 @@ use widget::Widget; @@ -14,15 +14,12 @@ use widget::Widget;
use meta::{Meta, Status};
use gtk::{
gio::{Cancellable, SimpleAction, SocketClient, SocketProtocol, TlsCertificateFlags},
gio::{Cancellable, SimpleAction},
glib::{
gformat, uuid_string_random, GString, Priority, Regex, RegexCompileFlags, RegexMatchFlags,
Uri, UriFlags,
},
prelude::{
ActionExt, IOStreamExt, OutputStreamExtManual, SocketClientExt, StaticVariantType,
ToVariant,
},
prelude::{ActionExt, StaticVariantType, ToVariant},
Box,
};
use sqlite::Transaction;
@ -191,299 +188,146 @@ impl Page { @@ -191,299 +188,146 @@ impl Page {
"gemini" => {
// Define local NS
use gemini::client::{
connection::Input,
response::{
header::{Mime as ResponseMime, Status as ResponseStatus},
Response,
},
request_async,
response::header::{Mime as ResponseMime, Status as ResponseStatus},
};
// Get host
let host = match uri.host() {
Some(host) => host,
None => todo!(),
};
// Update
// Update page status
meta.borrow_mut().status = Some(Status::Prepare);
meta.borrow_mut().description = Some(gformat!("Connect {host}.."));
meta.borrow_mut().description = Some(gformat!("Connect.."));
action_update.activate(Some(&id));
// Create new connection
let cancellable = Cancellable::new();
let client = SocketClient::new();
client.set_timeout(10);
client.set_tls(true);
client.set_tls_validation_flags(TlsCertificateFlags::INSECURE);
client.set_protocol(SocketProtocol::Tcp);
client.connect_to_uri_async(
&uri.to_str(),
1965,
Some(&cancellable.clone()),
// Begin request
request_async(
uri.clone(),
Some(Cancellable::new()),
Some(Priority::DEFAULT),
move |result| match result {
Ok(connection) => {
// Update
meta.borrow_mut().status = Some(Status::Connect);
meta.borrow_mut().description = Some(gformat!("Connected to {host}.."));
Ok(response) => {
// Format response
meta.borrow_mut().status = Some(Status::Response);
meta.borrow_mut().title = uri.host();
action_update.activate(Some(&id));
// Send request
connection.output_stream().write_all_async(
gformat!("{}\r\n", &uri.to_str()),
Priority::DEFAULT,
Some(&cancellable.clone()),
move |o| match o {
Ok(_) => {
// Update page status
meta.borrow_mut().status = Some(Status::Request);
meta.borrow_mut().description = Some(gformat!("Request data from {host}.."));
action_update.activate(Some(&id));
match response.header().status() {
// 10 | 11
Some(ResponseStatus::Input)
| Some(ResponseStatus::SensitiveInput) => {
// Format response
let status = Status::Input;
let title = gformat!("Input expected");
let description = match response.header().meta() {
Some(meta) => match meta.to_gstring() {
Ok(value) => value,
Err(_) => title.clone(),
},
None => title.clone(),
};
// Make input form
match response.header().status() {
Some(ResponseStatus::SensitiveInput) => input
.set_new_sensitive(
action_page_open,
uri,
Some(&description),
Some(1024),
),
_ => input.set_new_response(
action_page_open,
uri,
Some(&description),
Some(1024),
),
}
// Create new byte buffer and read server response
Input::new_from_stream(
connection.input_stream()
).read_all_async(
Some(cancellable.clone()),
None,
None,
move |i| {
match i {
Ok(buffer) => {
match Response::from_utf8(
&buffer.to_utf8(),
) {
Ok(response) => {
// Format response
meta.borrow_mut().status = Some(Status::Response);
meta.borrow_mut().description = Some(host);
meta.borrow_mut().title = uri.host();
action_update.activate(Some(&id));
match response.header().status() {
// 10 | 11
Some(ResponseStatus::Input) | Some(ResponseStatus::SensitiveInput) => {
// Format response
let status = Status::Input;
let title = gformat!("Input expected");
let description = match response.header().meta() {
Some(meta) => match meta.to_gstring() {
Ok(value) => value,
Err(_) => title.clone()
},
None => title.clone(),
};
// Make input form
match response.header().status() {
Some(ResponseStatus::SensitiveInput) =>
input.set_new_sensitive(
action_page_open, uri,
Some(&description),
Some(1024),
),
_ =>
input.set_new_response(
action_page_open, uri,
Some(&description),
Some(1024),
)
}
// Update meta
meta.borrow_mut().status = Some(status);
meta.borrow_mut().description = Some(description);
meta.borrow_mut().title = Some(title);
// Update page
action_update.activate(Some(&id));
},
// 20
Some(ResponseStatus::Success) =>
match response.header().mime() {
Some(ResponseMime::TextGemini) => {
// Update data
match response.body().to_gstring() {
Ok(source) => {
meta.borrow_mut().status = Some(Status::Success);
// This content type may return parsed title
meta.borrow_mut().title = content.set_text_gemini(&uri, &source);
// Add new history record
let request = uri.to_str();
match navigation.history_current() {
Some(current) => {
if current != request {
navigation.history_add(request);
}
}
None => navigation.history_add(request),
}
// Update window components
action_update.activate(Some(&id));
},
Err(_) => todo!(),
}
},
Some(ResponseMime::TextPlain) => {
meta.borrow_mut().status = Some(Status::Success);
action_update.activate(Some(&id));
todo!()
},
Some(ResponseMime::ImagePng) | Some(ResponseMime::ImageGif) | Some(ResponseMime::ImageJpeg) | Some(ResponseMime::ImageWebp) => {
// Update meta
meta.borrow_mut().status = Some(Status::Success);
meta.borrow_mut().title = Some(gformat!("Picture")); // @TODO
// Update content
content.set_image(); // @TODO
// Add new history record
let request = uri.to_str();
match navigation.history_current() {
Some(current) => {
if current != request {
navigation.history_add(request);
}
}
None => navigation.history_add(request),
}
// Update window components
action_update.activate(Some(&id));
},
_ => {
// Define common data
let status = Status::Failure;
let title = gformat!("Oops");
let description = gformat!("Content type not supported");
// Update widget
content.set_status_failure(title.as_str(), description.as_str());
// Update meta
meta.borrow_mut().status = Some(status);
meta.borrow_mut().title = Some(title);
meta.borrow_mut().description = Some(description);
// Update window
action_update.activate(Some(&id));
},
},
// 32
Some(ResponseStatus::Redirect) => {
// Update meta
meta.borrow_mut().status = Some(Status::Redirect);
meta.borrow_mut().title = Some(gformat!("Redirect"));
action_update.activate(Some(&id));
// Select widget
match response.header().meta() {
Some(meta) => {
let _ = content.set_text_gemini(
&uri,
// @TODO use template file
&gformat!(
"# Redirect\n\nAuto-follow disabled, click on link below to continue\n\n=> {}",
match meta.to_gstring() {
Ok(url) => url,
Err(_) => todo!()
}
)
);
},
None => todo!(),
}
},
// @TODO
None => {
// Define common data
let status = Status::Failure;
let title = gformat!("Oops");
let description = gformat!("Status code not supported");
// Update widget
content.set_status_failure(title.as_str(), description.as_str());
// Update meta
meta.borrow_mut().status = Some(status);
meta.borrow_mut().title = Some(title);
meta.borrow_mut().description = Some(description);
// Update window
action_update.activate(Some(&id));
},
};
}
Err(_) => {
// Define common data
let status = Status::Failure;
let title = gformat!("Oops");
let description = gformat!("Failed to read buffer data");
// Update widget
content.set_status_failure(title.as_str(), description.as_str());
// Update meta
meta.borrow_mut().status = Some(status);
meta.borrow_mut().title = Some(title);
meta.borrow_mut().description = Some(description);
// Update window
action_update.activate(Some(&id));
// Update meta
meta.borrow_mut().status = Some(status);
meta.borrow_mut().description = Some(description);
meta.borrow_mut().title = Some(title);
// Update page
action_update.activate(Some(&id));
}
// 20
Some(ResponseStatus::Success) => match response
.header()
.mime()
{
Some(ResponseMime::TextGemini) => {
// Update data
match response.body().to_gstring() {
Ok(source) => {
meta.borrow_mut().status =
Some(Status::Success);
// This content type may return parsed title
meta.borrow_mut().title =
content.set_text_gemini(&uri, &source);
// Add new history record
let request = uri.to_str();
match navigation.history_current() {
Some(current) => {
if current != request {
navigation.history_add(request);
}
}
// Close connection
if let Err(error) = connection.close(Some(&cancellable)) {
todo!("Error closing connection: {}", error.message());
}
}
Err(_) => {
// Define common data
let status = Status::Failure;
let title = gformat!("Oops");
let description = gformat!("Failed to read response");
// Update widget
content.set_status_failure(title.as_str(), description.as_str());
// Update meta
meta.borrow_mut().status = Some(status);
meta.borrow_mut().title = Some(title);
meta.borrow_mut().description = Some(description);
// Update window
action_update.activate(Some(&id));
// Close connection
if let Err(error) = connection.close(Some(&cancellable)) {
todo!("Error closing response connection: {}", error.message());
}
None => navigation.history_add(request),
}
// Update window components
action_update.activate(Some(&id));
}
Err(_) => todo!(),
}
}
Some(ResponseMime::TextPlain) => {
meta.borrow_mut().status = Some(Status::Success);
action_update.activate(Some(&id));
todo!()
}
Some(ResponseMime::ImagePng)
| Some(ResponseMime::ImageGif)
| Some(ResponseMime::ImageJpeg)
| Some(ResponseMime::ImageWebp) => {
// Update meta
meta.borrow_mut().status = Some(Status::Success);
meta.borrow_mut().title = Some(gformat!("Picture")); // @TODO
// Update content
content.set_image(); // @TODO
// Add new history record
let request = uri.to_str();
match navigation.history_current() {
Some(current) => {
if current != request {
navigation.history_add(request);
}
},
);
}
None => navigation.history_add(request),
}
// Update window components
action_update.activate(Some(&id));
}
Err(error) => {
_ => {
// Define common data
let status = Status::Failure;
let title = gformat!("Oops");
let description = gformat!("Failed to read request: {}", error.1.message());
let description =
gformat!("Content type not supported");
// Update widget
content.set_status_failure(title.as_str(), description.as_str());
content.set_status_failure(
title.as_str(),
description.as_str(),
);
// Update meta
meta.borrow_mut().status = Some(status);
@ -492,23 +336,66 @@ impl Page { @@ -492,23 +336,66 @@ impl Page {
// Update window
action_update.activate(Some(&id));
// Close connection
if let Err(error) = connection.close(Some(&cancellable)) {
todo!("Error closing request connection: {}", error.message());
}
}
},
);
// 32
Some(ResponseStatus::Redirect) => {
// Update meta
meta.borrow_mut().status = Some(Status::Redirect);
meta.borrow_mut().title = Some(gformat!("Redirect"));
action_update.activate(Some(&id));
// Select widget
match response.header().meta() {
Some(meta) => {
let _ = content.set_text_gemini(
&uri,
// @TODO use template file
&gformat!(
"# Redirect\n\nAuto-follow disabled, click on link below to continue\n\n=> {}",
match meta.to_gstring() {
Ok(url) => url,
Err(_) => todo!()
}
)
);
}
None => todo!(),
}
}
// @TODO
None => {
// Define common data
let status = Status::Failure;
let title = gformat!("Oops");
let description = gformat!("Status code not supported");
// Update widget
content.set_status_failure(
title.as_str(),
description.as_str(),
);
// Update meta
meta.borrow_mut().status = Some(status);
meta.borrow_mut().title = Some(title);
meta.borrow_mut().description = Some(description);
// Update window
action_update.activate(Some(&id));
}
};
}
Err(error) => {
Err(_) => {
// Define common data
let status = Status::Failure;
let title = gformat!("Oops");
let description = gformat!("Failed to connect: {}", error.message());
let description = gformat!("Failed to request");
// Update widget
content.set_status_failure(title.as_str(), description.as_str());
content
.set_status_failure(title.as_str(), description.as_str());
// Update meta
meta.borrow_mut().status = Some(status);

Loading…
Cancel
Save