@@ -9,7 +9,7 @@ use std::io::{self, Stdout, Write};
99use std:: sync:: mpsc;
1010use std:: time:: { Duration , Instant } ;
1111
12- use chrono:: { Datelike , Utc } ;
12+ use chrono:: { Datelike , Local , Utc } ;
1313use crossterm:: {
1414 cursor:: { Hide , MoveTo , Show } ,
1515 event:: {
@@ -877,7 +877,7 @@ fn handle_key(app: &mut App, key: KeyEvent) -> io::Result<bool> {
877877 let bp = char_byte_pos ( & app. input , app. input_cursor ) ;
878878 app. input . insert_str ( bp, & tag) ;
879879 app. input_cursor += tag. chars ( ) . count ( ) ;
880- app. tab = Tab :: Default ;
880+ app. input_mode = InputMode :: Chat ;
881881 app. focus = Focus :: Input ;
882882 return Ok ( false ) ;
883883 }
@@ -4728,10 +4728,14 @@ fn render_input_bar(stdout: &mut Stdout, app: &App, cols: u16, rows: u16) -> io:
47284728 let y_help = rows. saturating_sub ( 1 ) ;
47294729
47304730 let sep = "─" . repeat ( content_width) ;
4731+ let mode_color = match app. input_mode {
4732+ InputMode :: Chat => Color :: DarkGrey ,
4733+ InputMode :: Add => Color :: Green ,
4734+ } ;
47314735 queue ! (
47324736 stdout,
47334737 MoveTo ( x, y_sep_top) ,
4734- SetForegroundColor ( Color :: DarkGrey ) ,
4738+ SetForegroundColor ( mode_color ) ,
47354739 Print ( & sep) ,
47364740 ResetColor
47374741 ) ?;
@@ -4749,12 +4753,15 @@ fn render_input_bar(stdout: &mut Stdout, app: &App, cols: u16, rows: u16) -> io:
47494753
47504754 queue ! ( stdout, MoveTo ( x, y_input) ) ?;
47514755 match app. focus {
4752- Focus :: Input => queue ! ( stdout, ResetColor ) ?,
4756+ Focus :: Input => queue ! ( stdout, SetForegroundColor ( mode_color ) ) ?,
47534757 Focus :: Tabs | Focus :: Board | Focus :: Edit => {
47544758 queue ! ( stdout, SetForegroundColor ( Color :: DarkGrey ) ) ?
47554759 }
47564760 } ;
47574761 queue ! ( stdout, Print ( prompt) ) ?;
4762+ if app. focus == Focus :: Input {
4763+ queue ! ( stdout, ResetColor ) ?;
4764+ }
47584765
47594766 if shown. is_empty ( ) {
47604767 let placeholder = match app. input_mode {
@@ -4774,7 +4781,7 @@ fn render_input_bar(stdout: &mut Stdout, app: &App, cols: u16, rows: u16) -> io:
47744781 queue ! (
47754782 stdout,
47764783 MoveTo ( x, y_sep_bottom) ,
4777- SetForegroundColor ( Color :: DarkGrey ) ,
4784+ SetForegroundColor ( mode_color ) ,
47784785 Print ( & sep) ,
47794786 ResetColor
47804787 ) ?;
@@ -5094,7 +5101,15 @@ fn render_calendar_tab(stdout: &mut Stdout, app: &App, cols: u16, rows: u16) ->
50945101 if y_cur >= y_start + available_rows as u16 {
50955102 break ;
50965103 }
5097- let entry = format ! ( "{} • {} [{}]" , evt. start_date, evt. title, evt. calendar_name) ;
5104+ let time_str = if evt. all_day {
5105+ "All day" . to_string ( )
5106+ } else {
5107+ format ! ( "{} \u{2013} {}" , evt. start_date, evt. end_date)
5108+ } ;
5109+ let entry = format ! (
5110+ "{} \u{2022} {} [{}]" ,
5111+ time_str, evt. title, evt. calendar_name
5112+ ) ;
50985113 queue ! (
50995114 stdout,
51005115 MoveTo ( events_x, y_cur) ,
@@ -5103,6 +5118,31 @@ fn render_calendar_tab(stdout: &mut Stdout, app: &App, cols: u16, rows: u16) ->
51035118 ResetColor
51045119 ) ?;
51055120 y_cur += 1 ;
5121+ if let Some ( loc) = & evt. location {
5122+ if !loc. is_empty ( ) && y_cur < y_start + available_rows as u16 {
5123+ queue ! (
5124+ stdout,
5125+ MoveTo ( events_x, y_cur) ,
5126+ SetForegroundColor ( Color :: DarkGrey ) ,
5127+ Print ( clamp_text( & format!( " @ {}" , loc) , events_width) ) ,
5128+ ResetColor
5129+ ) ?;
5130+ y_cur += 1 ;
5131+ }
5132+ }
5133+ if let Some ( notes) = & evt. notes {
5134+ if !notes. is_empty ( ) && y_cur < y_start + available_rows as u16 {
5135+ let note_line = format ! ( " {}" , notes. lines( ) . next( ) . unwrap_or_default( ) ) ;
5136+ queue ! (
5137+ stdout,
5138+ MoveTo ( events_x, y_cur) ,
5139+ SetForegroundColor ( Color :: DarkGrey ) ,
5140+ Print ( clamp_text( & note_line, events_width) ) ,
5141+ ResetColor
5142+ ) ?;
5143+ y_cur += 1 ;
5144+ }
5145+ }
51065146 }
51075147 y_cur += 1 ;
51085148 } else if app. calendar_loading {
@@ -5224,6 +5264,7 @@ fn render_checklist_tab(stdout: &mut Stdout, app: &App, cols: u16, rows: u16) ->
52245264
52255265 let due_col_w = 12usize ;
52265266 let bucket_col_w = 14usize ;
5267+ let pri_col_w = 5usize ;
52275268
52285269 for ( draw_i, & ( task_idx, is_child) ) in ordered. iter ( ) . enumerate ( ) . skip ( scroll) . take ( list_height)
52295270 {
@@ -5254,11 +5295,26 @@ fn render_checklist_tab(stdout: &mut Stdout, app: &App, cols: u16, rows: u16) ->
52545295 . unwrap_or_else ( || "—" . to_string ( ) ) ;
52555296 let due_display = clamp_text ( & due_str, due_col_w) ;
52565297 let bucket_display = clamp_text ( & task. bucket , bucket_col_w) ;
5298+ let pri_str = match task. priority {
5299+ Priority :: Low => "Low" ,
5300+ Priority :: Medium => "Med" ,
5301+ Priority :: High => "High" ,
5302+ Priority :: Critical => "Crit" ,
5303+ } ;
5304+ let pri_display = clamp_text ( pri_str, pri_col_w) ;
52575305
52585306 let short_id = task. id . to_string ( ) . chars ( ) . take ( 8 ) . collect :: < String > ( ) ;
52595307 let id_col_w = 9 ;
5260- let fixed_cols =
5261- expand_icon. width ( ) + checkbox. len ( ) + 1 + id_col_w + 2 + due_col_w + 2 + bucket_col_w;
5308+ let fixed_cols = expand_icon. width ( )
5309+ + checkbox. len ( )
5310+ + 1
5311+ + id_col_w
5312+ + 2
5313+ + due_col_w
5314+ + 2
5315+ + bucket_col_w
5316+ + 2
5317+ + pri_col_w;
52625318 let title_max = content_width. saturating_sub ( fixed_cols + 1 ) ;
52635319 let title = clamp_text ( & task. title , title_max) ;
52645320 let title_pad = title_max. saturating_sub ( title. width ( ) ) ;
@@ -5267,7 +5323,7 @@ fn render_checklist_tab(stdout: &mut Stdout, app: &App, cols: u16, rows: u16) ->
52675323 queue ! ( stdout, MoveTo ( x, y) ) ?;
52685324 if is_sel && app. focus == Focus :: Board {
52695325 let line = format ! (
5270- "{}{} {} {}{}{}{}{}{}" ,
5326+ "{}{} {} {}{}{}{}{}{}{}{} " ,
52715327 expand_icon,
52725328 checkbox,
52735329 short_id,
@@ -5277,6 +5333,8 @@ fn render_checklist_tab(stdout: &mut Stdout, app: &App, cols: u16, rows: u16) ->
52775333 due_display,
52785334 " " . repeat( due_pad. saturating_sub( 0 ) + 2 ) ,
52795335 bucket_display,
5336+ " " ,
5337+ pri_display,
52805338 ) ;
52815339 queue ! (
52825340 stdout,
@@ -5291,19 +5349,6 @@ fn render_checklist_tab(stdout: &mut Stdout, app: &App, cols: u16, rows: u16) ->
52915349 } else {
52925350 let prefix = format ! ( "{}{} " , expand_icon, checkbox) ;
52935351 let id_str = format ! ( "{} " , short_id) ;
5294- let rest = format ! (
5295- "{}{}{}{}{}{}" ,
5296- title,
5297- " " . repeat( title_pad) ,
5298- " " ,
5299- due_display,
5300- " " . repeat( due_pad. saturating_sub( 0 ) + 2 ) ,
5301- bucket_display,
5302- ) ;
5303- let rest_padded = pad_to_width (
5304- & rest,
5305- content_width. saturating_sub ( prefix. width ( ) + id_str. width ( ) ) ,
5306- ) ;
53075352 let status_color = if task. progress == Progress :: Done {
53085353 Color :: DarkGrey
53095354 } else {
@@ -5315,6 +5360,25 @@ fn render_checklist_tab(stdout: &mut Stdout, app: &App, cols: u16, rows: u16) ->
53155360 Progress :: Done => Color :: Green ,
53165361 }
53175362 } ;
5363+ let rest_text = format ! (
5364+ "{}{}{}{}{}{}" ,
5365+ title,
5366+ " " . repeat( title_pad) ,
5367+ " " ,
5368+ due_display,
5369+ " " . repeat( due_pad. saturating_sub( 0 ) + 2 ) ,
5370+ bucket_display,
5371+ ) ;
5372+ let pri_color = match task. priority {
5373+ Priority :: Critical => Color :: Red ,
5374+ Priority :: High => Color :: Yellow ,
5375+ Priority :: Medium => Color :: White ,
5376+ Priority :: Low => Color :: DarkGrey ,
5377+ } ;
5378+ let rest_padded = pad_to_width (
5379+ & rest_text,
5380+ content_width. saturating_sub ( prefix. width ( ) + id_str. width ( ) + 2 + pri_col_w) ,
5381+ ) ;
53185382 queue ! (
53195383 stdout,
53205384 SetForegroundColor ( status_color) ,
@@ -5323,6 +5387,8 @@ fn render_checklist_tab(stdout: &mut Stdout, app: &App, cols: u16, rows: u16) ->
53235387 Print ( & id_str) ,
53245388 SetForegroundColor ( status_color) ,
53255389 Print ( & rest_padded) ,
5390+ SetForegroundColor ( pri_color) ,
5391+ Print ( format!( " {}" , pri_display) ) ,
53265392 ResetColor
53275393 ) ?;
53285394 }
@@ -5795,7 +5861,7 @@ fn render_bucket_column(
57955861}
57965862
57975863fn render_timeline_tab ( stdout : & mut Stdout , app : & mut App , cols : u16 , rows : u16 ) -> io:: Result < ( ) > {
5798- use chrono:: { Datelike , Duration as ChronoDuration , Local } ;
5864+ use chrono:: Duration as ChronoDuration ;
57995865
58005866 let width = cols as usize ;
58015867 let ( x_margin, _gap) = choose_layout ( width, 1 ) ;
@@ -6181,7 +6247,7 @@ fn render_kanban_tab(stdout: &mut Stdout, app: &mut App, cols: u16, rows: u16) -
61816247 let ( x_margin, gap) = choose_layout ( width, 4 ) ;
61826248 let x = x_margin as u16 ;
61836249 let y_help = rows. saturating_sub ( 5 ) ;
6184- let today = Utc :: now ( ) . date_naive ( ) ;
6250+ let today = Local :: now ( ) . date_naive ( ) ;
61856251
61866252 queue ! (
61876253 stdout,
@@ -6299,12 +6365,18 @@ fn render_kanban_tab(stdout: &mut Stdout, app: &mut App, cols: u16, rows: u16) -
62996365
63006366 // Due date string.
63016367 let due_str: Option < String > = task. due_date . map ( |d| {
6368+ let show_year = d. year ( ) != today. year ( ) ;
6369+ let date_fmt = if show_year {
6370+ d. format ( "%b %d %Y" ) . to_string ( )
6371+ } else {
6372+ d. format ( "%b %d" ) . to_string ( )
6373+ } ;
63026374 if d < today {
6303- format ! ( "⚠ {}" , d . format ( "%b %d" ) )
6375+ format ! ( "⚠ {}" , date_fmt )
63046376 } else if d == today {
63056377 "due today" . to_string ( )
63066378 } else {
6307- d . format ( "%b %d" ) . to_string ( )
6379+ date_fmt
63086380 }
63096381 } ) ;
63106382
0 commit comments