Skip to content
Merged
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
1 change: 1 addition & 0 deletions cosmic-notifications-util/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ libcosmic = { git = "https://github.com/pop-os/libcosmic", default-features = fa
serde = { version = "1.0", features = ["derive"] }
zbus = { version = "5.11.0", optional = true }
fast_image_resize = { version = "5.1.4", optional = true }
tl = { version = "0.7.8" }
tracing = "0.1.41"
url = "2.5.7"
4 changes: 3 additions & 1 deletion cosmic-notifications-util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ pub mod image;
#[cfg(feature = "image")]
pub use image::*;

use cosmic::widget::{Icon, icon};
pub mod markup;

use cosmic::widget::{icon, Icon};
use serde::{Deserialize, Serialize};
use std::{
collections::HashMap, convert::Infallible, fmt, path::PathBuf, str::FromStr, time::SystemTime,
Expand Down
87 changes: 87 additions & 0 deletions cosmic-notifications-util/src/markup.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use cosmic::{
cosmic_theme,
iced::{
Font,
font::{Style, Weight},
},
iced_core::text::Span,
};

// Handle break lines, etc. in the future
// Used only in `parse_html` function
fn _prepare_html(text: &str) -> String {
let text = text
// handle break lines
.replace("<br>", "\n")
.replace("<br/>", "\n")
.replace("<br />", "\n");

text.to_owned()
}

// Sanitize only tags allowed by Freedesktop Notification Specifications
// https://specifications.freedesktop.org/notification/1.2/markup.html
// TODO: impl <img> tag handling
fn sanitize_html(tags: &[String], content: &str) -> Span<'static> {
let mut font = Font::default();
let mut span = Span::new(content.to_owned());

for tag in tags {
match tag.as_str() {
"b" => font.weight = Weight::Bold,
"i" => font.style = Style::Italic,
"u" => span = span.underline(true),
"a" => {
let theme = cosmic_theme::Theme::preferred_theme();
span = span.underline(true).color(theme.accent_text_color());
}
_ => {}
}
}

span.font(font)
}

fn _handle_recursive(
handle: &tl::NodeHandle,
parser: &tl::Parser,
tags: &mut Vec<String>,
buffer: &mut Vec<Span<'static>>,
) {
if let Some(node) = handle.get(parser) {
match node {
tl::Node::Tag(tag) => {
let tag_name = tag.name().as_utf8_str();
tags.push(tag_name.into_owned());

tag.children().top().iter().for_each(|t| {
_handle_recursive(t, parser, tags, buffer);
});

tags.pop();
}
tl::Node::Raw(bytes) => {
buffer.push(sanitize_html(tags, &bytes.as_utf8_str()));
}
_ => {}
}
}
}

pub fn html_to_spans(text: &str) -> Vec<Span<'static>> {
let mut buffer = Vec::new();
let html = _prepare_html(text);
let dom = tl::parse(&html, tl::ParserOptions::default());

if let Ok(vdom) = dom {
let parser = vdom.parser();
let elements = vdom.children();
let mut tags = Vec::new();

for node_handle in elements {
_handle_recursive(node_handle, parser, &mut tags, &mut buffer);
}
}

buffer
}
8 changes: 5 additions & 3 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ use cosmic::iced::platform_specific::shell::wayland::commands::{
};
use cosmic::iced::{self, Length, Limits, Subscription};
use cosmic::iced_runtime::core::window::Id as SurfaceId;
use cosmic::iced_widget::{column, row, vertical_space};
use cosmic::iced_widget::{column, rich_text, row, vertical_space};
use cosmic::surface;
use cosmic::widget::{autosize, button, container, icon, text};
use cosmic::{Application, Element, app::Task};
use cosmic_notifications_config::NotificationsConfig;
use cosmic_notifications_util::markup::html_to_spans;
use cosmic_notifications_util::{ActionId, CloseReason, Notification};
use cosmic_panel_config::{CosmicPanelConfig, CosmicPanelOuput, PanelAnchor};
use cosmic_time::{Instant, Timeline, anim, id};
Expand Down Expand Up @@ -602,6 +603,7 @@ impl cosmic::Application for CosmicNotifications {
)
.on_press(Message::Dismissed(n.id))
.class(cosmic::theme::Button::Text);

let e = Element::from(
column!(
if let Some(icon) = n.notification_icon() {
Expand All @@ -616,8 +618,8 @@ impl cosmic::Application for CosmicNotifications {
column![
text::body(n.summary.lines().next().unwrap_or_default())
.width(Length::Fill),
text::caption(n.body.lines().next().unwrap_or_default())
.width(Length::Fill)
Element::from(rich_text(html_to_spans(&n.body)).size(12.0))
.map(|_: ()| Message::Ignore)
]
)
.width(Length::Fill),
Expand Down