diff --git a/cove/src/ui/chat/renderer.rs b/cove/src/ui/chat/renderer.rs index 7318f43..1edde46 100644 --- a/cove/src/ui/chat/renderer.rs +++ b/cove/src/ui/chat/renderer.rs @@ -178,7 +178,7 @@ where } /// Expand blocks such that the screen is full for any offset where the -/// specified block is visible. +/// specified block is visible. The block must exist. pub async fn expand_to_fill_screen_around_block(r: &mut R, id: &Id) -> Result<(), R::Error> where Id: Eq, @@ -196,6 +196,8 @@ where Ok(()) } +/// Scroll so that the top of the block is at the specified value. Returns +/// `true` if successful, or `false` if the block could not be found. pub fn scroll_to_set_block_top(r: &mut R, id: &Id, top: i32) -> bool where Id: Eq, diff --git a/cove/src/ui/chat/tree.rs b/cove/src/ui/chat/tree.rs index f2f230a..772363f 100644 --- a/cove/src/ui/chat/tree.rs +++ b/cove/src/ui/chat/tree.rs @@ -439,7 +439,7 @@ where let mut renderer = TreeRenderer::new( context, &self.state.store, - &self.state.folded, + &mut self.state.folded, self.cursor, self.editor, frame.widthdb(), diff --git a/cove/src/ui/chat/tree/renderer.rs b/cove/src/ui/chat/tree/renderer.rs index 07edab0..6932123 100644 --- a/cove/src/ui/chat/tree/renderer.rs +++ b/cove/src/ui/chat/tree/renderer.rs @@ -80,7 +80,7 @@ pub struct TreeRenderer<'a, M: Msg, S: MsgStore> { context: TreeContext, store: &'a S, - folded: &'a HashSet, + folded: &'a mut HashSet, cursor: &'a mut Cursor, editor: &'a mut EditorState, widthdb: &'a mut WidthDb, @@ -107,7 +107,7 @@ where pub fn new( context: TreeContext, store: &'a S, - folded: &'a HashSet, + folded: &'a mut HashSet, cursor: &'a mut Cursor, editor: &'a mut EditorState, widthdb: &'a mut WidthDb, @@ -279,12 +279,30 @@ where Ok(Some(path.into_first())) } - async fn prepare_initial_tree(&mut self, root_id: &Option) -> Result<(), S::Error> { + /// Render the tree containing the cursor to the blocks and set the top and + /// bottom root id accordingly. This function will always render a block + /// that has the cusor id. + async fn prepare_initial_tree( + &mut self, + cursor_id: &TreeBlockId, + root_id: &Option, + ) -> Result<(), S::Error> { self.top_root_id = root_id.clone(); self.bottom_root_id = root_id.clone(); let blocks = if let Some(root_id) = root_id { let tree = self.store.tree(root_id).await?; + + // To ensure the cursor block will be rendered, all its parents must + // be unfolded. + if let TreeBlockId::Msg(id) | TreeBlockId::After(id) = cursor_id { + let mut id = id.clone(); + while let Some(parent_id) = tree.parent(&id) { + self.folded.remove(&parent_id); + id = parent_id; + } + } + self.layout_tree(tree) } else { self.layout_bottom() @@ -318,9 +336,11 @@ where let cursor_id = TreeBlockId::from_cursor(self.cursor); let cursor_root_id = self.root_id(&cursor_id).await?; - // Render cursor and blocks around it until screen is filled as long as - // the cursor is visible, regardless of how the screen is scrolled. - self.prepare_initial_tree(&cursor_root_id).await?; + // Render cursor and blocks around it so that the screen will always be + // filled as long as the cursor is visible, regardless of how the screen + // is scrolled. + self.prepare_initial_tree(&cursor_id, &cursor_root_id) + .await?; renderer::expand_to_fill_screen_around_block(self, &cursor_id).await?; // Scroll based on last cursor position diff --git a/cove/src/ui/chat/tree/scroll.rs b/cove/src/ui/chat/tree/scroll.rs index 8f565b3..482c7ca 100644 --- a/cove/src/ui/chat/tree/scroll.rs +++ b/cove/src/ui/chat/tree/scroll.rs @@ -33,8 +33,14 @@ where delta: i32, ) -> Result<(), S::Error> { let context = self.last_context(); - let mut renderer = - TreeRenderer::new(context, &self.store, &self.folded, cursor, editor, widthdb); + let mut renderer = TreeRenderer::new( + context, + &self.store, + &mut self.folded, + cursor, + editor, + widthdb, + ); renderer.prepare_blocks_for_drawing().await?; renderer.scroll_by(delta).await?; @@ -54,8 +60,14 @@ where widthdb: &mut WidthDb, ) -> Result<(), S::Error> { let context = self.last_context(); - let mut renderer = - TreeRenderer::new(context, &self.store, &self.folded, cursor, editor, widthdb); + let mut renderer = TreeRenderer::new( + context, + &self.store, + &mut self.folded, + cursor, + editor, + widthdb, + ); renderer.prepare_blocks_for_drawing().await?; renderer.center_cursor();