11use std:: {
22 io,
3- sync:: { Arc , Mutex } ,
43 time:: { Duration , Instant } ,
54} ;
65
@@ -17,7 +16,6 @@ use ratatui::{
1716 text:: { Line , Span } ,
1817 widgets:: { Block , Borders , Gauge , Paragraph } ,
1918} ;
20- use rodio:: { OutputStream , Sink } ;
2119
2220mod ascii_digits;
2321mod audio;
@@ -66,22 +64,6 @@ struct PomodoroTimer {
6664
6765impl PomodoroTimer {
6866 fn new ( ) -> Result < Self , Box < dyn std:: error:: Error > > {
69- // Initialize audio system for notifications
70- let ( _stream_handle, sink) = match OutputStream :: try_default ( ) {
71- Ok ( ( stream, stream_handle) ) => match Sink :: try_new ( & stream_handle) {
72- Ok ( sink) => ( Some ( Box :: new ( stream) as Box < dyn std:: any:: Any > ) , Some ( Arc :: new ( Mutex :: new ( sink) ) ) ) ,
73- Err ( e) => {
74- eprintln ! ( "Warning: Could not create audio sink: {e}" ) ;
75- eprintln ! ( "The application will continue but notification sounds may not work." ) ;
76- ( None , None )
77- }
78- } ,
79- Err ( e) => {
80- eprintln ! ( "Warning: Could not initialize audio output: {e}" ) ;
81- eprintln ! ( "The application will continue but notification sounds may not work." ) ;
82- ( None , None )
83- }
84- } ;
8567
8668 let current_session = PomodoroSession {
8769 timer_type : TimerType :: Work ,
@@ -100,7 +82,7 @@ impl PomodoroTimer {
10082 custom_input : String :: new ( ) ,
10183 show_mario_animation : false ,
10284 mario_animation : MarioAnimation :: new ( ) ,
103- audio_manager : AudioManager { sink } ,
85+ audio_manager : AudioManager { } ,
10486 custom_work_duration : Duration :: from_secs ( 25 * 60 ) ,
10587 custom_break_duration : Duration :: from_secs ( 5 * 60 ) ,
10688 } )
@@ -279,7 +261,10 @@ impl PomodoroTimer {
279261 fn play_notification ( & self ) {
280262 match self . current_session . timer_type {
281263 TimerType :: Work => self . audio_manager . play_work_complete_sound ( ) ,
282- TimerType :: Break => self . audio_manager . play_break_complete_sound ( ) ,
264+ TimerType :: Break => {
265+ // Play the combined notification + music sequence for break completion
266+ self . audio_manager . play_break_complete_music ( ) ;
267+ }
283268 }
284269 }
285270
@@ -443,40 +428,40 @@ fn ui(f: &mut Frame, timer: &PomodoroTimer) {
443428
444429 // Custom input dialog
445430 if timer. show_custom_input {
446- let popup_area = centered_rect ( 50 , 30 , f. area ( ) ) ;
431+ let popup_area = centered_rect ( 70 , 50 , f. area ( ) ) ;
447432 f. render_widget ( ratatui:: widgets:: Clear , popup_area) ;
448433
449434 let input_popup = Paragraph :: new ( vec ! [
450- Line :: from( "" ) ,
451- Line :: from( vec![ Span :: styled(
452- "CUSTOM TIMER" ,
453- Style :: default ( ) . fg( PRIMARY_COLOR ) . add_modifier( Modifier :: BOLD ) ,
454- ) ] )
455- . alignment( Alignment :: Center ) ,
435+ // Line::from(""),
436+ // Line::from(vec![Span::styled(
437+ // "CUSTOM TIMER",
438+ // Style::default().fg(PRIMARY_COLOR).add_modifier(Modifier::BOLD),
439+ // )])
440+ // .alignment(Alignment::Center),
456441 Line :: from( "" ) ,
457442 Line :: from( vec![
458- Span :: raw( "Format: " ) ,
443+ Span :: raw( " Format: " ) ,
459444 Span :: styled( "work,break" , Style :: default ( ) . fg( HIGHLIGHT_COLOR ) ) ,
460445 Span :: raw( " or " ) ,
461446 Span :: styled( "work" , Style :: default ( ) . fg( HIGHLIGHT_COLOR ) ) ,
462447 ] ) ,
463448 Line :: from( vec![
464- Span :: raw( "Examples: " ) ,
449+ Span :: raw( " Examples: " ) ,
465450 Span :: styled( "30,10" , Style :: default ( ) . fg( HIGHLIGHT_COLOR ) ) ,
466451 Span :: raw( " or " ) ,
467452 Span :: styled( "20" , Style :: default ( ) . fg( HIGHLIGHT_COLOR ) ) ,
468453 ] ) ,
469454 Line :: from( "" ) ,
470455 Line :: from( vec![
471- Span :: raw( "Input: " ) ,
456+ Span :: raw( " Input: " ) ,
472457 Span :: styled( & timer. custom_input, Style :: default ( ) . fg( Color :: White ) . add_modifier( Modifier :: BOLD ) ) ,
473458 Span :: styled( "█" , Style :: default ( ) . fg( PRIMARY_COLOR ) ) , // Cursor
474459 ] ) ,
475460 Line :: from( "" ) ,
476461 Line :: from( vec![
477- Span :: styled( "Enter " , Style :: default ( ) . fg( PRIMARY_COLOR ) . add_modifier( Modifier :: BOLD ) ) ,
462+ Span :: styled( "↵ " , Style :: default ( ) . fg( PRIMARY_COLOR ) . add_modifier( Modifier :: BOLD ) ) ,
478463 Span :: raw( " - Confirm | " ) ,
479- Span :: styled( "Esc " , Style :: default ( ) . fg( PRIMARY_COLOR ) . add_modifier( Modifier :: BOLD ) ) ,
464+ Span :: styled( "X " , Style :: default ( ) . fg( PRIMARY_COLOR ) . add_modifier( Modifier :: BOLD ) ) ,
480465 Span :: raw( " - Cancel" ) ,
481466 ] ) ,
482467 ] )
@@ -485,7 +470,8 @@ fn ui(f: &mut Frame, timer: &PomodoroTimer) {
485470 Block :: default ( )
486471 . borders ( Borders :: ALL )
487472 . title ( "Custom Timer" )
488- . border_style ( Style :: default ( ) . fg ( PRIMARY_COLOR ) ) ,
473+ . border_style ( Style :: default ( ) . fg ( PRIMARY_COLOR ) )
474+ . title_alignment ( Alignment :: Center ) ,
489475 ) ;
490476 f. render_widget ( input_popup, popup_area) ;
491477 }
@@ -549,11 +535,7 @@ fn run_timer() -> Result<(), Box<dyn std::error::Error>> {
549535
550536 let result = main_loop ( & mut terminal, & mut timer) ;
551537
552- // Clean shutdown of audio to prevent warning messages
553- if let Some ( ref sink) = timer. audio_manager . sink {
554- let sink = sink. lock ( ) . unwrap ( ) ;
555- sink. stop ( ) ;
556- }
538+ // Audio cleanup is now handled automatically by each individual playback
557539
558540 disable_raw_mode ( ) ?;
559541 execute ! ( terminal. backend_mut( ) , LeaveAlternateScreen ) ?;
@@ -587,7 +569,7 @@ fn main_loop(terminal: &mut Terminal<CrosstermBackend<io::Stdout>>, timer: &mut
587569 if timer. show_custom_input {
588570 match key {
589571 KeyEvent {
590- code : KeyCode :: Esc ,
572+ code : KeyCode :: Char ( 'x' ) ,
591573 modifiers : KeyModifiers :: NONE ,
592574 ..
593575 } => {
0 commit comments