@@ -27,6 +27,7 @@ use iced::{
2727 Vertical ,
2828 } ,
2929 Background ,
30+ Color ,
3031 ContentFit ,
3132 Element ,
3233 Fill ,
@@ -297,6 +298,12 @@ impl App {
297298 self . paths . extend ( paths) ;
298299 }
299300
301+ /// # Current Foreground Color.
302+ const fn fg ( & self ) -> Color {
303+ if self . has_flag ( OTHER_NIGHT ) { DARK_PALETTE . text }
304+ else { LIGHT_PALETTE . text }
305+ }
306+
300307 /// # Toggle Flag.
301308 ///
302309 /// Flip the bits corresponding to a given flag, except in cases where
@@ -641,6 +648,7 @@ impl App {
641648 . width ( Fill )
642649 }
643650
651+ #[ expect( clippy:: too_many_lines, reason = "There's lots to do!" ) ]
644652 /// # View: Activity Log.
645653 ///
646654 /// This returns a table containing detailed information about each of the
@@ -653,9 +661,7 @@ impl App {
653661 if self . done . is_empty ( ) { return self . view_logo ( ) ; }
654662
655663 // Follow the theme for coloration pointers.
656- let fg =
657- if self . has_flag ( OTHER_NIGHT ) { DARK_PALETTE . text }
658- else { LIGHT_PALETTE . text } ;
664+ let fg = self . fg ( ) ;
659665
660666 // Reformat the data.
661667 let table = ActivityTable :: from ( self . done . as_slice ( ) ) ;
@@ -681,53 +687,82 @@ impl App {
681687 ) ) ;
682688
683689 // The rows, interspersed with dividers for each new source.
684- for ActivityTableRow { src, kind, quality, len, ratio, time } in table. 0 {
690+ let mut last_dir = OsStr :: new ( "" ) ;
691+ for ActivityTableRow { src, kind, quality, len, ratio, time } in & table. 0 {
685692 let Some ( dir) = src. parent ( ) . map ( Path :: as_os_str) else { continue ; } ;
686693 let Some ( file) = src. file_name ( ) else { continue ; } ;
687694 let is_src = matches ! ( kind, ImageKind :: Png | ImageKind :: Jpeg ) ;
695+ let skipped = is_src && time. is_some ( ) ;
688696 let color =
689- if is_src { fg }
697+ if is_src {
698+ if skipped { NiceColors :: RED } else { fg }
699+ }
690700 else if len. is_some ( ) { NiceColors :: GREEN }
691701 else { NiceColors :: RED } ;
692702
693- let link =
694- if len. is_some ( ) && src. is_file ( ) { Some ( Message :: OpenFile ( src. to_path_buf ( ) ) ) }
695- else { None } ;
696-
697703 if is_src {
704+ last_dir = OsStr :: new ( "" ) ;
698705 lines = lines. push ( text ( divider. clone ( ) ) . color ( NiceColors :: PINK ) ) ;
699706 }
700707
701708 lines = lines. push ( rich_text ! (
702- span( format!( "{}/" , dir. to_string_lossy( ) ) ) . color( NiceColors :: GREY ) ,
703- span( file. to_string_lossy( ) . into_owned( ) ) . color( color) . link_maybe( link) ,
704- span( format!( "{} | " , " " . repeat( widths[ 0 ] . saturating_sub( src. to_string_lossy( ) . width( ) ) ) ) ) . color( NiceColors :: PINK ) ,
709+ // Path, pretty-formatted.
710+ span( format!( "{}/" , dir. to_string_lossy( ) ) )
711+ . color(
712+ if dir == last_dir { NiceColors :: TRANSPARENT }
713+ else { NiceColors :: GREY }
714+ ) ,
715+ span( file. to_string_lossy( ) . into_owned( ) )
716+ . color( color)
717+ . link_maybe( ( len. is_some( ) && src. is_file( ) ) . then( || Message :: OpenFile ( src. to_path_buf( ) ) ) ) ,
718+ span( format!(
719+ "{:<w$} | " ,
720+ "" ,
721+ w=widths[ 0 ] . saturating_sub( src. to_string_lossy( ) . width( ) )
722+ ) )
723+ . color( NiceColors :: PINK ) ,
724+
725+ // Kind.
705726 span( format!( "{kind:<w$}" , w=widths[ 1 ] ) ) ,
706727 span( " | " ) . color( NiceColors :: PINK ) ,
728+
729+ // Quality.
707730 span( format!( "{:>w$}" , quality. as_str( ) , w=widths[ 2 ] ) ) ,
708731 span( " | " ) . color( NiceColors :: PINK ) ,
732+
733+ // Size.
709734 span( format!( "{:>w$}" , len. as_ref( ) . map_or( "" , NiceU64 :: as_str) , w=widths[ 3 ] ) ) ,
710735 span( " | " ) . color( NiceColors :: PINK ) ,
736+
737+ // Ratio.
711738 ratio. as_ref( ) . map_or_else(
712- || span( "" ) ,
739+ || span( " " . repeat ( widths [ 4 ] ) ) ,
713740 |n| {
714741 let nice = n. precise_str( 4 ) ;
715- let tmp = span( format!( "{nice:>w$}" , w=widths[ 4 ] ) ) ;
716- if nice == "1.0000" { tmp. color( NiceColors :: GREY ) }
717- else { tmp }
742+ span( format!( "{nice:>w$}" , w=widths[ 4 ] ) )
743+ . color_maybe( ( nice == "1.0000" ) . then_some( NiceColors :: GREY ) )
718744 } ,
719745 ) ,
720746 span( " | " ) . color( NiceColors :: PINK ) ,
747+
748+ // Time.
721749 time. as_ref( ) . map_or_else(
722750 || span( "" ) ,
723- |n| {
724- let nice = n. precise_str( 3 ) ;
725- let tmp = span( format!( "{nice:>w$}s" , w=widths[ 5 ] - 1 ) ) ;
726- if nice == "0.000" { tmp. color( NiceColors :: GREY ) }
727- else { tmp }
728- } ,
751+ |n|
752+ if skipped {
753+ span( format!( "{:>w$}" , "skipped" , w=widths[ 5 ] ) )
754+ . color( NiceColors :: RED )
755+ }
756+ else {
757+ let nice = n. precise_str( 3 ) ;
758+ span( format!( "{nice:>w$}s" , w=widths[ 5 ] - 1 ) )
759+ . color_maybe( ( nice == "0.000" ) . then_some( NiceColors :: GREY ) )
760+ } ,
729761 ) ,
730762 ) ) ;
763+
764+ // Update the last directory before leaving.
765+ last_dir = dir;
731766 }
732767
733768 // Add footnotes.
@@ -744,7 +779,7 @@ impl App {
744779 ) )
745780 . push ( rich_text ! (
746781 span( "**" ) . color( NiceColors :: PURPLE ) ,
747- span( " Total encoding time." ) . color( NiceColors :: GREY ) ,
782+ span( " Total encoding time, rejects and all ." ) . color( NiceColors :: GREY ) ,
748783 ) ) ;
749784
750785 scrollable ( container ( lines) . width ( Fill ) . padding ( 10 ) )
@@ -1073,7 +1108,9 @@ impl App {
10731108
10741109 let active = current. candidate . is_some ( ) ;
10751110 let new_kind = current. output_kind ( ) . unwrap_or ( ImageKind :: Png ) ;
1076- let mut formats = Vec :: new ( ) ;
1111+ let fg = self . fg ( ) ;
1112+
1113+ let mut formats = Vec :: with_capacity ( 5 ) ;
10771114 for ( flag, kind) in [
10781115 ( FMT_WEBP , ImageKind :: Webp ) ,
10791116 ( FMT_AVIF , ImageKind :: Avif ) ,
@@ -1096,18 +1133,35 @@ impl App {
10961133
10971134 column ! (
10981135 // Path.
1099- text( current. src. to_string_lossy( ) ) . color( NiceColors :: GREY ) ,
1136+ rich_text!(
1137+ span( format!(
1138+ "{}/" ,
1139+ current. src. parent( ) . map_or( Cow :: Borrowed ( "" ) , Path :: to_string_lossy)
1140+ ) )
1141+ . color( NiceColors :: GREY ) ,
1142+ span(
1143+ current. src. file_name( ) . map_or( Cow :: Borrowed ( "" ) , |o| o. to_string_lossy( ) ) . into_owned( )
1144+ )
1145+ . color( fg) ,
1146+ ) ,
11001147
11011148 // Formats.
11021149 Rich :: with_spans( formats) ,
11031150
11041151 // Cancel.
11051152 text( "" ) ,
1106-
11071153 rich_text!(
1108- span( "Not feeling it? " ) ,
1109- span( "Skip this image." )
1110- . color( NiceColors :: ORANGE )
1154+ span( "Ready for bed? " )
1155+ . color(
1156+ if active { fg }
1157+ else { fg. scale_alpha( 0.5 ) }
1158+ ) ,
1159+ span( "Skip ahead!" )
1160+ . color(
1161+ if active { NiceColors :: ORANGE }
1162+ else { NiceColors :: ORANGE . scale_alpha( 0.5 ) }
1163+ )
1164+ . font( FONT_BOLD )
11111165 . link_maybe( active. then_some( Message :: NextImage ) ) ,
11121166 )
11131167 )
@@ -1336,7 +1390,10 @@ impl<'a> From<&'a [ImageResults]> for ActivityTable<'a> {
13361390 quality : QualityValueFmt :: None ,
13371391 len : Some ( NiceU64 :: from ( job. src_len ) ) ,
13381392 ratio : Some ( NiceFloat :: from ( 1.0 ) ) ,
1339- time : None ,
1393+
1394+ // Sources never have times; we can use this to signal when
1395+ // an image was skipped.
1396+ time : job. dst . is_empty ( ) . then_some ( & NiceFloat :: ZERO ) ,
13401397 } ) ;
13411398
13421399 // Push the conversions.
@@ -1437,7 +1494,12 @@ impl ActivityTableRow<'_> {
14371494 self . quality . len ( ) ,
14381495 self . len . as_ref ( ) . map_or ( 0 , NiceU64 :: len) ,
14391496 self . ratio . as_ref ( ) . map_or ( 0 , |n| n. precise_str ( 4 ) . len ( ) ) ,
1440- self . time . as_ref ( ) . map_or ( 0 , |n| n. precise_str ( 3 ) . len ( ) + 1 ) ,
1497+ self . time . as_ref ( ) . map_or ( 0 , |n|
1498+ // Sources never have times; if there's a value here, it'll
1499+ // get printed as "skipped".
1500+ if matches ! ( self . kind, ImageKind :: Jpeg | ImageKind :: Png ) { 7 }
1501+ else { n. precise_str ( 3 ) . len ( ) + 1 }
1502+ ) ,
14411503 ]
14421504 }
14431505}
0 commit comments