327 lines
10 KiB
TypeScript
327 lines
10 KiB
TypeScript
import { useState, useEffect } from 'react'
|
||
import {
|
||
View,
|
||
Text,
|
||
StyleSheet,
|
||
ScrollView,
|
||
StatusBar as RNStatusBar,
|
||
Pressable,
|
||
} from 'react-native'
|
||
import { LinearGradient } from 'expo-linear-gradient'
|
||
import { StatusBar } from 'expo-status-bar'
|
||
import { SafeAreaView } from 'react-native-safe-area-context'
|
||
import { useTranslation } from 'react-i18next'
|
||
|
||
// 消息卡片数据
|
||
interface MessageCard {
|
||
id: number
|
||
title: string
|
||
subtitle: string
|
||
body: string
|
||
time: string
|
||
type: 'notice' | 'other'
|
||
isNew?: boolean // 是否为新消息
|
||
}
|
||
|
||
const messageCards: MessageCard[] = [
|
||
{
|
||
id: 1,
|
||
title: '恭喜你,获得双12新用户专享福利',
|
||
subtitle: '打开推送的内容,限时优惠,多种玩法,快来体验~',
|
||
body: '图片占位。',
|
||
time: '2023-12-29 18:32:21',
|
||
type: 'notice',
|
||
isNew: true, // 新消息
|
||
},
|
||
{
|
||
id: 2,
|
||
title: '新功能上线:AI 智能生成',
|
||
subtitle: '全新 AI 功能已上线,快来体验吧!',
|
||
body: '图片占位。',
|
||
time: '2023-12-28 15:20:10',
|
||
type: 'notice',
|
||
isNew: true, // 新消息
|
||
},
|
||
{
|
||
id: 3,
|
||
title: '系统维护通知',
|
||
subtitle: '系统将于今晚进行维护升级',
|
||
body: '图片占位。',
|
||
time: '2023-12-27 10:15:30',
|
||
type: 'other',
|
||
isNew: false, // 非新消息
|
||
},
|
||
{
|
||
id: 4,
|
||
title: '限时活动:分享有礼',
|
||
subtitle: '分享你的作品,赢取丰厚奖励',
|
||
body: '图片占位。',
|
||
time: '2023-12-26 14:05:22',
|
||
type: 'notice',
|
||
isNew: false, // 非新消息
|
||
},
|
||
{
|
||
id: 5,
|
||
title: '版本更新提醒',
|
||
subtitle: '新版本已发布,建议及时更新',
|
||
body: '图片占位。',
|
||
time: '2023-12-25 09:30:45',
|
||
type: 'other',
|
||
isNew: false, // 非新消息
|
||
},
|
||
]
|
||
|
||
export default function MessageScreen() {
|
||
const { t } = useTranslation()
|
||
const [activeTab, setActiveTab] = useState<'all' | 'notice' | 'other'>('all')
|
||
|
||
// 根据选中的标签过滤卡片
|
||
const filteredCards = messageCards.filter((card) => {
|
||
if (activeTab === 'all') return true
|
||
return card.type === activeTab
|
||
})
|
||
|
||
return (
|
||
<SafeAreaView style={styles.container} edges={['top']}>
|
||
<StatusBar style="light" />
|
||
<RNStatusBar barStyle="light-content" />
|
||
|
||
{/* 固定在顶部的标签选择器 */}
|
||
<View style={styles.segment}>
|
||
<Pressable onPress={() => setActiveTab('all')}>
|
||
{activeTab === 'all' ? (
|
||
<View style={styles.segmentTextActiveWrapper}>
|
||
<LinearGradient
|
||
colors={['#FF9966', '#FF6699', '#9966FF']}
|
||
start={{ x: 0, y: 0 }}
|
||
end={{ x: 1, y: 0 }}
|
||
style={styles.segmentTextActiveBg}
|
||
/>
|
||
<Text
|
||
style={[
|
||
styles.segmentText,
|
||
styles.segmentTextActiveText,
|
||
]}
|
||
>
|
||
{t('message.all')}
|
||
</Text>
|
||
</View>
|
||
) : (
|
||
<Text style={styles.segmentText}>{t('message.all')}</Text>
|
||
)}
|
||
</Pressable>
|
||
<Pressable onPress={() => setActiveTab('notice')}>
|
||
{activeTab === 'notice' ? (
|
||
<View style={styles.segmentTextActiveWrapper}>
|
||
<LinearGradient
|
||
colors={['#FF9966', '#FF6699', '#9966FF']}
|
||
start={{ x: 0, y: 0 }}
|
||
end={{ x: 1, y: 0 }}
|
||
style={styles.segmentTextActiveBg}
|
||
/>
|
||
<Text
|
||
style={[
|
||
styles.segmentText,
|
||
styles.segmentTextActiveText,
|
||
]}
|
||
>
|
||
{t('message.notice')}
|
||
</Text>
|
||
</View>
|
||
) : (
|
||
<Text style={styles.segmentText}>{t('message.notice')}</Text>
|
||
)}
|
||
</Pressable>
|
||
<Pressable onPress={() => setActiveTab('other')}>
|
||
{activeTab === 'other' ? (
|
||
<View style={styles.segmentTextActiveWrapper}>
|
||
<LinearGradient
|
||
colors={['#FF9966', '#FF6699', '#9966FF']}
|
||
start={{ x: 0, y: 0 }}
|
||
end={{ x: 1, y: 0 }}
|
||
style={styles.segmentTextActiveBg}
|
||
/>
|
||
<Text
|
||
style={[
|
||
styles.segmentText,
|
||
styles.segmentTextActiveText,
|
||
]}
|
||
>
|
||
{t('message.other')}
|
||
</Text>
|
||
</View>
|
||
) : (
|
||
<Text style={styles.segmentText}>{t('message.other')}</Text>
|
||
)}
|
||
</Pressable>
|
||
</View>
|
||
|
||
{/* 可滚动的消息卡片列表 */}
|
||
<ScrollView
|
||
style={styles.scrollView}
|
||
contentContainerStyle={styles.scrollContent}
|
||
showsVerticalScrollIndicator={false}
|
||
>
|
||
{/* 消息卡片列表 */}
|
||
{filteredCards.length > 0 ? (
|
||
filteredCards.map((card) => (
|
||
<View key={card.id} style={styles.cardContainer}>
|
||
{/* 新消息绿色指示点 */}
|
||
{card.isNew && (
|
||
<View style={styles.newMessageDotContainer}>
|
||
<View style={styles.newMessageDot} />
|
||
</View>
|
||
)}
|
||
<Text style={styles.cardTitle}>
|
||
{card.title}
|
||
</Text>
|
||
<Text style={styles.cardSubtitle} numberOfLines={2}>
|
||
{card.subtitle}
|
||
</Text>
|
||
|
||
<View style={styles.cardBody}>
|
||
<Text style={styles.cardBodyText}>
|
||
{/* TODO:这里是图片 */}
|
||
{card.body}
|
||
</Text>
|
||
</View>
|
||
|
||
<Text style={styles.cardTime}>
|
||
{card.time}
|
||
</Text>
|
||
</View>
|
||
))
|
||
) : (
|
||
<View style={styles.emptyContainer}>
|
||
{/* <NoNewsIcon /> */}
|
||
💭
|
||
<Text style={styles.emptyText}>{t('message.noMessages')}</Text>
|
||
</View>
|
||
)}
|
||
</ScrollView>
|
||
</SafeAreaView>
|
||
)
|
||
}
|
||
|
||
const styles = StyleSheet.create({
|
||
container: {
|
||
flex: 1,
|
||
backgroundColor: '#090A0B',
|
||
},
|
||
scrollView: {
|
||
flex: 1,
|
||
backgroundColor: '#090A0B',
|
||
},
|
||
scrollContent: {
|
||
paddingHorizontal: 4,
|
||
paddingTop: 12,
|
||
},
|
||
appMiniIcon: {
|
||
width: 28,
|
||
height: 18,
|
||
borderRadius: 4,
|
||
backgroundColor: '#FF66AA',
|
||
},
|
||
segment: {
|
||
flexDirection: 'row',
|
||
paddingHorizontal: 8,
|
||
paddingTop: 19,
|
||
paddingBottom: 12,
|
||
backgroundColor: '#090A0B',
|
||
gap: 16,
|
||
},
|
||
|
||
segmentText: {
|
||
fontSize: 14,
|
||
color: '#FFFFFF',
|
||
},
|
||
segmentTextActiveWrapper: {
|
||
position: 'relative',
|
||
paddingBottom: 2,
|
||
justifyContent: 'flex-end',
|
||
alignSelf: 'flex-start',
|
||
},
|
||
segmentTextActiveBg: {
|
||
position: 'absolute',
|
||
left: 0,
|
||
right: 0,
|
||
bottom: 0,
|
||
height: 10,
|
||
backgroundColor: '#FF9966',
|
||
},
|
||
segmentTextActiveText: {
|
||
zIndex: 1,
|
||
},
|
||
statusDot: {
|
||
width: 6,
|
||
height: 6,
|
||
borderRadius: 3,
|
||
backgroundColor: '#00FF66',
|
||
marginRight: 4,
|
||
},
|
||
cardContainer: {
|
||
backgroundColor: '#16181B',
|
||
borderRadius: 16,
|
||
padding: 16,
|
||
marginBottom: 12,
|
||
marginHorizontal: 4,
|
||
position: 'relative', // 用于定位新消息指示点
|
||
},
|
||
newMessageDotContainer: {
|
||
position: 'absolute',
|
||
top: -4,
|
||
right: -2,
|
||
width: 16,
|
||
height: 16,
|
||
borderWidth: 4,
|
||
borderColor: '#090A0B',
|
||
borderRadius: 8,
|
||
justifyContent: 'center',
|
||
alignItems: 'center',
|
||
},
|
||
newMessageDot: {
|
||
width: 6,
|
||
height: 6,
|
||
borderRadius: 4,
|
||
backgroundColor: '#00FF66', // 绿色
|
||
zIndex: 1,
|
||
},
|
||
cardTitle: {
|
||
color: '#FFFFFF',
|
||
fontSize: 15,
|
||
fontWeight: '600',
|
||
marginBottom: 8,
|
||
},
|
||
cardSubtitle: {
|
||
color: '#ABABAB',
|
||
fontSize: 11,
|
||
marginBottom: 16,
|
||
},
|
||
cardBody: {
|
||
backgroundColor: '#26292E',
|
||
borderRadius: 12,
|
||
height:100,
|
||
marginBottom: 12,
|
||
},
|
||
cardBodyText: {
|
||
color: '#FFFFFF',
|
||
fontSize: 12,
|
||
opacity: 0.8,
|
||
},
|
||
cardTime: {
|
||
color: '#8A8A8A',
|
||
fontSize: 10,
|
||
},
|
||
emptyContainer: {
|
||
flex: 1,
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
paddingTop: 200,
|
||
},
|
||
emptyText: {
|
||
color: '#8A8A8A',
|
||
fontSize: 12,
|
||
marginTop: 16,
|
||
},
|
||
})
|