Bluesky app fork with some witchin' additions 💫

fix web aux click on all browsers (#2633)

authored by hailey.at and committed by

GitHub 065a0940 2f1ce117

+44 -58
-2
src/lib/hooks/useAuxClick.ts
··· 1 - // does nothing in native 2 - export const useAuxClick = () => {}
-43
src/lib/hooks/useAuxClick.web.ts
··· 1 - import {useEffect} from 'react' 2 - 3 - // This is the handler for the middle mouse button click on the feed. 4 - // Normally, we would do this via `onAuxClick` handler on each link element 5 - // However, that handler is not supported on react-native-web and there are some 6 - // discrepancies between various browsers (i.e: safari doesn't trigger it and routes through click event) 7 - // So, this temporary alternative is meant to bridge the gap in an efficient way until the support improves. 8 - export const useAuxClick = () => { 9 - const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent) 10 - useEffect(() => { 11 - // On the web, it should always be there but in case it gets accidentally included in native builds 12 - const wrapperEl = document?.body 13 - 14 - // Safari already handles auxclick event as click+metaKey so we need to avoid doing this there in case it becomes recursive 15 - if (wrapperEl && !isSafari) { 16 - const handleAuxClick = (e: MouseEvent & {target: HTMLElement}) => { 17 - // Only handle the middle mouse button click 18 - // Only handle if the clicked element itself or one of its ancestors is a link 19 - if ( 20 - e.button !== 1 || 21 - e.target.closest('a') || 22 - e.target.tagName === 'A' 23 - ) { 24 - return 25 - } 26 - 27 - // On the original element, trigger a click event with metaKey set to true so that it triggers 28 - // the browser's default behavior of opening the link in a new tab 29 - e.target.dispatchEvent( 30 - new MouseEvent('click', {metaKey: true, bubbles: true}), 31 - ) 32 - } 33 - 34 - // @ts-ignore For web only 35 - wrapperEl.addEventListener('auxclick', handleAuxClick) 36 - 37 - return () => { 38 - // @ts-ignore For web only 39 - wrapperEl?.removeEventListener('auxclick', handleAuxClick) 40 - } 41 - } 42 - }, [isSafari]) 43 - }
+14 -11
src/view/com/util/Link.tsx
··· 31 31 import FixedTouchableHighlight from '../pager/FixedTouchableHighlight' 32 32 import {useModalControls} from '#/state/modals' 33 33 import {useOpenLink} from '#/state/preferences/in-app-browser' 34 + import {WebAuxClickWrapper} from 'view/com/util/WebAuxClickWrapper' 34 35 35 36 type Event = 36 37 | React.MouseEvent<HTMLAnchorElement, MouseEvent> ··· 104 105 ) 105 106 } 106 107 return ( 107 - <TouchableWithoutFeedback 108 - testID={testID} 109 - onPress={onPress} 110 - accessible={accessible} 111 - accessibilityRole="link" 112 - {...props}> 113 - {/* @ts-ignore web only -prf */} 114 - <View style={style} href={anchorHref}> 115 - {children ? children : <Text>{title || 'link'}</Text>} 116 - </View> 117 - </TouchableWithoutFeedback> 108 + <WebAuxClickWrapper> 109 + <TouchableWithoutFeedback 110 + testID={testID} 111 + onPress={onPress} 112 + accessible={accessible} 113 + accessibilityRole="link" 114 + {...props}> 115 + {/* @ts-ignore web only -prf */} 116 + <View style={style} href={anchorHref}> 117 + {children ? children : <Text>{title || 'link'}</Text>} 118 + </View> 119 + </TouchableWithoutFeedback> 120 + </WebAuxClickWrapper> 118 121 ) 119 122 } 120 123
+30
src/view/com/util/WebAuxClickWrapper.tsx
··· 1 + import React from 'react' 2 + import {Platform} from 'react-native' 3 + 4 + const onMouseUp = (e: React.MouseEvent & {target: HTMLElement}) => { 5 + // Only handle whenever it is the middle button 6 + if (e.button !== 1 || e.target.closest('a') || e.target.tagName === 'A') { 7 + return 8 + } 9 + 10 + e.target.dispatchEvent( 11 + new MouseEvent('click', {metaKey: true, bubbles: true}), 12 + ) 13 + } 14 + 15 + const onMouseDown = (e: React.MouseEvent) => { 16 + // Prevents the middle click scroll from enabling 17 + if (e.button !== 1) return 18 + e.preventDefault() 19 + } 20 + 21 + export function WebAuxClickWrapper({children}: React.PropsWithChildren<{}>) { 22 + if (Platform.OS !== 'web') return children 23 + 24 + return ( 25 + // @ts-ignore web only 26 + <div onMouseDown={onMouseDown} onMouseUp={onMouseUp}> 27 + {children} 28 + </div> 29 + ) 30 + }
-2
src/view/shell/index.web.tsx
··· 11 11 import {useWebMediaQueries} from '../../lib/hooks/useWebMediaQueries' 12 12 import {useNavigation} from '@react-navigation/native' 13 13 import {NavigationProp} from 'lib/routes/types' 14 - import {useAuxClick} from 'lib/hooks/useAuxClick' 15 14 import {t} from '@lingui/macro' 16 15 import {useIsDrawerOpen, useSetDrawerOpen} from '#/state/shell' 17 16 import {useCloseAllActiveElements} from '#/state/util' ··· 26 25 const closeAllActiveElements = useCloseAllActiveElements() 27 26 28 27 useWebBodyScrollLock(isDrawerOpen) 29 - useAuxClick() 30 28 31 29 useEffect(() => { 32 30 const unsubscribe = navigator.addListener('state', () => {