Skip to content

Commit 0832b21

Browse files
committed
feat: queue list
1 parent 7397014 commit 0832b21

File tree

2 files changed

+71
-42
lines changed

2 files changed

+71
-42
lines changed

apps/mobile/modules/player/FullPlayerControl.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Dimensions, StyleSheet, View } from 'react-native'
66
import { IconButton, Text, useTheme } from 'react-native-paper'
77
import Animated, { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated'
88
import { useSafeAreaInsets } from 'react-native-safe-area-context'
9+
import { QueueList } from './QueueList'
910

1011
const { width: screenWidth } = Dimensions.get('screen')
1112

@@ -16,7 +17,7 @@ export default function FullPlayerControl() {
1617
const isPlaying = usePlayerStore.use.isPlaying()
1718
const mode = usePlayerStore.use.mode()
1819
const position = usePlaybackStore.use.position()
19-
20+
const [queueListVisible, setQueueListVisible] = useState(false)
2021
const [slidingValue, setSlidingValue] = useState(0)
2122

2223
// Slider animation values
@@ -149,11 +150,14 @@ export default function FullPlayerControl() {
149150
<IconButton
150151
icon="playlist-music"
151152
size={24}
152-
onPress={() => {
153-
console.log('Pressed')
154-
}}
153+
onPress={() => setQueueListVisible(true)}
155154
/>
156155
</View>
156+
157+
<QueueList
158+
visible={queueListVisible}
159+
onDismiss={() => setQueueListVisible(false)}
160+
/>
157161
</View>
158162
)
159163
}
Lines changed: 63 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,31 @@
11
import type { Track } from '@flow/shared'
22
import { usePlayerStore } from '@flow/player'
3-
import { FlashList } from '@shopify/flash-list'
4-
import { Image, StyleSheet, View } from 'react-native'
5-
import { IconButton, List, Text } from 'react-native-paper'
6-
import { ThemedView } from '@/components/ui/ThemedView'
3+
import { BottomSheetFlashList } from '@gorhom/bottom-sheet'
4+
import { StyleSheet, View } from 'react-native'
5+
import { Appbar, IconButton, List, Text } from 'react-native-paper'
6+
import { ThemedBottomSheetModal } from '@/components/ui/ThemedBottomSheetModal'
77

8-
export default function QueueList() {
9-
const { queue } = usePlayerStore()
8+
interface QueueListProps {
9+
visible: boolean
10+
onDismiss: () => void
11+
}
12+
13+
export function QueueList({ visible, onDismiss }: QueueListProps) {
14+
const { queue, removeFromQueue } = usePlayerStore()
1015

1116
const renderItem = ({ item }: { item: Track }) => (
1217
<List.Item
1318
key={item.id}
1419
title={item.title}
1520
description={`${item.artist} - ${item.album}`}
1621
descriptionNumberOfLines={1}
17-
style={{ paddingLeft: 16, paddingRight: 8 }}
18-
left={() => <Image source={{ uri: item.artwork }} style={{ aspectRatio: 1, borderRadius: 10 }} />}
22+
style={{ paddingRight: 8 }}
1923
right={() => (
2024
<View style={styles.rightContent}>
2125
<IconButton
22-
icon="plus"
26+
icon="minus"
2327
size={14}
24-
onPress={() => console.log('Pressed')}
25-
/>
26-
27-
<IconButton
28-
icon="dots-vertical"
29-
size={14}
30-
onPress={() => console.log('Pressed')}
28+
onPress={() => removeFromQueue(item.id)}
3129
/>
3230
</View>
3331
)}
@@ -38,33 +36,58 @@ export default function QueueList() {
3836
)
3937

4038
return (
41-
<ThemedView style={styles.container}>
42-
{
43-
queue.length > 0
44-
? (
45-
<FlashList
46-
data={queue}
47-
renderItem={renderItem}
48-
keyExtractor={item => item.id}
49-
showsVerticalScrollIndicator={false}
50-
extraData={queue}
51-
estimatedItemSize={70}
52-
/>
53-
)
54-
: (
55-
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
56-
<Text>No songs</Text>
57-
</View>
58-
)
59-
}
60-
</ThemedView>
39+
<ThemedBottomSheetModal
40+
visible={visible}
41+
snapPoints={['60%', '90%']}
42+
onDismiss={onDismiss}
43+
>
44+
<View style={styles.header}>
45+
<Appbar.Content title="播放队列" />
46+
<Appbar.Action
47+
icon="close"
48+
onPress={onDismiss}
49+
/>
50+
</View>
51+
52+
<View style={styles.content}>
53+
{
54+
queue.length > 0
55+
? (
56+
<BottomSheetFlashList
57+
data={queue}
58+
renderItem={renderItem}
59+
keyExtractor={item => item.id}
60+
showsVerticalScrollIndicator={false}
61+
extraData={queue}
62+
estimatedItemSize={70}
63+
/>
64+
)
65+
: (
66+
<View style={styles.emptyContainer}>
67+
<Text>暂无歌曲</Text>
68+
</View>
69+
)
70+
}
71+
</View>
72+
</ThemedBottomSheetModal>
6173
)
6274
}
6375

6476
const styles = StyleSheet.create({
65-
container: {
77+
header: {
78+
flexDirection: 'row',
79+
alignItems: 'center',
80+
paddingHorizontal: 8,
81+
paddingVertical: 8,
82+
},
83+
content: {
6684
flex: 1,
67-
paddingVertical: 150,
85+
marginTop: 8,
86+
},
87+
emptyContainer: {
88+
flex: 1,
89+
justifyContent: 'center',
90+
alignItems: 'center',
6891
},
6992
rightContent: {
7093
flexDirection: 'row',
@@ -74,3 +97,5 @@ const styles = StyleSheet.create({
7497
opacity: 0.6,
7598
},
7699
})
100+
101+
export default QueueList

0 commit comments

Comments
 (0)