mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-19 17:55:17 -04:00
use useInterval hook in ui-notification-toast
Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
a96b06c95b
commit
1adb1bd52f
1 changed files with 27 additions and 45 deletions
|
@ -4,16 +4,17 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { Fragment, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
|
import React, { Fragment, useCallback, useEffect, useMemo, useState } from 'react'
|
||||||
import { Button, ProgressBar, Toast } from 'react-bootstrap'
|
import { Button, ProgressBar, Toast } from 'react-bootstrap'
|
||||||
import type { UiNotification } from '../../redux/ui-notifications/types'
|
import type { UiNotification } from '../../redux/ui-notifications/types'
|
||||||
import { ForkAwesomeIcon } from '../common/fork-awesome/fork-awesome-icon'
|
import { ForkAwesomeIcon } from '../common/fork-awesome/fork-awesome-icon'
|
||||||
import { ShowIf } from '../common/show-if/show-if'
|
import { ShowIf } from '../common/show-if/show-if'
|
||||||
import type { IconName } from '../common/fork-awesome/types'
|
import type { IconName } from '../common/fork-awesome/types'
|
||||||
import { dismissUiNotification } from '../../redux/ui-notifications/methods'
|
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
import { Trans, useTranslation } from 'react-i18next'
|
||||||
import { Logger } from '../../utils/logger'
|
import { Logger } from '../../utils/logger'
|
||||||
import { cypressId } from '../../utils/cypress-attribute'
|
import { cypressId } from '../../utils/cypress-attribute'
|
||||||
|
import { useEffectOnce, useInterval } from 'react-use'
|
||||||
|
import { dismissUiNotification } from '../../redux/ui-notifications/methods'
|
||||||
|
|
||||||
const STEPS_PER_SECOND = 10
|
const STEPS_PER_SECOND = 10
|
||||||
const log = new Logger('UiNotificationToast')
|
const log = new Logger('UiNotificationToast')
|
||||||
|
@ -35,56 +36,35 @@ export const UiNotificationToast: React.FC<UiNotificationProps> = ({
|
||||||
buttons
|
buttons
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const [eta, setEta] = useState<number>()
|
const [remainingSteps, setRemainingSteps] = useState<number>(() => durationInSecond * STEPS_PER_SECOND)
|
||||||
const interval = useRef<NodeJS.Timeout | undefined>(undefined)
|
|
||||||
|
|
||||||
const deleteInterval = useCallback(() => {
|
const dismissNow = useCallback(() => {
|
||||||
if (interval.current) {
|
log.debug(`Dismiss notification ${notificationId} immediately`)
|
||||||
clearInterval(interval.current)
|
setRemainingSteps(0)
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const dismissThisNotification = useCallback(() => {
|
|
||||||
log.debug(`Dismissed notification ${notificationId}`)
|
|
||||||
dismissUiNotification(notificationId)
|
|
||||||
}, [notificationId])
|
}, [notificationId])
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useEffectOnce(() => {
|
||||||
if (dismissed || !!interval.current) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.debug(`Show notification ${notificationId}`)
|
log.debug(`Show notification ${notificationId}`)
|
||||||
setEta(durationInSecond * STEPS_PER_SECOND)
|
})
|
||||||
interval.current = setInterval(
|
|
||||||
() =>
|
useInterval(
|
||||||
setEta((lastETA) => {
|
() => setRemainingSteps((lastRemainingSteps) => lastRemainingSteps - 1),
|
||||||
if (lastETA === undefined) {
|
useMemo(() => (dismissed || remainingSteps <= 0 ? null : 1000 / STEPS_PER_SECOND), [dismissed, remainingSteps])
|
||||||
return
|
)
|
||||||
} else if (lastETA <= 0) {
|
|
||||||
return 0
|
|
||||||
} else {
|
|
||||||
return lastETA - 1
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
1000 / STEPS_PER_SECOND
|
|
||||||
)
|
|
||||||
return () => {
|
|
||||||
deleteInterval()
|
|
||||||
}
|
|
||||||
}, [deleteInterval, dismissThisNotification, dismissed, durationInSecond, notificationId])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (eta === 0) {
|
if (remainingSteps <= 0 && !dismissed) {
|
||||||
dismissThisNotification()
|
log.debug(`Dismiss notification ${notificationId}`)
|
||||||
|
dismissUiNotification(notificationId)
|
||||||
}
|
}
|
||||||
}, [dismissThisNotification, eta])
|
}, [dismissed, remainingSteps, notificationId])
|
||||||
|
|
||||||
const buttonsDom = useMemo(
|
const buttonsDom = useMemo(
|
||||||
() =>
|
() =>
|
||||||
buttons?.map((button, buttonIndex) => {
|
buttons?.map((button, buttonIndex) => {
|
||||||
const buttonClick = () => {
|
const buttonClick = () => {
|
||||||
button.onClick()
|
button.onClick()
|
||||||
dismissThisNotification()
|
dismissNow()
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Button key={buttonIndex} size={'sm'} onClick={buttonClick} variant={'link'}>
|
<Button key={buttonIndex} size={'sm'} onClick={buttonClick} variant={'link'}>
|
||||||
|
@ -92,7 +72,7 @@ export const UiNotificationToast: React.FC<UiNotificationProps> = ({
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
[buttons, dismissThisNotification]
|
[buttons, dismissNow]
|
||||||
)
|
)
|
||||||
|
|
||||||
const contentDom = useMemo(() => {
|
const contentDom = useMemo(() => {
|
||||||
|
@ -109,10 +89,7 @@ export const UiNotificationToast: React.FC<UiNotificationProps> = ({
|
||||||
}, [contentI18nKey, contentI18nOptions, t])
|
}, [contentI18nKey, contentI18nOptions, t])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Toast
|
<Toast show={!dismissed} onClose={dismissNow} {...cypressId('notification-toast')}>
|
||||||
show={!dismissed && eta !== undefined}
|
|
||||||
onClose={dismissThisNotification}
|
|
||||||
{...cypressId('notification-toast')}>
|
|
||||||
<Toast.Header>
|
<Toast.Header>
|
||||||
<strong className='mr-auto'>
|
<strong className='mr-auto'>
|
||||||
<ShowIf condition={!!icon}>
|
<ShowIf condition={!!icon}>
|
||||||
|
@ -123,7 +100,12 @@ export const UiNotificationToast: React.FC<UiNotificationProps> = ({
|
||||||
<small>{date.toRelative({ style: 'short' })}</small>
|
<small>{date.toRelative({ style: 'short' })}</small>
|
||||||
</Toast.Header>
|
</Toast.Header>
|
||||||
<Toast.Body>{contentDom}</Toast.Body>
|
<Toast.Body>{contentDom}</Toast.Body>
|
||||||
<ProgressBar variant={'info'} now={eta} max={durationInSecond * STEPS_PER_SECOND} min={0} />
|
<ProgressBar
|
||||||
|
variant={'info'}
|
||||||
|
now={remainingSteps}
|
||||||
|
max={durationInSecond * STEPS_PER_SECOND}
|
||||||
|
min={STEPS_PER_SECOND}
|
||||||
|
/>
|
||||||
<div>{buttonsDom}</div>
|
<div>{buttonsDom}</div>
|
||||||
</Toast>
|
</Toast>
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue