Skip to content
This repository was archived by the owner on Aug 9, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions napture/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
adw = { version = "0.6.0", package = "libadwaita", features = ["v1_5"] }
adw = { version = "0.6.0", package = "libadwaita", features = ["v1_4"] }
chrono = "0.4.38"
directories = "5.0.1"
glib = "0.19.4"
gtk = { version = "0.8.1", package = "gtk4", features = ["v4_14"] }
gtk = { version = "0.8.1", package = "gtk4", features = ["v4_12"] }
html_parser = "0.7.0"
lazy_static = "1.4.0"
mlua = { version = "0.9.7", features = ["lua54", "macros", "async", "unstable", "serialize"] }
Expand Down
51 changes: 45 additions & 6 deletions napture/src/b9/css.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,45 @@ impl Styleable for gtk::Picture {
}
}

// video
impl Styleable for gtk::Video {
fn style(&self) -> String {
let guard = match CSS_RULES.lock() {
Ok(guard) => guard,
Err(_) => {
println!("FATAL: failed to lock CSS_RULES mutex! Aborting function at GtkVideo.");
return String::new();
}
};

if let Some(css) = guard.as_ref() {
let mut classes = self.css_classes();
let mut final_css = "".to_string();

classes.push(self.css_name());

for class in classes {
if let Some(rules) = css.get(&class.to_string()) {
let properties: Properties = get_properties(rules);

self.set_margin_top(properties.margin_top.parse::<i32>().unwrap_or(0));
self.set_margin_bottom(properties.margin_bottom.parse::<i32>().unwrap_or(0));
self.set_margin_start(properties.margin_left.parse::<i32>().unwrap_or(0));
self.set_margin_end(properties.margin_right.parse::<i32>().unwrap_or(0));

self.set_opacity(properties.opacity);

final_css += &compute_styling(class, &properties);
}
}

final_css
} else {
String::new()
}
}
}

