1
1
use crate :: {
2
2
components:: {
3
- dialog_paragraph, utils:: time_to_string, CommandBlocking ,
4
- CommandInfo , Component , DrawableComponent , EventState ,
5
- ScrollType ,
3
+ dialog_paragraph,
4
+ utils:: { scroll_vertical:: VerticalScroll , time_to_string} ,
5
+ CommandBlocking , CommandInfo , Component , DrawableComponent ,
6
+ EventState , ScrollType ,
6
7
} ,
7
8
keys:: SharedKeyConfig ,
8
9
strings:: { self , order} ,
9
- ui:: { self , style:: SharedTheme } ,
10
+ ui:: style:: SharedTheme ,
10
11
} ;
11
12
use anyhow:: Result ;
12
13
use asyncgit:: {
@@ -37,10 +38,9 @@ pub struct DetailsComponent {
37
38
tags : Vec < String > ,
38
39
theme : SharedTheme ,
39
40
focused : bool ,
40
- current_size : Cell < ( u16 , u16 ) > ,
41
- scroll_top : Cell < usize > ,
41
+ current_width : Cell < u16 > ,
42
+ scroll : VerticalScroll ,
42
43
key_config : SharedKeyConfig ,
43
- scroll_to_bottom_on_redraw : Cell < bool > ,
44
44
}
45
45
46
46
type WrappedCommitMessage < ' a > =
@@ -58,9 +58,8 @@ impl DetailsComponent {
58
58
tags : Vec :: new ( ) ,
59
59
theme,
60
60
focused,
61
- current_size : Cell :: new ( ( 0 , 0 ) ) ,
62
- scroll_top : Cell :: new ( 0 ) ,
63
- scroll_to_bottom_on_redraw : Cell :: new ( false ) ,
61
+ current_width : Cell :: new ( 0 ) ,
62
+ scroll : VerticalScroll :: new ( ) ,
64
63
key_config,
65
64
}
66
65
}
@@ -75,7 +74,7 @@ impl DetailsComponent {
75
74
self . data =
76
75
id. and_then ( |id| sync:: get_commit_details ( CWD , id) . ok ( ) ) ;
77
76
78
- self . scroll_top . set ( 0 ) ;
77
+ self . scroll . reset ( ) ;
79
78
80
79
if let Some ( tags) = tags {
81
80
self . tags . extend ( tags) ;
@@ -141,7 +140,7 @@ impl DetailsComponent {
141
140
. concat ( )
142
141
. iter ( )
143
142
. enumerate ( )
144
- . skip ( self . scroll_top . get ( ) )
143
+ . skip ( self . scroll . get ( ) )
145
144
. take ( height)
146
145
. map ( |( i, line) | {
147
146
Spans :: from ( vec ! [ Span :: styled(
@@ -275,34 +274,10 @@ impl DetailsComponent {
275
274
276
275
fn move_scroll_top ( & mut self , move_type : ScrollType ) -> bool {
277
276
if self . data . is_some ( ) {
278
- let old = self . scroll_top . get ( ) ;
279
- let width = self . current_size . get ( ) . 0 as usize ;
280
- let height = self . current_size . get ( ) . 1 as usize ;
281
-
282
- let number_of_lines =
283
- Self :: get_number_of_lines ( & self . data , width) ;
284
-
285
- let max = number_of_lines. saturating_sub ( height) as usize ;
286
-
287
- let new_scroll_top = match move_type {
288
- ScrollType :: Down => old. saturating_add ( 1 ) ,
289
- ScrollType :: Up => old. saturating_sub ( 1 ) ,
290
- ScrollType :: Home => 0 ,
291
- ScrollType :: End => max,
292
- _ => old,
293
- } ;
294
-
295
- let new_scroll_top = new_scroll_top. clamp ( 0 , max) ;
296
-
297
- if new_scroll_top == old {
298
- return false ;
299
- }
300
-
301
- self . scroll_top . set ( new_scroll_top) ;
302
-
303
- return true ;
277
+ self . scroll . move_top ( move_type)
278
+ } else {
279
+ false
304
280
}
305
- false
306
281
}
307
282
}
308
283
@@ -312,6 +287,9 @@ impl DrawableComponent for DetailsComponent {
312
287
f : & mut Frame < B > ,
313
288
rect : Rect ,
314
289
) -> Result < ( ) > {
290
+ const CANSCROLL_STRING : & str = "[\u{2026} ]" ;
291
+ const EMPTY_STRING : & str = "" ;
292
+
315
293
let chunks = Layout :: default ( )
316
294
. direction ( Direction :: Vertical )
317
295
. constraints (
@@ -338,28 +316,35 @@ impl DrawableComponent for DetailsComponent {
338
316
let width = chunks[ 1 ] . width . saturating_sub ( border_width) ;
339
317
let height = chunks[ 1 ] . height . saturating_sub ( border_width) ;
340
318
341
- self . current_size . set ( ( width, height) ) ;
342
-
343
- if self . scroll_to_bottom_on_redraw . get ( ) {
344
- self . scroll_top . set (
345
- Self :: get_number_of_lines (
346
- & self . data ,
347
- usize:: from ( width) ,
348
- )
349
- . saturating_sub ( usize:: from ( height) ) ,
350
- ) ;
351
- self . scroll_to_bottom_on_redraw . set ( false ) ;
352
- }
319
+ self . current_width . set ( width) ;
353
320
354
321
let wrapped_lines = self . get_wrapped_text_message (
355
322
width as usize ,
356
323
height as usize ,
357
324
) ;
358
325
326
+ let number_of_lines =
327
+ Self :: get_number_of_lines ( & self . data , usize:: from ( width) ) ;
328
+
329
+ self . scroll . update_no_selection (
330
+ number_of_lines,
331
+ usize:: from ( height) ,
332
+ ) ;
333
+
334
+ let can_scroll = usize:: from ( height) < number_of_lines;
335
+
359
336
f. render_widget (
360
337
dialog_paragraph (
361
- & strings:: commit:: details_message_title (
362
- & self . key_config ,
338
+ & format ! (
339
+ "{} {}" ,
340
+ strings:: commit:: details_message_title(
341
+ & self . key_config,
342
+ ) ,
343
+ if !self . focused && can_scroll {
344
+ CANSCROLL_STRING
345
+ } else {
346
+ EMPTY_STRING
347
+ }
363
348
) ,
364
349
Text :: from ( wrapped_lines) ,
365
350
& self . theme ,
@@ -369,13 +354,7 @@ impl DrawableComponent for DetailsComponent {
369
354
) ;
370
355
371
356
if self . focused {
372
- ui:: draw_scrollbar (
373
- f,
374
- chunks[ 1 ] ,
375
- & self . theme ,
376
- Self :: get_number_of_lines ( & self . data , width as usize ) ,
377
- self . scroll_top . get ( ) ,
378
- ) ;
357
+ self . scroll . draw ( f, chunks[ 1 ] , & self . theme ) ;
379
358
}
380
359
381
360
Ok ( ( ) )
@@ -388,9 +367,7 @@ impl Component for DetailsComponent {
388
367
out : & mut Vec < CommandInfo > ,
389
368
force_all : bool ,
390
369
) -> CommandBlocking {
391
- // visibility_blocking(self)
392
-
393
- let width = self . current_size . get ( ) . 0 as usize ;
370
+ let width = usize:: from ( self . current_width . get ( ) ) ;
394
371
let number_of_lines =
395
372
Self :: get_number_of_lines ( & self . data , width) ;
396
373
@@ -437,10 +414,6 @@ impl Component for DetailsComponent {
437
414
}
438
415
439
416
fn focus ( & mut self , focus : bool ) {
440
- if focus {
441
- self . scroll_to_bottom_on_redraw . set ( true ) ;
442
- }
443
-
444
417
self . focused = focus;
445
418
}
446
419
}
0 commit comments