diff options
author | Foysal Ahamed <foysal@blueskyweb.xyz> | 2023-09-18 23:34:12 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-18 14:34:12 -0700 |
commit | 3c4899b3c4ae55285559215023a25e365c9f4e30 (patch) | |
tree | d8a1433959b4a4ffadc85924c2abb7ff872bc852 /src | |
parent | 255beb0c1f74fe3a72a8069f30395b7774442f88 (diff) | |
download | voidsky-3c4899b3c4ae55285559215023a25e365c9f4e30.tar.zst |
:bug: Handle middle mouse click on feed list items (#1469)
* :bug: Handle middle mouse click on feed list items * :recycle: Refactor the event listener and turn it into a dedicated hook for web * :broom: Cleanup unnecessary Link changes * Fix import * Create native version of useAuxClick --------- Co-authored-by: Paul Frazee <pfrazee@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/hooks/useAuxClick.ts | 2 | ||||
-rw-r--r-- | src/lib/hooks/useAuxClick.web.ts | 43 | ||||
-rw-r--r-- | src/view/com/util/Link.tsx | 5 | ||||
-rw-r--r-- | src/view/shell/index.web.tsx | 2 |
4 files changed, 50 insertions, 2 deletions
diff --git a/src/lib/hooks/useAuxClick.ts b/src/lib/hooks/useAuxClick.ts new file mode 100644 index 000000000..ab6fd4365 --- /dev/null +++ b/src/lib/hooks/useAuxClick.ts @@ -0,0 +1,2 @@ +// does nothing in native +export const useAuxClick = () => {} diff --git a/src/lib/hooks/useAuxClick.web.ts b/src/lib/hooks/useAuxClick.web.ts new file mode 100644 index 000000000..ca9811615 --- /dev/null +++ b/src/lib/hooks/useAuxClick.web.ts @@ -0,0 +1,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]) +} diff --git a/src/view/com/util/Link.tsx b/src/view/com/util/Link.tsx index d4df2bec4..1a6f047f6 100644 --- a/src/view/com/util/Link.tsx +++ b/src/view/com/util/Link.tsx @@ -59,6 +59,7 @@ export const Link = observer(function Link({ }: Props) { const store = useStores() const navigation = useNavigation<NavigationProp>() + const anchorHref = asAnchor ? sanitizeUrl(href) : undefined const onPress = React.useCallback( (e?: Event) => { @@ -96,7 +97,7 @@ export const Link = observer(function Link({ accessibilityRole="link" {...props}> {/* @ts-ignore web only -prf */} - <View style={style} href={asAnchor ? sanitizeUrl(href) : undefined}> + <View style={style} href={anchorHref}> {children ? children : <Text>{title || 'link'}</Text>} </View> </TouchableWithoutFeedback> @@ -123,7 +124,7 @@ export const Link = observer(function Link({ accessible={accessible} accessibilityRole="link" // @ts-ignore web only -prf - href={asAnchor ? sanitizeUrl(href) : undefined} + href={anchorHref} {...props}> {children ? children : <Text>{title || 'link'}</Text>} </Com> diff --git a/src/view/shell/index.web.tsx b/src/view/shell/index.web.tsx index 124341917..67f988844 100644 --- a/src/view/shell/index.web.tsx +++ b/src/view/shell/index.web.tsx @@ -16,11 +16,13 @@ import {useWebMediaQueries} from '../../lib/hooks/useWebMediaQueries' import {BottomBarWeb} from './bottom-bar/BottomBarWeb' import {useNavigation} from '@react-navigation/native' import {NavigationProp} from 'lib/routes/types' +import {useAuxClick} from 'lib/hooks/useAuxClick' const ShellInner = observer(function ShellInnerImpl() { const store = useStores() const {isDesktop, isMobile} = useWebMediaQueries() const navigator = useNavigation<NavigationProp>() + useAuxClick() useEffect(() => { navigator.addListener('state', () => { |