Implement cursor movement
This commit is contained in:
parent
a1c714d116
commit
fee405b573
5 changed files with 234 additions and 172 deletions
|
|
@ -20,6 +20,16 @@ pub struct Cursor<I> {
|
||||||
proportion: f32,
|
proportion: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<I> Cursor<I> {
|
||||||
|
/// Create a new cursor with arbitrary proportion.
|
||||||
|
pub fn new(id: I) -> Self {
|
||||||
|
Self {
|
||||||
|
id,
|
||||||
|
proportion: 0.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Chat<M: Msg, S: MsgStore<M>> {
|
pub struct Chat<M: Msg, S: MsgStore<M>> {
|
||||||
store: S,
|
store: S,
|
||||||
room: String,
|
room: String,
|
||||||
|
|
@ -48,12 +58,12 @@ impl<M: Msg, S: MsgStore<M>> Chat<M, S> {
|
||||||
Mode::Tree => {
|
Mode::Tree => {
|
||||||
self.tree
|
self.tree
|
||||||
.handle_key_event(
|
.handle_key_event(
|
||||||
&mut self.store,
|
|
||||||
&self.room,
|
&self.room,
|
||||||
|
&mut self.store,
|
||||||
&mut self.cursor,
|
&mut self.cursor,
|
||||||
event,
|
|
||||||
frame,
|
frame,
|
||||||
size,
|
size,
|
||||||
|
event,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
@ -64,7 +74,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(&mut self.store, &self.room, &self.cursor, frame, pos, size)
|
.render(&self.room, &mut self.store, &self.cursor, frame, pos, size)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,24 +29,30 @@ 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,
|
||||||
store: &mut S,
|
r: &str,
|
||||||
room: &str,
|
s: &mut S,
|
||||||
cursor: &mut Option<Cursor<M::Id>>,
|
c: &mut Option<Cursor<M::Id>>,
|
||||||
|
f: &mut Frame,
|
||||||
|
z: Size,
|
||||||
event: KeyEvent,
|
event: KeyEvent,
|
||||||
frame: &mut Frame,
|
|
||||||
size: Size,
|
|
||||||
) {
|
) {
|
||||||
match event.code {
|
match event.code {
|
||||||
KeyCode::Char('k') => self.move_to_prev_msg(store, room, cursor).await,
|
KeyCode::Char('z') | KeyCode::Char('Z') => self.center_cursor(r, s, c, f, z).await,
|
||||||
KeyCode::Char('z') => self.center_cursor(cursor).await,
|
KeyCode::Char('k') => self.move_up(r, s, c, f, z).await,
|
||||||
|
KeyCode::Char('j') => self.move_down(r, s, c, f, z).await,
|
||||||
|
KeyCode::Char('K') => self.move_up_sibling(r, s, c, f, z).await,
|
||||||
|
KeyCode::Char('J') => self.move_down_sibling(r, s, c, f, z).await,
|
||||||
|
KeyCode::Char('g') => self.move_to_first(r, s, c, f, z).await,
|
||||||
|
KeyCode::Char('G') => self.move_to_last(r, s, c, f, z).await,
|
||||||
|
KeyCode::Esc => *c = None, // TODO Make 'G' do the same thing?
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn render<S: MsgStore<M>>(
|
pub async fn render<S: MsgStore<M>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
store: &mut S,
|
|
||||||
room: &str,
|
room: &str,
|
||||||
|
store: &mut S,
|
||||||
cursor: &Option<Cursor<M::Id>>,
|
cursor: &Option<Cursor<M::Id>>,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
pos: Pos,
|
pos: Pos,
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ use super::blocks::Blocks;
|
||||||
use super::{util, TreeView};
|
use super::{util, TreeView};
|
||||||
|
|
||||||
impl<M: Msg> TreeView<M> {
|
impl<M: Msg> TreeView<M> {
|
||||||
|
#[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,
|
room: &str,
|
||||||
|
|
@ -69,6 +70,33 @@ impl<M: Msg> TreeView<M> {
|
||||||
// goes for the other direction.
|
// goes for the other direction.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find_parent(tree: &Tree<M>, id: &mut M::Id) -> bool {
|
||||||
|
if let Some(parent) = tree.parent(id) {
|
||||||
|
*id = parent;
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_first_child(tree: &Tree<M>, id: &mut M::Id) -> bool {
|
||||||
|
if let Some(child) = tree.children(id).and_then(|c| c.first()) {
|
||||||
|
*id = child.clone();
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_last_child(tree: &Tree<M>, id: &mut M::Id) -> bool {
|
||||||
|
if let Some(child) = tree.children(id).and_then(|c| c.last()) {
|
||||||
|
*id = child.clone();
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Move to the previous sibling, or don't move if this is not possible.
|
/// Move to the previous sibling, or don't move if this is not possible.
|
||||||
///
|
///
|
||||||
/// Always stays at the same level of indentation.
|
/// Always stays at the same level of indentation.
|
||||||
|
|
@ -78,7 +106,7 @@ impl<M: Msg> TreeView<M> {
|
||||||
store: &S,
|
store: &S,
|
||||||
tree: &mut Tree<M>,
|
tree: &mut Tree<M>,
|
||||||
id: &mut M::Id,
|
id: &mut M::Id,
|
||||||
) {
|
) -> bool {
|
||||||
if let Some(siblings) = tree.siblings(id) {
|
if let Some(siblings) = tree.siblings(id) {
|
||||||
let prev_sibling = siblings
|
let prev_sibling = siblings
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -87,6 +115,9 @@ impl<M: Msg> TreeView<M> {
|
||||||
.map(|(s, _)| s);
|
.map(|(s, _)| s);
|
||||||
if let Some(prev_sibling) = prev_sibling {
|
if let Some(prev_sibling) = prev_sibling {
|
||||||
*id = prev_sibling.clone();
|
*id = prev_sibling.clone();
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
} 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
|
||||||
|
|
@ -94,6 +125,9 @@ impl<M: Msg> TreeView<M> {
|
||||||
if let Some(prev_tree_id) = store.prev_tree(room, tree.root()).await {
|
if let Some(prev_tree_id) = store.prev_tree(room, tree.root()).await {
|
||||||
*tree = store.tree(room, &prev_tree_id).await;
|
*tree = store.tree(room, &prev_tree_id).await;
|
||||||
*id = prev_tree_id;
|
*id = prev_tree_id;
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -107,7 +141,7 @@ impl<M: Msg> TreeView<M> {
|
||||||
store: &S,
|
store: &S,
|
||||||
tree: &mut Tree<M>,
|
tree: &mut Tree<M>,
|
||||||
id: &mut M::Id,
|
id: &mut M::Id,
|
||||||
) {
|
) -> bool {
|
||||||
if let Some(siblings) = tree.siblings(id) {
|
if let Some(siblings) = tree.siblings(id) {
|
||||||
let next_sibling = siblings
|
let next_sibling = siblings
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -116,6 +150,9 @@ impl<M: Msg> TreeView<M> {
|
||||||
.map(|(_, s)| s);
|
.map(|(_, s)| s);
|
||||||
if let Some(next_sibling) = next_sibling {
|
if let Some(next_sibling) = next_sibling {
|
||||||
*id = next_sibling.clone();
|
*id = next_sibling.clone();
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
} 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
|
||||||
|
|
@ -123,16 +160,9 @@ impl<M: Msg> TreeView<M> {
|
||||||
if let Some(next_tree_id) = store.next_tree(room, tree.root()).await {
|
if let Some(next_tree_id) = store.next_tree(room, tree.root()).await {
|
||||||
*tree = store.tree(room, &next_tree_id).await;
|
*tree = store.tree(room, &next_tree_id).await;
|
||||||
*id = next_tree_id;
|
*id = next_tree_id;
|
||||||
}
|
true
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_innermost_child(tree: &Tree<M>, id: &mut M::Id) {
|
|
||||||
while let Some(children) = tree.children(id) {
|
|
||||||
if let Some(child) = children.last() {
|
|
||||||
*id = child.clone()
|
|
||||||
} else {
|
} else {
|
||||||
break;
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -144,34 +174,15 @@ impl<M: Msg> TreeView<M> {
|
||||||
store: &S,
|
store: &S,
|
||||||
tree: &mut Tree<M>,
|
tree: &mut Tree<M>,
|
||||||
id: &mut M::Id,
|
id: &mut M::Id,
|
||||||
) {
|
) -> bool {
|
||||||
if let Some(siblings) = tree.siblings(id) {
|
// Move to previous sibling, then to its last child
|
||||||
let prev_sibling = siblings
|
// If not possible, move to parent
|
||||||
.iter()
|
if self.find_prev_sibling(room, store, tree, id).await {
|
||||||
.zip(siblings.iter().skip(1))
|
while Self::find_last_child(tree, id) {}
|
||||||
.find(|(_, s)| *s == id)
|
true
|
||||||
.map(|(s, _)| s);
|
|
||||||
if let Some(prev_sibling) = prev_sibling {
|
|
||||||
*id = prev_sibling.clone();
|
|
||||||
} else {
|
|
||||||
// We need to move up one parent and *not* down again. If there
|
|
||||||
// was no parent, we should be in the `else` case below instead.
|
|
||||||
if let Some(parent) = tree.parent(id) {
|
|
||||||
*id = parent;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// We're at the root of our tree, so we need to move to the root of
|
Self::find_parent(tree, id)
|
||||||
// the previous tree.
|
|
||||||
if let Some(prev_tree_id) = store.prev_tree(room, tree.root()).await {
|
|
||||||
*tree = store.tree(room, &prev_tree_id).await;
|
|
||||||
*id = prev_tree_id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now, we just need to move to the deepest and last child.
|
|
||||||
Self::find_innermost_child(tree, id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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.
|
||||||
|
|
@ -181,41 +192,26 @@ impl<M: Msg> TreeView<M> {
|
||||||
store: &S,
|
store: &S,
|
||||||
tree: &mut Tree<M>,
|
tree: &mut Tree<M>,
|
||||||
id: &mut M::Id,
|
id: &mut M::Id,
|
||||||
) {
|
) -> bool {
|
||||||
if let Some(children) = tree.children(id) {
|
if Self::find_first_child(tree, id) {
|
||||||
if let Some(child) = children.first() {
|
return true;
|
||||||
*id = child.clone();
|
}
|
||||||
return;
|
|
||||||
|
if self.find_next_sibling(room, store, tree, id).await {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Temporary id to avoid modifying the original one if no parent-sibling
|
||||||
|
// can be found.
|
||||||
|
let mut tmp_id = id.clone();
|
||||||
|
while Self::find_parent(tree, &mut tmp_id) {
|
||||||
|
if self.find_next_sibling(room, store, tree, &mut tmp_id).await {
|
||||||
|
*id = tmp_id;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(siblings) = tree.siblings(id) {
|
false
|
||||||
let prev_sibling = siblings
|
|
||||||
.iter()
|
|
||||||
.zip(siblings.iter().skip(1))
|
|
||||||
.find(|(_, s)| *s == id)
|
|
||||||
.map(|(s, _)| s);
|
|
||||||
if let Some(next_sibling) = prev_sibling {
|
|
||||||
*id = prev_sibling.clone();
|
|
||||||
} else {
|
|
||||||
// We need to move up one parent and *not* down again. If there
|
|
||||||
// was no parent, we should be in the `else` case below instead.
|
|
||||||
if let Some(parent) = tree.msg(id).and_then(|m| m.parent()) {
|
|
||||||
*id = parent;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// We're at the root of our tree, so we need to move to the root of
|
|
||||||
// the previous tree.
|
|
||||||
if let Some(prev_tree_id) = store.prev_tree(room, tree.root()).await {
|
|
||||||
*tree = store.tree(room, &prev_tree_id).await;
|
|
||||||
*id = prev_tree_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now, we just need to move to the deepest and last child.
|
|
||||||
Self::find_innermost_child(tree, id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn move_up<S: MsgStore<M>>(
|
pub async fn move_up<S: MsgStore<M>>(
|
||||||
|
|
@ -232,18 +228,20 @@ impl<M: Msg> TreeView<M> {
|
||||||
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 mut tree = store.tree(room, &cursor.id).await;
|
// We have a cursor to move around
|
||||||
|
let path = store.path(room, &cursor.id).await;
|
||||||
|
let mut tree = store.tree(room, path.first()).await;
|
||||||
self.find_prev_msg(room, store, &mut tree, &mut cursor.id)
|
self.find_prev_msg(room, 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(room).await {
|
||||||
|
// We need to select the last message of the last tree
|
||||||
let tree = store.tree(room, &last_tree).await;
|
let tree = store.tree(room, &last_tree).await;
|
||||||
let mut id = last_tree;
|
let mut id = last_tree;
|
||||||
Self::find_innermost_child(&tree, &mut id);
|
while Self::find_last_child(&tree, &mut id) {}
|
||||||
*cursor = Some(Cursor {
|
*cursor = Some(Cursor::new(id));
|
||||||
id,
|
|
||||||
proportion: 1.0,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
// If neither condition holds, we can't set a cursor because there's no
|
||||||
|
// message to move to.
|
||||||
|
|
||||||
if let Some(cursor) = cursor {
|
if let Some(cursor) = cursor {
|
||||||
self.correct_cursor_offset(
|
self.correct_cursor_offset(
|
||||||
|
|
@ -273,10 +271,13 @@ impl<M: Msg> TreeView<M> {
|
||||||
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 mut tree = store.tree(room, &cursor.id).await;
|
let path = store.path(room, &cursor.id).await;
|
||||||
|
let mut tree = store.tree(room, path.first()).await;
|
||||||
self.find_next_msg(room, store, &mut tree, &mut cursor.id)
|
self.find_next_msg(room, store, &mut tree, &mut cursor.id)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
// If that condition doesn't hold, we're already at the bottom in
|
||||||
|
// 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(
|
||||||
|
|
@ -306,14 +307,84 @@ impl<M: Msg> TreeView<M> {
|
||||||
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 mut tree = store.tree(room, &cursor.id).await;
|
let path = store.path(room, &cursor.id).await;
|
||||||
|
let mut tree = store.tree(room, path.first()).await;
|
||||||
self.find_prev_sibling(room, store, &mut tree, &mut cursor.id)
|
self.find_prev_sibling(room, 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(room).await {
|
||||||
*cursor = Some(Cursor {
|
// I think moving to the root of the last tree makes the most sense
|
||||||
id: last_tree,
|
// here. Alternatively, we could just not move the cursor, but that
|
||||||
proportion: 1.0,
|
// wouldn't be very useful.
|
||||||
});
|
*cursor = Some(Cursor::new(last_tree));
|
||||||
|
}
|
||||||
|
// If neither condition holds, we can't set a cursor because there's no
|
||||||
|
// message to move to.
|
||||||
|
|
||||||
|
if let Some(cursor) = cursor {
|
||||||
|
self.correct_cursor_offset(
|
||||||
|
room,
|
||||||
|
store,
|
||||||
|
frame,
|
||||||
|
size,
|
||||||
|
&old_blocks,
|
||||||
|
&old_cursor_id,
|
||||||
|
cursor,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn move_down_sibling<S: MsgStore<M>>(
|
||||||
|
&mut self,
|
||||||
|
room: &str,
|
||||||
|
store: &S,
|
||||||
|
cursor: &mut Option<Cursor<M::Id>>,
|
||||||
|
frame: &mut Frame,
|
||||||
|
size: Size,
|
||||||
|
) {
|
||||||
|
let old_blocks = self
|
||||||
|
.layout_blocks(room, store, cursor.as_ref(), frame, size)
|
||||||
|
.await;
|
||||||
|
let old_cursor_id = cursor.as_ref().map(|c| c.id.clone());
|
||||||
|
|
||||||
|
if let Some(cursor) = cursor {
|
||||||
|
let path = store.path(room, &cursor.id).await;
|
||||||
|
let mut tree = store.tree(room, path.first()).await;
|
||||||
|
self.find_next_sibling(room, store, &mut tree, &mut cursor.id)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
// If that condition doesn't hold, we're already at the bottom in
|
||||||
|
// cursor-less mode and can't move further down anyways.
|
||||||
|
|
||||||
|
if let Some(cursor) = cursor {
|
||||||
|
self.correct_cursor_offset(
|
||||||
|
room,
|
||||||
|
store,
|
||||||
|
frame,
|
||||||
|
size,
|
||||||
|
&old_blocks,
|
||||||
|
&old_cursor_id,
|
||||||
|
cursor,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn move_to_first<S: MsgStore<M>>(
|
||||||
|
&mut self,
|
||||||
|
room: &str,
|
||||||
|
store: &S,
|
||||||
|
cursor: &mut Option<Cursor<M::Id>>,
|
||||||
|
frame: &mut Frame,
|
||||||
|
size: Size,
|
||||||
|
) {
|
||||||
|
let old_blocks = self
|
||||||
|
.layout_blocks(room, store, cursor.as_ref(), frame, size)
|
||||||
|
.await;
|
||||||
|
let old_cursor_id = cursor.as_ref().map(|c| c.id.clone());
|
||||||
|
|
||||||
|
if let Some(tree_id) = store.first_tree(room).await {
|
||||||
|
*cursor = Some(Cursor::new(tree_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(cursor) = cursor {
|
if let Some(cursor) = cursor {
|
||||||
|
|
@ -330,60 +401,70 @@ impl<M: Msg> TreeView<M> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn move_down_sibling() {
|
pub async fn move_to_last<S: MsgStore<M>>(
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn move_older() {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn move_newer() {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO move_older_unseen
|
|
||||||
// TODO move_newer_unseen
|
|
||||||
|
|
||||||
pub async fn move_to_prev_msg<S: MsgStore<M>>(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
store: &mut S,
|
|
||||||
room: &str,
|
room: &str,
|
||||||
|
store: &S,
|
||||||
cursor: &mut Option<Cursor<M::Id>>,
|
cursor: &mut Option<Cursor<M::Id>>,
|
||||||
|
frame: &mut Frame,
|
||||||
|
size: Size,
|
||||||
) {
|
) {
|
||||||
let tree = if let Some(cursor) = cursor {
|
let old_blocks = self
|
||||||
let path = store.path(room, &cursor.id).await;
|
.layout_blocks(room, store, cursor.as_ref(), frame, size)
|
||||||
let tree = store.tree(room, path.first()).await;
|
.await;
|
||||||
if let Some(prev_sibling) = tree.prev_sibling(&cursor.id) {
|
let old_cursor_id = cursor.as_ref().map(|c| c.id.clone());
|
||||||
cursor.id = tree.last_child(prev_sibling.clone());
|
|
||||||
return;
|
|
||||||
} else if let Some(parent) = tree.parent(&cursor.id) {
|
|
||||||
cursor.id = parent;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
store.prev_tree(room, path.first()).await
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
store.last_tree(room).await
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(tree) = tree {
|
if let Some(tree_id) = store.last_tree(room).await {
|
||||||
let tree = store.tree(room, &tree).await;
|
let tree = store.tree(room, &tree_id).await;
|
||||||
let cursor_id = tree.last_child(tree.root().clone());
|
let mut id = tree_id;
|
||||||
if let Some(cursor) = cursor {
|
while Self::find_last_child(&tree, &mut id) {}
|
||||||
cursor.id = cursor_id;
|
*cursor = Some(Cursor::new(id));
|
||||||
} else {
|
}
|
||||||
*cursor = Some(Cursor {
|
|
||||||
id: cursor_id,
|
if let Some(cursor) = cursor {
|
||||||
proportion: 1.0,
|
self.correct_cursor_offset(
|
||||||
});
|
room,
|
||||||
}
|
store,
|
||||||
|
frame,
|
||||||
|
size,
|
||||||
|
&old_blocks,
|
||||||
|
&old_cursor_id,
|
||||||
|
cursor,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn center_cursor(&mut self, cursor: &mut Option<Cursor<M::Id>>) {
|
// TODO move_older[_unseen]
|
||||||
|
// TODO move_newer[_unseen]
|
||||||
|
|
||||||
|
pub async fn center_cursor<S: MsgStore<M>>(
|
||||||
|
&mut self,
|
||||||
|
room: &str,
|
||||||
|
store: &S,
|
||||||
|
cursor: &mut Option<Cursor<M::Id>>,
|
||||||
|
frame: &mut Frame,
|
||||||
|
size: Size,
|
||||||
|
) {
|
||||||
if let Some(cursor) = cursor {
|
if let Some(cursor) = cursor {
|
||||||
cursor.proportion = 0.5;
|
cursor.proportion = 0.5;
|
||||||
|
|
||||||
|
// Correcting the offset just to make sure that this function
|
||||||
|
// behaves nicely if the cursor has too many lines.
|
||||||
|
let old_blocks = self
|
||||||
|
.layout_blocks(room, store, Some(cursor), frame, size)
|
||||||
|
.await;
|
||||||
|
let old_cursor_id = Some(cursor.id.clone());
|
||||||
|
self.correct_cursor_offset(
|
||||||
|
room,
|
||||||
|
store,
|
||||||
|
frame,
|
||||||
|
size,
|
||||||
|
&old_blocks,
|
||||||
|
&old_cursor_id,
|
||||||
|
cursor,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
//! Constants and helper functions.
|
//! Constants and helper functions.
|
||||||
|
|
||||||
use crossterm::style::{ContentStyle, Stylize};
|
use crossterm::style::{ContentStyle, Stylize};
|
||||||
use toss::frame::{Frame, Size};
|
use toss::frame::Frame;
|
||||||
|
|
||||||
pub const TIME_FORMAT: &str = "%H:%M ";
|
pub const TIME_FORMAT: &str = "%H:%M ";
|
||||||
pub const TIME_EMPTY: &str = " ";
|
pub const TIME_EMPTY: &str = " ";
|
||||||
|
|
|
||||||
|
|
@ -99,41 +99,6 @@ impl<M: Msg> Tree<M> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prev_sibling(&self, id: &M::Id) -> Option<&M::Id> {
|
|
||||||
if let Some(siblings) = self.siblings(id) {
|
|
||||||
siblings
|
|
||||||
.iter()
|
|
||||||
.zip(siblings.iter().skip(1))
|
|
||||||
.find(|(_, s)| *s == id)
|
|
||||||
.map(|(s, _)| s)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn next_sibling(&self, id: &M::Id) -> Option<&M::Id> {
|
|
||||||
if let Some(siblings) = self.siblings(id) {
|
|
||||||
siblings
|
|
||||||
.iter()
|
|
||||||
.zip(siblings.iter().skip(1))
|
|
||||||
.find(|(s, _)| *s == id)
|
|
||||||
.map(|(_, s)| s)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn last_child(&self, mut id: M::Id) -> M::Id {
|
|
||||||
while let Some(children) = self.children(&id) {
|
|
||||||
if let Some(last_child) = children.last() {
|
|
||||||
id = last_child.clone();
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue