expo-popcore-app/app/(tabs)/message.tsx

327 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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,
},
})