wallet: chatview store properties directly in MessageBuffer which simplifies function signatures

This commit is contained in:
darkfi
2024-09-04 11:13:07 +02:00
parent ee4ec7fc4c
commit 8265976cfc
3 changed files with 122 additions and 105 deletions

View File

@@ -22,6 +22,7 @@ use crate::{
scene::SceneNode,
};
#[derive(Clone)]
pub struct PropertyBool {
prop: PropertyPtr,
role: Role,
@@ -51,6 +52,7 @@ impl PropertyBool {
}
}
#[derive(Clone)]
pub struct PropertyUint32 {
prop: PropertyPtr,
role: Role,
@@ -87,6 +89,7 @@ impl PropertyUint32 {
}
}
#[derive(Clone)]
pub struct PropertyFloat32 {
prop: PropertyPtr,
role: Role,
@@ -116,6 +119,7 @@ impl PropertyFloat32 {
}
}
#[derive(Clone)]
pub struct PropertyStr {
prop: PropertyPtr,
role: Role,
@@ -145,6 +149,7 @@ impl PropertyStr {
}
}
#[derive(Clone)]
pub struct PropertyColor {
prop: PropertyPtr,
role: Role,

View File

@@ -143,6 +143,9 @@ pub struct ChatView {
accel: AtomicF32,
speed: AtomicF32,
// Triggers the background loading task to wake up
bgload_cv: Arc<CondVar>,
/// Used for correct converting input event pos from screen to widget space.
/// We also use it when we re-eval rect when its changed via property.
parent_rect: SyncMutex<Option<Rectangle>>,
@@ -225,6 +228,21 @@ impl ChatView {
}
});
let me2 = me.clone();
let bgload_cv = Arc::new(CondVar::new());
let cv = bgload_cv.clone();
let bgload_task = ex.spawn(async move {
loop {
let Some(self_) = me2.upgrade() else {
// Should not happen
panic!("self destroyed before motion_task was stopped!");
};
cv.reset();
self_.handle_bgload().await;
cv.wait().await;
}
});
let mut on_modify = OnModify::new(ex, node_name, node_id, me.clone());
async fn reload_view(self_: Arc<ChatView>) {
@@ -245,6 +263,7 @@ impl ChatView {
key_down_task,
insert_line_method_task,
motion_task,
bgload_task,
];
tasks.append(&mut on_modify.tasks);
@@ -256,7 +275,17 @@ impl ChatView {
text_shaper: text_shaper.clone(),
tree,
msgbuf: AsyncMutex::new(MessageBuffer::new(render_api, text_shaper)),
msgbuf: AsyncMutex::new(MessageBuffer::new(
font_size.clone(),
line_height.clone(),
baseline.clone(),
timestamp_color.clone(),
text_color.clone(),
nick_colors.clone(),
debug.clone(),
render_api,
text_shaper,
)),
dc_key: OsRng.gen(),
mouse_pos: SyncMutex::new(Point::from([0., 0.])),
@@ -282,6 +311,8 @@ impl ChatView {
accel: AtomicF32::new(0.),
speed: AtomicF32::new(0.),
bgload_cv,
parent_rect: SyncMutex::new(None),
}
});
@@ -536,11 +567,7 @@ impl ChatView {
}
// Add message to page
self.msgbuf
.lock()
.await
.insert_privmsg(self.font_size.get(), timest, message_id, nick.clone(), text.clone())
.await;
self.msgbuf.lock().await.insert_privmsg(timest, message_id, nick, text).await;
// This will refresh the view, so we just use this
let scroll = self.scroll.get();
@@ -589,13 +616,12 @@ impl ChatView {
}
}
/// Descent = line height - baseline
fn descent(&self) -> f32 {
self.line_height.get() - self.baseline.get()
}
async fn handle_bgload(&self) {
// Do we need to load some more?
let scroll = self.scroll.get();
let mut msgbuf = self.msgbuf.lock().await;
/// Load extra msgs
async fn preload_msgs(&self, msgbuf: &mut MessageBuffer) -> usize {
// Get the current earliest timestamp
let iter = match msgbuf.oldest_timestamp() {
Some(oldest_timest) => {
@@ -611,17 +637,6 @@ impl ChatView {
None => self.tree.iter().rev(),
};
self.load_n_msgs(msgbuf, iter, PRELOAD_PAGES).await
}
async fn load_n_msgs<I: Iterator<Item = sled::Result<(sled::IVec, sled::IVec)>>>(
&self,
msgbuf: &mut MessageBuffer,
iter: I,
n: usize,
) -> usize {
let mut msgs_len = 0;
for entry in iter {
let Ok((k, v)) = entry else { break };
assert_eq!(k.len(), 8 + 32);
@@ -631,28 +646,13 @@ impl ChatView {
let chatmsg: ChatMsg = deserialize(&v).unwrap();
debug!(target: "ui::chatview", "{timest:?} {chatmsg:?}");
msgbuf
.push_privmsg(self.font_size.get(), timest, message_id, chatmsg.nick, chatmsg.text)
.await;
msgs_len += 1;
msgbuf.push_privmsg(timest, message_id, chatmsg.nick, chatmsg.text).await;
}
debug!(target: "ui::chatview", "populated {} messages", msgs_len);
msgs_len
}
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
/// Descent = line height - baseline
fn descent(&self) -> f32 {
self.line_height.get() - self.baseline.get()
}
/// Invalidates cache and redraws everything
@@ -723,27 +723,15 @@ impl ChatView {
mut scroll: f32,
rect_h: f32,
) -> Option<f32> {
let line_height = self.line_height.get();
let baseline = self.baseline.get();
let font_size = self.font_size.get();
// We still wish to preload pages to fill the screen, so we just adjust it up to 0.
let nonneg_scroll = max(scroll, 0.);
let mut total_height = msgbuf.calc_total_height(line_height, baseline, font_size).await;
// Load pages until we run out or we have enough
while total_height < nonneg_scroll + rect_h {
let n_loaded_pages = self.preload_msgs(msgbuf).await;
debug!(target: "ui::chatview", "set_adjusted_scroll() loaded until {:?}", msgbuf.oldest_timestamp());
let mut total_height = msgbuf.calc_total_height().await;
// We need this value after so first update it
total_height = msgbuf.calc_total_height(line_height, baseline, font_size).await;
// No more pages available to load
if n_loaded_pages == 0 {
break
}
}
//if total_height < nonneg_scroll + rect_h {
// // Trigger loading
// self.bgload_cv.notify();
//}
if scroll < 0. {
return Some(0.)
@@ -768,35 +756,15 @@ impl ChatView {
rect: &Rectangle,
) -> (Vec<DrawInstruction>, FreedData) {
let scroll = self.scroll.get();
let font_size = self.font_size.get();
let line_height = self.line_height.get();
let baseline = self.baseline.get();
let debug_render = self.debug.get();
let total_height = msgbuf.calc_total_height(line_height, baseline, font_size).await;
let total_height = msgbuf.calc_total_height().await;
// If lines aren't enough to fill the available buffer then start from the top
let start_pos = if total_height < rect.h { total_height } else { rect.h };
let mut instrs = vec![];
//let mut old_drawmesh = vec![];
let timest_color = self.timestamp_color.get();
let text_color = self.text_color.get();
let nick_colors = self.read_nick_colors();
let meshes = msgbuf
.gen_meshes(
rect,
scroll,
font_size,
line_height,
baseline,
&nick_colors,
timest_color.clone(),
text_color.clone(),
debug_render,
)
.await;
let meshes = msgbuf.gen_meshes(rect, scroll).await;
let mut current_height = 0.;
for (i, (y_pos, mesh)) in enumerate(meshes) {

View File

@@ -436,17 +436,45 @@ pub struct MessageBuffer {
date_msgs: HashMap<NaiveDate, Message>,
pub(super) freed: FreedData,
pub(super) line_width: f32,
font_size: PropertyFloat32,
line_height: PropertyFloat32,
baseline: PropertyFloat32,
timestamp_color: PropertyColor,
text_color: PropertyColor,
nick_colors: PropertyPtr,
debug: PropertyBool,
render_api: RenderApiPtr,
text_shaper: TextShaperPtr,
}
impl MessageBuffer {
pub(super) fn new(render_api: RenderApiPtr, text_shaper: TextShaperPtr) -> Self {
pub(super) fn new(
font_size: PropertyFloat32,
line_height: PropertyFloat32,
baseline: PropertyFloat32,
timestamp_color: PropertyColor,
text_color: PropertyColor,
nick_colors: PropertyPtr,
debug: PropertyBool,
render_api: RenderApiPtr,
text_shaper: TextShaperPtr,
) -> Self {
Self {
msgs: vec![],
date_msgs: HashMap::new(),
freed: Default::default(),
line_width: 0.,
font_size,
line_height,
baseline,
timestamp_color,
text_color,
nick_colors,
debug,
render_api,
text_shaper,
}
@@ -480,15 +508,11 @@ impl MessageBuffer {
}
}
pub(super) async fn calc_total_height(
&mut self,
line_height: f32,
baseline: f32,
font_size: f32,
) -> f32 {
pub(super) async fn calc_total_height(&mut self) -> f32 {
let line_height = self.line_height.get();
let mut height = 0.;
let msgs = self.msgs_with_date(font_size);
let msgs = self.msgs_with_date();
let mut msgs = pin!(msgs);
while let Some(msg) = msgs.next().await {
@@ -500,12 +524,13 @@ impl MessageBuffer {
pub(super) async fn insert_privmsg(
&mut self,
font_size: f32,
timest: Timestamp,
message_id: MessageId,
nick: String,
text: String,
) {
let font_size = self.font_size.get();
let msg = PrivMessage::new(
font_size,
timest,
@@ -549,17 +574,18 @@ impl MessageBuffer {
}
};
self.insert_msg(msg, idx, font_size).await;
self.insert_msg(msg, idx).await;
}
pub(super) async fn push_privmsg(
&mut self,
font_size: f32,
timest: Timestamp,
message_id: MessageId,
nick: String,
text: String,
) {
let font_size = self.font_size.get();
let msg = PrivMessage::new(
font_size,
timest,
@@ -578,10 +604,12 @@ impl MessageBuffer {
}
let idx = self.msgs.len() - 1;
self.insert_msg(msg, idx, font_size).await;
self.insert_msg(msg, idx).await;
}
async fn insert_msg(&mut self, msg: Message, idx: usize, font_size: f32) {
async fn insert_msg(&mut self, msg: Message, idx: usize) {
let font_size = self.font_size.get();
let timest = msg.timestamp();
let msg_is_date = msg.is_date();
@@ -600,17 +628,18 @@ impl MessageBuffer {
&mut self,
rect: &Rectangle,
scroll: f32,
font_size: f32,
line_height: f32,
baseline: f32,
nick_colors: &[Color],
timestamp_color: Color,
text_color: Color,
debug_render: bool,
) -> Vec<(f32, DrawMesh)> {
let line_height = self.line_height.get();
let baseline = self.baseline.get();
let debug_render = self.debug.get();
let timest_color = self.timestamp_color.get();
let text_color = self.text_color.get();
let nick_colors = self.read_nick_colors();
let render_api = self.render_api.clone();
let msgs = self.msgs_with_date(font_size);
let msgs = self.msgs_with_date();
let mut msgs = pin!(msgs);
let mut meshes = vec![];
@@ -633,8 +662,8 @@ impl MessageBuffer {
rect,
line_height,
baseline,
nick_colors,
timestamp_color,
&nick_colors,
timest_color,
text_color,
debug_render,
&render_api,
@@ -650,7 +679,8 @@ impl MessageBuffer {
}
/// Gets around borrow checker with unsafe
fn msgs_with_date(&mut self, font_size: f32) -> impl Stream<Item = &mut Message> {
fn msgs_with_date(&mut self) -> impl Stream<Item = &mut Message> {
let font_size = self.font_size.get();
AsyncIter::from(async_gen! {
let mut last_date = None;
@@ -705,4 +735,18 @@ impl MessageBuffer {
let first_msg = &self.msgs.first()?;
Some(first_msg.timestamp())
}
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
}
}