expo-popcore-app/components/message/AnnouncementBanner.tsx

113 lines
2.5 KiB
TypeScript

import React from 'react'
import {
View,
Text,
StyleSheet,
ScrollView,
TouchableOpacity,
} from 'react-native'
import { LinearGradient } from 'expo-linear-gradient'
export interface Announcement {
id: string
title: string
content?: string
link?: string
createdAt: Date
}
export interface AnnouncementBannerProps {
announcements: Announcement[]
onPress?: (announcement: Announcement) => void
}
const GRADIENT_COLORS = ['#FF9966', '#FF6699', '#9966FF'] as const
export const AnnouncementBanner: React.FC<AnnouncementBannerProps> = ({
announcements,
onPress,
}) => {
// 无公告时不渲染
if (!announcements || announcements.length === 0) {
return null
}
const handlePress = (announcement: Announcement) => {
onPress?.(announcement)
}
return (
<View testID="announcement-banner" style={styles.container}>
<LinearGradient
testID="gradient-container"
colors={[...GRADIENT_COLORS]}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
style={styles.gradientContainer}
>
<View testID="announcement-icon" style={styles.iconContainer}>
<Text style={styles.icon}>📢</Text>
</View>
<ScrollView
testID="announcement-scroll-view"
horizontal
showsHorizontalScrollIndicator={false}
style={styles.scrollView}
contentContainerStyle={styles.scrollContent}
>
{announcements.map((announcement) => (
<TouchableOpacity
key={announcement.id}
testID={`announcement-item-${announcement.id}`}
style={styles.announcementItem}
onPress={() => handlePress(announcement)}
activeOpacity={0.7}
>
<Text style={styles.title} numberOfLines={1}>
{announcement.title}
</Text>
</TouchableOpacity>
))}
</ScrollView>
</LinearGradient>
</View>
)
}
const styles = StyleSheet.create({
container: {
marginHorizontal: 16,
marginVertical: 8,
borderRadius: 12,
overflow: 'hidden',
},
gradientContainer: {
flexDirection: 'row',
alignItems: 'center',
paddingVertical: 12,
paddingHorizontal: 12,
},
iconContainer: {
marginRight: 8,
},
icon: {
fontSize: 18,
},
scrollView: {
flex: 1,
},
scrollContent: {
alignItems: 'center',
},
announcementItem: {
marginRight: 16,
},
title: {
color: '#FFFFFF',
fontSize: 14,
fontWeight: '500',
},
})
export default AnnouncementBanner