@@ -18,7 +18,11 @@ use crate::protocol::{
1818 Event as SessionEvent ,
1919 InputEvent ,
2020} ;
21- use crate :: ui:: action:: Action ;
21+ use crate :: ui:: action:: {
22+ Action ,
23+ Scroll ,
24+ ScrollDistance ,
25+ } ;
2226
2327#[ derive( Debug , Clone ) ]
2428struct Message {
@@ -43,6 +47,7 @@ pub struct ChatWindow {
4347 messages : Vec < Message > ,
4448 current_message : Option < Message > ,
4549 scroll_offset : u16 ,
50+ nearest_message_idx : usize ,
4651 visible : bool ,
4752 // TODO: update on resize
4853 pub dimension : ( u16 , u16 ) ,
@@ -108,7 +113,7 @@ impl Component for ChatWindow {
108113 Style :: default ( ) . fg( Color :: DarkGray ) ,
109114 ) ,
110115 Span :: styled( format!( "{}: " , prefix) , style. bold( ) ) ,
111- Span :: raw( & message. content) ,
116+ Span :: raw( strip_ansi_escapes :: strip_str ( & message. content) ) ,
112117 ] ) ) ;
113118 lines. push ( Line :: from ( "" ) ) ; // Empty line between messages
114119 }
@@ -196,20 +201,63 @@ impl Component for ChatWindow {
196201 }
197202
198203 fn update ( & mut self , action : Action ) -> eyre:: Result < Option < Action > > {
199- if let Action :: Input ( input_event) = action {
200- match input_event {
201- InputEvent :: Text ( text) => {
202- self . add_message ( MessageRole :: User , text) ;
203- self . scroll_offset = self . messages . last ( ) . as_ref ( ) . map ( |msg| msg. offset ) . unwrap_or_default ( ) ;
204- return Ok ( Some ( Action :: Render ) ) ;
205- } ,
206- InputEvent :: Interrupt => {
207- // Handle interrupt - could be used to cancel current streaming message
208- if self . current_message . is_some ( ) {
209- self . finalize_current_message ( ) ;
210- return Ok ( Some ( Action :: Render ) ) ;
204+ if self . visible {
205+ match action {
206+ Action :: Input ( input_event) => {
207+ match input_event {
208+ InputEvent :: Text ( text) => {
209+ self . add_message ( MessageRole :: User , text) ;
210+ self . scroll_offset =
211+ self . messages . last ( ) . as_ref ( ) . map ( |msg| msg. offset ) . unwrap_or_default ( ) ;
212+ self . nearest_message_idx = self . messages . len ( ) ;
213+ return Ok ( Some ( Action :: Render ) ) ;
214+ } ,
215+ InputEvent :: Interrupt => {
216+ // Handle interrupt - could be used to cancel current streaming message
217+ if self . current_message . is_some ( ) {
218+ self . finalize_current_message ( ) ;
219+ return Ok ( Some ( Action :: Render ) ) ;
220+ }
221+ } ,
211222 }
212223 } ,
224+ Action :: Scroll ( scroll) => match scroll {
225+ Scroll :: Up ( scroll_distance) => match scroll_distance {
226+ ScrollDistance :: Message => {
227+ if self . nearest_message_idx == 0 {
228+ return Ok ( None ) ;
229+ }
230+ self . nearest_message_idx -= 1 ;
231+ self . scroll_offset = self
232+ . messages
233+ . get ( self . nearest_message_idx )
234+ . as_ref ( )
235+ . map ( |msg| msg. offset )
236+ . unwrap_or_default ( ) ;
237+
238+ return Ok ( Some ( Action :: Render ) ) ;
239+ } ,
240+ ScrollDistance :: Line ( _) => { } ,
241+ } ,
242+ Scroll :: Down ( scroll_distance) => match scroll_distance {
243+ ScrollDistance :: Message => {
244+ if self . messages . is_empty ( ) || self . nearest_message_idx == self . messages . len ( ) - 1 {
245+ return Ok ( None ) ;
246+ }
247+ self . nearest_message_idx += 1 ;
248+ self . scroll_offset = self
249+ . messages
250+ . get ( self . nearest_message_idx )
251+ . as_ref ( )
252+ . map ( |msg| msg. offset )
253+ . unwrap_or_default ( ) ;
254+
255+ return Ok ( Some ( Action :: Render ) ) ;
256+ } ,
257+ ScrollDistance :: Line ( _) => { } ,
258+ } ,
259+ } ,
260+ _ => { } ,
213261 }
214262 }
215263
0 commit comments