mirror of
https://github.com/YGGverse/Yoda.git
synced 2026-03-31 16:45:27 +00:00
add text/plain content type support
This commit is contained in:
parent
63d2821c07
commit
f2da250376
6 changed files with 75 additions and 64 deletions
|
|
@ -123,7 +123,7 @@ GTK 4 / Libadwaita client written in Rust
|
||||||
|
|
||||||
#### Text
|
#### Text
|
||||||
* [x] `text/gemini`
|
* [x] `text/gemini`
|
||||||
* [ ] `text/plain`
|
* [x] `text/plain`
|
||||||
|
|
||||||
#### Images
|
#### Images
|
||||||
* [x] `image/gif`
|
* [x] `image/gif`
|
||||||
|
|
|
||||||
|
|
@ -236,7 +236,7 @@ fn handle(
|
||||||
redirects.replace(0); // reset
|
redirects.replace(0); // reset
|
||||||
},
|
},
|
||||||
_ => match success.mime() {
|
_ => match success.mime() {
|
||||||
"text/gemini" => memory_input_stream::from_stream_async(
|
"text/gemini" | "text/plain" => memory_input_stream::from_stream_async(
|
||||||
connection.stream(),
|
connection.stream(),
|
||||||
Priority::DEFAULT,
|
Priority::DEFAULT,
|
||||||
cancellable.clone(),
|
cancellable.clone(),
|
||||||
|
|
@ -257,7 +257,11 @@ fn handle(
|
||||||
let widget = if matches!(*feature, Feature::Source) {
|
let widget = if matches!(*feature, Feature::Source) {
|
||||||
page.content.to_text_source(data)
|
page.content.to_text_source(data)
|
||||||
} else {
|
} 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.search.set(Some(widget.text_view));
|
||||||
page.set_title(&match widget.meta.title {
|
page.set_title(&match widget.meta.title {
|
||||||
|
|
|
||||||
|
|
@ -113,21 +113,7 @@ impl Content {
|
||||||
status
|
status
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set new `content::Text` component for `Self` with new `text::Gemini` preset
|
/// `text/gemini`
|
||||||
///
|
|
||||||
/// 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
|
|
||||||
pub fn to_text_gemini(&self, base: &Uri, data: &str) -> Text {
|
pub fn to_text_gemini(&self, base: &Uri, data: &str) -> Text {
|
||||||
self.clean();
|
self.clean();
|
||||||
let text = Text::gemini((&self.window_action, &self.item_action), base, data);
|
let text = Text::gemini((&self.window_action, &self.item_action), base, data);
|
||||||
|
|
@ -135,6 +121,15 @@ impl Content {
|
||||||
text
|
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 {
|
pub fn to_text_source(&self, data: &str) -> Text {
|
||||||
self.clean();
|
self.clean();
|
||||||
let text = Text::source(data);
|
let text = Text::source(data);
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
mod gemini;
|
mod gemini;
|
||||||
|
mod plain;
|
||||||
mod source;
|
mod source;
|
||||||
|
|
||||||
use super::{ItemAction, WindowAction};
|
use super::{ItemAction, WindowAction};
|
||||||
use adw::ClampScrollable;
|
use adw::ClampScrollable;
|
||||||
use gemini::Gemini;
|
use gemini::Gemini;
|
||||||
use gtk::{glib::Uri, prelude::Cast, ScrolledWindow, TextView};
|
use gtk::{glib::Uri, prelude::Cast, ScrolledWindow, TextView};
|
||||||
|
use plain::Plain;
|
||||||
use source::Source;
|
use source::Source;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
|
@ -34,19 +36,7 @@ impl Text {
|
||||||
.maximum_size(800)
|
.maximum_size(800)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Grab focus into the `TextView` on click empty `ClampScrollable` area
|
grab_focus_patch(&clamp_scrollable, &gemini.text_view);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
text_view: gemini.text_view,
|
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 {
|
pub fn source(data: &str) -> Self {
|
||||||
let source = Source::new(data);
|
let source = Source::new(data);
|
||||||
Self {
|
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);
|
||||||
|
}
|
||||||
|
|
|
||||||
22
src/app/browser/window/tab/item/page/content/text/plain.rs
Normal file
22
src/app/browser/window/tab/item/page/content/text/plain.rs
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue