use-browser-window.ts 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import { useEffect, useState } from 'react'
  2. let titleIsFlashing = false
  3. let originalTitle = ''
  4. let flashIntervalHandle: ReturnType<typeof setInterval>
  5. function flashTitle(message: string) {
  6. if (document.hasFocus() || titleIsFlashing) {
  7. return
  8. }
  9. function swapTitle() {
  10. if (window.document.title === originalTitle) {
  11. window.document.title = message
  12. } else {
  13. window.document.title = originalTitle
  14. }
  15. }
  16. originalTitle = window.document.title
  17. window.document.title = message
  18. titleIsFlashing = true
  19. flashIntervalHandle = setInterval(swapTitle, 800)
  20. }
  21. function stopFlashingTitle() {
  22. if (!titleIsFlashing) {
  23. return
  24. }
  25. clearInterval(flashIntervalHandle)
  26. window.document.title = originalTitle
  27. originalTitle = ''
  28. titleIsFlashing = false
  29. }
  30. function setTitle(title: string) {
  31. if (titleIsFlashing) {
  32. originalTitle = title
  33. } else {
  34. window.document.title = title
  35. }
  36. }
  37. function useBrowserWindow() {
  38. const [hasFocus, setHasFocus] = useState(() => document.hasFocus())
  39. useEffect(() => {
  40. function handleFocusEvent() {
  41. setHasFocus(true)
  42. }
  43. function handleBlurEvent() {
  44. setHasFocus(false)
  45. }
  46. window.addEventListener('focus', handleFocusEvent)
  47. window.addEventListener('blur', handleBlurEvent)
  48. return () => {
  49. window.removeEventListener('focus', handleFocusEvent)
  50. window.removeEventListener('blur', handleBlurEvent)
  51. }
  52. }, [])
  53. return { hasFocus, flashTitle, stopFlashingTitle, setTitle }
  54. }
  55. export default useBrowserWindow