diff --git a/apps/mobile/src/modules/entry-list/EntryListEmpty.tsx b/apps/mobile/src/modules/entry-list/EntryListEmpty.tsx index e854c587d..6d6b184d8 100644 --- a/apps/mobile/src/modules/entry-list/EntryListEmpty.tsx +++ b/apps/mobile/src/modules/entry-list/EntryListEmpty.tsx @@ -13,12 +13,10 @@ export const EntryListEmpty = () => { {unreadOnly ? ( <> - - Zero Unread - + Zero Unread ) : ( - No entries + No entries )} ) diff --git a/apps/mobile/src/modules/screen/TimelineViewSelector.tsx b/apps/mobile/src/modules/screen/TimelineViewSelector.tsx index 1dd27317a..34c0ba03d 100644 --- a/apps/mobile/src/modules/screen/TimelineViewSelector.tsx +++ b/apps/mobile/src/modules/screen/TimelineViewSelector.tsx @@ -1,3 +1,4 @@ +import * as React from "react" import { useEffect } from "react" import { useTranslation } from "react-i18next" import type { StyleProp, ViewStyle } from "react-native" @@ -25,6 +26,8 @@ const INACTIVE_WIDTH = 48 export function TimelineViewSelector() { const activeViews = useViewWithSubscription() + const scrollViewRef = React.useRef(null) + const selectedFeed = useSelectedFeed() return ( {activeViews.map((view) => ( - + ))} @@ -101,46 +110,75 @@ function ItemWrapper({ ) } -function ViewItem({ view }: { view: ViewDefinition }) { +function ViewItem({ + view, + scrollViewRef, + isActive, +}: { + view: ViewDefinition + scrollViewRef: React.RefObject + isActive: boolean +}) { const textColor = useColor("gray") - const selectedFeed = useSelectedFeed() - const isActive = selectedFeed?.type === "view" && selectedFeed.viewId === view.view const unreadCount = useUnreadCountByView(view.view) const borderColor = useColor("gray5") const { t } = useTranslation("common") + const itemRef = React.useRef(null) + const { width: windowWidth } = useWindowDimensions() + + // Scroll to center the active item when it becomes active + useEffect(() => { + let timeout: NodeJS.Timeout | null = null + if (isActive && scrollViewRef.current && itemRef.current) { + // Give time for animation to start + timeout = setTimeout(() => { + itemRef.current?.measureInWindow((x, y, width) => { + const scrollX = x - windowWidth / 2 + width / 2 + scrollViewRef.current?.scrollTo({ x: Math.max(0, scrollX), animated: true }) + }) + }, 50) + } + return () => { + if (timeout) { + clearTimeout(timeout) + } + } + }, [isActive, scrollViewRef, windowWidth]) return ( - selectTimeline({ type: "view", viewId: view.view })} - style={isActive ? { backgroundColor: view.activeColor } : undefined} - > - - {isActive ? ( - <> - - {t(view.name)} - - {!!unreadCount && ( - - )} - - ) : ( - !!unreadCount && - !isActive && ( - - ) - )} - + + selectTimeline({ type: "view", viewId: view.view })} + style={isActive ? { backgroundColor: view.activeColor } : undefined} + > + + {isActive ? ( + <> + + {t(view.name)} + + {!!unreadCount && ( + + )} + + ) : ( + !!unreadCount && + !isActive && ( + + ) + )} + + ) }