Files
Verso/services/web/frontend/js/features/ide-react/hooks/use-status-favicon.ts
T
Antoine ClausseandCopybot c6905fc94d [web] Fetch favicons from CDN (#28419)
* 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
2025-09-16 08:05:03 +00:00

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])
}