Initial commit: expo-popcore-app
This commit is contained in:
326
app/(tabs)/message.tsx
Normal file
326
app/(tabs)/message.tsx
Normal file
@@ -0,0 +1,326 @@
|
||||
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,
|
||||
},
|
||||
})
|
||||
Reference in New Issue
Block a user