Make store room-specific
This commit is contained in:
parent
15213f8003
commit
23c551a5b7
7 changed files with 85 additions and 173 deletions
|
|
@ -32,7 +32,6 @@ impl<I> Cursor<I> {
|
||||||
|
|
||||||
pub struct Chat<M: Msg, S: MsgStore<M>> {
|
pub struct Chat<M: Msg, S: MsgStore<M>> {
|
||||||
store: S,
|
store: S,
|
||||||
room: String,
|
|
||||||
cursor: Option<Cursor<M::Id>>,
|
cursor: Option<Cursor<M::Id>>,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
tree: TreeView<M>,
|
tree: TreeView<M>,
|
||||||
|
|
@ -41,10 +40,9 @@ pub struct Chat<M: Msg, S: MsgStore<M>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M: Msg, S: MsgStore<M>> Chat<M, S> {
|
impl<M: Msg, S: MsgStore<M>> Chat<M, S> {
|
||||||
pub fn new(store: S, room: String) -> Self {
|
pub fn new(store: S) -> Self {
|
||||||
Self {
|
Self {
|
||||||
store,
|
store,
|
||||||
room,
|
|
||||||
cursor: None,
|
cursor: None,
|
||||||
mode: Mode::Tree,
|
mode: Mode::Tree,
|
||||||
tree: TreeView::new(),
|
tree: TreeView::new(),
|
||||||
|
|
@ -57,14 +55,7 @@ impl<M: Msg, S: MsgStore<M>> Chat<M, S> {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
Mode::Tree => {
|
Mode::Tree => {
|
||||||
self.tree
|
self.tree
|
||||||
.handle_key_event(
|
.handle_key_event(&mut self.store, &mut self.cursor, frame, size, event)
|
||||||
&self.room,
|
|
||||||
&mut self.store,
|
|
||||||
&mut self.cursor,
|
|
||||||
frame,
|
|
||||||
size,
|
|
||||||
event,
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -74,7 +65,7 @@ impl<M: Msg, S: MsgStore<M>> Chat<M, S> {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
Mode::Tree => {
|
Mode::Tree => {
|
||||||
self.tree
|
self.tree
|
||||||
.render(&self.room, &mut self.store, &self.cursor, frame, pos, size)
|
.render(&mut self.store, &self.cursor, frame, pos, size)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ impl<M: Msg> TreeView<M> {
|
||||||
|
|
||||||
pub async fn handle_key_event<S: MsgStore<M>>(
|
pub async fn handle_key_event<S: MsgStore<M>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
r: &str,
|
|
||||||
s: &mut S,
|
s: &mut S,
|
||||||
c: &mut Option<Cursor<M::Id>>,
|
c: &mut Option<Cursor<M::Id>>,
|
||||||
f: &mut Frame,
|
f: &mut Frame,
|
||||||
|
|
@ -37,13 +36,13 @@ impl<M: Msg> TreeView<M> {
|
||||||
event: KeyEvent,
|
event: KeyEvent,
|
||||||
) {
|
) {
|
||||||
match event.code {
|
match event.code {
|
||||||
KeyCode::Char('z') | KeyCode::Char('Z') => self.center_cursor(r, s, c, f, z).await,
|
KeyCode::Char('z') | KeyCode::Char('Z') => self.center_cursor(s, c, f, z).await,
|
||||||
KeyCode::Char('k') => self.move_up(r, s, c, f, z).await,
|
KeyCode::Char('k') => self.move_up(s, c, f, z).await,
|
||||||
KeyCode::Char('j') => self.move_down(r, s, c, f, z).await,
|
KeyCode::Char('j') => self.move_down(s, c, f, z).await,
|
||||||
KeyCode::Char('K') => self.move_up_sibling(r, s, c, f, z).await,
|
KeyCode::Char('K') => self.move_up_sibling(s, c, f, z).await,
|
||||||
KeyCode::Char('J') => self.move_down_sibling(r, s, c, f, z).await,
|
KeyCode::Char('J') => self.move_down_sibling(s, c, f, z).await,
|
||||||
KeyCode::Char('g') => self.move_to_first(r, s, c, f, z).await,
|
KeyCode::Char('g') => self.move_to_first(s, c, f, z).await,
|
||||||
KeyCode::Char('G') => self.move_to_last(r, s, c, f, z).await,
|
KeyCode::Char('G') => self.move_to_last(s, c, f, z).await,
|
||||||
KeyCode::Esc => *c = None, // TODO Make 'G' do the same thing?
|
KeyCode::Esc => *c = None, // TODO Make 'G' do the same thing?
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
@ -51,7 +50,6 @@ impl<M: Msg> TreeView<M> {
|
||||||
|
|
||||||
pub async fn render<S: MsgStore<M>>(
|
pub async fn render<S: MsgStore<M>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
room: &str,
|
|
||||||
store: &mut S,
|
store: &mut S,
|
||||||
cursor: &Option<Cursor<M::Id>>,
|
cursor: &Option<Cursor<M::Id>>,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
|
|
@ -59,7 +57,7 @@ impl<M: Msg> TreeView<M> {
|
||||||
size: Size,
|
size: Size,
|
||||||
) {
|
) {
|
||||||
let blocks = self
|
let blocks = self
|
||||||
.layout_blocks(room, store, cursor.as_ref(), frame, size)
|
.layout_blocks(store, cursor.as_ref(), frame, size)
|
||||||
.await;
|
.await;
|
||||||
Self::render_blocks(frame, pos, size, &blocks);
|
Self::render_blocks(frame, pos, size, &blocks);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ impl<M: Msg> TreeView<M> {
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
async fn correct_cursor_offset<S: MsgStore<M>>(
|
async fn correct_cursor_offset<S: MsgStore<M>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
room: &str,
|
|
||||||
store: &S,
|
store: &S,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
size: Size,
|
size: Size,
|
||||||
|
|
@ -28,8 +27,8 @@ impl<M: Msg> TreeView<M> {
|
||||||
// The cursor is not visible any more. However, we can estimate
|
// The cursor is not visible any more. However, we can estimate
|
||||||
// whether it is above or below the previous cursor position by
|
// whether it is above or below the previous cursor position by
|
||||||
// lexicographically comparing both positions' paths.
|
// lexicographically comparing both positions' paths.
|
||||||
let old_path = store.path(room, old_cursor_id).await;
|
let old_path = store.path(old_cursor_id).await;
|
||||||
let new_path = store.path(room, &cursor.id).await;
|
let new_path = store.path(&cursor.id).await;
|
||||||
if new_path < old_path {
|
if new_path < old_path {
|
||||||
// Because we moved upwards, the cursor should appear at the top
|
// Because we moved upwards, the cursor should appear at the top
|
||||||
// of the screen.
|
// of the screen.
|
||||||
|
|
@ -49,9 +48,7 @@ impl<M: Msg> TreeView<M> {
|
||||||
// isn't, we need to scroll the screen such that the cursor becomes fully
|
// isn't, we need to scroll the screen such that the cursor becomes fully
|
||||||
// visible again. To do this, we'll need to re-layout because the cursor
|
// visible again. To do this, we'll need to re-layout because the cursor
|
||||||
// could've moved anywhere.
|
// could've moved anywhere.
|
||||||
let blocks = self
|
let blocks = self.layout_blocks(store, Some(cursor), frame, size).await;
|
||||||
.layout_blocks(room, store, Some(cursor), frame, size)
|
|
||||||
.await;
|
|
||||||
let cursor_block = blocks.find(&cursor.id).expect("cursor must be in blocks");
|
let cursor_block = blocks.find(&cursor.id).expect("cursor must be in blocks");
|
||||||
// First, ensure the cursor's last line is not below the bottom of the
|
// First, ensure the cursor's last line is not below the bottom of the
|
||||||
// screen. Then, ensure its top line is not above the top of the screen.
|
// screen. Then, ensure its top line is not above the top of the screen.
|
||||||
|
|
@ -102,7 +99,6 @@ impl<M: Msg> TreeView<M> {
|
||||||
/// Always stays at the same level of indentation.
|
/// Always stays at the same level of indentation.
|
||||||
async fn find_prev_sibling<S: MsgStore<M>>(
|
async fn find_prev_sibling<S: MsgStore<M>>(
|
||||||
&self,
|
&self,
|
||||||
room: &str,
|
|
||||||
store: &S,
|
store: &S,
|
||||||
tree: &mut Tree<M>,
|
tree: &mut Tree<M>,
|
||||||
id: &mut M::Id,
|
id: &mut M::Id,
|
||||||
|
|
@ -122,8 +118,8 @@ impl<M: Msg> TreeView<M> {
|
||||||
} else {
|
} else {
|
||||||
// We're at the root of our tree, so we need to move to the root of
|
// We're at the root of our tree, so we need to move to the root of
|
||||||
// the previous tree.
|
// the previous tree.
|
||||||
if let Some(prev_tree_id) = store.prev_tree(room, tree.root()).await {
|
if let Some(prev_tree_id) = store.prev_tree(tree.root()).await {
|
||||||
*tree = store.tree(room, &prev_tree_id).await;
|
*tree = store.tree(&prev_tree_id).await;
|
||||||
*id = prev_tree_id;
|
*id = prev_tree_id;
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -137,7 +133,6 @@ impl<M: Msg> TreeView<M> {
|
||||||
/// Always stays at the same level of indentation.
|
/// Always stays at the same level of indentation.
|
||||||
async fn find_next_sibling<S: MsgStore<M>>(
|
async fn find_next_sibling<S: MsgStore<M>>(
|
||||||
&self,
|
&self,
|
||||||
room: &str,
|
|
||||||
store: &S,
|
store: &S,
|
||||||
tree: &mut Tree<M>,
|
tree: &mut Tree<M>,
|
||||||
id: &mut M::Id,
|
id: &mut M::Id,
|
||||||
|
|
@ -157,8 +152,8 @@ impl<M: Msg> TreeView<M> {
|
||||||
} else {
|
} else {
|
||||||
// We're at the root of our tree, so we need to move to the root of
|
// We're at the root of our tree, so we need to move to the root of
|
||||||
// the next tree.
|
// the next tree.
|
||||||
if let Some(next_tree_id) = store.next_tree(room, tree.root()).await {
|
if let Some(next_tree_id) = store.next_tree(tree.root()).await {
|
||||||
*tree = store.tree(room, &next_tree_id).await;
|
*tree = store.tree(&next_tree_id).await;
|
||||||
*id = next_tree_id;
|
*id = next_tree_id;
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -170,14 +165,13 @@ impl<M: Msg> TreeView<M> {
|
||||||
/// Move to the previous message, or don't move if this is not possible.
|
/// Move to the previous message, or don't move if this is not possible.
|
||||||
async fn find_prev_msg<S: MsgStore<M>>(
|
async fn find_prev_msg<S: MsgStore<M>>(
|
||||||
&self,
|
&self,
|
||||||
room: &str,
|
|
||||||
store: &S,
|
store: &S,
|
||||||
tree: &mut Tree<M>,
|
tree: &mut Tree<M>,
|
||||||
id: &mut M::Id,
|
id: &mut M::Id,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
// Move to previous sibling, then to its last child
|
// Move to previous sibling, then to its last child
|
||||||
// If not possible, move to parent
|
// If not possible, move to parent
|
||||||
if self.find_prev_sibling(room, store, tree, id).await {
|
if self.find_prev_sibling(store, tree, id).await {
|
||||||
while Self::find_last_child(tree, id) {}
|
while Self::find_last_child(tree, id) {}
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -188,7 +182,6 @@ impl<M: Msg> TreeView<M> {
|
||||||
/// Move to the next message, or don't move if this is not possible.
|
/// Move to the next message, or don't move if this is not possible.
|
||||||
async fn find_next_msg<S: MsgStore<M>>(
|
async fn find_next_msg<S: MsgStore<M>>(
|
||||||
&self,
|
&self,
|
||||||
room: &str,
|
|
||||||
store: &S,
|
store: &S,
|
||||||
tree: &mut Tree<M>,
|
tree: &mut Tree<M>,
|
||||||
id: &mut M::Id,
|
id: &mut M::Id,
|
||||||
|
|
@ -197,7 +190,7 @@ impl<M: Msg> TreeView<M> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.find_next_sibling(room, store, tree, id).await {
|
if self.find_next_sibling(store, tree, id).await {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,7 +198,7 @@ impl<M: Msg> TreeView<M> {
|
||||||
// can be found.
|
// can be found.
|
||||||
let mut tmp_id = id.clone();
|
let mut tmp_id = id.clone();
|
||||||
while Self::find_parent(tree, &mut tmp_id) {
|
while Self::find_parent(tree, &mut tmp_id) {
|
||||||
if self.find_next_sibling(room, store, tree, &mut tmp_id).await {
|
if self.find_next_sibling(store, tree, &mut tmp_id).await {
|
||||||
*id = tmp_id;
|
*id = tmp_id;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -216,26 +209,24 @@ impl<M: Msg> TreeView<M> {
|
||||||
|
|
||||||
pub async fn move_up<S: MsgStore<M>>(
|
pub async fn move_up<S: MsgStore<M>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
room: &str,
|
|
||||||
store: &S,
|
store: &S,
|
||||||
cursor: &mut Option<Cursor<M::Id>>,
|
cursor: &mut Option<Cursor<M::Id>>,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
size: Size,
|
size: Size,
|
||||||
) {
|
) {
|
||||||
let old_blocks = self
|
let old_blocks = self
|
||||||
.layout_blocks(room, store, cursor.as_ref(), frame, size)
|
.layout_blocks(store, cursor.as_ref(), frame, size)
|
||||||
.await;
|
.await;
|
||||||
let old_cursor_id = cursor.as_ref().map(|c| c.id.clone());
|
let old_cursor_id = cursor.as_ref().map(|c| c.id.clone());
|
||||||
|
|
||||||
if let Some(cursor) = cursor {
|
if let Some(cursor) = cursor {
|
||||||
// We have a cursor to move around
|
// We have a cursor to move around
|
||||||
let path = store.path(room, &cursor.id).await;
|
let path = store.path(&cursor.id).await;
|
||||||
let mut tree = store.tree(room, path.first()).await;
|
let mut tree = store.tree(path.first()).await;
|
||||||
self.find_prev_msg(room, store, &mut tree, &mut cursor.id)
|
self.find_prev_msg(store, &mut tree, &mut cursor.id).await;
|
||||||
.await;
|
} else if let Some(last_tree) = store.last_tree().await {
|
||||||
} else if let Some(last_tree) = store.last_tree(room).await {
|
|
||||||
// We need to select the last message of the last tree
|
// We need to select the last message of the last tree
|
||||||
let tree = store.tree(room, &last_tree).await;
|
let tree = store.tree(&last_tree).await;
|
||||||
let mut id = last_tree;
|
let mut id = last_tree;
|
||||||
while Self::find_last_child(&tree, &mut id) {}
|
while Self::find_last_child(&tree, &mut id) {}
|
||||||
*cursor = Some(Cursor::new(id));
|
*cursor = Some(Cursor::new(id));
|
||||||
|
|
@ -244,74 +235,55 @@ impl<M: Msg> TreeView<M> {
|
||||||
// message to move to.
|
// message to move to.
|
||||||
|
|
||||||
if let Some(cursor) = cursor {
|
if let Some(cursor) = cursor {
|
||||||
self.correct_cursor_offset(
|
self.correct_cursor_offset(store, frame, size, &old_blocks, &old_cursor_id, cursor)
|
||||||
room,
|
|
||||||
store,
|
|
||||||
frame,
|
|
||||||
size,
|
|
||||||
&old_blocks,
|
|
||||||
&old_cursor_id,
|
|
||||||
cursor,
|
|
||||||
)
|
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn move_down<S: MsgStore<M>>(
|
pub async fn move_down<S: MsgStore<M>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
room: &str,
|
|
||||||
store: &S,
|
store: &S,
|
||||||
cursor: &mut Option<Cursor<M::Id>>,
|
cursor: &mut Option<Cursor<M::Id>>,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
size: Size,
|
size: Size,
|
||||||
) {
|
) {
|
||||||
let old_blocks = self
|
let old_blocks = self
|
||||||
.layout_blocks(room, store, cursor.as_ref(), frame, size)
|
.layout_blocks(store, cursor.as_ref(), frame, size)
|
||||||
.await;
|
.await;
|
||||||
let old_cursor_id = cursor.as_ref().map(|c| c.id.clone());
|
let old_cursor_id = cursor.as_ref().map(|c| c.id.clone());
|
||||||
|
|
||||||
if let Some(cursor) = cursor {
|
if let Some(cursor) = cursor {
|
||||||
let path = store.path(room, &cursor.id).await;
|
let path = store.path(&cursor.id).await;
|
||||||
let mut tree = store.tree(room, path.first()).await;
|
let mut tree = store.tree(path.first()).await;
|
||||||
self.find_next_msg(room, store, &mut tree, &mut cursor.id)
|
self.find_next_msg(store, &mut tree, &mut cursor.id).await;
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
// If that condition doesn't hold, we're already at the bottom in
|
// If that condition doesn't hold, we're already at the bottom in
|
||||||
// cursor-less mode and can't move further down anyways.
|
// cursor-less mode and can't move further down anyways.
|
||||||
|
|
||||||
if let Some(cursor) = cursor {
|
if let Some(cursor) = cursor {
|
||||||
self.correct_cursor_offset(
|
self.correct_cursor_offset(store, frame, size, &old_blocks, &old_cursor_id, cursor)
|
||||||
room,
|
|
||||||
store,
|
|
||||||
frame,
|
|
||||||
size,
|
|
||||||
&old_blocks,
|
|
||||||
&old_cursor_id,
|
|
||||||
cursor,
|
|
||||||
)
|
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn move_up_sibling<S: MsgStore<M>>(
|
pub async fn move_up_sibling<S: MsgStore<M>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
room: &str,
|
|
||||||
store: &S,
|
store: &S,
|
||||||
cursor: &mut Option<Cursor<M::Id>>,
|
cursor: &mut Option<Cursor<M::Id>>,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
size: Size,
|
size: Size,
|
||||||
) {
|
) {
|
||||||
let old_blocks = self
|
let old_blocks = self
|
||||||
.layout_blocks(room, store, cursor.as_ref(), frame, size)
|
.layout_blocks(store, cursor.as_ref(), frame, size)
|
||||||
.await;
|
.await;
|
||||||
let old_cursor_id = cursor.as_ref().map(|c| c.id.clone());
|
let old_cursor_id = cursor.as_ref().map(|c| c.id.clone());
|
||||||
|
|
||||||
if let Some(cursor) = cursor {
|
if let Some(cursor) = cursor {
|
||||||
let path = store.path(room, &cursor.id).await;
|
let path = store.path(&cursor.id).await;
|
||||||
let mut tree = store.tree(room, path.first()).await;
|
let mut tree = store.tree(path.first()).await;
|
||||||
self.find_prev_sibling(room, store, &mut tree, &mut cursor.id)
|
self.find_prev_sibling(store, &mut tree, &mut cursor.id)
|
||||||
.await;
|
.await;
|
||||||
} else if let Some(last_tree) = store.last_tree(room).await {
|
} else if let Some(last_tree) = store.last_tree().await {
|
||||||
// I think moving to the root of the last tree makes the most sense
|
// I think moving to the root of the last tree makes the most sense
|
||||||
// here. Alternatively, we could just not move the cursor, but that
|
// here. Alternatively, we could just not move the cursor, but that
|
||||||
// wouldn't be very useful.
|
// wouldn't be very useful.
|
||||||
|
|
@ -321,116 +293,81 @@ impl<M: Msg> TreeView<M> {
|
||||||
// message to move to.
|
// message to move to.
|
||||||
|
|
||||||
if let Some(cursor) = cursor {
|
if let Some(cursor) = cursor {
|
||||||
self.correct_cursor_offset(
|
self.correct_cursor_offset(store, frame, size, &old_blocks, &old_cursor_id, cursor)
|
||||||
room,
|
|
||||||
store,
|
|
||||||
frame,
|
|
||||||
size,
|
|
||||||
&old_blocks,
|
|
||||||
&old_cursor_id,
|
|
||||||
cursor,
|
|
||||||
)
|
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn move_down_sibling<S: MsgStore<M>>(
|
pub async fn move_down_sibling<S: MsgStore<M>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
room: &str,
|
|
||||||
store: &S,
|
store: &S,
|
||||||
cursor: &mut Option<Cursor<M::Id>>,
|
cursor: &mut Option<Cursor<M::Id>>,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
size: Size,
|
size: Size,
|
||||||
) {
|
) {
|
||||||
let old_blocks = self
|
let old_blocks = self
|
||||||
.layout_blocks(room, store, cursor.as_ref(), frame, size)
|
.layout_blocks(store, cursor.as_ref(), frame, size)
|
||||||
.await;
|
.await;
|
||||||
let old_cursor_id = cursor.as_ref().map(|c| c.id.clone());
|
let old_cursor_id = cursor.as_ref().map(|c| c.id.clone());
|
||||||
|
|
||||||
if let Some(cursor) = cursor {
|
if let Some(cursor) = cursor {
|
||||||
let path = store.path(room, &cursor.id).await;
|
let path = store.path(&cursor.id).await;
|
||||||
let mut tree = store.tree(room, path.first()).await;
|
let mut tree = store.tree(path.first()).await;
|
||||||
self.find_next_sibling(room, store, &mut tree, &mut cursor.id)
|
self.find_next_sibling(store, &mut tree, &mut cursor.id)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
// If that condition doesn't hold, we're already at the bottom in
|
// If that condition doesn't hold, we're already at the bottom in
|
||||||
// cursor-less mode and can't move further down anyways.
|
// cursor-less mode and can't move further down anyways.
|
||||||
|
|
||||||
if let Some(cursor) = cursor {
|
if let Some(cursor) = cursor {
|
||||||
self.correct_cursor_offset(
|
self.correct_cursor_offset(store, frame, size, &old_blocks, &old_cursor_id, cursor)
|
||||||
room,
|
|
||||||
store,
|
|
||||||
frame,
|
|
||||||
size,
|
|
||||||
&old_blocks,
|
|
||||||
&old_cursor_id,
|
|
||||||
cursor,
|
|
||||||
)
|
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn move_to_first<S: MsgStore<M>>(
|
pub async fn move_to_first<S: MsgStore<M>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
room: &str,
|
|
||||||
store: &S,
|
store: &S,
|
||||||
cursor: &mut Option<Cursor<M::Id>>,
|
cursor: &mut Option<Cursor<M::Id>>,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
size: Size,
|
size: Size,
|
||||||
) {
|
) {
|
||||||
let old_blocks = self
|
let old_blocks = self
|
||||||
.layout_blocks(room, store, cursor.as_ref(), frame, size)
|
.layout_blocks(store, cursor.as_ref(), frame, size)
|
||||||
.await;
|
.await;
|
||||||
let old_cursor_id = cursor.as_ref().map(|c| c.id.clone());
|
let old_cursor_id = cursor.as_ref().map(|c| c.id.clone());
|
||||||
|
|
||||||
if let Some(tree_id) = store.first_tree(room).await {
|
if let Some(tree_id) = store.first_tree().await {
|
||||||
*cursor = Some(Cursor::new(tree_id));
|
*cursor = Some(Cursor::new(tree_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(cursor) = cursor {
|
if let Some(cursor) = cursor {
|
||||||
self.correct_cursor_offset(
|
self.correct_cursor_offset(store, frame, size, &old_blocks, &old_cursor_id, cursor)
|
||||||
room,
|
|
||||||
store,
|
|
||||||
frame,
|
|
||||||
size,
|
|
||||||
&old_blocks,
|
|
||||||
&old_cursor_id,
|
|
||||||
cursor,
|
|
||||||
)
|
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn move_to_last<S: MsgStore<M>>(
|
pub async fn move_to_last<S: MsgStore<M>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
room: &str,
|
|
||||||
store: &S,
|
store: &S,
|
||||||
cursor: &mut Option<Cursor<M::Id>>,
|
cursor: &mut Option<Cursor<M::Id>>,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
size: Size,
|
size: Size,
|
||||||
) {
|
) {
|
||||||
let old_blocks = self
|
let old_blocks = self
|
||||||
.layout_blocks(room, store, cursor.as_ref(), frame, size)
|
.layout_blocks(store, cursor.as_ref(), frame, size)
|
||||||
.await;
|
.await;
|
||||||
let old_cursor_id = cursor.as_ref().map(|c| c.id.clone());
|
let old_cursor_id = cursor.as_ref().map(|c| c.id.clone());
|
||||||
|
|
||||||
if let Some(tree_id) = store.last_tree(room).await {
|
if let Some(tree_id) = store.last_tree().await {
|
||||||
let tree = store.tree(room, &tree_id).await;
|
let tree = store.tree(&tree_id).await;
|
||||||
let mut id = tree_id;
|
let mut id = tree_id;
|
||||||
while Self::find_last_child(&tree, &mut id) {}
|
while Self::find_last_child(&tree, &mut id) {}
|
||||||
*cursor = Some(Cursor::new(id));
|
*cursor = Some(Cursor::new(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(cursor) = cursor {
|
if let Some(cursor) = cursor {
|
||||||
self.correct_cursor_offset(
|
self.correct_cursor_offset(store, frame, size, &old_blocks, &old_cursor_id, cursor)
|
||||||
room,
|
|
||||||
store,
|
|
||||||
frame,
|
|
||||||
size,
|
|
||||||
&old_blocks,
|
|
||||||
&old_cursor_id,
|
|
||||||
cursor,
|
|
||||||
)
|
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -440,7 +377,6 @@ impl<M: Msg> TreeView<M> {
|
||||||
|
|
||||||
pub async fn center_cursor<S: MsgStore<M>>(
|
pub async fn center_cursor<S: MsgStore<M>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
room: &str,
|
|
||||||
store: &S,
|
store: &S,
|
||||||
cursor: &mut Option<Cursor<M::Id>>,
|
cursor: &mut Option<Cursor<M::Id>>,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
|
|
@ -451,19 +387,9 @@ impl<M: Msg> TreeView<M> {
|
||||||
|
|
||||||
// Correcting the offset just to make sure that this function
|
// Correcting the offset just to make sure that this function
|
||||||
// behaves nicely if the cursor has too many lines.
|
// behaves nicely if the cursor has too many lines.
|
||||||
let old_blocks = self
|
let old_blocks = self.layout_blocks(store, Some(cursor), frame, size).await;
|
||||||
.layout_blocks(room, store, Some(cursor), frame, size)
|
|
||||||
.await;
|
|
||||||
let old_cursor_id = Some(cursor.id.clone());
|
let old_cursor_id = Some(cursor.id.clone());
|
||||||
self.correct_cursor_offset(
|
self.correct_cursor_offset(store, frame, size, &old_blocks, &old_cursor_id, cursor)
|
||||||
room,
|
|
||||||
store,
|
|
||||||
frame,
|
|
||||||
size,
|
|
||||||
&old_blocks,
|
|
||||||
&old_cursor_id,
|
|
||||||
cursor,
|
|
||||||
)
|
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,6 @@ fn layout_tree<M: Msg>(frame: &mut Frame, size: Size, tree: Tree<M>) -> Blocks<M
|
||||||
|
|
||||||
impl<M: Msg> TreeView<M> {
|
impl<M: Msg> TreeView<M> {
|
||||||
pub async fn expand_blocks_up<S: MsgStore<M>>(
|
pub async fn expand_blocks_up<S: MsgStore<M>>(
|
||||||
room: &str,
|
|
||||||
store: &S,
|
store: &S,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
size: Size,
|
size: Size,
|
||||||
|
|
@ -63,13 +62,13 @@ impl<M: Msg> TreeView<M> {
|
||||||
) {
|
) {
|
||||||
while blocks.top_line > 0 {
|
while blocks.top_line > 0 {
|
||||||
*tree_id = if let Some(tree_id) = tree_id {
|
*tree_id = if let Some(tree_id) = tree_id {
|
||||||
store.prev_tree(room, tree_id).await
|
store.prev_tree(tree_id).await
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(tree_id) = tree_id {
|
if let Some(tree_id) = tree_id {
|
||||||
let tree = store.tree(room, tree_id).await;
|
let tree = store.tree(tree_id).await;
|
||||||
blocks.prepend(layout_tree(frame, size, tree));
|
blocks.prepend(layout_tree(frame, size, tree));
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
|
@ -78,7 +77,6 @@ impl<M: Msg> TreeView<M> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn expand_blocks_down<S: MsgStore<M>>(
|
pub async fn expand_blocks_down<S: MsgStore<M>>(
|
||||||
room: &str,
|
|
||||||
store: &S,
|
store: &S,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
size: Size,
|
size: Size,
|
||||||
|
|
@ -87,13 +85,13 @@ impl<M: Msg> TreeView<M> {
|
||||||
) {
|
) {
|
||||||
while blocks.bottom_line < size.height as i32 {
|
while blocks.bottom_line < size.height as i32 {
|
||||||
*tree_id = if let Some(tree_id) = tree_id {
|
*tree_id = if let Some(tree_id) = tree_id {
|
||||||
store.next_tree(room, tree_id).await
|
store.next_tree(tree_id).await
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(tree_id) = tree_id {
|
if let Some(tree_id) = tree_id {
|
||||||
let tree = store.tree(room, tree_id).await;
|
let tree = store.tree(tree_id).await;
|
||||||
blocks.append(layout_tree(frame, size, tree));
|
blocks.append(layout_tree(frame, size, tree));
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
|
@ -104,7 +102,6 @@ impl<M: Msg> TreeView<M> {
|
||||||
// TODO Split up based on cursor presence
|
// TODO Split up based on cursor presence
|
||||||
pub async fn layout_blocks<S: MsgStore<M>>(
|
pub async fn layout_blocks<S: MsgStore<M>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
room: &str,
|
|
||||||
store: &S,
|
store: &S,
|
||||||
cursor: Option<&Cursor<M::Id>>,
|
cursor: Option<&Cursor<M::Id>>,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
|
|
@ -115,9 +112,9 @@ impl<M: Msg> TreeView<M> {
|
||||||
// TODO Unfold all messages on path to cursor
|
// TODO Unfold all messages on path to cursor
|
||||||
|
|
||||||
// Layout cursor subtree (with correct offsets based on cursor)
|
// Layout cursor subtree (with correct offsets based on cursor)
|
||||||
let cursor_path = store.path(room, &cursor.id).await;
|
let cursor_path = store.path(&cursor.id).await;
|
||||||
let cursor_tree_id = cursor_path.first();
|
let cursor_tree_id = cursor_path.first();
|
||||||
let cursor_tree = store.tree(room, cursor_tree_id).await;
|
let cursor_tree = store.tree(cursor_tree_id).await;
|
||||||
let mut blocks = layout_tree(frame, size, cursor_tree);
|
let mut blocks = layout_tree(frame, size, cursor_tree);
|
||||||
blocks.calculate_offsets_with_cursor(cursor, size.height);
|
blocks.calculate_offsets_with_cursor(cursor, size.height);
|
||||||
|
|
||||||
|
|
@ -136,18 +133,18 @@ impl<M: Msg> TreeView<M> {
|
||||||
//
|
//
|
||||||
// TODO Don't expand if there is a focus
|
// TODO Don't expand if there is a focus
|
||||||
let mut top_tree_id = Some(cursor_tree_id.clone());
|
let mut top_tree_id = Some(cursor_tree_id.clone());
|
||||||
Self::expand_blocks_up(room, store, frame, size, &mut blocks, &mut top_tree_id).await;
|
Self::expand_blocks_up(store, frame, size, &mut blocks, &mut top_tree_id).await;
|
||||||
if blocks.top_line > 0 {
|
if blocks.top_line > 0 {
|
||||||
blocks.offset(-blocks.top_line);
|
blocks.offset(-blocks.top_line);
|
||||||
}
|
}
|
||||||
let mut bot_tree_id = Some(cursor_tree_id.clone());
|
let mut bot_tree_id = Some(cursor_tree_id.clone());
|
||||||
Self::expand_blocks_down(room, store, frame, size, &mut blocks, &mut bot_tree_id).await;
|
Self::expand_blocks_down(store, frame, size, &mut blocks, &mut bot_tree_id).await;
|
||||||
if blocks.bottom_line < size.height as i32 - 1 {
|
if blocks.bottom_line < size.height as i32 - 1 {
|
||||||
blocks.offset(size.height as i32 - 1 - blocks.bottom_line);
|
blocks.offset(size.height as i32 - 1 - blocks.bottom_line);
|
||||||
}
|
}
|
||||||
// If we only moved the blocks down, we need to expand upwards again
|
// If we only moved the blocks down, we need to expand upwards again
|
||||||
// to make sure we fill the screen.
|
// to make sure we fill the screen.
|
||||||
Self::expand_blocks_up(room, store, frame, size, &mut blocks, &mut top_tree_id).await;
|
Self::expand_blocks_up(store, frame, size, &mut blocks, &mut top_tree_id).await;
|
||||||
|
|
||||||
blocks
|
blocks
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -157,12 +154,12 @@ impl<M: Msg> TreeView<M> {
|
||||||
let mut blocks = Blocks::new_below(size.height as i32 - 1);
|
let mut blocks = Blocks::new_below(size.height as i32 - 1);
|
||||||
|
|
||||||
// Expand upwards from last tree
|
// Expand upwards from last tree
|
||||||
if let Some(last_tree_id) = store.last_tree(room).await {
|
if let Some(last_tree_id) = store.last_tree().await {
|
||||||
let last_tree = store.tree(room, &last_tree_id).await;
|
let last_tree = store.tree(&last_tree_id).await;
|
||||||
blocks.prepend(layout_tree(frame, size, last_tree));
|
blocks.prepend(layout_tree(frame, size, last_tree));
|
||||||
|
|
||||||
let mut tree_id = Some(last_tree_id);
|
let mut tree_id = Some(last_tree_id);
|
||||||
Self::expand_blocks_up(room, store, frame, size, &mut blocks, &mut tree_id).await;
|
Self::expand_blocks_up(store, frame, size, &mut blocks, &mut tree_id).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
blocks
|
blocks
|
||||||
|
|
|
||||||
|
|
@ -103,10 +103,10 @@ impl<M: Msg> Tree<M> {
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait MsgStore<M: Msg> {
|
pub trait MsgStore<M: Msg> {
|
||||||
async fn path(&self, room: &str, id: &M::Id) -> Path<M::Id>;
|
async fn path(&self, id: &M::Id) -> Path<M::Id>;
|
||||||
async fn tree(&self, room: &str, root: &M::Id) -> Tree<M>;
|
async fn tree(&self, root: &M::Id) -> Tree<M>;
|
||||||
async fn prev_tree(&self, room: &str, tree: &M::Id) -> Option<M::Id>;
|
async fn prev_tree(&self, tree: &M::Id) -> Option<M::Id>;
|
||||||
async fn next_tree(&self, room: &str, tree: &M::Id) -> Option<M::Id>;
|
async fn next_tree(&self, tree: &M::Id) -> Option<M::Id>;
|
||||||
async fn first_tree(&self, room: &str) -> Option<M::Id>;
|
async fn first_tree(&self) -> Option<M::Id>;
|
||||||
async fn last_tree(&self, room: &str) -> Option<M::Id>;
|
async fn last_tree(&self) -> Option<M::Id>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ impl DummyStore {
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl MsgStore<DummyMsg> for DummyStore {
|
impl MsgStore<DummyMsg> for DummyStore {
|
||||||
async fn path(&self, _room: &str, id: &usize) -> Path<usize> {
|
async fn path(&self, id: &usize) -> Path<usize> {
|
||||||
let mut id = *id;
|
let mut id = *id;
|
||||||
let mut segments = vec![id];
|
let mut segments = vec![id];
|
||||||
while let Some(parent) = self.msgs.get(&id).and_then(|msg| msg.parent) {
|
while let Some(parent) = self.msgs.get(&id).and_then(|msg| msg.parent) {
|
||||||
|
|
@ -122,13 +122,13 @@ impl MsgStore<DummyMsg> for DummyStore {
|
||||||
Path::new(segments)
|
Path::new(segments)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn tree(&self, _room: &str, root: &usize) -> Tree<DummyMsg> {
|
async fn tree(&self, root: &usize) -> Tree<DummyMsg> {
|
||||||
let mut msgs = vec![];
|
let mut msgs = vec![];
|
||||||
self.collect_tree(*root, &mut msgs);
|
self.collect_tree(*root, &mut msgs);
|
||||||
Tree::new(*root, msgs)
|
Tree::new(*root, msgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn prev_tree(&self, _room: &str, tree: &usize) -> Option<usize> {
|
async fn prev_tree(&self, tree: &usize) -> Option<usize> {
|
||||||
let trees = self.trees();
|
let trees = self.trees();
|
||||||
trees
|
trees
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -137,7 +137,7 @@ impl MsgStore<DummyMsg> for DummyStore {
|
||||||
.map(|(t, _)| *t)
|
.map(|(t, _)| *t)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn next_tree(&self, _room: &str, tree: &usize) -> Option<usize> {
|
async fn next_tree(&self, tree: &usize) -> Option<usize> {
|
||||||
let trees = self.trees();
|
let trees = self.trees();
|
||||||
trees
|
trees
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -146,11 +146,11 @@ impl MsgStore<DummyMsg> for DummyStore {
|
||||||
.map(|(_, t)| *t)
|
.map(|(_, t)| *t)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn first_tree(&self, _room: &str) -> Option<usize> {
|
async fn first_tree(&self) -> Option<usize> {
|
||||||
self.trees().first().cloned()
|
self.trees().first().cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn last_tree(&self, _room: &str) -> Option<usize> {
|
async fn last_tree(&self) -> Option<usize> {
|
||||||
self.trees().last().cloned()
|
self.trees().last().cloned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ impl Ui {
|
||||||
.msg(DummyMsg::new(10, "abc123", "reply to reply to nothing").parent(8))
|
.msg(DummyMsg::new(10, "abc123", "reply to reply to nothing").parent(8))
|
||||||
.msg(DummyMsg::new(11, "nick", "yet another reply to nothing").parent(7))
|
.msg(DummyMsg::new(11, "nick", "yet another reply to nothing").parent(7))
|
||||||
.msg(DummyMsg::new(12, "abc123", "beep\nboop").parent(11));
|
.msg(DummyMsg::new(12, "abc123", "beep\nboop").parent(11));
|
||||||
let chat = Chat::new(store, "testroom".to_string());
|
let chat = Chat::new(store);
|
||||||
|
|
||||||
// Run main UI.
|
// Run main UI.
|
||||||
//
|
//
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue