mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-28 16:20:57 -05:00
fix(iframe-loader): add fallback for iframe loading
Some browsers (mostly cypress's chrome) doesn't execute the onLoad callback automatically on the iframe. The fallback is a timer that triggers this after a timeout of 500ms. Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
62abd9cbe0
commit
5a1edea00a
2 changed files with 64 additions and 2 deletions
|
@ -7,7 +7,9 @@ import { ORIGIN, useBaseUrl } from '../../../../hooks/common/use-base-url'
|
||||||
import { Logger } from '../../../../utils/logger'
|
import { Logger } from '../../../../utils/logger'
|
||||||
import { useEditorToRendererCommunicator } from '../../../editor-page/render-context/editor-to-renderer-communicator-context-provider'
|
import { useEditorToRendererCommunicator } from '../../../editor-page/render-context/editor-to-renderer-communicator-context-provider'
|
||||||
import type { RefObject } from 'react'
|
import type { RefObject } from 'react'
|
||||||
import { useCallback, useMemo, useRef } from 'react'
|
import { useCallback, useEffect, useMemo, useRef } from 'react'
|
||||||
|
import { useTimeoutFn } from '../../../../hooks/common/use-timeout-fn'
|
||||||
|
import { isTestMode } from '../../../../utils/test-modes'
|
||||||
|
|
||||||
const log = new Logger('IframeLoader')
|
const log = new Logger('IframeLoader')
|
||||||
|
|
||||||
|
@ -31,7 +33,9 @@ export const useForceRenderPageUrlOnIframeLoadCallback = (
|
||||||
}, [iframeCommunicator, rendererBaseUrl])
|
}, [iframeCommunicator, rendererBaseUrl])
|
||||||
const redirectionInProgress = useRef<boolean>(false)
|
const redirectionInProgress = useRef<boolean>(false)
|
||||||
|
|
||||||
return useCallback(() => {
|
const loadedAtLeastOnce = useRef(false)
|
||||||
|
|
||||||
|
const onIframeLoad = useCallback(() => {
|
||||||
const frame = iFrameReference.current
|
const frame = iFrameReference.current
|
||||||
|
|
||||||
if (!frame) {
|
if (!frame) {
|
||||||
|
@ -45,9 +49,31 @@ export const useForceRenderPageUrlOnIframeLoadCallback = (
|
||||||
} else {
|
} else {
|
||||||
const oldUrl = frame.src === '' ? '(none)' : frame.src
|
const oldUrl = frame.src === '' ? '(none)' : frame.src
|
||||||
log.warn(`Navigated away from unknown URL. Was ${oldUrl}. Forcing back to ${forcedUrl}`)
|
log.warn(`Navigated away from unknown URL. Was ${oldUrl}. Forcing back to ${forcedUrl}`)
|
||||||
|
loadedAtLeastOnce.current = true
|
||||||
onNavigateAway?.()
|
onNavigateAway?.()
|
||||||
redirectionInProgress.current = true
|
redirectionInProgress.current = true
|
||||||
frame.src = forcedUrl
|
frame.src = forcedUrl
|
||||||
}
|
}
|
||||||
}, [iFrameReference, onNavigateAway, forcedUrl])
|
}, [iFrameReference, onNavigateAway, forcedUrl])
|
||||||
|
|
||||||
|
const [startForceTimer, stopForceTimer] = useTimeoutFn(
|
||||||
|
500,
|
||||||
|
useCallback(() => {
|
||||||
|
if (loadedAtLeastOnce.current) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.debug('Forced load of iframe')
|
||||||
|
onIframeLoad()
|
||||||
|
}, [onIframeLoad])
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isTestMode) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
startForceTimer()
|
||||||
|
return () => stopForceTimer()
|
||||||
|
}, [startForceTimer, stopForceTimer])
|
||||||
|
|
||||||
|
return onIframeLoad
|
||||||
}
|
}
|
||||||
|
|
36
frontend/src/hooks/common/use-timeout-fn.ts
Normal file
36
frontend/src/hooks/common/use-timeout-fn.ts
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useCallback, useRef } from 'react'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a timer with the given timeout and callback.
|
||||||
|
* The timer is not started automatically.
|
||||||
|
*
|
||||||
|
* @param timeout The timeout in milliseconds
|
||||||
|
* @param callback The callback to execute when the time is up
|
||||||
|
* @return [startTimer, stopTimer] Functions to start and stop the timeout
|
||||||
|
*/
|
||||||
|
export const useTimeoutFn = (timeout: number, callback: () => void) => {
|
||||||
|
const timerRef = useRef<NodeJS.Timeout | null>(null)
|
||||||
|
|
||||||
|
const stopTimer = useCallback(() => {
|
||||||
|
if (timerRef.current === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
clearTimeout(timerRef.current)
|
||||||
|
timerRef.current = null
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const startTimer = useCallback(() => {
|
||||||
|
if (timerRef.current !== null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
timerRef.current = setTimeout(callback, timeout)
|
||||||
|
}, [callback, timeout])
|
||||||
|
|
||||||
|
return [startTimer, stopTimer]
|
||||||
|
}
|
Loading…
Reference in a new issue