wallet: add chatview coloring

This commit is contained in:
darkfi
2024-07-28 11:42:42 +02:00
parent a79d3ab15f
commit 0bcd7d9386
3 changed files with 118 additions and 7 deletions

View File

@@ -569,6 +569,35 @@ impl App {
node.set_property_f32("baseline", 10.).unwrap();
node.set_property_u32("z_index", 1).unwrap();
let prop = node.get_property("timestamp_color").unwrap();
prop.set_f32(0, 0.5).unwrap();
prop.set_f32(1, 0.5).unwrap();
prop.set_f32(2, 0.5).unwrap();
prop.set_f32(3, 0.5).unwrap();
let prop = node.get_property("text_color").unwrap();
prop.set_f32(0, 1.).unwrap();
prop.set_f32(1, 1.).unwrap();
prop.set_f32(2, 1.).unwrap();
prop.set_f32(3, 1.).unwrap();
let prop = node.get_property("nick_colors").unwrap();
#[rustfmt::skip]
let nick_colors = [
0.00, 0.94, 1.00, 1.,
0.36, 1.00, 0.69, 1.,
0.29, 1.00, 0.45, 1.,
0.00, 0.73, 0.38, 1.,
0.21, 0.67, 0.67, 1.,
0.56, 0.61, 1.00, 1.,
0.84, 0.48, 1.00, 1.,
1.00, 0.61, 0.94, 1.,
1.00, 0.36, 0.48, 1.,
1.00, 0.30, 0.00, 1.
];
for c in nick_colors {
prop.push_f32(c).unwrap();
}
drop(sg);
let db = sled::open(CHATDB_PATH).expect("cannot open sleddb");
let chat_tree = db.open_tree(b"chat").unwrap();
@@ -793,6 +822,21 @@ fn create_chatview(sg: &mut SceneGraph, name: &str) -> SceneNodeId {
let prop = Property::new("line_height", PropertyType::Float32, PropertySubType::Pixel);
node.add_property(prop).unwrap();
let mut prop = Property::new("timestamp_color", PropertyType::Float32, PropertySubType::Color);
prop.set_array_len(4);
prop.set_range_f32(0., 1.);
node.add_property(prop).unwrap();
let mut prop = Property::new("text_color", PropertyType::Float32, PropertySubType::Color);
prop.set_array_len(4);
prop.set_range_f32(0., 1.);
node.add_property(prop).unwrap();
let mut prop = Property::new("nick_colors", PropertyType::Float32, PropertySubType::Pixel);
prop.set_unbounded();
prop.set_range_f32(0., 1.);
node.add_property(prop).unwrap();
let prop = Property::new("baseline", PropertyType::Float32, PropertySubType::Pixel);
node.add_property(prop).unwrap();

View File

@@ -26,9 +26,12 @@ pub type Color = [f32; 4];
pub const COLOR_RED: Color = [1., 0., 0., 1.];
pub const COLOR_DARKGREY: Color = [0.2, 0.2, 0.2, 1.];
pub const COLOR_LIGHTGREY: Color = [0.7, 0.7, 0.7, 1.];
pub const COLOR_GREEN: Color = [0., 1., 0., 1.];
pub const COLOR_BLUE: Color = [0., 0., 1., 1.];
pub const COLOR_WHITE: Color = [1., 1., 1., 1.];
pub const COLOR_BLACK: Color = [1., 1., 1., 1.];
pub const COLOR_GREY: Color = [0.5, 0.5, 0.5, 1.];
#[derive(Clone)]
pub struct MeshInfo {

View File

@@ -21,6 +21,7 @@ use miniquad::TouchPhase;
use rand::{rngs::OsRng, Rng};
use std::{
collections::BTreeMap,
hash::{DefaultHasher, Hash, Hasher},
sync::{Arc, Mutex as SyncMutex, Weak},
};
@@ -30,7 +31,7 @@ use crate::{
DrawCall, DrawInstruction, DrawMesh, GraphicsEventPublisherPtr, Point, Rectangle,
RenderApi, RenderApiPtr, Vertex,
},
mesh::{Color, MeshBuilder, MeshInfo, COLOR_BLUE, COLOR_WHITE},
mesh::{Color, MeshBuilder, MeshInfo, COLOR_BLUE, COLOR_GREY, COLOR_WHITE},
prop::{
PropertyBool, PropertyColor, PropertyFloat32, PropertyPtr, PropertyStr, PropertyUint32,
},
@@ -44,6 +45,10 @@ use super::{eval_rect, get_parent_rect, read_rect, DrawUpdate, OnModify, Stoppab
const DEBUG_RENDER: bool = false;
fn is_whitespace(s: &str) -> bool {
s.chars().all(char::is_whitespace)
}
#[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
pub struct ChatMsg {
pub nick: String,
@@ -104,6 +109,9 @@ pub struct ChatView {
font_size: PropertyFloat32,
line_height: PropertyFloat32,
baseline: PropertyFloat32,
timestamp_color: PropertyColor,
text_color: PropertyColor,
nick_colors: PropertyPtr,
z_index: PropertyUint32,
}
@@ -126,7 +134,10 @@ impl ChatView {
let scroll = PropertyFloat32::wrap(node, "scroll", 0).unwrap();
let font_size = PropertyFloat32::wrap(node, "font_size", 0).unwrap();
let line_height = PropertyFloat32::wrap(node, "line_height", 0).unwrap();
let baseline = PropertyFloat32::wrap(node, "line_height", 0).unwrap();
let baseline = PropertyFloat32::wrap(node, "baseline", 0).unwrap();
let timestamp_color = PropertyColor::wrap(node, "timestamp_color").unwrap();
let text_color = PropertyColor::wrap(node, "text_color").unwrap();
let nick_colors = node.get_property("nick_colors").expect("ChatView::nick_colors");
let z_index = PropertyUint32::wrap(node, "z_index", 0).unwrap();
drop(scene_graph);
@@ -188,6 +199,9 @@ impl ChatView {
font_size,
line_height,
baseline,
timestamp_color,
text_color,
nick_colors,
z_index,
}
});
@@ -252,7 +266,7 @@ impl ChatView {
debug!(target: "ui::chatview", "inside rect");
let scroll = self.scroll.get();
self.scroll.set(scroll + wheel_y * 50.);
// Render will auto update from on_modify hook
self.scrollview().await;
}
async fn handle_mouse_move(&self, mouse_x: f32, mouse_y: f32) {
@@ -460,35 +474,63 @@ impl ChatView {
let mut draws = vec![];
let color = COLOR_WHITE;
let timestamp_color = self.timestamp_color.get();
let text_color = self.text_color.get();
let nick_colors = self.read_nick_colors();
// This is a little hack to nudge the bottom line up slightly, otherwise
// chars like p will cross the bottom.
let descent = line_height / 2.;
let descent = baseline / 2.;
// Pages start at the bottom.
let mut current_idx = 1;
let mut current_idx = 0;
'pageloop: for page in pages {
let mut mesh = MeshBuilder::new();
for msg in page.msgs {
let glyphs = msg.glyphs;
let nick_color = self.select_nick_color(&msg.chatmsg.nick, &nick_colors);
// Keep track of the 'section'
// Section 0 is the timestamp
// Section 1 is the nickname (colorized)
// Finally is just the message itself
let mut section = 2;
let mut lines = text2::wrap(clip.w, font_size, &glyphs);
// We are drawing bottom up but line wrap gives us lines in normal order
lines.reverse();
for line in lines {
let off_y = descent + current_idx as f32 * line_height;
let last_idx = lines.len() - 1;
for (i, line) in lines.into_iter().enumerate() {
let off_y = descent + baseline + current_idx as f32 * line_height;
//if px_height > clip.h {
// break 'pageloop;
//}
if i == last_idx {
section = 0;
}
// Render line
let mut glyph_pos_iter = GlyphPositionIter::new(font_size, &line, baseline);
for (mut glyph_rect, glyph) in glyph_pos_iter.zip(line.iter()) {
let uv_rect =
page.atlas.fetch_uv(glyph.glyph_id).expect("missing glyph UV rect");
glyph_rect.y -= off_y;
let color = match section {
0 => timestamp_color,
1 => nick_color,
_ => text_color,
};
mesh.draw_box(&glyph_rect, color, uv_rect);
if section < 2 && is_whitespace(&glyph.substr) {
section += 1;
}
}
current_idx += 1;
@@ -524,6 +566,28 @@ impl ChatView {
draws
}
fn read_nick_colors(&self) -> Vec<Color> {
let mut colors = vec![];
let mut color = [0f32; 4];
for i in 0..self.nick_colors.get_len() {
color[i % 4] = self.nick_colors.get_f32(i).expect("prop logic err");
if i > 0 && i % 4 == 0 {
let color = std::mem::take(&mut color);
colors.push(color);
}
}
colors
}
fn select_nick_color(&self, nick: &str, nick_colors: &[Color]) -> Color {
let mut hasher = DefaultHasher::new();
nick.hash(&mut hasher);
let i = hasher.finish() as usize;
let color = nick_colors[i % nick_colors.len()];
color
}
pub async fn draw(&self, sg: &SceneGraph, parent_rect: &Rectangle) -> Option<DrawUpdate> {
debug!(target: "ui::chatview", "ChatView::draw()");
// Only used for debug messages