Render editor and pseudo message
This commit is contained in:
parent
4ead592e59
commit
415da3afd8
6 changed files with 132 additions and 42 deletions
|
|
@ -184,7 +184,7 @@ impl Ui {
|
||||||
async fn widget(&mut self) -> BoxedWidget {
|
async fn widget(&mut self) -> BoxedWidget {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
Mode::Main => self.rooms.widget().await,
|
Mode::Main => self.rooms.widget().await,
|
||||||
Mode::Log => self.log_chat.widget().into(),
|
Mode::Log => self.log_chat.widget(String::new()).into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,9 +61,9 @@ impl<M: Msg, S: MsgStore<M>> ChatState<M, S> {
|
||||||
&self.store
|
&self.store
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn widget(&self) -> Chat<M, S> {
|
pub fn widget(&self, nick: String) -> Chat<M, S> {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
Mode::Tree => Chat::Tree(self.tree.widget()),
|
Mode::Tree => Chat::Tree(self.tree.widget(nick)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,8 +88,11 @@ impl<M: Msg, S: MsgStore<M>> TreeViewState<M, S> {
|
||||||
Self(Arc::new(Mutex::new(InnerTreeViewState::new(store))))
|
Self(Arc::new(Mutex::new(InnerTreeViewState::new(store))))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn widget(&self) -> TreeView<M, S> {
|
pub fn widget(&self, nick: String) -> TreeView<M, S> {
|
||||||
TreeView(self.0.clone())
|
TreeView {
|
||||||
|
inner: self.0.clone(),
|
||||||
|
nick,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_navigation(&mut self, event: KeyEvent) -> bool {
|
pub async fn handle_navigation(&mut self, event: KeyEvent) -> bool {
|
||||||
|
|
@ -114,7 +117,10 @@ impl<M: Msg, S: MsgStore<M>> TreeViewState<M, S> {
|
||||||
// Widget //
|
// Widget //
|
||||||
////////////
|
////////////
|
||||||
|
|
||||||
pub struct TreeView<M: Msg, S: MsgStore<M>>(Arc<Mutex<InnerTreeViewState<M, S>>>);
|
pub struct TreeView<M: Msg, S: MsgStore<M>> {
|
||||||
|
inner: Arc<Mutex<InnerTreeViewState<M, S>>>,
|
||||||
|
nick: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<M, S> Widget for TreeView<M, S>
|
impl<M, S> Widget for TreeView<M, S>
|
||||||
|
|
@ -128,8 +134,8 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn render(self: Box<Self>, frame: &mut Frame) {
|
async fn render(self: Box<Self>, frame: &mut Frame) {
|
||||||
let mut guard = self.0.lock().await;
|
let mut guard = self.inner.lock().await;
|
||||||
let blocks = guard.relayout(frame).await;
|
let blocks = guard.relayout(&self.nick, frame).await;
|
||||||
|
|
||||||
let size = frame.size();
|
let size = frame.size();
|
||||||
for block in blocks.into_blocks().blocks {
|
for block in blocks.into_blocks().blocks {
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,20 @@ impl<M: Msg + ChatMsg, S: MsgStore<M>> InnerTreeViewState<M, S> {
|
||||||
.is_some()
|
.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn editor_block(&self, nick: &str, frame: &mut Frame, indent: usize) -> Block<BlockId<M::Id>> {
|
||||||
|
let (widget, cursor_line) = widgets::editor::<M>(frame, indent, nick, &self.editor);
|
||||||
|
let cursor_line = cursor_line as i32;
|
||||||
|
Block::new(frame, BlockId::Cursor, widget).focus(cursor_line..cursor_line + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pseudo_block(&self, nick: &str, frame: &mut Frame, indent: usize) -> Block<BlockId<M::Id>> {
|
||||||
|
let widget = widgets::pseudo::<M>(indent, nick, &self.editor);
|
||||||
|
Block::new(frame, BlockId::Cursor, widget)
|
||||||
|
}
|
||||||
|
|
||||||
fn layout_subtree(
|
fn layout_subtree(
|
||||||
&self,
|
&self,
|
||||||
|
nick: &str,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
tree: &Tree<M>,
|
tree: &Tree<M>,
|
||||||
indent: usize,
|
indent: usize,
|
||||||
|
|
@ -78,7 +90,7 @@ impl<M: Msg + ChatMsg, S: MsgStore<M>> InnerTreeViewState<M, S> {
|
||||||
// Children, recursively
|
// Children, recursively
|
||||||
if let Some(children) = tree.children(id) {
|
if let Some(children) = tree.children(id) {
|
||||||
for child in children {
|
for child in children {
|
||||||
self.layout_subtree(frame, tree, indent + 1, child, blocks);
|
self.layout_subtree(nick, frame, tree, indent + 1, child, blocks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,20 +102,29 @@ impl<M: Msg + ChatMsg, S: MsgStore<M>> InnerTreeViewState<M, S> {
|
||||||
|
|
||||||
// Trailing editor or pseudomessage
|
// Trailing editor or pseudomessage
|
||||||
if self.cursor.refers_to_last_child_of(id) {
|
if self.cursor.refers_to_last_child_of(id) {
|
||||||
|
match self.cursor {
|
||||||
|
Cursor::Editor { .. } => blocks
|
||||||
|
.blocks_mut()
|
||||||
|
.push_back(self.editor_block(nick, frame, indent)),
|
||||||
|
Cursor::Pseudo { .. } => blocks
|
||||||
|
.blocks_mut()
|
||||||
|
.push_back(self.pseudo_block(nick, frame, indent)),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
// TODO Render proper editor or pseudocursor
|
// TODO Render proper editor or pseudocursor
|
||||||
let block = Block::new(frame, BlockId::Cursor, Text::new("TODO"));
|
let block = Block::new(frame, BlockId::Cursor, Text::new("TODO"));
|
||||||
blocks.blocks_mut().push_back(block);
|
blocks.blocks_mut().push_back(block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout_tree(&self, frame: &mut Frame, tree: Tree<M>) -> TreeBlocks<M::Id> {
|
fn layout_tree(&self, nick: &str, frame: &mut Frame, tree: Tree<M>) -> TreeBlocks<M::Id> {
|
||||||
let root = Root::Tree(tree.root().clone());
|
let root = Root::Tree(tree.root().clone());
|
||||||
let mut blocks = TreeBlocks::new(root.clone(), root);
|
let mut blocks = TreeBlocks::new(root.clone(), root);
|
||||||
self.layout_subtree(frame, &tree, 0, tree.root(), &mut blocks);
|
self.layout_subtree(nick, frame, &tree, 0, tree.root(), &mut blocks);
|
||||||
blocks
|
blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout_bottom(&self, frame: &mut Frame) -> TreeBlocks<M::Id> {
|
fn layout_bottom(&self, nick: &str, frame: &mut Frame) -> TreeBlocks<M::Id> {
|
||||||
let mut blocks = TreeBlocks::new(Root::Bottom, Root::Bottom);
|
let mut blocks = TreeBlocks::new(Root::Bottom, Root::Bottom);
|
||||||
|
|
||||||
// Ghost cursor, for positioning according to last cursor line
|
// Ghost cursor, for positioning according to last cursor line
|
||||||
|
|
@ -119,18 +140,19 @@ impl<M: Msg + ChatMsg, S: MsgStore<M>> InnerTreeViewState<M, S> {
|
||||||
let block = Block::new(frame, BlockId::Cursor, Empty);
|
let block = Block::new(frame, BlockId::Cursor, Empty);
|
||||||
blocks.blocks_mut().push_back(block);
|
blocks.blocks_mut().push_back(block);
|
||||||
}
|
}
|
||||||
Cursor::Editor { parent: None, .. } | Cursor::Pseudo { parent: None, .. } => {
|
Cursor::Editor { parent: None, .. } => blocks
|
||||||
// TODO Render proper editor or pseudocursor
|
.blocks_mut()
|
||||||
let block = Block::new(frame, BlockId::Cursor, Text::new("TODO"));
|
.push_back(self.editor_block(nick, frame, 0)),
|
||||||
blocks.blocks_mut().push_back(block);
|
Cursor::Pseudo { parent: None, .. } => blocks
|
||||||
}
|
.blocks_mut()
|
||||||
|
.push_back(self.pseudo_block(nick, frame, 0)),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
blocks
|
blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn expand_to_top(&self, frame: &mut Frame, blocks: &mut TreeBlocks<M::Id>) {
|
async fn expand_to_top(&self, nick: &str, frame: &mut Frame, blocks: &mut TreeBlocks<M::Id>) {
|
||||||
let top_line = 0;
|
let top_line = 0;
|
||||||
|
|
||||||
while blocks.blocks().top_line > top_line {
|
while blocks.blocks().top_line > top_line {
|
||||||
|
|
@ -144,11 +166,16 @@ impl<M: Msg + ChatMsg, S: MsgStore<M>> InnerTreeViewState<M, S> {
|
||||||
None => break,
|
None => break,
|
||||||
};
|
};
|
||||||
let prev_tree = self.store.tree(&prev_tree_id).await;
|
let prev_tree = self.store.tree(&prev_tree_id).await;
|
||||||
blocks.prepend(self.layout_tree(frame, prev_tree));
|
blocks.prepend(self.layout_tree(nick, frame, prev_tree));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn expand_to_bottom(&self, frame: &mut Frame, blocks: &mut TreeBlocks<M::Id>) {
|
async fn expand_to_bottom(
|
||||||
|
&self,
|
||||||
|
nick: &str,
|
||||||
|
frame: &mut Frame,
|
||||||
|
blocks: &mut TreeBlocks<M::Id>,
|
||||||
|
) {
|
||||||
let bottom_line = frame.size().height as i32 - 1;
|
let bottom_line = frame.size().height as i32 - 1;
|
||||||
|
|
||||||
while blocks.blocks().bottom_line < bottom_line {
|
while blocks.blocks().bottom_line < bottom_line {
|
||||||
|
|
@ -159,44 +186,46 @@ impl<M: Msg + ChatMsg, S: MsgStore<M>> InnerTreeViewState<M, S> {
|
||||||
};
|
};
|
||||||
if let Some(next_tree_id) = next_tree_id {
|
if let Some(next_tree_id) = next_tree_id {
|
||||||
let next_tree = self.store.tree(&next_tree_id).await;
|
let next_tree = self.store.tree(&next_tree_id).await;
|
||||||
blocks.append(self.layout_tree(frame, next_tree));
|
blocks.append(self.layout_tree(nick, frame, next_tree));
|
||||||
} else {
|
} else {
|
||||||
blocks.append(self.layout_bottom(frame));
|
blocks.append(self.layout_bottom(nick, frame));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fill_screen_and_clamp_scrolling(
|
async fn fill_screen_and_clamp_scrolling(
|
||||||
&self,
|
&self,
|
||||||
|
nick: &str,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
blocks: &mut TreeBlocks<M::Id>,
|
blocks: &mut TreeBlocks<M::Id>,
|
||||||
) {
|
) {
|
||||||
let top_line = 0;
|
let top_line = 0;
|
||||||
let bottom_line = frame.size().height as i32 - 1;
|
let bottom_line = frame.size().height as i32 - 1;
|
||||||
|
|
||||||
self.expand_to_top(frame, blocks).await;
|
self.expand_to_top(nick, frame, blocks).await;
|
||||||
|
|
||||||
if blocks.blocks().top_line > top_line {
|
if blocks.blocks().top_line > top_line {
|
||||||
blocks.blocks_mut().set_top_line(0);
|
blocks.blocks_mut().set_top_line(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.expand_to_bottom(frame, blocks).await;
|
self.expand_to_bottom(nick, frame, blocks).await;
|
||||||
|
|
||||||
if blocks.blocks().bottom_line < bottom_line {
|
if blocks.blocks().bottom_line < bottom_line {
|
||||||
blocks.blocks_mut().set_bottom_line(bottom_line);
|
blocks.blocks_mut().set_bottom_line(bottom_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.expand_to_top(frame, blocks).await;
|
self.expand_to_top(nick, frame, blocks).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn layout_last_cursor_seed(
|
async fn layout_last_cursor_seed(
|
||||||
&self,
|
&self,
|
||||||
|
nick: &str,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
last_cursor_path: &Path<M::Id>,
|
last_cursor_path: &Path<M::Id>,
|
||||||
) -> TreeBlocks<M::Id> {
|
) -> TreeBlocks<M::Id> {
|
||||||
match &self.last_cursor {
|
match &self.last_cursor {
|
||||||
Cursor::Bottom => {
|
Cursor::Bottom => {
|
||||||
let mut blocks = self.layout_bottom(frame);
|
let mut blocks = self.layout_bottom(nick, frame);
|
||||||
|
|
||||||
let bottom_line = frame.size().height as i32 - 1;
|
let bottom_line = frame.size().height as i32 - 1;
|
||||||
blocks.blocks_mut().set_bottom_line(bottom_line);
|
blocks.blocks_mut().set_bottom_line(bottom_line);
|
||||||
|
|
@ -204,7 +233,7 @@ impl<M: Msg + ChatMsg, S: MsgStore<M>> InnerTreeViewState<M, S> {
|
||||||
blocks
|
blocks
|
||||||
}
|
}
|
||||||
Cursor::Editor { parent: None, .. } | Cursor::Pseudo { parent: None, .. } => {
|
Cursor::Editor { parent: None, .. } | Cursor::Pseudo { parent: None, .. } => {
|
||||||
let mut blocks = self.layout_bottom(frame);
|
let mut blocks = self.layout_bottom(nick, frame);
|
||||||
|
|
||||||
blocks
|
blocks
|
||||||
.blocks_mut()
|
.blocks_mut()
|
||||||
|
|
@ -221,7 +250,7 @@ impl<M: Msg + ChatMsg, S: MsgStore<M>> InnerTreeViewState<M, S> {
|
||||||
} => {
|
} => {
|
||||||
let root = last_cursor_path.first();
|
let root = last_cursor_path.first();
|
||||||
let tree = self.store.tree(root).await;
|
let tree = self.store.tree(root).await;
|
||||||
let mut blocks = self.layout_tree(frame, tree);
|
let mut blocks = self.layout_tree(nick, frame, tree);
|
||||||
|
|
||||||
blocks
|
blocks
|
||||||
.blocks_mut()
|
.blocks_mut()
|
||||||
|
|
@ -234,6 +263,7 @@ impl<M: Msg + ChatMsg, S: MsgStore<M>> InnerTreeViewState<M, S> {
|
||||||
|
|
||||||
async fn layout_cursor_seed(
|
async fn layout_cursor_seed(
|
||||||
&self,
|
&self,
|
||||||
|
nick: &str,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
last_cursor_path: &Path<M::Id>,
|
last_cursor_path: &Path<M::Id>,
|
||||||
cursor_path: &Path<M::Id>,
|
cursor_path: &Path<M::Id>,
|
||||||
|
|
@ -244,7 +274,7 @@ impl<M: Msg + ChatMsg, S: MsgStore<M>> InnerTreeViewState<M, S> {
|
||||||
Cursor::Bottom
|
Cursor::Bottom
|
||||||
| Cursor::Editor { parent: None, .. }
|
| Cursor::Editor { parent: None, .. }
|
||||||
| Cursor::Pseudo { parent: None, .. } => {
|
| Cursor::Pseudo { parent: None, .. } => {
|
||||||
let mut blocks = self.layout_bottom(frame);
|
let mut blocks = self.layout_bottom(nick, frame);
|
||||||
|
|
||||||
blocks.blocks_mut().set_bottom_line(bottom_line);
|
blocks.blocks_mut().set_bottom_line(bottom_line);
|
||||||
|
|
||||||
|
|
@ -259,7 +289,7 @@ impl<M: Msg + ChatMsg, S: MsgStore<M>> InnerTreeViewState<M, S> {
|
||||||
} => {
|
} => {
|
||||||
let root = cursor_path.first();
|
let root = cursor_path.first();
|
||||||
let tree = self.store.tree(root).await;
|
let tree = self.store.tree(root).await;
|
||||||
let mut blocks = self.layout_tree(frame, tree);
|
let mut blocks = self.layout_tree(nick, frame, tree);
|
||||||
|
|
||||||
let cursor_above_last = cursor_path < last_cursor_path;
|
let cursor_above_last = cursor_path < last_cursor_path;
|
||||||
let cursor_line = if cursor_above_last { 0 } else { bottom_line };
|
let cursor_line = if cursor_above_last { 0 } else { bottom_line };
|
||||||
|
|
@ -274,15 +304,17 @@ impl<M: Msg + ChatMsg, S: MsgStore<M>> InnerTreeViewState<M, S> {
|
||||||
|
|
||||||
async fn layout_initial_seed(
|
async fn layout_initial_seed(
|
||||||
&self,
|
&self,
|
||||||
|
nick: &str,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
last_cursor_path: &Path<M::Id>,
|
last_cursor_path: &Path<M::Id>,
|
||||||
cursor_path: &Path<M::Id>,
|
cursor_path: &Path<M::Id>,
|
||||||
) -> TreeBlocks<M::Id> {
|
) -> TreeBlocks<M::Id> {
|
||||||
if let Cursor::Bottom = self.cursor {
|
if let Cursor::Bottom = self.cursor {
|
||||||
self.layout_cursor_seed(frame, last_cursor_path, cursor_path)
|
self.layout_cursor_seed(nick, frame, last_cursor_path, cursor_path)
|
||||||
.await
|
.await
|
||||||
} else {
|
} else {
|
||||||
self.layout_last_cursor_seed(frame, last_cursor_path).await
|
self.layout_last_cursor_seed(nick, frame, last_cursor_path)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -377,7 +409,7 @@ impl<M: Msg + ChatMsg, S: MsgStore<M>> InnerTreeViewState<M, S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn relayout(&mut self, frame: &mut Frame) -> TreeBlocks<M::Id> {
|
pub async fn relayout(&mut self, nick: &str, frame: &mut Frame) -> TreeBlocks<M::Id> {
|
||||||
// The basic idea is this:
|
// The basic idea is this:
|
||||||
//
|
//
|
||||||
// First, layout a full screen of blocks around self.last_cursor, using
|
// First, layout a full screen of blocks around self.last_cursor, using
|
||||||
|
|
@ -400,24 +432,24 @@ impl<M: Msg + ChatMsg, S: MsgStore<M>> InnerTreeViewState<M, S> {
|
||||||
let cursor_path = self.cursor_path(&self.cursor).await;
|
let cursor_path = self.cursor_path(&self.cursor).await;
|
||||||
|
|
||||||
let mut blocks = self
|
let mut blocks = self
|
||||||
.layout_initial_seed(frame, &last_cursor_path, &cursor_path)
|
.layout_initial_seed(nick, frame, &last_cursor_path, &cursor_path)
|
||||||
.await;
|
.await;
|
||||||
blocks.blocks_mut().offset(self.scroll);
|
blocks.blocks_mut().offset(self.scroll);
|
||||||
self.fill_screen_and_clamp_scrolling(frame, &mut blocks)
|
self.fill_screen_and_clamp_scrolling(nick, frame, &mut blocks)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
if !self.contains_cursor(&blocks) {
|
if !self.contains_cursor(&blocks) {
|
||||||
blocks = self
|
blocks = self
|
||||||
.layout_cursor_seed(frame, &last_cursor_path, &cursor_path)
|
.layout_cursor_seed(nick, frame, &last_cursor_path, &cursor_path)
|
||||||
.await;
|
.await;
|
||||||
self.fill_screen_and_clamp_scrolling(frame, &mut blocks)
|
self.fill_screen_and_clamp_scrolling(nick, frame, &mut blocks)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.correction {
|
match self.correction {
|
||||||
Some(Correction::MakeCursorVisible) => {
|
Some(Correction::MakeCursorVisible) => {
|
||||||
self.scroll_so_cursor_is_visible(frame, &mut blocks);
|
self.scroll_so_cursor_is_visible(frame, &mut blocks);
|
||||||
self.fill_screen_and_clamp_scrolling(frame, &mut blocks)
|
self.fill_screen_and_clamp_scrolling(nick, frame, &mut blocks)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
Some(Correction::MoveCursorToVisibleArea) => {
|
Some(Correction::MoveCursorToVisibleArea) => {
|
||||||
|
|
@ -433,8 +465,10 @@ impl<M: Msg + ChatMsg, S: MsgStore<M>> InnerTreeViewState<M, S> {
|
||||||
self.correction = None;
|
self.correction = None;
|
||||||
|
|
||||||
let last_cursor_path = self.store.path(&cursor_msg_id).await;
|
let last_cursor_path = self.store.path(&cursor_msg_id).await;
|
||||||
blocks = self.layout_last_cursor_seed(frame, &last_cursor_path).await;
|
blocks = self
|
||||||
self.fill_screen_and_clamp_scrolling(frame, &mut blocks)
|
.layout_last_cursor_seed(nick, frame, &last_cursor_path)
|
||||||
|
.await;
|
||||||
|
self.fill_screen_and_clamp_scrolling(nick, frame, &mut blocks)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,11 @@ mod indent;
|
||||||
mod time;
|
mod time;
|
||||||
|
|
||||||
use crossterm::style::{ContentStyle, Stylize};
|
use crossterm::style::{ContentStyle, Stylize};
|
||||||
|
use toss::frame::Frame;
|
||||||
|
|
||||||
use super::super::ChatMsg;
|
use super::super::ChatMsg;
|
||||||
use crate::store::Msg;
|
use crate::store::Msg;
|
||||||
|
use crate::ui::widgets::editor::EditorState;
|
||||||
use crate::ui::widgets::join::{HJoin, Segment};
|
use crate::ui::widgets::join::{HJoin, Segment};
|
||||||
use crate::ui::widgets::layer::Layer;
|
use crate::ui::widgets::layer::Layer;
|
||||||
use crate::ui::widgets::padding::Padding;
|
use crate::ui::widgets::padding::Padding;
|
||||||
|
|
@ -53,3 +55,50 @@ pub fn msg_placeholder(highlighted: bool, indent: usize) -> BoxedWidget {
|
||||||
])
|
])
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn editor<M: ChatMsg>(
|
||||||
|
frame: &mut Frame,
|
||||||
|
indent: usize,
|
||||||
|
nick: &str,
|
||||||
|
editor: &EditorState,
|
||||||
|
) -> (BoxedWidget, usize) {
|
||||||
|
let (nick, content) = M::edit(nick, &editor.text());
|
||||||
|
let editor = editor.widget().highlight(|_| content);
|
||||||
|
let cursor_row = editor.cursor_row(frame);
|
||||||
|
|
||||||
|
let widget = HJoin::new(vec![
|
||||||
|
Segment::new(
|
||||||
|
Padding::new(time::widget(None, true))
|
||||||
|
.stretch(true)
|
||||||
|
.right(1),
|
||||||
|
),
|
||||||
|
Segment::new(Indent::new(indent, true)),
|
||||||
|
Segment::new(Layer::new(vec![
|
||||||
|
Indent::new(1, false).into(),
|
||||||
|
Padding::new(Text::new(nick)).right(1).into(),
|
||||||
|
])),
|
||||||
|
Segment::new(editor).priority(1),
|
||||||
|
])
|
||||||
|
.into();
|
||||||
|
|
||||||
|
(widget, cursor_row)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pseudo<M: ChatMsg>(indent: usize, nick: &str, editor: &EditorState) -> BoxedWidget {
|
||||||
|
let (nick, content) = M::edit(nick, &editor.text());
|
||||||
|
|
||||||
|
HJoin::new(vec![
|
||||||
|
Segment::new(
|
||||||
|
Padding::new(time::widget(None, true))
|
||||||
|
.stretch(true)
|
||||||
|
.right(1),
|
||||||
|
),
|
||||||
|
Segment::new(Indent::new(indent, true)),
|
||||||
|
Segment::new(Layer::new(vec![
|
||||||
|
Indent::new(1, false).into(),
|
||||||
|
Padding::new(Text::new(nick)).right(1).into(),
|
||||||
|
])),
|
||||||
|
Segment::new(Text::new(content).wrap(true)).priority(1),
|
||||||
|
])
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,8 @@ impl EuphRoom {
|
||||||
Segment::new(Border::new(
|
Segment::new(Border::new(
|
||||||
Padding::new(self.status_widget(status)).horizontal(1),
|
Padding::new(self.status_widget(status)).horizontal(1),
|
||||||
)),
|
)),
|
||||||
Segment::new(self.chat.widget()).expanding(true),
|
// TODO Use last known nick?
|
||||||
|
Segment::new(self.chat.widget(String::new())).expanding(true),
|
||||||
])
|
])
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
@ -133,7 +134,7 @@ impl EuphRoom {
|
||||||
Segment::new(Border::new(
|
Segment::new(Border::new(
|
||||||
Padding::new(self.status_widget(status)).horizontal(1),
|
Padding::new(self.status_widget(status)).horizontal(1),
|
||||||
)),
|
)),
|
||||||
Segment::new(self.chat.widget()).expanding(true),
|
Segment::new(self.chat.widget(joined.session.name.clone())).expanding(true),
|
||||||
]))
|
]))
|
||||||
.expanding(true),
|
.expanding(true),
|
||||||
Segment::new(Border::new(
|
Segment::new(Border::new(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue