feat: integrate BlurView for enhanced UI in TableScreen and adjust padding in TableBackground

This commit is contained in:
2025-12-21 00:29:28 +01:00
parent 5181b36014
commit 8532fee1c3
3 changed files with 87 additions and 59 deletions

View File

@@ -13,6 +13,7 @@
"@babel/runtime": "^7.25.6", "@babel/runtime": "^7.25.6",
"@react-native-async-storage/async-storage": "1.23.1", "@react-native-async-storage/async-storage": "1.23.1",
"@stripe/stripe-react-native": "0.38.3", "@stripe/stripe-react-native": "0.38.3",
"expo-blur": "~13.0.2",
"expo": "~51.0.0", "expo": "~51.0.0",
"expo-auth-session": "~5.0.2", "expo-auth-session": "~5.0.2",
"expo-linear-gradient": "~12.7.2", "expo-linear-gradient": "~12.7.2",

View File

@@ -28,7 +28,7 @@ export default function TableBackground({ children, style }) {
const styles = StyleSheet.create({ const styles = StyleSheet.create({
wrapper: { wrapper: {
width: '100%', width: '100%',
padding: 12 padding: 0
}, },
edge: { edge: {
flex: 1, flex: 1,
@@ -36,7 +36,7 @@ const styles = StyleSheet.create({
borderTopRightRadius: 60, borderTopRightRadius: 60,
borderBottomLeftRadius: 280, borderBottomLeftRadius: 280,
borderBottomRightRadius: 280, borderBottomRightRadius: 280,
padding: 10 padding: 6
}, },
felt: { felt: {
flex: 1, flex: 1,
@@ -44,7 +44,7 @@ const styles = StyleSheet.create({
borderTopRightRadius: 48, borderTopRightRadius: 48,
borderBottomLeftRadius: 260, borderBottomLeftRadius: 260,
borderBottomRightRadius: 260, borderBottomRightRadius: 260,
padding: 20, padding: 14,
overflow: 'hidden' overflow: 'hidden'
}, },
innerRing: { innerRing: {

View File

@@ -1,6 +1,7 @@
import { useEffect, useMemo, useRef, useState } from 'react'; import { useEffect, useMemo, useRef, useState } from 'react';
import { Animated, Pressable, StyleSheet, Text, View } from 'react-native'; import { Animated, Pressable, StyleSheet, Text, View } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient'; import { LinearGradient } from 'expo-linear-gradient';
import { BlurView } from 'expo-blur';
import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { WS_URL } from '../api'; import { WS_URL } from '../api';
import { colors, fonts } from '../theme'; import { colors, fonts } from '../theme';
@@ -134,7 +135,7 @@ export default function TableScreen({ token, tableId, user, onLeave }) {
styles.container, styles.container,
{ {
paddingTop: insets.top + 12, paddingTop: insets.top + 12,
paddingBottom: insets.bottom + 16 paddingBottom: insets.bottom + 12
} }
]} ]}
> >
@@ -148,48 +149,55 @@ export default function TableScreen({ token, tableId, user, onLeave }) {
<View style={styles.tableWrap}> <View style={styles.tableWrap}>
<TableBackground style={styles.tableSurface}> <TableBackground style={styles.tableSurface}>
<TableMarkings /> <View style={styles.tableInner}>
<View style={styles.tableContent}> <TableMarkings />
<View style={styles.dealerArea}> <View style={styles.tableContent}>
<DealerArea hand={table?.dealerHand || []} /> <View style={styles.dealerArea}>
<DealerArea hand={table?.dealerHand || []} />
</View>
<View style={styles.seatLayer}>
{seats.map((seat) => (
<View key={seat.index} style={[styles.seatSpot, seatPositions[seat.index]]}>
<Seat seat={seat} highlight={table.currentSeatIndex === seat.index} />
</View>
))}
</View>
</View> </View>
<View style={styles.seatLayer}>
{seats.map((seat) => ( <View style={styles.controlsOverlay}>
<View key={seat.index} style={[styles.seatSpot, seatPositions[seat.index]]}> <BlurView intensity={28} tint="dark" style={styles.blurPanel}>
<Seat seat={seat} highlight={table.currentSeatIndex === seat.index} /> <View style={styles.betRow}>
<Text style={styles.sectionLabel}>Tét</Text>
<View style={styles.betControls}>
<Pressable onPress={() => adjustBet(-10)} style={[styles.betAdjust, bettingLocked && styles.betAdjustDisabled]} disabled={bettingLocked}>
<Text style={styles.betAdjustText}>-</Text>
</Pressable>
<Chip label={`${betAmount}`} color="red" />
<Pressable onPress={() => adjustBet(10)} style={[styles.betAdjust, bettingLocked && styles.betAdjustDisabled]} disabled={bettingLocked}>
<Text style={styles.betAdjustText}>+</Text>
</Pressable>
</View>
<CasinoButton label="Tét" onPress={() => send({ type: 'bet', amount: betAmount })} variant="gold" disabled={bettingLocked} />
<CasinoButton label="Kész" onPress={() => send({ type: 'ready' })} variant="green" disabled={bettingLocked} />
</View> </View>
))} </BlurView>
<BlurView intensity={28} tint="dark" style={styles.blurPanel}>
{isMyTurn && turnSeconds !== null ? (
<Text style={styles.timer}>Idő: {turnSeconds} mp</Text>
) : null}
<Animated.View style={[styles.actionRow, isMyTurn && pulseStyle]}>
<CasinoButton label="Hit" onPress={() => send({ type: 'action', action: 'hit' })} variant="gold" disabled={!isMyTurn} />
<CasinoButton label="Stand" onPress={() => send({ type: 'action', action: 'stand' })} variant="gold" disabled={!isMyTurn} />
<CasinoButton label="Double" onPress={() => send({ type: 'action', action: 'double' })} variant="gold" disabled={!isMyTurn} />
</Animated.View>
</BlurView>
</View> </View>
{message ? <Text style={styles.message}>{message}</Text> : null}
</View> </View>
</TableBackground> </TableBackground>
</View> </View>
<View style={styles.controls}>
<View style={styles.betRow}>
<Text style={styles.sectionLabel}>Tét</Text>
<View style={styles.betControls}>
<Pressable onPress={() => adjustBet(-10)} style={[styles.betAdjust, bettingLocked && styles.betAdjustDisabled]} disabled={bettingLocked}>
<Text style={styles.betAdjustText}>-</Text>
</Pressable>
<Chip label={`${betAmount}`} color="red" />
<Pressable onPress={() => adjustBet(10)} style={[styles.betAdjust, bettingLocked && styles.betAdjustDisabled]} disabled={bettingLocked}>
<Text style={styles.betAdjustText}>+</Text>
</Pressable>
</View>
<CasinoButton label="Tét" onPress={() => send({ type: 'bet', amount: betAmount })} variant="gold" disabled={bettingLocked} />
<CasinoButton label="Kész" onPress={() => send({ type: 'ready' })} variant="green" disabled={bettingLocked} />
</View>
{isMyTurn && turnSeconds !== null ? (
<Text style={styles.timer}>Idő: {turnSeconds} mp</Text>
) : null}
<Animated.View style={[styles.actionRow, isMyTurn && pulseStyle]}>
<CasinoButton label="Hit" onPress={() => send({ type: 'action', action: 'hit' })} variant="gold" disabled={!isMyTurn} />
<CasinoButton label="Stand" onPress={() => send({ type: 'action', action: 'stand' })} variant="gold" disabled={!isMyTurn} />
<CasinoButton label="Double" onPress={() => send({ type: 'action', action: 'double' })} variant="gold" disabled={!isMyTurn} />
</Animated.View>
{message ? <Text style={styles.message}>{message}</Text> : null}
</View>
</LinearGradient> </LinearGradient>
); );
} }
@@ -197,10 +205,10 @@ export default function TableScreen({ token, tableId, user, onLeave }) {
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
paddingHorizontal: 20 paddingHorizontal: 12
}, },
topBar: { topBar: {
paddingHorizontal: 20, paddingHorizontal: 6,
flexDirection: 'row', flexDirection: 'row',
justifyContent: 'space-between', justifyContent: 'space-between',
alignItems: 'center' alignItems: 'center'
@@ -219,11 +227,19 @@ const styles = StyleSheet.create({
tableWrap: { tableWrap: {
flex: 1, flex: 1,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center' alignItems: 'center',
marginTop: 8,
marginBottom: 8,
width: '100%'
}, },
tableSurface: { tableSurface: {
aspectRatio: 1.8, flex: 1,
maxHeight: 420 width: '100%',
padding: 0
},
tableInner: {
flex: 1,
position: 'relative'
}, },
dealerArea: { dealerArea: {
alignItems: 'center', alignItems: 'center',
@@ -243,16 +259,27 @@ const styles = StyleSheet.create({
width: 110, width: 110,
transform: [{ translateX: -55 }] transform: [{ translateX: -55 }]
}, },
controls: { controlsOverlay: {
paddingHorizontal: 20, position: 'absolute',
paddingBottom: 24 left: 12,
right: 12,
bottom: 14,
gap: 10
},
blurPanel: {
borderRadius: 18,
paddingVertical: 10,
paddingHorizontal: 12,
backgroundColor: 'rgba(10, 18, 14, 0.45)',
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.12)',
overflow: 'hidden'
}, },
betRow: { betRow: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
justifyContent: 'space-between', justifyContent: 'space-between',
gap: 8, gap: 8
marginBottom: 12
}, },
betControls: { betControls: {
flexDirection: 'row', flexDirection: 'row',
@@ -288,23 +315,23 @@ const styles = StyleSheet.create({
message: { message: {
color: colors.goldBright, color: colors.goldBright,
textAlign: 'center', textAlign: 'center',
marginTop: 10, marginTop: 8,
fontFamily: fonts.body fontFamily: fonts.body
}, },
timer: { timer: {
color: colors.goldBright, color: colors.goldBright,
textAlign: 'center', textAlign: 'center',
marginBottom: 8, marginBottom: 6,
fontFamily: fonts.mono fontFamily: fonts.mono
} }
}); });
const seatPositions = { const seatPositions = {
0: { left: '12%', top: '55%' }, 0: { left: '10%', top: '50%' },
1: { left: '25%', top: '48%' }, 1: { left: '24%', top: '44%' },
2: { left: '38%', top: '42%' }, 2: { left: '38%', top: '38%' },
3: { left: '50%', top: '40%' }, 3: { left: '50%', top: '36%' },
4: { left: '62%', top: '42%' }, 4: { left: '62%', top: '38%' },
5: { left: '75%', top: '48%' }, 5: { left: '76%', top: '44%' },
6: { left: '88%', top: '55%' } 6: { left: '90%', top: '50%' }
}; };