11"use client" ;
22
33import { useEffect , useRef } from "react" ;
4+ import { usePathname } from "next/navigation" ;
45import { ANKI_CONFIG } from "@/config/constants" ;
56import { useToast } from "@/contexts/ToastContext" ;
67
@@ -11,16 +12,19 @@ interface APIStatus {
1112}
1213
1314export default function StatusChecker ( ) {
15+ const pathname = usePathname ( ) ;
16+ // Moved toast context hook up as it's needed even when on homepage to hide toasts
1417 const { showToast, hideAllToasts } = useToast ( ) ;
18+
1519 const statusesRef = useRef < APIStatus [ ] > ( [
1620 { name : "AnkiConnect" , description : "Anki synchronization" , available : null } ,
1721 { name : "Card Generator" , description : "Card creation API" , available : null } ,
1822 ] ) ;
1923
2024 const pollingIntervalRef = useRef < NodeJS . Timeout | null > ( null ) ;
21- const isMounted = useRef ( true ) ;
25+ const isMounted = useRef ( true ) ; // To track if component is mounted for async operations
2226
23- // Define the API status check function
27+ // Define the API status check function (no changes here)
2428 const checkAPIStatus = async ( name : string ) : Promise < boolean > => {
2529 try {
2630 if ( name === "AnkiConnect" ) {
@@ -47,50 +51,57 @@ export default function StatusChecker() {
4751 }
4852 } ;
4953
50- // Cleanup when component unmounts
54+ // Effect for mount/unmount status
5155 useEffect ( ( ) => {
56+ isMounted . current = true ;
5257 return ( ) => {
5358 isMounted . current = false ;
59+ // General cleanup for interval if component fully unmounts
5460 if ( pollingIntervalRef . current ) {
5561 clearInterval ( pollingIntervalRef . current ) ;
5662 pollingIntervalRef . current = null ;
5763 }
5864 } ;
5965 } , [ ] ) ;
6066
61- // Set up the polling mechanism
62- const POLLING_INTERVAL = 5000 ; // 5 seconds between checks
63- const SUCCESS_DISPLAY_TIME = 3000 ; // 3 seconds to display success
6467
68+ const POLLING_INTERVAL = 5000 ;
69+ const SUCCESS_DISPLAY_TIME = 3000 ;
70+
71+ // Main effect for polling and toast logic, now dependent on pathname
6572 useEffect ( ( ) => {
66- // Function to check all statuses at once
73+
74+ if ( pathname === "/" ) {
75+ if ( pollingIntervalRef . current ) {
76+ clearInterval ( pollingIntervalRef . current ) ;
77+ pollingIntervalRef . current = null ;
78+ }
79+ hideAllToasts ( ) ; // Crucial: hide toasts when navigating to or on the homepage
80+ return ;
81+ }
82+
83+ // --- Logic for non-homepage paths ---
84+
6785 const checkAllStatuses = async ( ) => {
6886 if ( ! isMounted . current ) return ;
6987
70- // Create a copy to work with
7188 const currentStatuses = [ ...statusesRef . current ] ;
7289 const updatedStatuses = [ ...currentStatuses ] ;
7390 const recoveredServices : string [ ] = [ ] ;
7491 let hasServiceDown = false ;
7592 let statusChanged = false ;
7693
77- // Check each service
7894 for ( let i = 0 ; i < updatedStatuses . length ; i ++ ) {
7995 const status = updatedStatuses [ i ] ;
8096 const isAvailable = await checkAPIStatus ( status . name ) ;
8197
82- // If status changed from not available to available (true transition)
8398 if ( status . available === false && isAvailable ) {
8499 updatedStatuses [ i ] = { ...status , available : true } ;
85100 recoveredServices . push ( status . name ) ;
86101 statusChanged = true ;
87- }
88- // If checking for the first time and it's available
89- else if ( status . available === null && isAvailable ) {
102+ } else if ( status . available === null && isAvailable ) {
90103 updatedStatuses [ i ] = { ...status , available : true } ;
91- }
92- // If service is unavailable
93- else if ( ! isAvailable ) {
104+ } else if ( ! isAvailable ) {
94105 if ( status . available !== false ) {
95106 statusChanged = true ;
96107 }
@@ -99,76 +110,72 @@ export default function StatusChecker() {
99110 }
100111 }
101112
102- // Update statuses ref
103113 statusesRef . current = updatedStatuses ;
104114
105- // Show appropriate toast notifications
106115 if ( statusChanged ) {
107- // Clear existing toasts when status changes
108116 hideAllToasts ( ) ;
109117
110- // If any service was recovered, show a success toast for it
111118 if ( recoveredServices . length > 0 ) {
112- // Show success toast for specifically recovered services
113119 showToast ( {
114120 type : 'success' ,
115121 title : `Service${ recoveredServices . length > 1 ? 's' : '' } Recovered` ,
116122 message : `${ recoveredServices . join ( ", " ) } ${ recoveredServices . length > 1 ? 'are' : 'is' } now available.` ,
117- duration : SUCCESS_DISPLAY_TIME // Show longer so users notice it
123+ duration : SUCCESS_DISPLAY_TIME
118124 } ) ;
119125 }
120126
121- // If we still have services down, show an error toast after a brief delay
122- // This prevents the toasts from appearing simultaneously
123127 if ( hasServiceDown ) {
124128 setTimeout ( ( ) => {
125129 if ( ! isMounted . current ) return ;
126-
127130 const unavailableServices = statusesRef . current
128131 . filter ( s => s . available === false )
129132 . map ( s => s . name )
130133 . join ( ", " ) ;
131-
132- showToast ( {
133- type : 'error' ,
134- title : 'Service Interruption' ,
135- message : `${ unavailableServices } ${ statusesRef . current . filter ( s => s . available === false ) . length > 1 ? 'are' : 'is' } unavailable. Please check your connections.` ,
136- duration : 0 // Keep until resolved
137- } ) ;
138- } , recoveredServices . length > 0 ? 300 : 0 ) ; // Small delay if we just showed a recovery toast
134+ if ( unavailableServices ) { // Only show if there are actually unavailable services
135+ showToast ( {
136+ type : 'error' ,
137+ title : 'Service Interruption' ,
138+ message : `${ unavailableServices } ${ statusesRef . current . filter ( s => s . available === false ) . length > 1 ? 'are' : 'is' } unavailable. Please check your connections.` ,
139+ duration : 0
140+ } ) ;
141+ }
142+ } , recoveredServices . length > 0 ? 300 : 0 ) ;
139143 } else if ( recoveredServices . length > 0 ) {
140- // If all services are up after some were down, show an additional "all clear" notification
141144 setTimeout ( ( ) => {
142145 if ( ! isMounted . current ) return ;
143-
144146 showToast ( {
145147 type : 'info' ,
146148 title : 'All Systems Operational' ,
147149 message : 'All services are now running properly.' ,
148150 duration : SUCCESS_DISPLAY_TIME
149151 } ) ;
150- } , 300 ) ; // Small delay after the recovery toast
152+ } , 300 ) ;
151153 }
152154 }
153155 } ;
154156
155- // Run initial check
157+ // Run initial check only if not on homepage (already handled by the if (pathname === "/") check)
156158 checkAllStatuses ( ) ;
157159
158- // Set up single polling interval ( only if not already set)
160+ // Set up polling interval only if not already set and not on homepage
159161 if ( ! pollingIntervalRef . current ) {
160162 pollingIntervalRef . current = setInterval ( checkAllStatuses , POLLING_INTERVAL ) ;
161163 }
162164
163- // Cleanup on effect change
165+ // Cleanup for this effect:
166+
164167 return ( ) => {
165168 if ( pollingIntervalRef . current ) {
166169 clearInterval ( pollingIntervalRef . current ) ;
167170 pollingIntervalRef . current = null ;
168171 }
172+
169173 } ;
170- } , [ showToast , hideAllToasts ] ) ; // Include toast functions as dependencies
174+ } , [ pathname , showToast , hideAllToasts ] ) ;
175+
176+ if ( pathname === "/" ) {
177+ return null ;
178+ }
171179
172- // This component doesn't render anything visible on its own now
173180 return null ;
174- }
181+ }
0 commit comments