@@ -30,6 +30,8 @@ export class PomodoroTimer {
3030 this . currentSessionElapsedTime = 0 ; // Actual elapsed time for current session (in seconds)
3131 this . lastCompletedSessionTime = 0 ; // Time of the last completed session for undo functionality
3232 this . sessionCompletedButNotSaved = false ; // Flag to track if session completed but not saved yet
33+ this . maxSessionTime = 120 * 60 * 1000 ; // Default 2 hours in milliseconds
34+ this . maxSessionTimeReached = false ; // Flag to track if max session time was reached
3335
3436 // Timer accuracy tracking (for background throttling fix)
3537 this . timerStartTime = null ; // When the timer was started (Date.now())
@@ -86,6 +88,10 @@ export class PomodoroTimer {
8688 skip : "CommandOrControl+Alt+S" // Save Session
8789 } ;
8890
91+ // Midnight monitoring for daily reset
92+ this . midnightMonitorInterval = null ;
93+ this . currentDateString = new Date ( ) . toDateString ( ) ;
94+
8995 this . init ( ) ;
9096 }
9197
@@ -180,6 +186,9 @@ export class PomodoroTimer {
180186
181187 // Initialize tray menu state
182188 this . updateTrayMenu ( ) ;
189+
190+ // Start midnight monitoring for daily reset
191+ this . startMidnightMonitoring ( ) ;
183192 }
184193
185194 setupEventListeners ( ) {
@@ -667,6 +676,9 @@ export class PomodoroTimer {
667676 }
668677 }
669678
679+ // Check if max session time has been reached
680+ this . checkMaxSessionTime ( ) ;
681+
670682 this . updateDisplay ( ) ;
671683
672684 // Warning when less than 2 minutes remaining
@@ -696,6 +708,35 @@ export class PomodoroTimer {
696708 }
697709 }
698710
711+ checkMaxSessionTime ( ) {
712+ // Only check during focus sessions and if a session is active
713+ if ( this . currentMode !== 'focus' || ! this . sessionStartTime || this . maxSessionTimeReached ) {
714+ return ;
715+ }
716+
717+ const now = Date . now ( ) ;
718+ const sessionElapsed = now - this . sessionStartTime ;
719+
720+ // Check if session has exceeded max time
721+ if ( sessionElapsed >= this . maxSessionTime ) {
722+ this . maxSessionTimeReached = true ;
723+ this . pauseTimer ( ) ;
724+
725+ // Show notification
726+ const maxTimeInMinutes = Math . floor ( this . maxSessionTime / ( 60 * 1000 ) ) ;
727+ NotificationUtils . showNotificationPing (
728+ `Session automatically paused after ${ maxTimeInMinutes } minutes. Take a break! 🛑` ,
729+ 'warning'
730+ ) ;
731+
732+ // Show desktop notification if enabled
733+ NotificationUtils . showDesktopNotification (
734+ 'Session Time Limit Reached' ,
735+ `Your session has been automatically paused after ${ maxTimeInMinutes } minutes. Consider taking a break!`
736+ ) ;
737+ }
738+ }
739+
699740 pauseTimer ( ) {
700741 if ( this . isRunning ) {
701742 this . isRunning = false ;
@@ -748,6 +789,7 @@ export class PomodoroTimer {
748789 this . sessionStartTime = null ;
749790 this . currentSessionElapsedTime = 0 ;
750791 this . sessionCompletedButNotSaved = false ; // Reset flag
792+ this . maxSessionTimeReached = false ; // Reset max session time flag
751793
752794 // Reset timer accuracy tracking
753795 this . timerStartTime = null ;
@@ -801,6 +843,82 @@ export class PomodoroTimer {
801843 ) ;
802844 }
803845
846+ // Midnight monitoring methods for daily reset
847+ startMidnightMonitoring ( ) {
848+ // Clear any existing monitoring
849+ this . stopMidnightMonitoring ( ) ;
850+
851+ // Check for date change every minute
852+ this . midnightMonitorInterval = setInterval ( ( ) => {
853+ this . checkForMidnightReset ( ) ;
854+ } , 60000 ) ; // Check every minute
855+
856+ console . log ( '🌙 Midnight monitoring started' ) ;
857+ }
858+
859+ stopMidnightMonitoring ( ) {
860+ if ( this . midnightMonitorInterval ) {
861+ clearInterval ( this . midnightMonitorInterval ) ;
862+ this . midnightMonitorInterval = null ;
863+ console . log ( '🌙 Midnight monitoring stopped' ) ;
864+ }
865+ }
866+
867+ checkForMidnightReset ( ) {
868+ const newDateString = new Date ( ) . toDateString ( ) ;
869+
870+ if ( newDateString !== this . currentDateString ) {
871+ console . log ( '🌙 Date change detected:' , this . currentDateString , '→' , newDateString ) ;
872+ this . currentDateString = newDateString ;
873+ this . performMidnightReset ( ) ;
874+ }
875+ }
876+
877+ async performMidnightReset ( ) {
878+ console . log ( '🌅 Performing midnight reset...' ) ;
879+
880+ // Store previous session count for notification
881+ const previousPomodoros = this . completedPomodoros ;
882+
883+ // Use enhanced loadSessionData with force reset to ensure clean state
884+ await this . loadSessionData ( true ) ;
885+
886+ // Update display to show the reset state
887+ this . updateDisplay ( ) ;
888+
889+ // Save the reset state
890+ await this . saveSessionData ( ) ;
891+
892+ // Show user notification about the reset
893+ if ( previousPomodoros > 0 ) {
894+ NotificationUtils . showNotificationPing (
895+ `New day! Yesterday's ${ previousPomodoros } sessions have been saved. Fresh start! 🌅` ,
896+ 'info'
897+ ) ;
898+ } else {
899+ NotificationUtils . showNotificationPing (
900+ 'Good morning! Ready for a productive new day? 🌅' ,
901+ 'info'
902+ ) ;
903+ }
904+
905+ // Update all visual elements
906+ this . updateTrayIcon ( ) ;
907+
908+ // Refresh navigation charts if available
909+ if ( window . navigationManager ) {
910+ try {
911+ await window . navigationManager . updateDailyChart ( ) ;
912+ await window . navigationManager . updateFocusSummary ( ) ;
913+ await window . navigationManager . updateWeeklySessionsChart ( ) ;
914+ } catch ( error ) {
915+ console . error ( 'Failed to update navigation charts after midnight reset:' , error ) ;
916+ }
917+ }
918+
919+ console . log ( '✅ Midnight reset completed successfully' ) ;
920+ }
921+
804922 async skipSession ( ) {
805923 this . isRunning = false ;
806924 this . isPaused = false ;
@@ -835,8 +953,24 @@ export class PomodoroTimer {
835953 } else {
836954 this . currentMode = 'break' ;
837955 }
956+
957+ // Reset display state tracking when switching to break modes
958+ this . _lastLoggedState = null ;
959+ this . _lastAutoPausedLogged = false ;
960+ this . _lastPausedLogged = false ;
838961 } else {
839962 this . currentMode = 'focus' ;
963+
964+ // Reset display state tracking when switching to focus mode
965+ this . _lastLoggedState = null ;
966+ this . _lastAutoPausedLogged = false ;
967+ this . _lastPausedLogged = false ;
968+
969+ // Restore TagManager display when returning to focus mode
970+ if ( window . tagManager ) {
971+ window . tagManager . updateStatusDisplay ( ) ;
972+ }
973+
840974 if ( this . completedPomodoros < this . totalSessions ) {
841975 this . currentSession = this . completedPomodoros + 1 ;
842976 }
@@ -884,8 +1018,18 @@ export class PomodoroTimer {
8841018 } else {
8851019 this . currentMode = 'break' ;
8861020 }
1021+
1022+ // Reset display state tracking when switching to break modes
1023+ this . _lastLoggedState = null ;
1024+ this . _lastAutoPausedLogged = false ;
1025+ this . _lastPausedLogged = false ;
8871026 } else {
8881027 this . currentMode = 'focus' ;
1028+
1029+ // Reset display state tracking when switching to focus mode
1030+ this . _lastLoggedState = null ;
1031+ this . _lastAutoPausedLogged = false ;
1032+ this . _lastPausedLogged = false ;
8891033
8901034 // Restore TagManager display when returning to focus mode
8911035 if ( window . tagManager ) {
@@ -962,6 +1106,11 @@ export class PomodoroTimer {
9621106 } else {
9631107 this . currentMode = 'break' ;
9641108 }
1109+
1110+ // Reset display state tracking when switching to break modes
1111+ this . _lastLoggedState = null ;
1112+ this . _lastAutoPausedLogged = false ;
1113+ this . _lastPausedLogged = false ;
9651114 }
9661115 } else {
9671116 // Break completed
@@ -971,6 +1120,11 @@ export class PomodoroTimer {
9711120 } else {
9721121 // Traditional behavior - go back to focus
9731122 this . currentMode = 'focus' ;
1123+
1124+ // Reset display state tracking when switching to focus mode
1125+ this . _lastLoggedState = null ;
1126+ this . _lastAutoPausedLogged = false ;
1127+ this . _lastPausedLogged = false ;
9741128
9751129 // Restore TagManager display when returning to focus mode
9761130 if ( window . tagManager ) {
@@ -986,6 +1140,7 @@ export class PomodoroTimer {
9861140 this . sessionStartTime = null ;
9871141 this . currentSessionElapsedTime = 0 ;
9881142 this . sessionCompletedButNotSaved = false ; // Reset flag
1143+ this . maxSessionTimeReached = false ; // Reset max session time flag
9891144
9901145 // Reset timer accuracy tracking
9911146 this . timerStartTime = null ;
@@ -1581,6 +1736,7 @@ export class PomodoroTimer {
15811736 this . currentSessionElapsedTime = 0 ;
15821737 this . lastCompletedSessionTime = 0 ;
15831738 this . sessionCompletedButNotSaved = false ; // Reset flag
1739+ this . maxSessionTimeReached = false ; // Reset max session time flag
15841740
15851741 // Reset timer accuracy tracking
15861742 this . timerStartTime = null ;
@@ -1932,26 +2088,57 @@ export class PomodoroTimer {
19322088 }
19332089 }
19342090
1935- async loadSessionData ( ) {
2091+ async loadSessionData ( forceReset = false ) {
2092+ const today = new Date ( ) . toDateString ( ) ;
2093+
2094+ // Update current date string for midnight monitoring
2095+ this . currentDateString = today ;
2096+
19362097 try {
19372098 const data = await invoke ( 'load_session_data' ) ;
1938- if ( data && data . date === new Date ( ) . toDateString ( ) ) {
2099+ if ( data && data . date === today && ! forceReset ) {
2100+ // Load today's session data
19392101 this . completedPomodoros = data . completed_pomodoros || 0 ;
19402102 this . totalFocusTime = data . total_focus_time || 0 ;
19412103 this . currentSession = data . current_session || 1 ;
19422104 this . updateProgressDots ( ) ;
2105+ console . log ( '📊 Loaded existing session data for today' ) ;
2106+ } else {
2107+ // Reset to default values for new day, no data, or forced reset
2108+ this . completedPomodoros = 0 ;
2109+ this . totalFocusTime = 0 ;
2110+ this . currentSession = 1 ;
2111+ this . updateProgressDots ( ) ;
2112+ console . log ( '🌅 Reset session data for new day or forced reset' ) ;
19432113 }
19442114 } catch ( error ) {
19452115 console . error ( 'Failed to load session data from Tauri, using localStorage:' , error ) ;
19462116 const saved = localStorage . getItem ( 'pomodoro-session' ) ;
2117+
19472118 if ( saved ) {
19482119 const data = JSON . parse ( saved ) ;
1949- if ( data . date === new Date ( ) . toDateString ( ) ) {
2120+ if ( data . date === today && ! forceReset ) {
2121+ // Load today's session data from localStorage
19502122 this . completedPomodoros = data . completedPomodoros || 0 ;
19512123 this . totalFocusTime = data . totalFocusTime || 0 ;
19522124 this . currentSession = data . currentSession || 1 ;
19532125 this . updateProgressDots ( ) ;
2126+ console . log ( '📊 Loaded existing session data from localStorage' ) ;
2127+ } else {
2128+ // Reset to default values for new day, no data, or forced reset
2129+ this . completedPomodoros = 0 ;
2130+ this . totalFocusTime = 0 ;
2131+ this . currentSession = 1 ;
2132+ this . updateProgressDots ( ) ;
2133+ console . log ( '🌅 Reset session data from localStorage for new day or forced reset' ) ;
19542134 }
2135+ } else {
2136+ // No saved data at all, reset to defaults
2137+ this . completedPomodoros = 0 ;
2138+ this . totalFocusTime = 0 ;
2139+ this . currentSession = 1 ;
2140+ this . updateProgressDots ( ) ;
2141+ console . log ( '🌅 No saved data found, using defaults' ) ;
19552142 }
19562143 }
19572144 }
@@ -2089,6 +2276,9 @@ export class PomodoroTimer {
20892276 }
20902277
20912278 this . totalSessions = settings . timer . total_sessions ;
2279+
2280+ // Update max session time (convert from minutes to milliseconds)
2281+ this . maxSessionTime = ( settings . timer . max_session_time || 120 ) * 60 * 1000 ;
20922282
20932283 // If timer is not running, update current time remaining
20942284 if ( ! this . isRunning ) {
@@ -2160,6 +2350,9 @@ export class PomodoroTimer {
21602350 this . smartPauseEnabled = false ;
21612351 this . inactivityThreshold = 30000 ; // Reset to default 30 seconds
21622352
2353+ // Clear midnight monitoring
2354+ this . stopMidnightMonitoring ( ) ;
2355+
21632356 // Reset all counters and state
21642357 this . completedPomodoros = 0 ;
21652358 this . generateProgressDots ( ) ;
@@ -2172,6 +2365,7 @@ export class PomodoroTimer {
21722365 this . sessionStartTime = null ;
21732366 this . currentSessionElapsedTime = 0 ;
21742367 this . lastCompletedSessionTime = 0 ;
2368+ this . maxSessionTimeReached = false ; // Reset max session time flag
21752369
21762370 // Reset timer accuracy tracking
21772371 this . timerStartTime = null ;
@@ -2207,6 +2401,9 @@ export class PomodoroTimer {
22072401 this . updateTrayIcon ( ) ;
22082402 this . updateSettingIndicators ( ) ;
22092403
2404+ // Restart midnight monitoring
2405+ this . startMidnightMonitoring ( ) ;
2406+
22102407 console . log ( 'Timer reset to initial state' ) ;
22112408 }
22122409}
0 commit comments