1
- import { Image } from "expo-image"
2
1
import { useEffect } from "react"
3
2
import type { StyleProp , ViewStyle } from "react-native"
4
- import { ScrollView , StyleSheet , Text , View } from "react-native"
5
- import { Grayscale } from "react-native-color-matrix-image-filters"
3
+ import { ScrollView , useWindowDimensions , View } from "react-native"
6
4
import Animated , {
7
5
FadeOut ,
8
6
useAnimatedStyle ,
@@ -11,20 +9,20 @@ import Animated, {
11
9
} from "react-native-reanimated"
12
10
13
11
import { ReAnimatedTouchableOpacity } from "@/src/components/common/AnimatedComponents"
14
- import { FallbackIcon } from "@/src/components/ui/icon/fallback-icon"
15
12
import { gentleSpringPreset } from "@/src/constants/spring"
16
13
import type { ViewDefinition } from "@/src/constants/views"
17
- import { views } from "@/src/constants/views"
18
14
import { selectTimeline , useSelectedFeed } from "@/src/modules/screen/atoms"
19
- import { useList } from "@/src/store/list/hooks"
20
- import { useAllListSubscription } from "@/src/store/subscription/hooks"
15
+ import { useViewWithSubscription } from "@/src/store/subscription/hooks"
21
16
import { useUnreadCountByView } from "@/src/store/unread/hooks"
22
- import { accentColor , useColor } from "@/src/theme/colors"
17
+ import { useColor } from "@/src/theme/colors"
23
18
24
19
import { TimelineViewSelectorContextMenu } from "./TimelineViewSelectorContextMenu"
25
20
21
+ const ACTIVE_WIDTH = 180
22
+ const INACTIVE_WIDTH = 48
23
+
26
24
export function TimelineViewSelector ( ) {
27
- const lists = useAllListSubscription ( )
25
+ const activeViews = useViewWithSubscription ( )
28
26
29
27
return (
30
28
< View className = "flex items-center justify-between py-2" >
@@ -34,13 +32,9 @@ export function TimelineViewSelector() {
34
32
contentContainerClassName = "flex-row gap-3 items-center px-3"
35
33
showsHorizontalScrollIndicator = { false }
36
34
>
37
- { views . map ( ( view ) => (
35
+ { activeViews . map ( ( view ) => (
38
36
< ViewItem key = { view . name } view = { view } />
39
37
) ) }
40
- { lists . length > 0 && < View className = "bg-opaque-separator mx-3 h-8 w-px" /> }
41
- { lists . map ( ( listId ) => (
42
- < ListItem key = { listId } listId = { listId } />
43
- ) ) }
44
38
</ ScrollView >
45
39
</ View >
46
40
)
@@ -57,16 +51,26 @@ function ItemWrapper({
57
51
onPress : ( ) => void
58
52
style ?: Exclude < StyleProp < ViewStyle > , number >
59
53
} ) {
60
- const textWidth = useSharedValue ( 130 )
61
- const width = useSharedValue ( isActive ? Math . max ( 130 , textWidth . value + 48 ) : 48 )
54
+ const { width : windowWidth } = useWindowDimensions ( )
55
+ const activeViews = useViewWithSubscription ( )
56
+
57
+ const activeWidth = Math . max (
58
+ windowWidth - ( INACTIVE_WIDTH + 12 ) * ( activeViews . length - 1 ) - 8 * 2 ,
59
+ ACTIVE_WIDTH ,
60
+ )
61
+
62
+ const textWidth = useSharedValue ( 0 )
63
+ const width = useSharedValue (
64
+ isActive ? Math . max ( activeWidth , textWidth . value + INACTIVE_WIDTH ) : INACTIVE_WIDTH ,
65
+ )
62
66
const bgColor = useColor ( "gray5" )
63
67
64
68
useEffect ( ( ) => {
65
69
width . value = withSpring (
66
- isActive ? Math . max ( 130 , textWidth . value + 48 ) : 48 ,
70
+ isActive ? Math . max ( activeWidth , textWidth . value + INACTIVE_WIDTH ) : INACTIVE_WIDTH ,
67
71
gentleSpringPreset ,
68
72
)
69
- } , [ isActive , width , textWidth ] )
73
+ } , [ isActive , width , textWidth , activeWidth ] )
70
74
71
75
return (
72
76
< ReAnimatedTouchableOpacity
@@ -99,15 +103,6 @@ function ViewItem({ view }: { view: ViewDefinition }) {
99
103
const unreadCount = useUnreadCountByView ( view . view )
100
104
const borderColor = useColor ( "gray5" )
101
105
102
- const textWidth = useSharedValue ( 130 )
103
- const width = useSharedValue ( isActive ? Math . max ( 130 , textWidth . value + 48 ) : 48 )
104
-
105
- useEffect ( ( ) => {
106
- if ( isActive ) {
107
- width . value = withSpring ( Math . max ( 130 , textWidth . value + 48 ) , gentleSpringPreset )
108
- }
109
- } , [ isActive , unreadCount ] )
110
-
111
106
return (
112
107
< TimelineViewSelectorContextMenu type = "view" viewId = { view . view } >
113
108
< ItemWrapper
@@ -143,44 +138,3 @@ function ViewItem({ view }: { view: ViewDefinition }) {
143
138
</ TimelineViewSelectorContextMenu >
144
139
)
145
140
}
146
-
147
- function ListItem ( { listId } : { listId : string } ) {
148
- const list = useList ( listId )
149
- const selectedFeed = useSelectedFeed ( )
150
-
151
- if ( ! selectedFeed ) return null
152
- const isActive = selectedFeed . type === "list" && selectedFeed . listId === listId
153
-
154
- if ( ! list ) return null
155
-
156
- return (
157
- < ItemWrapper
158
- isActive = { isActive }
159
- onPress = { ( ) => selectTimeline ( { type : "list" , listId } ) }
160
- style = { isActive ? { backgroundColor : accentColor } : undefined }
161
- >
162
- { list . image ? (
163
- isActive ? (
164
- < Image source = { list . image } contentFit = "cover" className = "size-7 rounded-lg" />
165
- ) : (
166
- < Grayscale >
167
- < Image source = { list . image } contentFit = "cover" className = "size-7 rounded-lg" />
168
- </ Grayscale >
169
- )
170
- ) : (
171
- < FallbackIcon title = { list . title } size = { 28 } gray = { ! isActive } style = { styles . fallbackIcon } />
172
- ) }
173
- { isActive && (
174
- < Text className = "max-w-24 text-sm font-semibold text-white" numberOfLines = { 1 } >
175
- { list . title }
176
- </ Text >
177
- ) }
178
- </ ItemWrapper >
179
- )
180
- }
181
-
182
- const styles = StyleSheet . create ( {
183
- fallbackIcon : {
184
- borderRadius : 8 ,
185
- } ,
186
- } )
0 commit comments