about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorHailey <me@haileyok.com>2024-02-06 09:00:16 -0800
committerGitHub <noreply@github.com>2024-02-06 09:00:16 -0800
commit065a09408767a870c48c99549cc0198955ea1ccf (patch)
tree65474dcd1dade94870b7318dbc27004ea0b53835 /src
parent2f1ce117d7db8db168303f6064e69024e920585e (diff)
downloadvoidsky-065a09408767a870c48c99549cc0198955ea1ccf.tar.zst
fix web aux click on all browsers (#2633)
Diffstat (limited to 'src')
-rw-r--r--src/lib/hooks/useAuxClick.ts2
-rw-r--r--src/lib/hooks/useAuxClick.web.ts43
-rw-r--r--src/view/com/util/Link.tsx25
-rw-r--r--src/view/com/util/WebAuxClickWrapper.tsx30
-rw-r--r--src/view/shell/index.web.tsx2
5 files changed, 44 insertions, 58 deletions
diff --git a/src/lib/hooks/useAuxClick.ts b/src/lib/hooks/useAuxClick.ts
deleted file mode 100644
index ab6fd4365..000000000
--- a/src/lib/hooks/useAuxClick.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// does nothing in native
-export const useAuxClick = () => {}
diff --git a/src/lib/hooks/useAuxClick.web.ts b/src/lib/hooks/useAuxClick.web.ts
deleted file mode 100644
index ca9811615..000000000
--- a/src/lib/hooks/useAuxClick.web.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-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])
-}
diff --git a/src/view/com/util/Link.tsx b/src/view/com/util/Link.tsx
index a517ba430..afbdeb8f4 100644
--- a/src/view/com/util/Link.tsx
+++ b/src/view/com/util/Link.tsx
@@ -31,6 +31,7 @@ import {PressableWithHover} from './PressableWithHover'
 import FixedTouchableHighlight from '../pager/FixedTouchableHighlight'
 import {useModalControls} from '#/state/modals'
 import {useOpenLink} from '#/state/preferences/in-app-browser'
+import {WebAuxClickWrapper} from 'view/com/util/WebAuxClickWrapper'
 
 type Event =
   | React.MouseEvent<HTMLAnchorElement, MouseEvent>
@@ -104,17 +105,19 @@ export const Link = memo(function Link({
       )
     }
     return (
-      <TouchableWithoutFeedback
-        testID={testID}
-        onPress={onPress}
-        accessible={accessible}
-        accessibilityRole="link"
-        {...props}>
-        {/* @ts-ignore web only -prf */}
-        <View style={style} href={anchorHref}>
-          {children ? children : <Text>{title || 'link'}</Text>}
-        </View>
-      </TouchableWithoutFeedback>
+      <WebAuxClickWrapper>
+        <TouchableWithoutFeedback
+          testID={testID}
+          onPress={onPress}
+          accessible={accessible}
+          accessibilityRole="link"
+          {...props}>
+          {/* @ts-ignore web only -prf */}
+          <View style={style} href={anchorHref}>
+            {children ? children : <Text>{title || 'link'}</Text>}
+          </View>
+        </TouchableWithoutFeedback>
+      </WebAuxClickWrapper>
     )
   }
 
diff --git a/src/view/com/util/WebAuxClickWrapper.tsx b/src/view/com/util/WebAuxClickWrapper.tsx
new file mode 100644
index 000000000..8105a8518
--- /dev/null
+++ b/src/view/com/util/WebAuxClickWrapper.tsx
@@ -0,0 +1,30 @@
+import React from 'react'
+import {Platform} from 'react-native'
+
+const onMouseUp = (e: React.MouseEvent & {target: HTMLElement}) => {
+  // Only handle whenever it is the middle button
+  if (e.button !== 1 || e.target.closest('a') || e.target.tagName === 'A') {
+    return
+  }
+
+  e.target.dispatchEvent(
+    new MouseEvent('click', {metaKey: true, bubbles: true}),
+  )
+}
+
+const onMouseDown = (e: React.MouseEvent) => {
+  // Prevents the middle click scroll from enabling
+  if (e.button !== 1) return
+  e.preventDefault()
+}
+
+export function WebAuxClickWrapper({children}: React.PropsWithChildren<{}>) {
+  if (Platform.OS !== 'web') return children
+
+  return (
+    // @ts-ignore web only
+    <div onMouseDown={onMouseDown} onMouseUp={onMouseUp}>
+      {children}
+    </div>
+  )
+}
diff --git a/src/view/shell/index.web.tsx b/src/view/shell/index.web.tsx
index 76f4f5c9b..97c065502 100644
--- a/src/view/shell/index.web.tsx
+++ b/src/view/shell/index.web.tsx
@@ -11,7 +11,6 @@ import {DrawerContent} from './Drawer'
 import {useWebMediaQueries} from '../../lib/hooks/useWebMediaQueries'
 import {useNavigation} from '@react-navigation/native'
 import {NavigationProp} from 'lib/routes/types'
-import {useAuxClick} from 'lib/hooks/useAuxClick'
 import {t} from '@lingui/macro'
 import {useIsDrawerOpen, useSetDrawerOpen} from '#/state/shell'
 import {useCloseAllActiveElements} from '#/state/util'
@@ -26,7 +25,6 @@ function ShellInner() {
   const closeAllActiveElements = useCloseAllActiveElements()
 
   useWebBodyScrollLock(isDrawerOpen)
-  useAuxClick()
 
   useEffect(() => {
     const unsubscribe = navigator.addListener('state', () => {