diff --git a/cove-tui/src/chat/tree.rs b/cove-tui/src/chat/tree.rs index 22f8988..d6ec8bd 100644 --- a/cove-tui/src/chat/tree.rs +++ b/cove-tui/src/chat/tree.rs @@ -1,22 +1,15 @@ mod blocks; mod layout; +mod render; mod util; use std::marker::PhantomData; -use chrono::{DateTime, Utc}; use crossterm::event::{KeyCode, KeyEvent}; -use crossterm::style::ContentStyle; use toss::frame::{Frame, Pos, Size}; use crate::store::{Msg, MsgStore}; -use self::blocks::{BlockBody, Blocks}; -use self::util::{ - after_indent, style_indent, style_indent_inverted, style_placeholder, style_time, - style_time_inverted, INDENT, INDENT_WIDTH, PLACEHOLDER, TIME_EMPTY, TIME_FORMAT, TIME_WIDTH, -}; - use super::Cursor; pub struct TreeView { @@ -33,74 +26,6 @@ impl TreeView { } } - fn render_time(frame: &mut Frame, x: i32, y: i32, time: Option>, cursor: bool) { - let pos = Pos::new(x, y); - - let style = if cursor { - style_time_inverted() - } else { - style_time() - }; - - if let Some(time) = time { - let time = format!("{}", time.format(TIME_FORMAT)); - frame.write(pos, &time, style); - } else { - frame.write(pos, TIME_EMPTY, style); - } - } - - fn render_indent(frame: &mut Frame, x: i32, y: i32, indent: usize, cursor: bool) { - for i in 0..indent { - let pos = Pos::new(x + after_indent(i), y); - - let style = if cursor { - style_indent_inverted() - } else { - style_indent() - }; - - frame.write(pos, INDENT, style); - } - } - - fn render_layout(&mut self, frame: &mut Frame, pos: Pos, size: Size, layout: &Blocks) { - for block in &layout.blocks { - // Draw rest of block - match &block.body { - BlockBody::Msg(msg) => { - let nick_width = frame.width(&msg.nick) as i32; - for (i, line) in msg.lines.iter().enumerate() { - let y = pos.y + block.line + i as i32; - if y < 0 || y >= size.height as i32 { - continue; - } - - Self::render_indent(frame, pos.x, y, block.indent, block.cursor); - let after_indent = - pos.x + (TIME_WIDTH + INDENT_WIDTH * block.indent) as i32; - if i == 0 { - Self::render_time(frame, pos.x, y, block.time, block.cursor); - let nick = format!("[{}]", msg.nick); - frame.write(Pos::new(after_indent, y), &nick, ContentStyle::default()); - } else { - Self::render_time(frame, pos.x, y, None, block.cursor); - } - let msg_x = after_indent + 1 + nick_width + 2; - frame.write(Pos::new(msg_x, y), line, ContentStyle::default()); - } - } - BlockBody::Placeholder => { - let y = pos.y + block.line; - Self::render_time(frame, pos.x, y, block.time, block.cursor); - Self::render_indent(frame, pos.x, y, block.indent, block.cursor); - let pos = Pos::new(pos.x + after_indent(block.indent), y); - frame.write(pos, PLACEHOLDER, style_placeholder()); - } - } - } - } - async fn move_to_prev_msg>( &mut self, store: &mut S, @@ -168,7 +93,7 @@ impl TreeView { pos: Pos, size: Size, ) { - let layout = self.layout(room, store, cursor, frame, size).await; - self.render_layout(frame, pos, size, &layout); + let blocks = self.layout_blocks(room, store, cursor, frame, size).await; + Self::render_blocks(frame, pos, size, &blocks); } } diff --git a/cove-tui/src/chat/tree/layout.rs b/cove-tui/src/chat/tree/layout.rs index c5daa96..8cc9f81 100644 --- a/cove-tui/src/chat/tree/layout.rs +++ b/cove-tui/src/chat/tree/layout.rs @@ -89,7 +89,7 @@ impl TreeView { } } - pub async fn layout>( + pub async fn layout_blocks>( &mut self, room: &str, store: &S, diff --git a/cove-tui/src/chat/tree/render.rs b/cove-tui/src/chat/tree/render.rs new file mode 100644 index 0000000..f464ecb --- /dev/null +++ b/cove-tui/src/chat/tree/render.rs @@ -0,0 +1,91 @@ +use chrono::{DateTime, Utc}; +use crossterm::style::ContentStyle; +use toss::frame::{Frame, Pos, Size}; + +use crate::store::Msg; + +use super::blocks::{Block, BlockBody, Blocks}; +use super::util::{ + self, style_indent, style_indent_inverted, style_placeholder, style_time, style_time_inverted, + INDENT, PLACEHOLDER, TIME_EMPTY, TIME_FORMAT, +}; +use super::TreeView; + +fn render_time(frame: &mut Frame, x: i32, y: i32, cursor: bool, time: Option>) { + let pos = Pos::new(x, y); + + let style = if cursor { + style_time_inverted() + } else { + style_time() + }; + + if let Some(time) = time { + let time = format!("{}", time.format(TIME_FORMAT)); + frame.write(pos, &time, style); + } else { + frame.write(pos, TIME_EMPTY, style); + } +} + +fn render_indent(frame: &mut Frame, x: i32, y: i32, cursor: bool, indent: usize) { + for i in 0..indent { + let pos = Pos::new(x + util::after_indent(i), y); + + let style = if cursor { + style_indent_inverted() + } else { + style_indent() + }; + + frame.write(pos, INDENT, style); + } +} + +fn render_nick(frame: &mut Frame, x: i32, y: i32, indent: usize, nick: &str) { + let nick_pos = Pos::new(x + util::after_indent(indent), y); + let nick = format!("[{}]", nick); + frame.write(nick_pos, &nick, ContentStyle::default()); +} + +fn render_block(frame: &mut Frame, pos: Pos, size: Size, block: &Block) { + match &block.body { + BlockBody::Msg(msg) => { + let after_nick = util::after_nick(frame, block.indent, &msg.nick); + + for (i, line) in msg.lines.iter().enumerate() { + let y = pos.y + block.line + i as i32; + if y < 0 || y >= size.height as i32 { + continue; + } + + render_indent(frame, pos.x, y, block.cursor, block.indent); + + if i == 0 { + render_time(frame, pos.x, y, block.cursor, block.time); + render_nick(frame, pos.x, y, block.indent, &msg.nick); + } else { + render_time(frame, pos.x, y, block.cursor, None); + } + + let line_pos = Pos::new(pos.x + after_nick, y); + frame.write(line_pos, line, ContentStyle::default()); + } + } + BlockBody::Placeholder => { + let y = pos.y + block.line; + render_time(frame, pos.x, y, block.cursor, block.time); + render_indent(frame, pos.x, y, block.cursor, block.indent); + let pos = Pos::new(pos.x + util::after_indent(block.indent), y); + frame.write(pos, PLACEHOLDER, style_placeholder()); + } + } +} + +impl TreeView { + pub fn render_blocks(frame: &mut Frame, pos: Pos, size: Size, layout: &Blocks) { + for block in &layout.blocks { + render_block::(frame, pos, size, block); + } + } +}