| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- import { useDetachCompileContext as useCompileContext } from '@/shared/context/detach-compile-context'
- import { useEffect, useState } from 'react'
- import usePreviousValue from '@/shared/hooks/use-previous-value'
- const RESET_AFTER_MS = 5_000
- const COMPILE_ICONS = {
- ERROR: '/favicon-error.svg',
- COMPILING: '/favicon-compiling.svg',
- COMPILED: '/favicon-compiled.svg',
- UNCOMPILED: '/favicon.svg',
- }
- type CompileStatus = keyof typeof COMPILE_ICONS
- const useCompileStatus = (): CompileStatus => {
- const compileContext = useCompileContext()
- if (compileContext.uncompiled) return 'UNCOMPILED'
- if (compileContext.compiling) return 'COMPILING'
- if (compileContext.error) return 'ERROR'
- return 'COMPILED'
- }
- const removeFavicon = () => {
- const existingFavicons = document.head.querySelectorAll(
- "link[rel='icon']"
- ) as NodeListOf<HTMLLinkElement>
- existingFavicons.forEach(favicon => {
- if (favicon.href.endsWith('.svg')) favicon.parentNode?.removeChild(favicon)
- })
- }
- const updateFavicon = (status: CompileStatus = 'UNCOMPILED') => {
- removeFavicon()
- const linkElement = document.createElement('link')
- linkElement.rel = 'icon'
- linkElement.href = COMPILE_ICONS[status]
- linkElement.type = 'image/svg+xml'
- linkElement.setAttribute('data-compile-status', 'true')
- document.head.appendChild(linkElement)
- }
- const isActive = () => !document.hidden
- const useIsWindowActive = () => {
- const [isWindowActive, setIsWindowActive] = useState(isActive())
- useEffect(() => {
- const handleVisibilityChange = () => setIsWindowActive(isActive())
- document.addEventListener('visibilitychange', handleVisibilityChange)
- return () => {
- document.removeEventListener('visibilitychange', handleVisibilityChange)
- }
- }, [])
- return isWindowActive
- }
- export const useStatusFavicon = () => {
- const compileStatus = useCompileStatus()
- const previousCompileStatus = usePreviousValue(compileStatus)
- const isWindowActive = useIsWindowActive()
- useEffect(() => {
- if (previousCompileStatus !== compileStatus) {
- return updateFavicon(compileStatus)
- }
- if (
- isWindowActive &&
- (compileStatus === 'COMPILED' || compileStatus === 'ERROR')
- ) {
- const timeout = setTimeout(updateFavicon, RESET_AFTER_MS)
- return () => clearTimeout(timeout)
- }
- }, [compileStatus, isWindowActive, previousCompileStatus])
- }
|