@@ -578,19 +578,6 @@ fn parse_event_range(event: &DisplayEvent) -> Option<(u32, u32)> {
578578 Some ( ( event_start, event_end) )
579579}
580580
581- /// Check if a given 30-minute slot is busy
582- /// slot_start is minutes from midnight (e.g., 8*60 = 480 for 8:00am)
583- fn is_slot_busy ( events : & [ DisplayEvent ] , slot_start : u32 , slot_end : u32 ) -> bool {
584- for event in events {
585- if let Some ( ( event_start, event_end) ) = parse_event_range ( event) {
586- if slot_start < event_end && slot_end > event_start {
587- return true ;
588- }
589- }
590- }
591- false
592- }
593-
594581/// Detect overlapping events across two source panels.
595582/// Returns sets of indices into google_events and icloud_events that overlap with any other event.
596583fn compute_overlapping_events (
@@ -643,6 +630,14 @@ fn compute_overlapping_events(
643630 ( google_overlaps, icloud_overlaps)
644631}
645632
633+ /// Count how many time-blocking events cover a given slot (across both sources).
634+ fn count_slot_events ( google_events : & [ DisplayEvent ] , icloud_events : & [ DisplayEvent ] , slot_start : u32 , slot_end : u32 ) -> usize {
635+ google_events. iter ( ) . chain ( icloud_events. iter ( ) )
636+ . filter_map ( parse_event_range)
637+ . filter ( |( es, ee) | slot_start < * ee && slot_end > * es)
638+ . count ( )
639+ }
640+
646641/// Get the Monday of the week containing the given date
647642fn get_week_monday ( date : NaiveDate ) -> NaiveDate {
648643 let weekday = date. weekday ( ) . num_days_from_monday ( ) ;
@@ -697,24 +692,36 @@ fn render_week_availability(
697692 let slot2_start = hour * 60 + 30 ; // :30
698693 let slot2_end = ( hour + 1 ) * 60 ; // :00 next hour
699694
700- let first_half_busy = is_slot_busy ( google_events, slot1_start, slot1_end)
701- || is_slot_busy ( icloud_events, slot1_start, slot1_end) ;
702- let second_half_busy = is_slot_busy ( google_events, slot2_start, slot2_end)
703- || is_slot_busy ( icloud_events, slot2_start, slot2_end) ;
695+ let first_half_count = count_slot_events ( google_events, icloud_events, slot1_start, slot1_end) ;
696+ let second_half_count = count_slot_events ( google_events, icloud_events, slot2_start, slot2_end) ;
697+
698+ let first_half_busy = first_half_count > 0 ;
699+ let second_half_busy = second_half_count > 0 ;
700+
701+ let color_for = |count : usize | -> Color {
702+ if count >= 2 { colors:: OVERLAP_EVENT } else { colors:: BUSY_BLOCK }
703+ } ;
704704
705705 // Vertical half-blocks: top = first 30 min, bottom = second 30 min
706706 // ▀ draws top with fg, bottom with bg
707707 match ( first_half_busy, second_half_busy) {
708708 ( true , true ) => {
709- execute ! ( out, SetForegroundColor ( colors:: BUSY_BLOCK ) ) . unwrap ( ) ;
710- print ! ( "██" ) ;
709+ let top = color_for ( first_half_count) ;
710+ let bot = color_for ( second_half_count) ;
711+ if top == bot {
712+ execute ! ( out, SetForegroundColor ( top) ) . unwrap ( ) ;
713+ print ! ( "██" ) ;
714+ } else {
715+ execute ! ( out, SetForegroundColor ( top) , SetBackgroundColor ( bot) ) . unwrap ( ) ;
716+ print ! ( "▀▀" ) ;
717+ }
711718 }
712719 ( true , false ) => {
713- execute ! ( out, SetForegroundColor ( colors :: BUSY_BLOCK ) , SetBackgroundColor ( colors:: FREE_BLOCK ) ) . unwrap ( ) ;
720+ execute ! ( out, SetForegroundColor ( color_for ( first_half_count ) ) , SetBackgroundColor ( colors:: FREE_BLOCK ) ) . unwrap ( ) ;
714721 print ! ( "▀▀" ) ;
715722 }
716723 ( false , true ) => {
717- execute ! ( out, SetForegroundColor ( colors:: FREE_BLOCK ) , SetBackgroundColor ( colors :: BUSY_BLOCK ) ) . unwrap ( ) ;
724+ execute ! ( out, SetForegroundColor ( colors:: FREE_BLOCK ) , SetBackgroundColor ( color_for ( second_half_count ) ) ) . unwrap ( ) ;
718725 print ! ( "▀▀" ) ;
719726 }
720727 ( false , false ) => {
0 commit comments