refactor(mobile): update EntryListEmpty styles and enhance TimelineViewSelector functionality

Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
Innei 2025-04-03 21:29:43 +08:00
parent d237ad1b9d
commit f08d2033da
No known key found for this signature in database
GPG Key ID: 0F62D33977F021F7
2 changed files with 74 additions and 38 deletions

View File

@ -13,12 +13,10 @@ export const EntryListEmpty = () => {
{unreadOnly ? (
<>
<CelebrateCuteReIcon height={30} width={30} color={color} />
<Text className="text-lg font-medium" style={{ color }}>
Zero Unread
</Text>
<Text className="text-secondary-label text-lg font-medium">Zero Unread</Text>
</>
) : (
<Text style={{ color }}>No entries</Text>
<Text className="text-secondary-label">No entries</Text>
)}
</View>
)

View File

@ -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<ScrollView>(null)
const selectedFeed = useSelectedFeed()
return (
<View
@ -32,13 +35,19 @@ export function TimelineViewSelector() {
style={{ height: TIMELINE_VIEW_SELECTOR_HEIGHT }}
>
<ScrollView
ref={scrollViewRef}
horizontal
scrollsToTop={false}
contentContainerClassName="flex-row gap-3 items-center px-3"
showsHorizontalScrollIndicator={false}
>
{activeViews.map((view) => (
<ViewItem key={view.name} view={view} />
<ViewItem
key={view.name}
view={view}
scrollViewRef={scrollViewRef}
isActive={selectedFeed?.type === "view" && selectedFeed.viewId === view.view}
/>
))}
</ScrollView>
</View>
@ -101,46 +110,75 @@ function ItemWrapper({
)
}
function ViewItem({ view }: { view: ViewDefinition }) {
function ViewItem({
view,
scrollViewRef,
isActive,
}: {
view: ViewDefinition
scrollViewRef: React.RefObject<ScrollView>
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<View>(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 (
<TimelineViewSelectorContextMenu type="view" viewId={view.view}>
<ItemWrapper
isActive={isActive}
onPress={() => selectTimeline({ type: "view", viewId: view.view })}
style={isActive ? { backgroundColor: view.activeColor } : undefined}
>
<view.icon color={isActive ? "#fff" : textColor} height={21} width={21} />
{isActive ? (
<>
<Animated.Text
key={view.name}
exiting={FadeOut}
className="text-sm font-semibold text-white"
numberOfLines={1}
>
{t(view.name)}
</Animated.Text>
{!!unreadCount && (
<Animated.View exiting={FadeOut} className="size-1.5 rounded-full bg-white" />
)}
</>
) : (
!!unreadCount &&
!isActive && (
<View
className="absolute -right-0.5 -top-0.5 size-2 rounded-full border"
style={{ backgroundColor: textColor, borderColor }}
/>
)
)}
</ItemWrapper>
<View ref={itemRef}>
<ItemWrapper
isActive={isActive}
onPress={() => selectTimeline({ type: "view", viewId: view.view })}
style={isActive ? { backgroundColor: view.activeColor } : undefined}
>
<view.icon color={isActive ? "#fff" : textColor} height={21} width={21} />
{isActive ? (
<>
<Animated.Text
key={view.name}
exiting={FadeOut}
className="text-sm font-semibold text-white"
numberOfLines={1}
>
{t(view.name)}
</Animated.Text>
{!!unreadCount && (
<Animated.View exiting={FadeOut} className="size-1.5 rounded-full bg-white" />
)}
</>
) : (
!!unreadCount &&
!isActive && (
<View
className="absolute -right-0.5 -top-0.5 size-2 rounded-full border"
style={{ backgroundColor: textColor, borderColor }}
/>
)
)}
</ItemWrapper>
</View>
</TimelineViewSelectorContextMenu>
)
}