Render messages with less async
This commit is contained in:
parent
8182cc5d38
commit
a638caadcb
5 changed files with 62 additions and 100 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
|
@ -68,17 +68,6 @@ version = "1.0.70"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
|
||||
|
||||
[[package]]
|
||||
name = "async-recursion"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.13",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.68"
|
||||
|
|
@ -251,7 +240,6 @@ name = "cove"
|
|||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
"async-trait",
|
||||
"clap",
|
||||
"cookie",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
anyhow = "1.0.70"
|
||||
async-recursion = "1.0.4"
|
||||
async-trait = "0.1.68"
|
||||
clap = { version = "4.2.1", features = ["derive", "deprecated"] }
|
||||
cookie = "0.17.0"
|
||||
|
|
|
|||
|
|
@ -2,10 +2,9 @@
|
|||
|
||||
use std::convert::Infallible;
|
||||
|
||||
use async_recursion::async_recursion;
|
||||
use async_trait::async_trait;
|
||||
use toss::widgets::{EditorState, Empty, Predrawn, Resize};
|
||||
use toss::{AsyncWidget, Size, WidthDb};
|
||||
use toss::{Size, Widget, WidthDb};
|
||||
|
||||
use crate::store::{Msg, MsgStore, Tree};
|
||||
use crate::ui::chat::blocks::{Block, Blocks, Range};
|
||||
|
|
@ -122,26 +121,24 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
async fn predraw<W>(widget: W, size: Size, widthdb: &mut WidthDb) -> Predrawn
|
||||
fn predraw<W>(widget: W, size: Size, widthdb: &mut WidthDb) -> Predrawn
|
||||
where
|
||||
W: AsyncWidget<Infallible> + Send + Sync,
|
||||
W: Widget<Infallible>,
|
||||
{
|
||||
Predrawn::new_async(Resize::new(widget).with_max_width(size.width), widthdb)
|
||||
.await
|
||||
.infallible()
|
||||
Predrawn::new(Resize::new(widget).with_max_width(size.width), widthdb).infallible()
|
||||
}
|
||||
|
||||
async fn zero_height_block(&mut self, parent: Option<&M::Id>) -> TreeBlock<M::Id> {
|
||||
fn zero_height_block(&mut self, parent: Option<&M::Id>) -> TreeBlock<M::Id> {
|
||||
let id = match parent {
|
||||
Some(parent) => TreeBlockId::After(parent.clone()),
|
||||
None => TreeBlockId::Bottom,
|
||||
};
|
||||
|
||||
let widget = Self::predraw(Empty::new(), self.context.size, self.widthdb).await;
|
||||
let widget = Self::predraw(Empty::new(), self.context.size, self.widthdb);
|
||||
Block::new(id, widget, false)
|
||||
}
|
||||
|
||||
async fn editor_block(&mut self, indent: usize, parent: Option<&M::Id>) -> TreeBlock<M::Id> {
|
||||
fn editor_block(&mut self, indent: usize, parent: Option<&M::Id>) -> TreeBlock<M::Id> {
|
||||
let id = match parent {
|
||||
Some(parent) => TreeBlockId::After(parent.clone()),
|
||||
None => TreeBlockId::Bottom,
|
||||
|
|
@ -149,7 +146,7 @@ where
|
|||
|
||||
// TODO Unhighlighted version when focusing on nick list
|
||||
let widget = widgets::editor::<M>(indent, &self.context.nick, self.editor);
|
||||
let widget = Self::predraw(widget, self.context.size, self.widthdb).await;
|
||||
let widget = Self::predraw(widget, self.context.size, self.widthdb);
|
||||
let mut block = Block::new(id, widget, false);
|
||||
|
||||
// Since the editor was rendered when the `Predrawn` was created, the
|
||||
|
|
@ -160,7 +157,7 @@ where
|
|||
block
|
||||
}
|
||||
|
||||
async fn pseudo_block(&mut self, indent: usize, parent: Option<&M::Id>) -> TreeBlock<M::Id> {
|
||||
fn pseudo_block(&mut self, indent: usize, parent: Option<&M::Id>) -> TreeBlock<M::Id> {
|
||||
let id = match parent {
|
||||
Some(parent) => TreeBlockId::After(parent.clone()),
|
||||
None => TreeBlockId::Bottom,
|
||||
|
|
@ -168,11 +165,11 @@ where
|
|||
|
||||
// TODO Unhighlighted version when focusing on nick list
|
||||
let widget = widgets::pseudo::<M>(indent, &self.context.nick, self.editor);
|
||||
let widget = Self::predraw(widget, self.context.size, self.widthdb).await;
|
||||
let widget = Self::predraw(widget, self.context.size, self.widthdb);
|
||||
Block::new(id, widget, false)
|
||||
}
|
||||
|
||||
async fn message_block(&mut self, indent: usize, msg: &M) -> TreeBlock<M::Id> {
|
||||
fn message_block(&mut self, indent: usize, msg: &M) -> TreeBlock<M::Id> {
|
||||
let msg_id = msg.id();
|
||||
|
||||
let highlighted = match self.cursor {
|
||||
|
|
@ -182,15 +179,11 @@ where
|
|||
|
||||
// TODO Amount of folded messages
|
||||
let widget = widgets::msg(self.context.focused && highlighted, indent, msg, None);
|
||||
let widget = Self::predraw(widget, self.context.size, self.widthdb).await;
|
||||
let widget = Self::predraw(widget, self.context.size, self.widthdb);
|
||||
Block::new(TreeBlockId::Msg(msg_id), widget, true)
|
||||
}
|
||||
|
||||
async fn message_placeholder_block(
|
||||
&mut self,
|
||||
indent: usize,
|
||||
msg_id: &M::Id,
|
||||
) -> TreeBlock<M::Id> {
|
||||
fn message_placeholder_block(&mut self, indent: usize, msg_id: &M::Id) -> TreeBlock<M::Id> {
|
||||
let highlighted = match self.cursor {
|
||||
Cursor::Msg(id) => id == msg_id,
|
||||
_ => false,
|
||||
|
|
@ -198,28 +191,23 @@ where
|
|||
|
||||
// TODO Amount of folded messages
|
||||
let widget = widgets::msg_placeholder(self.context.focused && highlighted, indent, None);
|
||||
let widget = Self::predraw(widget, self.context.size, self.widthdb).await;
|
||||
let widget = Self::predraw(widget, self.context.size, self.widthdb);
|
||||
Block::new(TreeBlockId::Msg(msg_id.clone()), widget, true)
|
||||
}
|
||||
|
||||
async fn layout_bottom(&mut self) -> TreeBlocks<M::Id> {
|
||||
fn layout_bottom(&mut self) -> TreeBlocks<M::Id> {
|
||||
let mut blocks = Blocks::new(0);
|
||||
|
||||
match self.cursor {
|
||||
Cursor::Editor { parent: None, .. } => {
|
||||
blocks.push_bottom(self.editor_block(0, None).await)
|
||||
}
|
||||
Cursor::Pseudo { parent: None, .. } => {
|
||||
blocks.push_bottom(self.pseudo_block(0, None).await)
|
||||
}
|
||||
_ => blocks.push_bottom(self.zero_height_block(None).await),
|
||||
Cursor::Editor { parent: None, .. } => blocks.push_bottom(self.editor_block(0, None)),
|
||||
Cursor::Pseudo { parent: None, .. } => blocks.push_bottom(self.pseudo_block(0, None)),
|
||||
_ => blocks.push_bottom(self.zero_height_block(None)),
|
||||
}
|
||||
|
||||
blocks
|
||||
}
|
||||
|
||||
#[async_recursion]
|
||||
async fn layout_subtree(
|
||||
fn layout_subtree(
|
||||
&mut self,
|
||||
tree: &Tree<M>,
|
||||
indent: usize,
|
||||
|
|
@ -228,16 +216,16 @@ where
|
|||
) {
|
||||
// Message itself
|
||||
let block = if let Some(msg) = tree.msg(msg_id) {
|
||||
self.message_block(indent, msg).await
|
||||
self.message_block(indent, msg)
|
||||
} else {
|
||||
self.message_placeholder_block(indent, msg_id).await
|
||||
self.message_placeholder_block(indent, msg_id)
|
||||
};
|
||||
blocks.push_bottom(block);
|
||||
|
||||
// Children, recursively
|
||||
if let Some(children) = tree.children(msg_id) {
|
||||
for child in children {
|
||||
self.layout_subtree(tree, indent + 1, child, blocks).await;
|
||||
self.layout_subtree(tree, indent + 1, child, blocks);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -245,21 +233,20 @@ where
|
|||
let block = match self.cursor {
|
||||
Cursor::Editor {
|
||||
parent: Some(id), ..
|
||||
} if id == msg_id => self.editor_block(indent + 1, Some(msg_id)).await,
|
||||
} if id == msg_id => self.editor_block(indent + 1, Some(msg_id)),
|
||||
|
||||
Cursor::Pseudo {
|
||||
parent: Some(id), ..
|
||||
} if id == msg_id => self.pseudo_block(indent + 1, Some(msg_id)).await,
|
||||
} if id == msg_id => self.pseudo_block(indent + 1, Some(msg_id)),
|
||||
|
||||
_ => self.zero_height_block(Some(msg_id)).await,
|
||||
_ => self.zero_height_block(Some(msg_id)),
|
||||
};
|
||||
blocks.push_bottom(block);
|
||||
}
|
||||
|
||||
async fn layout_tree(&mut self, tree: Tree<M>) -> TreeBlocks<M::Id> {
|
||||
fn layout_tree(&mut self, tree: Tree<M>) -> TreeBlocks<M::Id> {
|
||||
let mut blocks = Blocks::new(0);
|
||||
self.layout_subtree(&tree, 0, tree.root(), &mut blocks)
|
||||
.await;
|
||||
self.layout_subtree(&tree, 0, tree.root(), &mut blocks);
|
||||
blocks
|
||||
}
|
||||
|
||||
|
|
@ -275,9 +262,9 @@ where
|
|||
|
||||
let blocks = if let Some(root_id) = root_id {
|
||||
let tree = self.store.tree(root_id).await?;
|
||||
self.layout_tree(tree).await
|
||||
self.layout_tree(tree)
|
||||
} else {
|
||||
self.layout_bottom().await
|
||||
self.layout_bottom()
|
||||
};
|
||||
self.blocks.append_bottom(blocks);
|
||||
|
||||
|
|
@ -429,7 +416,7 @@ where
|
|||
|
||||
if let Some(prev_root_id) = prev_root_id {
|
||||
let tree = self.store.tree(&prev_root_id).await?;
|
||||
let blocks = self.layout_tree(tree).await;
|
||||
let blocks = self.layout_tree(tree);
|
||||
self.blocks.append_top(blocks);
|
||||
self.top_root_id = Some(prev_root_id);
|
||||
} else {
|
||||
|
|
@ -448,11 +435,11 @@ where
|
|||
let next_root_id = self.store.next_root_id(bottom_root_id).await?;
|
||||
if let Some(next_root_id) = next_root_id {
|
||||
let tree = self.store.tree(&next_root_id).await?;
|
||||
let blocks = self.layout_tree(tree).await;
|
||||
let blocks = self.layout_tree(tree);
|
||||
self.blocks.append_bottom(blocks);
|
||||
self.bottom_root_id = Some(next_root_id);
|
||||
} else {
|
||||
let blocks = self.layout_bottom().await;
|
||||
let blocks = self.layout_bottom();
|
||||
self.blocks.append_bottom(blocks);
|
||||
self.blocks.end_bottom();
|
||||
self.bottom_root_id = None;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::convert::Infallible;
|
||||
|
||||
use crossterm::style::Stylize;
|
||||
use toss::widgets::{BoxedAsync, EditorState, Join2, Join4, Join5, Text};
|
||||
use toss::widgets::{Boxed, EditorState, Join2, Join4, Join5, Text};
|
||||
use toss::{Style, Styled, WidgetExt};
|
||||
|
||||
use crate::store::Msg;
|
||||
|
|
@ -47,7 +47,7 @@ pub fn msg<M: Msg + ChatMsg>(
|
|||
indent: usize,
|
||||
msg: &M,
|
||||
folded_info: Option<usize>,
|
||||
) -> BoxedAsync<'static, Infallible> {
|
||||
) -> Boxed<'static, Infallible> {
|
||||
let (nick, mut content) = msg.styled();
|
||||
|
||||
if let Some(amount) = folded_info {
|
||||
|
|
@ -81,14 +81,14 @@ pub fn msg<M: Msg + ChatMsg>(
|
|||
// TODO Minimizing and maximizing messages
|
||||
Text::new(content).segment(),
|
||||
)
|
||||
.boxed_async()
|
||||
.boxed()
|
||||
}
|
||||
|
||||
pub fn msg_placeholder(
|
||||
highlighted: bool,
|
||||
indent: usize,
|
||||
folded_info: Option<usize>,
|
||||
) -> BoxedAsync<'static, Infallible> {
|
||||
) -> Boxed<'static, Infallible> {
|
||||
let mut content = Styled::new(PLACEHOLDER, style_placeholder());
|
||||
|
||||
if let Some(amount) = folded_info {
|
||||
|
|
@ -110,14 +110,14 @@ pub fn msg_placeholder(
|
|||
.with_fixed(true),
|
||||
Text::new(content).segment(),
|
||||
)
|
||||
.boxed_async()
|
||||
.boxed()
|
||||
}
|
||||
|
||||
pub fn editor<'a, M: ChatMsg>(
|
||||
indent: usize,
|
||||
nick: &str,
|
||||
editor: &'a mut EditorState,
|
||||
) -> BoxedAsync<'a, Infallible> {
|
||||
) -> Boxed<'a, Infallible> {
|
||||
let (nick, content) = M::edit(nick, editor.text());
|
||||
let editor = editor.widget().with_highlight(|_| content);
|
||||
|
||||
|
|
@ -144,14 +144,14 @@ pub fn editor<'a, M: ChatMsg>(
|
|||
.with_fixed(true),
|
||||
editor.segment(),
|
||||
)
|
||||
.boxed_async()
|
||||
.boxed()
|
||||
}
|
||||
|
||||
pub fn pseudo<'a, M: ChatMsg>(
|
||||
indent: usize,
|
||||
nick: &str,
|
||||
editor: &'a mut EditorState,
|
||||
) -> BoxedAsync<'a, Infallible> {
|
||||
) -> Boxed<'a, Infallible> {
|
||||
let (nick, content) = M::edit(nick, editor.text());
|
||||
|
||||
Join5::horizontal(
|
||||
|
|
@ -177,5 +177,5 @@ pub fn pseudo<'a, M: ChatMsg>(
|
|||
.with_fixed(true),
|
||||
Text::new(content).segment(),
|
||||
)
|
||||
.boxed_async()
|
||||
.boxed()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
use std::convert::Infallible;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use crossterm::style::Stylize;
|
||||
use time::format_description::FormatItem;
|
||||
use time::macros::format_description;
|
||||
use time::OffsetDateTime;
|
||||
use toss::widgets::{BoxedAsync, Empty, Text};
|
||||
use toss::{AsyncWidget, Frame, Pos, Size, Style, WidgetExt, WidthDb};
|
||||
use toss::widgets::{Boxed, Empty, Text};
|
||||
use toss::{Frame, Pos, Size, Style, Widget, WidgetExt, WidthDb};
|
||||
|
||||
use crate::util::InfallibleExt;
|
||||
|
||||
|
|
@ -24,9 +23,8 @@ impl Indent {
|
|||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<E> AsyncWidget<E> for Indent {
|
||||
async fn size(
|
||||
impl<E> Widget<E> for Indent {
|
||||
fn size(
|
||||
&self,
|
||||
_widthdb: &mut WidthDb,
|
||||
_max_width: Option<u16>,
|
||||
|
|
@ -36,7 +34,7 @@ impl<E> AsyncWidget<E> for Indent {
|
|||
Ok(Size::new(width, 0))
|
||||
}
|
||||
|
||||
async fn draw(self, frame: &mut Frame) -> Result<(), E> {
|
||||
fn draw(self, frame: &mut Frame) -> Result<(), E> {
|
||||
let size = frame.size();
|
||||
let indent_string = INDENT_STR.repeat(self.level);
|
||||
|
||||
|
|
@ -51,7 +49,7 @@ impl<E> AsyncWidget<E> for Indent {
|
|||
const TIME_FORMAT: &[FormatItem<'_>] = format_description!("[year]-[month]-[day] [hour]:[minute]");
|
||||
const TIME_WIDTH: u16 = 16;
|
||||
|
||||
pub struct Time(BoxedAsync<'static, Infallible>);
|
||||
pub struct Time(Boxed<'static, Infallible>);
|
||||
|
||||
impl Time {
|
||||
pub fn new(time: Option<OffsetDateTime>, style: Style) -> Self {
|
||||
|
|
@ -60,70 +58,60 @@ impl Time {
|
|||
Text::new((text, style))
|
||||
.background()
|
||||
.with_style(style)
|
||||
.boxed_async()
|
||||
.boxed()
|
||||
} else {
|
||||
Empty::new()
|
||||
.with_width(TIME_WIDTH)
|
||||
.background()
|
||||
.with_style(style)
|
||||
.boxed_async()
|
||||
.boxed()
|
||||
};
|
||||
Self(widget)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<E> AsyncWidget<E> for Time {
|
||||
async fn size(
|
||||
impl<E> Widget<E> for Time {
|
||||
fn size(
|
||||
&self,
|
||||
widthdb: &mut WidthDb,
|
||||
max_width: Option<u16>,
|
||||
max_height: Option<u16>,
|
||||
) -> Result<Size, E> {
|
||||
Ok(self
|
||||
.0
|
||||
.size(widthdb, max_width, max_height)
|
||||
.await
|
||||
.infallible())
|
||||
Ok(self.0.size(widthdb, max_width, max_height).infallible())
|
||||
}
|
||||
|
||||
async fn draw(self, frame: &mut Frame) -> Result<(), E> {
|
||||
self.0.draw(frame).await.infallible();
|
||||
fn draw(self, frame: &mut Frame) -> Result<(), E> {
|
||||
self.0.draw(frame).infallible();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Seen(BoxedAsync<'static, Infallible>);
|
||||
pub struct Seen(Boxed<'static, Infallible>);
|
||||
|
||||
impl Seen {
|
||||
pub fn new(seen: bool) -> Self {
|
||||
let widget = if seen {
|
||||
Empty::new().with_width(1).boxed_async()
|
||||
Empty::new().with_width(1).boxed()
|
||||
} else {
|
||||
let style = Style::new().black().on_green();
|
||||
Text::new("*").background().with_style(style).boxed_async()
|
||||
Text::new("*").background().with_style(style).boxed()
|
||||
};
|
||||
Self(widget)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<E> AsyncWidget<E> for Seen {
|
||||
async fn size(
|
||||
impl<E> Widget<E> for Seen {
|
||||
fn size(
|
||||
&self,
|
||||
widthdb: &mut WidthDb,
|
||||
max_width: Option<u16>,
|
||||
max_height: Option<u16>,
|
||||
) -> Result<Size, E> {
|
||||
Ok(self
|
||||
.0
|
||||
.size(widthdb, max_width, max_height)
|
||||
.await
|
||||
.infallible())
|
||||
Ok(self.0.size(widthdb, max_width, max_height).infallible())
|
||||
}
|
||||
|
||||
async fn draw(self, frame: &mut Frame) -> Result<(), E> {
|
||||
self.0.draw(frame).await.infallible();
|
||||
fn draw(self, frame: &mut Frame) -> Result<(), E> {
|
||||
self.0.draw(frame).infallible();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue