about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorSamuel Newman <mozzius@protonmail.com>2024-12-18 16:58:20 +0000
committerGitHub <noreply@github.com>2024-12-18 16:58:20 +0000
commit2d827430eeff14b44944aaae282dbbe3f52f0fbf (patch)
tree17e087c29c6ac85746c1ac6f0804dcba0034f386 /src
parent3262b8342026388a31547645c8543068cada6daf (diff)
downloadvoidsky-2d827430eeff14b44944aaae282dbbe3f52f0fbf.tar.zst
Web sticky headers for most screens (#7153)
* web sticky headers, with opt-out for notifs

* rm from postthread

* Fix jump

---------

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/components/Layout/Header/index.tsx19
-rw-r--r--src/view/com/post-thread/PostThread.tsx35
-rw-r--r--src/view/screens/Notifications.tsx2
3 files changed, 28 insertions, 28 deletions
diff --git a/src/components/Layout/Header/index.tsx b/src/components/Layout/Header/index.tsx
index 16b484cea..2d0fc149e 100644
--- a/src/components/Layout/Header/index.tsx
+++ b/src/components/Layout/Header/index.tsx
@@ -15,6 +15,7 @@ import {
   useBreakpoints,
   useGutters,
   useTheme,
+  web,
 } from '#/alf'
 import {Button, ButtonIcon, ButtonProps} from '#/components/Button'
 import {ArrowLeft_Stroke2_Corner0_Rounded as ArrowLeft} from '#/components/icons/Arrow'
@@ -29,9 +30,13 @@ import {Text} from '#/components/Typography'
 export function Outer({
   children,
   noBottomBorder,
+  headerRef,
+  sticky = true,
 }: {
   children: React.ReactNode
   noBottomBorder?: boolean
+  headerRef?: React.MutableRefObject<View | null>
+  sticky?: boolean
 }) {
   const t = useTheme()
   const gutters = useGutters([0, 'base'])
@@ -40,12 +45,14 @@ export function Outer({
 
   return (
     <View
+      ref={headerRef}
       style={[
         a.w_full,
         !noBottomBorder && a.border_b,
         a.flex_row,
         a.align_center,
         a.gap_sm,
+        sticky && web([a.sticky, {top: 0}, a.z_10, t.atoms.bg]),
         gutters,
         platform({
           native: [a.pb_xs, {minHeight: 48}],
@@ -85,17 +92,7 @@ export function Content({
 }
 
 export function Slot({children}: {children?: React.ReactNode}) {
-  return (
-    <View
-      style={[
-        a.z_50,
-        {
-          width: HEADER_SLOT_SIZE,
-        },
-      ]}>
-      {children}
-    </View>
-  )
+  return <View style={[a.z_50, {width: HEADER_SLOT_SIZE}]}>{children}</View>
 }
 
 export function BackButton({onPress, style, ...props}: Partial<ButtonProps>) {
diff --git a/src/view/com/post-thread/PostThread.tsx b/src/view/com/post-thread/PostThread.tsx
index 477d77aff..af58edcbf 100644
--- a/src/view/com/post-thread/PostThread.tsx
+++ b/src/view/com/post-thread/PostThread.tsx
@@ -32,11 +32,11 @@ import {usePreferencesQuery} from '#/state/queries/preferences'
 import {useSession} from '#/state/session'
 import {useComposerControls} from '#/state/shell'
 import {useMergedThreadgateHiddenReplies} from '#/state/threadgate-hidden-replies'
+import {List, ListMethods} from '#/view/com/util/List'
 import {atoms as a, useTheme} from '#/alf'
+import {Header} from '#/components/Layout'
 import {ListFooter, ListMaybePlaceholder} from '#/components/Lists'
 import {Text} from '#/components/Typography'
-import {List, ListMethods} from '../util/List'
-import {ViewHeader} from '../util/ViewHeader'
 import {PostThreadComposePrompt} from './PostThreadComposePrompt'
 import {PostThreadItem} from './PostThreadItem'
 import {PostThreadLoadMore} from './PostThreadLoadMore'
@@ -95,6 +95,7 @@ export function PostThread({uri}: {uri: string | undefined}) {
   const [hiddenRepliesState, setHiddenRepliesState] = React.useState(
     HiddenRepliesState.Hide,
   )
+  const headerRef = React.useRef<View | null>(null)
 
   const {data: preferences} = usePreferencesQuery()
   const {
@@ -284,18 +285,18 @@ export function PostThread({uri}: {uri: string | undefined}) {
     }
     // wait for loading to finish
     if (thread?.type === 'post' && !!thread.parent) {
-      function onMeasure(pageY: number) {
+      // Measure synchronously to avoid a layout jump.
+      const postNode = highlightedPostRef.current
+      const headerNode = headerRef.current
+      if (postNode && headerNode) {
+        let pageY = (postNode as any as Element).getBoundingClientRect().top
+        pageY -= (headerNode as any as Element).getBoundingClientRect().height
+        pageY = Math.max(0, pageY)
         ref.current?.scrollToOffset({
           animated: false,
           offset: pageY,
         })
       }
-      // Measure synchronously to avoid a layout jump.
-      const domNode = highlightedPostRef.current
-      if (domNode) {
-        const pageY = (domNode as any as Element).getBoundingClientRect().top
-        onMeasure(pageY)
-      }
       didAdjustScrollWeb.current = true
     }
   }, [thread])
@@ -367,7 +368,6 @@ export function PostThread({uri}: {uri: string | undefined}) {
     skeleton?.highlightedPost?.type === 'post' &&
     (skeleton.highlightedPost.ctx.isParentLoading ||
       Boolean(skeleton?.parents && skeleton.parents.length > 0))
-  const showHeader = isNative || !hasParents || !isFetching
 
   const renderItem = ({item, index}: {item: RowItem; index: number}) => {
     if (item === REPLY_PROMPT && hasSession) {
@@ -484,12 +484,15 @@ export function PostThread({uri}: {uri: string | undefined}) {
 
   return (
     <>
-      {showHeader && (
-        <ViewHeader
-          title={_(msg({message: `Post`, context: 'description'}))}
-          showBorder
-        />
-      )}
+      <Header.Outer sticky={true} headerRef={headerRef}>
+        <Header.BackButton />
+        <Header.Content>
+          <Header.TitleText>
+            <Trans context="description">Post</Trans>
+          </Header.TitleText>
+        </Header.Content>
+        <Header.Slot />
+      </Header.Outer>
 
       <ScrollProvider onMomentumEnd={onMomentumEnd}>
         <List
diff --git a/src/view/screens/Notifications.tsx b/src/view/screens/Notifications.tsx
index 4794cdcd0..1880fb816 100644
--- a/src/view/screens/Notifications.tsx
+++ b/src/view/screens/Notifications.tsx
@@ -121,7 +121,7 @@ export function NotificationsScreen({}: Props) {
 
   return (
     <Layout.Screen testID="notificationsScreen">
-      <Layout.Header.Outer noBottomBorder>
+      <Layout.Header.Outer noBottomBorder sticky={false}>
         <Layout.Header.MenuButton />
         <Layout.Header.Content>
           <Layout.Header.TitleText>