* Simplify paths in `buildImgPath` * Move favicons from `public` to `public/img/favicons` * Create links to favicons in `public` (`ln -s img/favicons/* .`) * Import favicons dynamically in use-status-favicon.ts * Update pug files with cdn favicon paths * Update test * Revert change in layout-no-js.pug * Fetch web.sitemanifest from CDN * Revert favicon move * Fix favicon paths (use `buildBaseAssetPath`) * Fixup web.sitemanifest path * Format * Update `buildImgPath` mock to be more realistic * Revert web.sitemanifest link to local origin * Revert "Revert web.sitemanifest link to local origin" This reverts commit aa13431b743b55c2f536c33e736f657e1c0db598. GitOrigin-RevId: fe278fec0f1eaae16de9fabc2b13da3e7a316463
77 lines
2.4 KiB
TypeScript
77 lines
2.4 KiB
TypeScript
import { useDetachCompileContext as useCompileContext } from '@/shared/context/detach-compile-context'
|
|
import { useEffect, useState } from 'react'
|
|
import usePreviousValue from '@/shared/hooks/use-previous-value'
|
|
import getMeta from '@/utils/meta'
|
|
|
|
const RESET_AFTER_MS = 5_000
|
|
|
|
const COMPILE_ICONS = {
|
|
ERROR: 'favicon-error.svg',
|
|
COMPILING: 'favicon-compiling.svg',
|
|
COMPILED: 'favicon-compiled.svg',
|
|
UNCOMPILED: 'favicon.svg',
|
|
} as const
|
|
|
|
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 = getMeta('ol-baseAssetPath') + 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])
|
|
}
|