@@ -11,6 +11,7 @@ pub struct TodoDialog {
1111 tags : String ,
1212 filter : String ,
1313 pub persist_tags : bool ,
14+ pending_clear_confirm : bool ,
1415}
1516
1617impl TodoDialog {
@@ -21,6 +22,7 @@ impl TodoDialog {
2122 self . priority = 0 ;
2223 self . tags . clear ( ) ;
2324 self . filter . clear ( ) ;
25+ self . pending_clear_confirm = false ;
2426 }
2527
2628 fn save ( & mut self , app : & mut LauncherApp , focus : bool ) {
@@ -97,6 +99,20 @@ impl TodoDialog {
9799 true
98100 }
99101
102+ fn confirm_clear_completed ( & mut self , app : & mut LauncherApp , confirmed : bool ) {
103+ if !self . pending_clear_confirm {
104+ return ;
105+ }
106+ if confirmed {
107+ let original_len = self . entries . len ( ) ;
108+ self . entries . retain ( |e| !e. done ) ;
109+ if self . entries . len ( ) != original_len {
110+ self . save ( app, false ) ;
111+ }
112+ }
113+ self . pending_clear_confirm = false ;
114+ }
115+
100116 pub fn test_set_text ( & mut self , text : & str ) {
101117 self . text = text. to_owned ( ) ;
102118 }
@@ -119,6 +135,7 @@ impl TodoDialog {
119135 }
120136 let mut save_now = false ;
121137 let mut add_now = false ;
138+ let mut clear_confirmed: Option < bool > = None ;
122139 egui:: Window :: new ( "Todos" )
123140 . open ( & mut self . open )
124141 . resizable ( true )
@@ -189,10 +206,20 @@ impl TodoDialog {
189206 } ) ;
190207 ui. horizontal ( |ui| {
191208 if ui. button ( "Clear Completed" ) . clicked ( ) {
192- self . entries . retain ( |e| !e. done ) ;
193- save_now = true ;
209+ self . pending_clear_confirm = true ;
194210 }
195211 } ) ;
212+ if self . pending_clear_confirm {
213+ ui. horizontal ( |ui| {
214+ ui. label ( "Clear completed todos?" ) ;
215+ if ui. button ( "Confirm" ) . clicked ( ) {
216+ clear_confirmed = Some ( true ) ;
217+ }
218+ if ui. button ( "Cancel" ) . clicked ( ) {
219+ clear_confirmed = Some ( false ) ;
220+ }
221+ } ) ;
222+ }
196223 ui. separator ( ) ;
197224 ui. horizontal ( |ui| {
198225 ui. label ( "Filter" ) ;
@@ -255,6 +282,9 @@ impl TodoDialog {
255282 tracing:: debug!( "Enter pressed but todo text empty; ignoring" ) ;
256283 }
257284 }
285+ if let Some ( confirmed) = clear_confirmed {
286+ self . confirm_clear_completed ( app, confirmed) ;
287+ }
258288 if save_now {
259289 self . save ( app, false ) ;
260290 }
@@ -344,4 +374,65 @@ mod tests {
344374 assert_eq ! ( dlg. entries[ 0 ] . text, "tagged" ) ;
345375 assert_eq ! ( dlg. entries[ 0 ] . tags, vec![ "a" , "b" ] ) ;
346376 }
377+
378+ #[ test]
379+ fn clear_completed_requires_confirmation ( ) {
380+ let dir = tempdir ( ) . unwrap ( ) ;
381+ std:: env:: set_current_dir ( dir. path ( ) ) . unwrap ( ) ;
382+ let ctx = egui:: Context :: default ( ) ;
383+ let mut app = new_app ( & ctx) ;
384+ let mut dlg = TodoDialog :: default ( ) ;
385+ dlg. entries = vec ! [
386+ TodoEntry {
387+ text: "done" . into( ) ,
388+ done: true ,
389+ priority: 0 ,
390+ tags: Vec :: new( ) ,
391+ } ,
392+ TodoEntry {
393+ text: "pending" . into( ) ,
394+ done: false ,
395+ priority: 0 ,
396+ tags: Vec :: new( ) ,
397+ } ,
398+ ] ;
399+ dlg. pending_clear_confirm = true ;
400+
401+ dlg. confirm_clear_completed ( & mut app, false ) ;
402+
403+ assert_eq ! ( dlg. entries. len( ) , 2 ) ;
404+ assert ! ( dlg. entries. iter( ) . any( |e| e. done) ) ;
405+ }
406+
407+ #[ test]
408+ fn clear_completed_after_confirmation_saves ( ) {
409+ let dir = tempdir ( ) . unwrap ( ) ;
410+ std:: env:: set_current_dir ( dir. path ( ) ) . unwrap ( ) ;
411+ let ctx = egui:: Context :: default ( ) ;
412+ let mut app = new_app ( & ctx) ;
413+ let mut dlg = TodoDialog :: default ( ) ;
414+ dlg. entries = vec ! [
415+ TodoEntry {
416+ text: "done" . into( ) ,
417+ done: true ,
418+ priority: 0 ,
419+ tags: Vec :: new( ) ,
420+ } ,
421+ TodoEntry {
422+ text: "pending" . into( ) ,
423+ done: false ,
424+ priority: 0 ,
425+ tags: Vec :: new( ) ,
426+ } ,
427+ ] ;
428+ dlg. pending_clear_confirm = true ;
429+
430+ dlg. confirm_clear_completed ( & mut app, true ) ;
431+
432+ assert_eq ! ( dlg. entries. len( ) , 1 ) ;
433+ assert ! ( !dlg. entries[ 0 ] . done) ;
434+ let saved = load_todos ( TODO_FILE ) . unwrap_or_default ( ) ;
435+ assert_eq ! ( saved. len( ) , 1 ) ;
436+ assert ! ( !saved[ 0 ] . done) ;
437+ }
347438}
0 commit comments