import { useConfig } from 'domains/config/hooks' import { selectShowNotifications } from 'domains/store/selectors' import { useCallback, useEffect, useMemo, useState } from 'preact/hooks' import { useSelector } from 'react-redux' import { textEntryControlName } from 'ui/components/entry/text-entry' import { useSeamlyServiceInfo } from './seamly-state-hooks' import beep from './sounds/beep.mp3' const hasNotificationSupport = !!window.Notification const useNotification = () => { const { proactiveMessages } = useSeamlyServiceInfo() const { notificationAudioURL } = useConfig() const [permission, setPermission] = useState( hasNotificationSupport ? Notification.permission : 'default', ) const [visibilityState, setVisibilityState] = useState( document.visibilityState, ) const showNotifications = useSelector(selectShowNotifications) const requestPermission = useCallback(async () => { if (hasNotificationSupport && permission !== 'granted') { const notificationPermission = await Notification.requestPermission() setPermission(notificationPermission) } }, [permission]) const permissionGranted = useMemo( () => permission === 'granted', [permission], ) const visibilityStateHidden = useMemo( () => visibilityState === 'hidden', [visibilityState], ) useEffect(() => { if (permission === 'default' && proactiveMessages) { requestPermission() } }, [permission, proactiveMessages, requestPermission]) const sendNotification = useCallback( async (title: string, options?: NotificationOptions) => { if (!showNotifications || !hasNotificationSupport) return if (permission === 'default') { requestPermission() } if ( notificationAudioURL !== false && !permissionGranted && (visibilityStateHidden || !document.hasFocus()) ) { try { const AudioPlay = new Audio(notificationAudioURL || beep) await AudioPlay.play() } catch (error) { // Autoplay was prevented. See link for more details // https://developer.chrome.com/blog/autoplay/#audiovideo-elements console.warn(error) } } if ( permissionGranted && (visibilityStateHidden || !document.hasFocus()) ) { const notification = new Notification(title, options) notification.onclick = function () { window.parent.focus() window.focus() notification.close() const entry = document.querySelector( `input[name=${textEntryControlName}]`, ) if (entry) entry.focus() } } }, [ notificationAudioURL, permission, permissionGranted, requestPermission, showNotifications, visibilityStateHidden, ], ) useEffect(() => { if (!showNotifications) return () => {} function handleVisibilityChange() { setVisibilityState(document.visibilityState) } document.addEventListener('visibilitychange', handleVisibilityChange, false) return () => { document.removeEventListener('visibilitychange', handleVisibilityChange) } }, [showNotifications]) return { permission, requestPermission, sendNotification, } } export default useNotification