add text/plain content type support

This commit is contained in:
yggverse 2025-02-04 15:15:12 +02:00
parent 63d2821c07
commit f2da250376
6 changed files with 75 additions and 64 deletions

View file

@ -123,7 +123,7 @@ GTK 4 / Libadwaita client written in Rust
#### Text
* [x] `text/gemini`
* [ ] `text/plain`
* [x] `text/plain`
#### Images
* [x] `image/gif`

View file

@ -236,7 +236,7 @@ fn handle(
redirects.replace(0); // reset
},
_ => match success.mime() {
"text/gemini" => memory_input_stream::from_stream_async(
"text/gemini" | "text/plain" => memory_input_stream::from_stream_async(
connection.stream(),
Priority::DEFAULT,
cancellable.clone(),
@ -257,7 +257,11 @@ fn handle(
let widget = if matches!(*feature, Feature::Source) {
page.content.to_text_source(data)
} else {
page.content.to_text_gemini(&uri, data)
match success.mime() {
"text/gemini" => page.content.to_text_gemini(&uri, data),
"text/plain" => page.content.to_text_plain(data),
_ => panic!() // unexpected
}
};
page.search.set(Some(widget.text_view));
page.set_title(&match widget.meta.title {

View file

@ -113,21 +113,7 @@ impl Content {
status
}
/// Set new `content::Text` component for `Self` with new `text::Gemini` preset
///
/// Useful as reader for [Gemtext](https://geminiprotocol.net/docs/gemtext.gmi)
///
/// * action removes previous children component from `Self`
///
/// **Arguments**
///
/// * `base` - [Uri](https://docs.gtk.org/glib/struct.Uri.html) to resolve relative links in Gemtext
/// * `data` - Gemtext source to be parsed
///
/// **Return**
///
/// `Text` component with it public API
/// * could be useful to extract document title parsed from Gemtext
/// `text/gemini`
pub fn to_text_gemini(&self, base: &Uri, data: &str) -> Text {
self.clean();
let text = Text::gemini((&self.window_action, &self.item_action), base, data);
@ -135,6 +121,15 @@ impl Content {
text
}
/// `text/plain`
pub fn to_text_plain(&self, data: &str) -> Text {
self.clean();
let text = Text::plain(data);
self.g_box.append(&text.scrolled_window);
text
}
/// * system `source:`
pub fn to_text_source(&self, data: &str) -> Text {
self.clean();
let text = Text::source(data);

View file

@ -1,10 +1,12 @@
mod gemini;
mod plain;
mod source;
use super::{ItemAction, WindowAction};
use adw::ClampScrollable;
use gemini::Gemini;
use gtk::{glib::Uri, prelude::Cast, ScrolledWindow, TextView};
use plain::Plain;
use source::Source;
use std::rc::Rc;
@ -34,19 +36,7 @@ impl Text {
.maximum_size(800)
.build();
// Grab focus into the `TextView` on click empty `ClampScrollable` area
{
use gtk::{prelude::WidgetExt, GestureClick};
let controller = GestureClick::new();
controller.connect_pressed({
let text_view = gemini.text_view.clone();
move |_, _, _, _| {
text_view.grab_focus();
}
});
clamp_scrollable.add_controller(controller);
}
grab_focus_patch(&clamp_scrollable, &gemini.text_view);
Self {
text_view: gemini.text_view,
@ -57,6 +47,22 @@ impl Text {
}
}
pub fn plain(data: &str) -> Self {
let text_view = TextView::plain(data);
let clamp_scrollable = ClampScrollable::builder()
.child(&text_view)
.css_classes(["view"])
.build();
grab_focus_patch(&clamp_scrollable, &text_view);
Self {
scrolled_window: ScrolledWindow::builder().child(&clamp_scrollable).build(),
text_view,
meta: Meta { title: None },
}
}
pub fn source(data: &str) -> Self {
let source = Source::new(data);
Self {
@ -66,3 +72,20 @@ impl Text {
}
}
}
// Tools
// Grab focus into the `TextView` on click empty `ClampScrollable` area
fn grab_focus_patch(clamp_scrollable: &ClampScrollable, text_view: &TextView) {
use gtk::{prelude::WidgetExt, GestureClick};
let controller = GestureClick::new();
controller.connect_pressed({
let text_view = text_view.clone();
move |_, _, _, _| {
text_view.grab_focus();
}
});
clamp_scrollable.add_controller(controller);
}

View file

@ -0,0 +1,22 @@
use gtk::{TextBuffer, TextView};
pub trait Plain {
fn plain(data: &str) -> Self;
}
impl Plain for TextView {
fn plain(data: &str) -> Self {
const MARGIN: i32 = 8;
TextView::builder()
.bottom_margin(MARGIN)
.cursor_visible(false)
.buffer(&TextBuffer::builder().text(data).build())
.editable(false)
.left_margin(MARGIN)
.monospace(true)
.right_margin(MARGIN)
.top_margin(MARGIN)
.vexpand(true)
.build()
}
}

View file

@ -1,33 +0,0 @@
use gtk::{Align, Label};
pub struct Reader {
widget: Label,
}
impl Default for Reader {
fn default() -> Self {
Self::new()
}
}
impl Reader {
// Construct
pub fn new() -> Self {
Self {
widget: Label::builder()
.halign(Align::Start)
.valign(Align::Start)
.margin_start(8)
.margin_end(8)
.wrap(true)
.selectable(true)
.use_markup(true)
.build(),
}
}
// Getters
pub fn widget(&self) -> &Label {
&self.widget
}
}