about summary refs log tree commit diff
path: root/src/lib/hooks/useAuxClick.web.ts
blob: ca98116159aa38d983c3a2ced5d4b522cae89b60 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import {useEffect} from 'react'

// This is the handler for the middle mouse button click on the feed.
// Normally, we would do this via `onAuxClick` handler on each link element
// However, that handler is not supported on react-native-web and there are some
// discrepancies between various browsers (i.e: safari doesn't trigger it and routes through click event)
// So, this temporary alternative is meant to bridge the gap in an efficient way until the support improves.
export const useAuxClick = () => {
  const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
  useEffect(() => {
    // On the web, it should always be there but in case it gets accidentally included in native builds
    const wrapperEl = document?.body

    // Safari already handles auxclick event as click+metaKey so we need to avoid doing this there in case it becomes recursive
    if (wrapperEl && !isSafari) {
      const handleAuxClick = (e: MouseEvent & {target: HTMLElement}) => {
        // Only handle the middle mouse button click
        // Only handle if the clicked element itself or one of its ancestors is a link
        if (
          e.button !== 1 ||
          e.target.closest('a') ||
          e.target.tagName === 'A'
        ) {
          return
        }

        // On the original element, trigger a click event with metaKey set to true so that it triggers
        // the browser's default behavior of opening the link in a new tab
        e.target.dispatchEvent(
          new MouseEvent('click', {metaKey: true, bubbles: true}),
        )
      }

      // @ts-ignore For web only
      wrapperEl.addEventListener('auxclick', handleAuxClick)

      return () => {
        // @ts-ignore For web only
        wrapperEl?.removeEventListener('auxclick', handleAuxClick)
      }
    }
  }, [isSafari])
}