Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More rich Html message support: color, themeing for blocks, etc. #64

Merged
merged 3 commits into from
Apr 10, 2024
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
60 changes: 30 additions & 30 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

108 changes: 105 additions & 3 deletions src/shared/html_or_plaintext.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! A `HtmlOrPlaintext` view can display either plaintext or rich HTML content.

use makepad_widgets::*;
use makepad_widgets::{makepad_html::HtmlDoc, *};

live_design! {
import makepad_draw::shader::std::*;
Expand All @@ -9,8 +9,27 @@ live_design! {
import makepad_widgets::theme_desktop_dark::*;
import crate::shared::styles::*;

// These match the `MESSAGE_*` styles defined in `styles.rs`.
// For some reason, they're not the same. That's TBD.
HTML_LINE_SPACING = 8.0
HTML_TEXT_HEIGHT_FACTOR = 1.3


// This is an HTML subwidget used to handle `<font>` and `<span>` tags,
// specifically: foreground text color, background color, and spoilers.
MatrixHtmlSpan = {{MatrixHtmlSpan}}<Label> {
width: Fit,
height: Fit,

draw_text: {
wrap: Word,
color: (MESSAGE_TEXT_COLOR),
text_style: <MESSAGE_TEXT_STYLE> { height_factor: (HTML_TEXT_HEIGHT_FACTOR), line_spacing: (HTML_LINE_SPACING) },
}
text: "MatrixHtmlSpan placeholder",

}

// A centralized widget where we define styles and custom elements for HTML
// message content. This is a wrapper around Makepad's built-in `Html` widget.
RobrixHtml = <Html> {
Expand All @@ -22,9 +41,20 @@ live_design! {
draw_italic: { color: (MESSAGE_TEXT_COLOR), text_style: { height_factor: (HTML_TEXT_HEIGHT_FACTOR), line_spacing: (HTML_LINE_SPACING) } }
draw_bold: { color: (MESSAGE_TEXT_COLOR), text_style: { height_factor: (HTML_TEXT_HEIGHT_FACTOR), line_spacing: (HTML_LINE_SPACING) } }
draw_bold_italic: { color: (MESSAGE_TEXT_COLOR), text_style: { height_factor: (HTML_TEXT_HEIGHT_FACTOR), line_spacing: (HTML_LINE_SPACING) } }
draw_fixed: { text_style: { height_factor: (HTML_TEXT_HEIGHT_FACTOR), line_spacing: (HTML_LINE_SPACING) } }

draw_fixed: { color: (MESSAGE_TEXT_COLOR), text_style: { height_factor: (HTML_TEXT_HEIGHT_FACTOR), line_spacing: (HTML_LINE_SPACING) } }
draw_block:{
line_color: (MESSAGE_TEXT_COLOR)
sep_color: (MESSAGE_TEXT_COLOR)
quote_bg_color: (#EDEDED)
quote_fg_color: (MESSAGE_TEXT_COLOR)
block_color: (#EDEDED)
code_color: (#EDEDED)
}
list_item_layout: { line_spacing: 5.0, padding: {top: 1.0, bottom: 1.0}, }

font = <MatrixHtmlSpan> { }
span = <MatrixHtmlSpan> { }

body: "[<i> HTML message placeholder</i>]",
}

Expand Down Expand Up @@ -65,6 +95,78 @@ live_design! {
}


/// A custom HTML subwidget used to handle `<font>` and `<span>` tags,
/// specifically: foreground text color, background text color, and spoilers.
#[derive(Live, Widget)]
pub struct MatrixHtmlSpan {
/// The URL of the image to display.
#[deref] ll: Label,
/// Background color: the `data-mx-bg-color` attribute.
#[rust] bg_color: Option<Vec4>,
/// Foreground (text) color: the `data-mx-color` or `color` attributes.
#[rust] fg_color: Option<Vec4>,
/// There are three possible spoiler variants:
/// 1. `None`: no spoiler attribute was present at all.
/// 2. `Some(empty)`: there was a spoiler but no reason was given.
/// 3. `Some(reason)`: there was a spoiler with a reason given for it being hidden.
#[rust] spoiler: Option<String>,
}

impl Widget for MatrixHtmlSpan {
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
self.ll.handle_event(cx, event, scope);
}

fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
self.ll.draw_walk(cx, scope, walk)
}

fn set_text(&mut self, v: &str) {
self.ll.set_text(v);
}
}

impl LiveHook for MatrixHtmlSpan {
// After an MatrixHtmlSpan instance has been instantiated ("applied"),
// populate its struct fields from the `<span>` tag's attributes.
fn after_apply(&mut self, cx: &mut Cx, apply: &mut Apply, _index: usize, _nodes: &[LiveNode]) {
// The attributes we care about in `<font>` and `<span>` tags are:
// * data-mx-bg-color, data-mx-color, data-mx-spoiler, color.

if let ApplyFrom::NewFromDoc {..} = apply.from {
if let Some(scope) = apply.scope.as_ref() {
if let Some(doc) = scope.props.get::<HtmlDoc>() {
let mut walker = doc.new_walker_with_index(scope.index + 1);
while let Some((lc, attr)) = walker.while_attr_lc(){
let attr = attr.trim_matches(&['"', '\'']);
match lc {
live_id!(color)
| live_id!(data-mx-color) => self.fg_color = Vec4::from_hex_str(attr).ok(),
live_id!(data-mx-bg-color) => self.bg_color = Vec4::from_hex_str(attr).ok(),
live_id!(data-mx-spoiler) => self.spoiler = Some(attr.into()),
_ => ()
}
}

// Set the Label's foreground text color and background color
if let Some(fg_color) = self.fg_color {
self.ll.apply_over(cx, live!{ draw_text: { color: (fg_color) } });
};
if let Some(bg_color) = self.bg_color {
self.ll.apply_over(cx, live!{ draw_bg: { color: (bg_color) } });
};

// TODO: need to handle label events to handle the spoiler, so we can toggle it upon click.
}
} else {
warning!("MatrixHtmlSpan::after_apply(): scope not found, cannot set attributes.");
}
}
}
}



#[derive(LiveHook, Live, Widget)]
pub struct HtmlOrPlaintext {
#[deref] view: View,
Expand Down