about summary refs log tree commit diff
diff options
context:
space:
mode:
authordan <dan.abramov@gmail.com>2023-11-09 00:25:27 +0000
committerGitHub <noreply@github.com>2023-11-09 00:25:27 +0000
commit82059b7ee138d24ff50b0f4fad0eaeac860bb78c (patch)
tree05db1953b6405d218d3a23d3030dab47a10e05ec
parentbd531f2344c181261afaf8c43c96daf569b58f09 (diff)
downloadvoidsky-82059b7ee138d24ff50b0f4fad0eaeac860bb78c.tar.zst
Hide/show header and footer without re-renders, take two (#1849)
* Remove callsites using the state value

* Remove unused code

* Change shell mode without re-renders

* Adjust "write your reply" for mode
-rw-r--r--src/lib/hooks/useMinimalShellMode.tsx59
-rw-r--r--src/lib/hooks/useOnMainScroll.ts7
-rw-r--r--src/state/shell/minimal-mode.tsx22
-rw-r--r--src/view/com/pager/FeedsTabBarMobile.tsx6
-rw-r--r--src/view/screens/PostThread.tsx18
-rw-r--r--src/view/shell/bottom-bar/BottomBar.tsx3
-rw-r--r--src/view/shell/bottom-bar/BottomBarStyles.tsx3
7 files changed, 63 insertions, 55 deletions
diff --git a/src/lib/hooks/useMinimalShellMode.tsx b/src/lib/hooks/useMinimalShellMode.tsx
index ada934a26..4738b8e2c 100644
--- a/src/lib/hooks/useMinimalShellMode.tsx
+++ b/src/lib/hooks/useMinimalShellMode.tsx
@@ -1,60 +1,61 @@
-import React from 'react'
-import {autorun} from 'mobx'
 import {
-  Easing,
+  AnimatableValue,
   interpolate,
   useAnimatedStyle,
-  useSharedValue,
   withTiming,
+  Easing,
 } from 'react-native-reanimated'
 
 import {useMinimalShellMode as useMinimalShellModeState} from '#/state/shell/minimal-mode'
 
+function withShellTiming<T extends AnimatableValue>(value: T): T {
+  'worklet'
+  return withTiming(value, {
+    duration: 125,
+    easing: Easing.bezier(0.25, 0.1, 0.25, 1),
+  })
+}
+
 export function useMinimalShellMode() {
-  const minimalShellMode = useMinimalShellModeState()
-  const minimalShellInterp = useSharedValue(0)
+  const mode = useMinimalShellModeState()
   const footerMinimalShellTransform = useAnimatedStyle(() => {
     return {
-      opacity: interpolate(minimalShellInterp.value, [0, 1], [1, 0]),
+      pointerEvents: mode.value ? 'none' : 'auto',
+      opacity: withShellTiming(interpolate(mode.value ? 1 : 0, [0, 1], [1, 0])),
       transform: [
-        {translateY: interpolate(minimalShellInterp.value, [0, 1], [0, 25])},
+        {
+          translateY: withShellTiming(
+            interpolate(mode.value ? 1 : 0, [0, 1], [0, 25]),
+          ),
+        },
       ],
     }
   })
   const headerMinimalShellTransform = useAnimatedStyle(() => {
     return {
-      opacity: interpolate(minimalShellInterp.value, [0, 1], [1, 0]),
+      pointerEvents: mode.value ? 'none' : 'auto',
+      opacity: withShellTiming(interpolate(mode.value ? 1 : 0, [0, 1], [1, 0])),
       transform: [
-        {translateY: interpolate(minimalShellInterp.value, [0, 1], [0, -25])},
+        {
+          translateY: withShellTiming(
+            interpolate(mode.value ? 1 : 0, [0, 1], [0, -25]),
+          ),
+        },
       ],
     }
   })
   const fabMinimalShellTransform = useAnimatedStyle(() => {
     return {
       transform: [
-        {translateY: interpolate(minimalShellInterp.value, [0, 1], [-44, 0])},
+        {
+          translateY: withShellTiming(
+            interpolate(mode.value ? 1 : 0, [0, 1], [-44, 0]),
+          ),
+        },
       ],
     }
   })
-
-  React.useEffect(() => {
-    return autorun(() => {
-      if (minimalShellMode) {
-        minimalShellInterp.value = withTiming(1, {
-          duration: 125,
-          easing: Easing.bezier(0.25, 0.1, 0.25, 1),
-        })
-      } else {
-        minimalShellInterp.value = withTiming(0, {
-          duration: 125,
-          easing: Easing.bezier(0.25, 0.1, 0.25, 1),
-        })
-      }
-    })
-  }, [minimalShellInterp, minimalShellMode])
-
   return {
-    minimalShellMode,
     footerMinimalShellTransform,
     headerMinimalShellTransform,
     fabMinimalShellTransform,
diff --git a/src/lib/hooks/useOnMainScroll.ts b/src/lib/hooks/useOnMainScroll.ts
index 2eab4b250..a213d5317 100644
--- a/src/lib/hooks/useOnMainScroll.ts
+++ b/src/lib/hooks/useOnMainScroll.ts
@@ -33,9 +33,12 @@ export function useOnMainScroll(): [OnScrollCb, boolean, ResetCb] {
         const dy = y - (lastY.current || 0)
         lastY.current = y
 
-        if (!minimalShellMode && dy > dyLimitDown && y > Y_LIMIT) {
+        if (!minimalShellMode.value && dy > dyLimitDown && y > Y_LIMIT) {
           setMinimalShellMode(true)
-        } else if (minimalShellMode && (dy < dyLimitUp * -1 || y <= Y_LIMIT)) {
+        } else if (
+          minimalShellMode.value &&
+          (dy < dyLimitUp * -1 || y <= Y_LIMIT)
+        ) {
           setMinimalShellMode(false)
         }
 
diff --git a/src/state/shell/minimal-mode.tsx b/src/state/shell/minimal-mode.tsx
index 4909a9a65..b506c21db 100644
--- a/src/state/shell/minimal-mode.tsx
+++ b/src/state/shell/minimal-mode.tsx
@@ -1,16 +1,28 @@
 import React from 'react'
+import {useSharedValue, SharedValue} from 'react-native-reanimated'
 
-type StateContext = boolean
+type StateContext = SharedValue<boolean>
 type SetContext = (v: boolean) => void
 
-const stateContext = React.createContext<StateContext>(false)
+const stateContext = React.createContext<StateContext>({
+  value: false,
+  addListener() {},
+  removeListener() {},
+  modify() {},
+})
 const setContext = React.createContext<SetContext>((_: boolean) => {})
 
 export function Provider({children}: React.PropsWithChildren<{}>) {
-  const [state, setState] = React.useState(false)
+  const mode = useSharedValue(false)
+  const setMode = React.useCallback(
+    (v: boolean) => {
+      mode.value = v
+    },
+    [mode],
+  )
   return (
-    <stateContext.Provider value={state}>
-      <setContext.Provider value={setState}>{children}</setContext.Provider>
+    <stateContext.Provider value={mode}>
+      <setContext.Provider value={setMode}>{children}</setContext.Provider>
     </stateContext.Provider>
   )
 }
diff --git a/src/view/com/pager/FeedsTabBarMobile.tsx b/src/view/com/pager/FeedsTabBarMobile.tsx
index 9848ce2d5..b33829ee5 100644
--- a/src/view/com/pager/FeedsTabBarMobile.tsx
+++ b/src/view/com/pager/FeedsTabBarMobile.tsx
@@ -25,7 +25,7 @@ export const FeedsTabBar = observer(function FeedsTabBarImpl(
   const setDrawerOpen = useSetDrawerOpen()
   const items = useHomeTabs(store.preferences.pinnedFeeds)
   const brandBlue = useColorSchemeStyle(s.brandBlue, s.blue3)
-  const {minimalShellMode, headerMinimalShellTransform} = useMinimalShellMode()
+  const {headerMinimalShellTransform} = useMinimalShellMode()
 
   const onPressAvi = React.useCallback(() => {
     setDrawerOpen(true)
@@ -38,7 +38,6 @@ export const FeedsTabBar = observer(function FeedsTabBarImpl(
         pal.border,
         styles.tabBar,
         headerMinimalShellTransform,
-        minimalShellMode && styles.disabled,
       ]}>
       <View style={[pal.view, styles.topBar]}>
         <View style={[pal.view]}>
@@ -110,7 +109,4 @@ const styles = StyleSheet.create({
   title: {
     fontSize: 21,
   },
-  disabled: {
-    pointerEvents: 'none',
-  },
 })
diff --git a/src/view/screens/PostThread.tsx b/src/view/screens/PostThread.tsx
index 0bdd06269..0abce45fa 100644
--- a/src/view/screens/PostThread.tsx
+++ b/src/view/screens/PostThread.tsx
@@ -1,5 +1,6 @@
 import React, {useMemo} from 'react'
 import {InteractionManager, StyleSheet, View} from 'react-native'
+import Animated from 'react-native-reanimated'
 import {useFocusEffect} from '@react-navigation/native'
 import {observer} from 'mobx-react-lite'
 import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
@@ -15,15 +16,14 @@ import {useSafeAreaInsets} from 'react-native-safe-area-context'
 import {clamp} from 'lodash'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import {logger} from '#/logger'
-import {useMinimalShellMode, useSetMinimalShellMode} from '#/state/shell'
-
-const SHELL_FOOTER_HEIGHT = 44
+import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode'
+import {useSetMinimalShellMode} from '#/state/shell'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostThread'>
 export const PostThreadScreen = withAuthRequired(
   observer(function PostThreadScreenImpl({route}: Props) {
     const store = useStores()
-    const minimalShellMode = useMinimalShellMode()
+    const {fabMinimalShellTransform} = useMinimalShellMode()
     const setMinimalShellMode = useSetMinimalShellMode()
     const safeAreaInsets = useSafeAreaInsets()
     const {name, rkey} = route.params
@@ -83,17 +83,17 @@ export const PostThreadScreen = withAuthRequired(
             treeView={!!store.preferences.thread.lab_treeViewEnabled}
           />
         </View>
-        {isMobile && !minimalShellMode && (
-          <View
+        {isMobile && (
+          <Animated.View
             style={[
               styles.prompt,
+              fabMinimalShellTransform,
               {
-                bottom:
-                  SHELL_FOOTER_HEIGHT + clamp(safeAreaInsets.bottom, 15, 30),
+                bottom: clamp(safeAreaInsets.bottom, 15, 30),
               },
             ]}>
             <ComposePrompt onPressCompose={onPressReply} />
-          </View>
+          </Animated.View>
         )}
       </View>
     )
diff --git a/src/view/shell/bottom-bar/BottomBar.tsx b/src/view/shell/bottom-bar/BottomBar.tsx
index fedfcdfca..db4fa9d71 100644
--- a/src/view/shell/bottom-bar/BottomBar.tsx
+++ b/src/view/shell/bottom-bar/BottomBar.tsx
@@ -39,7 +39,7 @@ export const BottomBar = observer(function BottomBarImpl({
   const {isAtHome, isAtSearch, isAtFeeds, isAtNotifications, isAtMyProfile} =
     useNavigationTabState()
 
-  const {minimalShellMode, footerMinimalShellTransform} = useMinimalShellMode()
+  const {footerMinimalShellTransform} = useMinimalShellMode()
   const {notifications} = store.me
 
   const onPressTab = React.useCallback(
@@ -85,7 +85,6 @@ export const BottomBar = observer(function BottomBarImpl({
         pal.border,
         {paddingBottom: clamp(safeAreaInsets.bottom, 15, 30)},
         footerMinimalShellTransform,
-        minimalShellMode && styles.disabled,
       ]}>
       <Btn
         testID="bottomBarHomeBtn"
diff --git a/src/view/shell/bottom-bar/BottomBarStyles.tsx b/src/view/shell/bottom-bar/BottomBarStyles.tsx
index c175ed848..ae9381440 100644
--- a/src/view/shell/bottom-bar/BottomBarStyles.tsx
+++ b/src/view/shell/bottom-bar/BottomBarStyles.tsx
@@ -65,7 +65,4 @@ export const styles = StyleSheet.create({
     borderWidth: 1,
     borderRadius: 100,
   },
-  disabled: {
-    pointerEvents: 'none',
-  },
 })