Skip to content

Commit 989811e

Browse files
Merge pull request #2743 from devtron-labs/fix/announcement-banner
chore: fix multiple polling from useOnline
2 parents 959e6a7 + c34981c commit 989811e

File tree

3 files changed

+42
-42
lines changed

3 files changed

+42
-42
lines changed

src/components/common/Banner/Banner.tsx

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { useCallback, useEffect, useRef, useState } from 'react'
17+
import { useEffect, useRef, useState } from 'react'
1818

1919
import {
2020
AnimatePresence,
@@ -83,36 +83,21 @@ export const Banner = () => {
8383
const [showAnnouncementBanner, setShowAnnouncementBanner] = useState(
8484
ANNOUNCEMENT_CONFIG.message ? shouldShowAnnouncementBanner() : false,
8585
)
86-
const hasShownOnlineBanner = useRef(false)
8786
const onlineTimer = useRef<ReturnType<typeof setTimeout>>(null)
8887

89-
const onOnline = useCallback(() => {
90-
// Only show the online banner if we haven't shown it since the last offline state
91-
if (!hasShownOnlineBanner.current) {
92-
setShowOnlineBanner(true)
93-
hasShownOnlineBanner.current = true
94-
95-
// Clear any existing timer before setting a new one
96-
if (onlineTimer.current) {
97-
clearTimeout(onlineTimer.current)
98-
}
99-
100-
onlineTimer.current = setTimeout(() => setShowOnlineBanner(false), ONLINE_BANNER_TIMEOUT)
101-
}
102-
}, [])
103-
104-
const onOffline = () => {
105-
hasShownOnlineBanner.current = false
88+
const onOnline = () => {
89+
clearTimeout(onlineTimer.current)
90+
setShowOnlineBanner(true)
91+
onlineTimer.current = setTimeout(() => setShowOnlineBanner(false), ONLINE_BANNER_TIMEOUT)
10692
}
10793

108-
const isOnline = useOnline({ onOnline, onOffline })
94+
const isOnline = useOnline({ onOnline })
10995

11096
useEffect(
11197
() => () => {
11298
if (onlineTimer.current) {
11399
clearTimeout(onlineTimer.current)
114100
}
115-
hasShownOnlineBanner.current = false
116101
},
117102
[],
118103
)

src/components/common/hooks/useOnline/useOnline.ts

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,62 @@
11
import { useEffect, useRef, useState } from 'react'
22

3-
import { noop, useMainContext } from '@devtron-labs/devtron-fe-common-lib'
3+
import { getIsRequestAborted, noop, useMainContext } from '@devtron-labs/devtron-fe-common-lib'
44

55
import { getInternetConnectivity } from '@Services/service'
66

77
import { INTERNET_CONNECTIVITY_INTERVAL } from '../constants'
88

9-
export const useOnline = ({ onOnline = noop, onOffline = noop }: { onOnline?: () => void; onOffline?: () => void }) => {
9+
export const useOnline = ({ onOnline = noop }: { onOnline?: () => void }) => {
1010
const [online, setOnline] = useState(structuredClone(navigator.onLine))
1111
const abortControllerRef = useRef<AbortController>(new AbortController())
1212
const timeoutRef = useRef<NodeJS.Timeout>(null)
1313
const { isAirgapped } = useMainContext()
1414

15+
const handleClearTimeout = () => {
16+
if (timeoutRef.current) {
17+
clearTimeout(timeoutRef.current)
18+
}
19+
abortControllerRef.current.abort()
20+
}
21+
1522
const checkConnectivity = async () => {
1623
if (isAirgapped) return
17-
// Cancel any pending request
18-
if (abortControllerRef.current) {
19-
abortControllerRef.current.abort()
20-
}
2124

25+
handleClearTimeout()
2226
const controller = new AbortController()
2327
abortControllerRef.current = controller
2428

2529
try {
2630
await getInternetConnectivity(abortControllerRef.current)
27-
setOnline(true)
28-
if (online) {
29-
onOnline()
30-
}
31-
} catch {
32-
setOnline(false)
33-
} finally {
31+
setOnline((prev) => {
32+
if (!prev) {
33+
onOnline()
34+
}
35+
return true
36+
})
3437
timeoutRef.current = setTimeout(checkConnectivity, INTERNET_CONNECTIVITY_INTERVAL)
38+
} catch (error) {
39+
setOnline(false)
40+
if (!getIsRequestAborted(error)) {
41+
timeoutRef.current = setTimeout(checkConnectivity, INTERNET_CONNECTIVITY_INTERVAL)
42+
}
3543
}
3644
}
3745
const handleOffline = () => {
38-
if (timeoutRef.current) {
39-
clearTimeout(timeoutRef.current)
40-
}
41-
abortControllerRef.current.abort()
46+
handleClearTimeout()
4247
setOnline(false)
43-
if (onOffline) {
44-
onOffline()
45-
}
4648
}
4749

4850
const handleOnline = async () => {
4951
// Verify connectivity when browser reports online
5052
await checkConnectivity()
5153
}
5254

55+
useEffect(() => {
56+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
57+
handleOnline()
58+
}, [])
59+
5360
useEffect(() => {
5461
if (isAirgapped) return null
5562
window.addEventListener('online', handleOnline)

src/services/service.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,15 @@ export const getTemplateOptions = (appId: number, envId: number): Promise<Respon
559559
get(getUrlWithSearchParams(Routes.DEPLOYMENT_OPTIONS, { appId, envId }))
560560

561561
export const getInternetConnectivity = (controller: AbortController): Promise<any> => {
562+
const timeoutId = setTimeout(() => {
563+
controller.abort()
564+
}, 10000)
565+
562566
return fetch(`${window._env_?.CENTRAL_API_ENDPOINT ?? 'https://api.devtron.ai'}/${Routes.HEALTH}`, {
563567
signal: controller.signal,
564-
}).then((res) => res.json())
568+
})
569+
.then((res) => res.json())
570+
.finally(() => {
571+
clearTimeout(timeoutId)
572+
})
565573
}

0 commit comments

Comments
 (0)