Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

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

Toggle minimal shell on any scroll for web (#2499)

authored by

dan and committed by
GitHub
b147f7ae 3662259c

+47 -42
+47 -42
src/view/com/util/MainScrollProvider.tsx
··· 3 3 import {NativeScrollEvent} from 'react-native' 4 4 import {useSetMinimalShellMode, useMinimalShellMode} from '#/state/shell' 5 5 import {useShellLayout} from '#/state/shell/shell-layout' 6 - import {isWeb} from 'platform/detection' 6 + import {isNative} from 'platform/detection' 7 7 import {useSharedValue, interpolate} from 'react-native-reanimated' 8 + 9 + const WEB_HIDE_SHELL_THRESHOLD = 200 8 10 9 11 function clamp(num: number, min: number, max: number) { 10 12 'worklet' ··· 21 23 const onBeginDrag = useCallback( 22 24 (e: NativeScrollEvent) => { 23 25 'worklet' 24 - startDragOffset.value = e.contentOffset.y 25 - startMode.value = mode.value 26 + if (isNative) { 27 + startDragOffset.value = e.contentOffset.y 28 + startMode.value = mode.value 29 + } 26 30 }, 27 31 [mode, startDragOffset, startMode], 28 32 ) ··· 30 34 const onEndDrag = useCallback( 31 35 (e: NativeScrollEvent) => { 32 36 'worklet' 33 - startDragOffset.value = null 34 - startMode.value = null 35 - if (e.contentOffset.y < headerHeight.value / 2) { 36 - // If we're close to the top, show the shell. 37 - setMode(false) 38 - } else { 39 - // Snap to whichever state is the closest. 40 - setMode(Math.round(mode.value) === 1) 37 + if (isNative) { 38 + startDragOffset.value = null 39 + startMode.value = null 40 + if (e.contentOffset.y < headerHeight.value / 2) { 41 + // If we're close to the top, show the shell. 42 + setMode(false) 43 + } else { 44 + // Snap to whichever state is the closest. 45 + setMode(Math.round(mode.value) === 1) 46 + } 41 47 } 42 48 }, 43 49 [startDragOffset, startMode, setMode, mode, headerHeight], ··· 46 52 const onScroll = useCallback( 47 53 (e: NativeScrollEvent) => { 48 54 'worklet' 49 - if (startDragOffset.value === null || startMode.value === null) { 50 - if (mode.value !== 0 && e.contentOffset.y < headerHeight.value) { 51 - // If we're close enough to the top, always show the shell. 52 - // Even if we're not dragging. 53 - setMode(false) 55 + if (isNative) { 56 + if (startDragOffset.value === null || startMode.value === null) { 57 + if (mode.value !== 0 && e.contentOffset.y < headerHeight.value) { 58 + // If we're close enough to the top, always show the shell. 59 + // Even if we're not dragging. 60 + setMode(false) 61 + } 54 62 return 55 63 } 56 - if (isWeb) { 57 - // On the web, there is no concept of "starting" the drag. 58 - // When we get the first scroll event, we consider that the start. 59 - startDragOffset.value = e.contentOffset.y 60 - startMode.value = mode.value 64 + 65 + // The "mode" value is always between 0 and 1. 66 + // Figure out how much to move it based on the current dragged distance. 67 + const dy = e.contentOffset.y - startDragOffset.value 68 + const dProgress = interpolate( 69 + dy, 70 + [-headerHeight.value, headerHeight.value], 71 + [-1, 1], 72 + ) 73 + const newValue = clamp(startMode.value + dProgress, 0, 1) 74 + if (newValue !== mode.value) { 75 + // Manually adjust the value. This won't be (and shouldn't be) animated. 76 + mode.value = newValue 61 77 } 62 - return 63 - } 64 - 65 - // The "mode" value is always between 0 and 1. 66 - // Figure out how much to move it based on the current dragged distance. 67 - const dy = e.contentOffset.y - startDragOffset.value 68 - const dProgress = interpolate( 69 - dy, 70 - [-headerHeight.value, headerHeight.value], 71 - [-1, 1], 72 - ) 73 - const newValue = clamp(startMode.value + dProgress, 0, 1) 74 - if (newValue !== mode.value) { 75 - // Manually adjust the value. This won't be (and shouldn't be) animated. 76 - mode.value = newValue 77 - } 78 - if (isWeb) { 79 - // On the web, there is no concept of "starting" the drag, 80 - // so we don't have any specific anchor point to calculate the distance. 81 - // Instead, update it continuosly along the way and diff with the last event. 78 + } else { 79 + // On the web, we don't try to follow the drag because we don't know when it ends. 80 + // Instead, show/hide immediately based on whether we're scrolling up or down. 81 + const dy = e.contentOffset.y - (startDragOffset.value ?? 0) 82 82 startDragOffset.value = e.contentOffset.y 83 - startMode.value = mode.value 83 + 84 + if (dy < 0 || e.contentOffset.y < WEB_HIDE_SHELL_THRESHOLD) { 85 + setMode(false) 86 + } else if (dy > 0) { 87 + setMode(true) 88 + } 84 89 } 85 90 }, 86 91 [headerHeight, mode, setMode, startDragOffset, startMode],