Bluesky app fork with some witchin' additions 馃挮 witchsky.app
bluesky fork client
119
fork

Configure Feed

Select the types of activity you want to include in your feed.

at a876aae44ea07494ebea9727350aa060b81f317b 85 lines 2.2 kB view raw
1import {type ForwardedRef, useEffect, useMemo, useRef} from 'react' 2import {type ScrollView} from 'react-native' 3import {Platform} from 'react-native' 4 5import {mergeRefs} from '#/lib/merge-refs' 6 7type Props<Scrollable extends ScrollView = ScrollView> = { 8 cursor?: string 9 outerRef?: ForwardedRef<Scrollable> 10} 11 12export function useDraggableScroll<Scrollable extends ScrollView = ScrollView>({ 13 outerRef, 14 cursor = 'grab', 15}: Props<Scrollable> = {}) { 16 const ref = useRef<Scrollable>(null) 17 18 useEffect(() => { 19 if (Platform.OS !== 'web' || !ref.current) { 20 return 21 } 22 const slider = ref.current as unknown as HTMLDivElement 23 let isDragging = false 24 let isMouseDown = false 25 let startX = 0 26 let scrollLeft = 0 27 28 const mouseDown = (e: MouseEvent) => { 29 isMouseDown = true 30 startX = e.pageX - slider.offsetLeft 31 scrollLeft = slider.scrollLeft 32 33 slider.style.cursor = cursor 34 } 35 36 const mouseUp = () => { 37 if (isDragging) { 38 slider.addEventListener('click', e => e.stopPropagation(), {once: true}) 39 } 40 41 isMouseDown = false 42 isDragging = false 43 slider.style.cursor = 'default' 44 } 45 46 const mouseMove = (e: MouseEvent) => { 47 if (!isMouseDown) { 48 return 49 } 50 51 // Require n pixels momement before start of drag (3 in this case ) 52 const x = e.pageX - slider.offsetLeft 53 if (Math.abs(x - startX) < 3) { 54 return 55 } 56 57 isDragging = true 58 e.preventDefault() 59 const walk = x - startX 60 slider.scrollLeft = scrollLeft - walk 61 62 if (slider.contains(document.activeElement)) 63 (document.activeElement as HTMLElement)?.blur?.() 64 } 65 66 slider.addEventListener('mousedown', mouseDown) 67 window.addEventListener('mouseup', mouseUp) 68 window.addEventListener('mousemove', mouseMove) 69 70 return () => { 71 slider.removeEventListener('mousedown', mouseDown) 72 window.removeEventListener('mouseup', mouseUp) 73 window.removeEventListener('mousemove', mouseMove) 74 } 75 }, [cursor]) 76 77 const refs = useMemo( 78 () => mergeRefs(outerRef ? [ref, outerRef] : [ref]), 79 [ref, outerRef], 80 ) 81 82 return { 83 refs, 84 } 85}