// input
impl Styleable for gtk::Entry {
fn style(&self) -> String {
Expand All @@ -507,7 +546,7 @@ impl Styleable for gtk::Entry {

let width = properties.width;
let height = properties.height;

if width > 0 || height > 0 {
let normalized_width = if width > 0 { width } else { -1 };
let normalized_height = if height > 0 { height } else { -1 };
Expand Down Expand Up @@ -558,7 +597,7 @@ impl Styleable for gtk::Button {
self.set_margin_bottom(properties.margin_bottom.parse::<i32>().unwrap_or(0));
self.set_margin_start(properties.margin_left.parse::<i32>().unwrap_or(0));
self.set_margin_end(properties.margin_right.parse::<i32>().unwrap_or(0));

self.set_opacity(properties.opacity);

final_css += &compute_styling(class, &properties);
Expand Down Expand Up @@ -658,7 +697,7 @@ fn compute_styling(class: GString, properties: &Properties) -> String {
if properties.border_style != "none" {
borders.push_str(&format!("border-style: {};", properties.border_style));
}

format!(
"
.{} {{
Expand Down Expand Up @@ -726,8 +765,8 @@ fn get_properties(rules: &[(String, String)]) -> Properties {
.parse::<i32>()
.unwrap_or(0);
let opacity = get_rule(rules, "opacity", "1.0")
.parse::<f64>()
.unwrap_or(1.0);
.parse::<f64>()
.unwrap_or(1.0);

Properties {
direction,
Expand Down Expand Up @@ -757,6 +796,6 @@ fn get_properties(rules: &[(String, String)]) -> Properties {
padding,
gap,
font_size,
opacity
opacity,
}
}
137 changes: 124 additions & 13 deletions napture/src/b9/html.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,16 @@ use super::{
lua,
};

use std::{cell::RefCell, fs, rc::Rc, thread};

use gtk::{gdk::Display, gdk_pixbuf, gio, glib::Bytes, prelude::*, CssProvider};
use std::{cell::RefCell, fs, io::Write, rc::Rc, thread};

use gtk::{
gdk::Display,
gdk_pixbuf,
gio::{self, File},
glib::Bytes,
prelude::*,
CssProvider,
};
use html_parser::{Dom, Element, Node, Result};

use lua::Luable;
Expand Down Expand Up @@ -87,7 +94,7 @@ pub async fn build_ui(
.build();

let mut css: String = css::reset_css();

let (head, body) = match parse_html(furl.to_string()).await {
Ok(ok) => ok,
Err(e) => {
Expand Down Expand Up @@ -208,7 +215,12 @@ pub async fn build_ui(
Ok((html_view, provider))
}

async fn render_head(element: &Element, contents: Option<&Node>, tab: Rc<RefCell<&Tab>>, furl: &String) {
async fn render_head(
element: &Element,
contents: Option<&Node>,
tab: Rc<RefCell<&Tab>>,
furl: &String,
) {
match element.name.as_str() {
"title" => {
if let Some(contents) = contents {
Expand Down Expand Up @@ -480,6 +492,78 @@ fn render_html(
wrapper.append(&image);
html_view.append(&wrapper);
}
"video" => {
let url = match element.attributes.get("src") {
Some(Some(url)) => url.clone(),
_ => {
println!("INFO: <video> tag must have a src attribute");
return;
}
};

let file = match fetch_media_file(url.clone()) {
Ok(s) => s,
Err(e) => {
println!("ERROR: Failed to load video: {}", e);
return;
}
};

let video = gtk::Video::builder()
.css_name("video")
.css_classes(element.classes.clone())
.halign(gtk::Align::Start)
.valign(gtk::Align::Start)
.file(&file)
.build();
tags.borrow_mut().push(Tag {
classes: element.classes.clone(),
widget: Box::new(video.clone()),
tied_variables: Vec::new(),
});

css.push_str(&video.style());

let wrapper = gtk::Box::builder().build();
wrapper.append(&video);

html_view.append(&wrapper);
}
// Copies the video tag, couldn't think of a better way to copy it
"audio" => {
let url = match element.attributes.get("src") {
Some(Some(url)) => url.clone(),
_ => {
println!("INFO: <audio> tag must have a src attribute");
return;
}
};

let file = match fetch_media_file(url.clone()) {
Ok(s) => s,
Err(e) => {
println!("ERROR: Failed to load audio: {}", e);
return;
}
};

let audio = gtk::Video::builder()
.css_name("audio")
.css_classes(element.classes.clone())
.halign(gtk::Align::Start)
.valign(gtk::Align::Start)
.file(&file)
.build();
tags.borrow_mut().push(Tag {
classes: element.classes.clone(),
widget: Box::new(audio.clone()),
tied_variables: Vec::new(),
});

css.push_str(&audio.style());

html_view.append(&audio);
}
"input" => {
let input_type = match element.attributes.get("type") {
Some(Some(t)) => t.to_string(),
Expand Down Expand Up @@ -556,9 +640,14 @@ fn render_html(

css.push_str(&textview.style());

textview
.buffer()
.set_text(element.children.first().unwrap_or(&Node::Text(String::new())).text().unwrap_or(""));
textview.buffer().set_text(
element
.children
.first()
.unwrap_or(&Node::Text(String::new()))
.text()
.unwrap_or(""),
);

html_view.append(&textview);

Expand Down Expand Up @@ -619,7 +708,13 @@ fn render_a(
};

let link_button = gtk::LinkButton::builder()
.label(el.children.first().unwrap_or(&Node::Text(String::new())).text().unwrap_or(""))
.label(
el.children
.first()
.unwrap_or(&Node::Text(String::new()))
.text()
.unwrap_or(""),
)
.uri(uri)
.css_name("a")
.css_classes(el.classes.clone())
Expand Down Expand Up @@ -687,7 +782,13 @@ fn render_list(
.build();

let label = gtk::Label::builder()
.label(el.children.first().unwrap_or(&Node::Text(String::new())).text().unwrap_or(""))
.label(
el.children
.first()
.unwrap_or(&Node::Text(String::new()))
.text()
.unwrap_or(""),
)
.css_name("li")
.css_classes(el.classes.clone())
.halign(gtk::Align::Start)
Expand Down Expand Up @@ -746,12 +847,16 @@ pub(crate) fn fetch_image_to_pixbuf(url: String) -> Result<gdk_pixbuf::Pixbuf> {
}
}

pub(crate) fn fetch_media_file(url: String) -> Result<File> {
Ok(File::for_uri(&url))
}

async fn fetch_file(url: String) -> String {
println!("Attempting to navigate to {url}...");

if url.starts_with("file://") {
let path = url.replace("file://", "");

match fs::read_to_string(&format!("{}", path)) {
Ok(text) => text,
Err(_) => {
Expand Down Expand Up @@ -840,7 +945,13 @@ async fn fetch_from_github(url: String) -> String {
}
}

fn render_p(child: &Node, element: &Element, label_box: &gtk::Box, css: &mut String, tags: &Rc<RefCell<Vec<Tag>>>){
fn render_p(
child: &Node,
element: &Element,
label_box: &gtk::Box,
css: &mut String,
tags: &Rc<RefCell<Vec<Tag>>>,
) {
let label = gtk::Label::builder()
.label(child.text().unwrap_or(""))
.css_name(element.name.as_str())
Expand All @@ -858,4 +969,4 @@ fn render_p(child: &Node, element: &Element, label_box: &gtk::Box, css: &mut Str
widget: Box::new(label),
tied_variables: Vec::new(),
});
}
}
Loading