You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

210 lines
4.5 KiB

/**
*
*
* 使
*/
import React, { useState, useEffect, useMemo } from 'react';
import {
View,
Text,
StyleSheet,
FlatList,
TouchableOpacity,
Image,
ActivityIndicator,
Dimensions,
} from 'react-native';
import { createThemeStyles } from '@/theme';
import Colors from '@/constants/Colors';
import { getMockGamesByCategory } from '@/services/mockHomeService';
import type { Game } from '@/types/home';
const { width } = Dimensions.get('window');
/**
*
*/
const styles = createThemeStyles((colors) => ({
container: {
flex: 1,
backgroundColor: colors.background,
paddingHorizontal: 12,
paddingVertical: 12,
},
gameGrid: {
paddingBottom: 20,
},
gameCard: {
flex: 1,
margin: 6,
borderRadius: 12,
overflow: 'hidden',
backgroundColor: colors.card,
elevation: 3,
shadowColor: colors.cardShadow,
shadowOffset: { width: 0, height: 3 },
shadowOpacity: 0.15,
shadowRadius: 6,
},
gameCardPressed: {
opacity: 0.8,
},
gameImage: {
width: '100%',
height: 140,
backgroundColor: colors.backgroundSecondary,
justifyContent: 'center',
alignItems: 'center',
},
gameIcon: {
fontSize: 48,
},
gameInfo: {
padding: 10,
},
gameName: {
fontSize: 13,
fontWeight: '600',
color: colors.text,
marginBottom: 6,
},
gameButton: {
backgroundColor: colors.primary,
paddingVertical: 8,
borderRadius: 6,
alignItems: 'center',
marginTop: 6,
},
gameButtonText: {
color: '#FFFFFF',
fontSize: 12,
fontWeight: '600',
},
emptyContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingVertical: 40,
},
emptyText: {
fontSize: 14,
color: colors.textSecondary,
marginTop: 12,
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
}));
interface LobbyProps {
theme: 'light' | 'dark';
games?: Game[];
selectedCategory?: number;
onGamePress?: (game: Game) => void;
topHeight?: number;
}
/**
*
*/
export default function Lobby({
theme,
games: propGames,
selectedCategory = 0,
onGamePress,
topHeight = 0,
}: LobbyProps) {
const s = styles[theme];
const [games, setGames] = useState<Game[]>(propGames || []);
const [loading, setLoading] = useState(true);
// 加载游戏数据
useEffect(() => {
if (propGames && propGames.length > 0) {
setGames(propGames);
setLoading(false);
return;
}
const loadGames = async () => {
try {
setLoading(true);
// const response = await getGames(selectedCategory);
// setGames(response.games.length > 0 ? response.games : getMockGamesByCategory(selectedCategory));
} catch (error) {
console.error('加载游戏失败:', error);
setGames(getMockGamesByCategory(selectedCategory));
} finally {
setLoading(false);
}
};
loadGames();
}, [propGames, selectedCategory]);
const renderGameCard = ({ item }: { item: Game }) => (
<TouchableOpacity
style={s.gameCard}
activeOpacity={0.7}
onPress={() => onGamePress?.(item)}
>
<View style={s.gameImage}>
{item.icon ? (
<Image
source={{ uri: item.icon }}
style={{ width: '100%', height: '100%' }}
resizeMode="cover"
/>
) : (
<Text style={s.gameIcon}>🎮</Text>
)}
</View>
<View style={s.gameInfo}>
<Text style={s.gameName} numberOfLines={2}>
{item.play_up_name}
{item.play_cname ? ` - ${item.play_cname}` : ''}
</Text>
<TouchableOpacity
style={s.gameButton}
onPress={() => onGamePress?.(item)}
>
<Text style={s.gameButtonText}></Text>
</TouchableOpacity>
</View>
</TouchableOpacity>
);
if (loading) {
return (
<View style={s.loadingContainer}>
<ActivityIndicator size="large" color={Colors[theme].primary} />
</View>
);
}
if (games.length === 0) {
return (
<View style={s.emptyContainer}>
<Text style={{ fontSize: 40 }}>🎮</Text>
<Text style={s.emptyText}></Text>
</View>
);
}
return (
<View style={s.container}>
<FlatList
data={games}
renderItem={renderGameCard}
keyExtractor={(item) => item.id}
numColumns={2}
scrollEnabled={false}
contentContainerStyle={s.gameGrid}
/>
</View>
);
}