Cambios visuales completos
This commit is contained in:
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:farolero/l10n/generated/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../estado/estado_juego.dart';
|
||||
import '../tema/componentes_farolero.dart';
|
||||
import '../tema/tema_app.dart';
|
||||
import 'pantalla_debate.dart';
|
||||
import 'pantalla_fin_partida.dart';
|
||||
@@ -41,24 +42,24 @@ class _PantallaAdivinanzaState extends State<PantallaAdivinanza> {
|
||||
title: Text(l10n.impostorGuessTitle),
|
||||
automaticallyImplyLeading: false,
|
||||
),
|
||||
body: Center(
|
||||
child: SingleChildScrollView(
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: Center(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(32),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Text('🎭', style: TextStyle(fontSize: 64)),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
l10n.impostorCanGuess,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
l10n.ifCorrectImpostorsWin,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: TemaApp.colorNaranja,
|
||||
EncabezadoFarolero(
|
||||
icono: Icons.theater_comedy,
|
||||
titulo: l10n.impostorCanGuess,
|
||||
subtitulo: l10n.ifCorrectImpostorsWin,
|
||||
color: TemaApp.colorAcento,
|
||||
trailing: Image.asset(
|
||||
'assets/ui/premium/vote_danger_glow.png',
|
||||
width: 42,
|
||||
height: 42,
|
||||
opacity: const AlwaysStoppedAnimation(0.64),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
@@ -231,6 +232,7 @@ class _PantallaAdivinanzaState extends State<PantallaAdivinanza> {
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -23,6 +23,7 @@ class _PantallaAjustesState extends State<PantallaAjustes> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(l10n.settingsTitle)),
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
|
||||
@@ -317,42 +317,23 @@ class _PantallaCrearPartidaState extends State<PantallaCrearPartida> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(l10n.createGame)),
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.fromLTRB(18, 18, 18, 28),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
PanelFarolero(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 18),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.groups, color: TemaApp.colorNaranja, size: 42),
|
||||
const SizedBox(width: 14),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'¿Cómo quieres jugar?',
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 3),
|
||||
Text(
|
||||
l10n.playersRange,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
EncabezadoFarolero(
|
||||
icono: Icons.groups,
|
||||
titulo: '¿Cómo quieres jugar?',
|
||||
subtitulo: l10n.playersRange,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
if (!widget.bloquearModo) ...[
|
||||
// Modo de juego
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.fromLTRB(18, 18, 18, 28),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -416,7 +397,7 @@ class _PantallaCrearPartidaState extends State<PantallaCrearPartida> {
|
||||
// Categoría
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.fromLTRB(18, 18, 18, 28),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -453,7 +434,7 @@ class _PantallaCrearPartidaState extends State<PantallaCrearPartida> {
|
||||
// Jugadores
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.fromLTRB(18, 18, 18, 28),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -542,7 +523,7 @@ class _PantallaCrearPartidaState extends State<PantallaCrearPartida> {
|
||||
// Configuración de partida
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.fromLTRB(18, 18, 18, 28),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -614,22 +595,12 @@ class _PantallaCrearPartidaState extends State<PantallaCrearPartida> {
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// Botón iniciar
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: 56,
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: (_modoMultimovil || _jugadores.length >= 3)
|
||||
? _iniciarPartida
|
||||
: null,
|
||||
icon: const Icon(Icons.play_arrow),
|
||||
label: Text(l10n.startGame),
|
||||
style: ElevatedButton.styleFrom(
|
||||
textStyle: const TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
BotonFarolero(
|
||||
texto: l10n.startGame,
|
||||
icono: Icons.play_arrow,
|
||||
onPressed: (_modoMultimovil || _jugadores.length >= 3)
|
||||
? _iniciarPartida
|
||||
: null,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
|
||||
@@ -77,6 +77,7 @@ class _PantallaDebateState extends State<PantallaDebate> {
|
||||
automaticallyImplyLeading: false,
|
||||
),
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
@@ -95,40 +96,56 @@ class _PantallaDebateState extends State<PantallaDebate> {
|
||||
? Border.all(color: TemaApp.colorAcento, width: 2)
|
||||
: null,
|
||||
),
|
||||
child: Column(
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Text(
|
||||
_tiempoAgotado ? l10n.timeUp : l10n.timeRemaining,
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color: _tiempoAgotado
|
||||
? TemaApp.colorAcento
|
||||
: TemaApp.colorTextoSecundario,
|
||||
Positioned.fill(
|
||||
child: Image.asset(
|
||||
'assets/ui/premium/timer_ring_glow.png',
|
||||
fit: BoxFit.contain,
|
||||
opacity: const AlwaysStoppedAnimation(0.36),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
_formatearTiempo(_segundosRestantes),
|
||||
style: Theme.of(context).textTheme.headlineLarge?.copyWith(
|
||||
fontSize: 48,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: _segundosRestantes < 10 && !_tiempoAgotado
|
||||
? TemaApp.colorAcento
|
||||
: TemaApp.colorTexto,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
child: LinearProgressIndicator(
|
||||
value: progreso,
|
||||
backgroundColor: TemaApp.colorSuperficie,
|
||||
valueColor: AlwaysStoppedAnimation(
|
||||
_segundosRestantes < 10
|
||||
? TemaApp.colorAcento
|
||||
: TemaApp.colorVerde,
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
_tiempoAgotado ? l10n.timeUp : l10n.timeRemaining,
|
||||
style:
|
||||
Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color: _tiempoAgotado
|
||||
? TemaApp.colorAcento
|
||||
: TemaApp.colorTextoSecundario,
|
||||
),
|
||||
),
|
||||
minHeight: 6,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
_formatearTiempo(_segundosRestantes),
|
||||
style:
|
||||
Theme.of(context).textTheme.headlineLarge?.copyWith(
|
||||
fontSize: 48,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: _segundosRestantes < 10 &&
|
||||
!_tiempoAgotado
|
||||
? TemaApp.colorAcento
|
||||
: TemaApp.colorTexto,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
child: LinearProgressIndicator(
|
||||
value: progreso,
|
||||
backgroundColor: TemaApp.colorSuperficie,
|
||||
valueColor: AlwaysStoppedAnimation(
|
||||
_segundosRestantes < 10
|
||||
? TemaApp.colorAcento
|
||||
: TemaApp.colorVerde,
|
||||
),
|
||||
minHeight: 6,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:farolero/pantallas/pantalla_notas_online.dart';
|
||||
import 'package:farolero/pantallas/pantalla_revision_palabra.dart';
|
||||
import 'package:farolero/pantallas/pantalla_votacion_cliente.dart';
|
||||
import 'package:farolero/servicios/servicio_nearby.dart';
|
||||
import 'package:farolero/tema/componentes_farolero.dart';
|
||||
import 'package:farolero/tema/tema_app.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
@@ -157,9 +158,11 @@ class _PantallaDebateClienteState extends State<PantallaDebateCliente> {
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
children: [
|
||||
const Spacer(),
|
||||
|
||||
@@ -173,23 +176,37 @@ class _PantallaDebateClienteState extends State<PantallaDebateCliente> {
|
||||
: TemaApp.colorTarjeta,
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
),
|
||||
child: Column(
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Text(
|
||||
_segundosRestantes == 0
|
||||
? l10n.timeUp
|
||||
: l10n.timeRemaining,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
Positioned.fill(
|
||||
child: Image.asset(
|
||||
'assets/ui/premium/timer_ring_glow.png',
|
||||
fit: BoxFit.contain,
|
||||
opacity: const AlwaysStoppedAnimation(0.42),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
_formatearTiempo(_segundosRestantes),
|
||||
style: Theme.of(context).textTheme.displayMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: _segundosRestantes == 0
|
||||
? TemaApp.colorAcento
|
||||
: TemaApp.colorTexto,
|
||||
),
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
_segundosRestantes == 0
|
||||
? l10n.timeUp
|
||||
: l10n.timeRemaining,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
_formatearTiempo(_segundosRestantes),
|
||||
style:
|
||||
Theme.of(context).textTheme.displayMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: _segundosRestantes == 0
|
||||
? TemaApp.colorAcento
|
||||
: TemaApp.colorTexto,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -273,6 +290,7 @@ class _PantallaDebateClienteState extends State<PantallaDebateCliente> {
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -96,9 +96,11 @@ class _PantallaFinPartidaOnlineState extends State<PantallaFinPartidaOnline> {
|
||||
),
|
||||
],
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
width: double.infinity,
|
||||
@@ -266,6 +268,7 @@ class _PantallaFinPartidaOnlineState extends State<PantallaFinPartidaOnline> {
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -201,6 +201,7 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
|
||||
],
|
||||
),
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
|
||||
@@ -16,6 +16,7 @@ class PantallaHistorial extends StatelessWidget {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Historial')),
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: partidas.isEmpty
|
||||
? const Center(child: Text('Todavía no hay partidas guardadas.'))
|
||||
: ListView.builder(
|
||||
|
||||
@@ -48,25 +48,66 @@ class _PantallaLobbyHostState extends State<PantallaLobbyHost> {
|
||||
),
|
||||
),
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
children: [
|
||||
EncabezadoFarolero(
|
||||
icono: Icons.wifi_tethering,
|
||||
titulo: widget.nombreSala,
|
||||
subtitulo: l10n.scanToJoin,
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
PanelFarolero(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
child: QrImageView(
|
||||
data: nearby.generarDatosQR(widget.nombreSala),
|
||||
version: QrVersions.auto,
|
||||
size: 160,
|
||||
backgroundColor: Colors.white,
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 196,
|
||||
height: 196,
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: TemaApp.colorNaranja.withValues(alpha: 0.18),
|
||||
blurRadius: 24,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: QrImageView(
|
||||
data: nearby.generarDatosQR(widget.nombreSala),
|
||||
version: QrVersions.auto,
|
||||
size: 156,
|
||||
backgroundColor: Colors.white,
|
||||
),
|
||||
),
|
||||
Positioned.fill(
|
||||
child: IgnorePointer(
|
||||
child: Image.asset(
|
||||
'assets/ui/premium/qr_frame_overlay.png',
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
'Escanea este código desde otro móvil',
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(l10n.scanToJoin),
|
||||
const SizedBox(height: 16),
|
||||
_buildResumenSala(context, seleccionados, nearby.jugadores.length),
|
||||
const SizedBox(height: 12),
|
||||
@@ -119,15 +160,15 @@ class _PantallaLobbyHostState extends State<PantallaLobbyHost> {
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton.icon(
|
||||
child: BotonFarolero(
|
||||
texto: _iniciando ? l10n.starting : l10n.startGame,
|
||||
icono: Icons.play_arrow,
|
||||
onPressed: puedeIniciar && !_iniciando
|
||||
? () {
|
||||
setState(() => _iniciando = true);
|
||||
widget.onIniciar();
|
||||
}
|
||||
: null,
|
||||
icon: const Icon(Icons.play_arrow),
|
||||
label: Text(_iniciando ? l10n.starting : l10n.startGame),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:farolero/l10n/generated/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../estado/estado_juego.dart';
|
||||
import '../servicios/servicio_notas.dart';
|
||||
import '../tema/componentes_farolero.dart';
|
||||
import '../tema/tema_app.dart';
|
||||
|
||||
class PantallaNotas extends StatefulWidget {
|
||||
@@ -86,9 +87,12 @@ class _PantallaNotasState extends State<PantallaNotas> {
|
||||
),
|
||||
],
|
||||
),
|
||||
body: _jugadorSeleccionadoId == null
|
||||
? _construirSelectorJugador(partida)
|
||||
: _construirNotas(partida),
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: _jugadorSeleccionadoId == null
|
||||
? _construirSelectorJugador(partida)
|
||||
: _construirNotas(partida),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:farolero/l10n/generated/app_localizations.dart';
|
||||
import 'package:farolero/modelos/inicio_partida_multijugador.dart';
|
||||
import 'package:farolero/modelos/jugador.dart';
|
||||
import 'package:farolero/servicios/servicio_notas.dart';
|
||||
import 'package:farolero/tema/componentes_farolero.dart';
|
||||
import 'package:farolero/tema/tema_app.dart';
|
||||
|
||||
class PantallaNotasOnline extends StatefulWidget {
|
||||
@@ -115,7 +116,10 @@ class _PantallaNotasOnlineState extends State<PantallaNotasOnline> {
|
||||
),
|
||||
],
|
||||
),
|
||||
body: _autor == null ? _buildSelector(context) : _buildNotas(context),
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: _autor == null ? _buildSelector(context) : _buildNotas(context),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ class PantallaPrincipal extends StatelessWidget {
|
||||
final gamificacion = servicioPerfil.resumenGamificacion;
|
||||
|
||||
return Scaffold(
|
||||
extendBodyBehindAppBar: true,
|
||||
backgroundColor: const Color(0xFF05070D),
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
|
||||
@@ -13,6 +13,7 @@ class PantallaReglas extends StatelessWidget {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(l10n.rulesTitle)),
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
|
||||
@@ -64,6 +64,7 @@ class _PantallaResultadoState extends State<PantallaResultado>
|
||||
automaticallyImplyLeading: false,
|
||||
),
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: Center(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(32),
|
||||
|
||||
@@ -4,6 +4,7 @@ import '../modelos/inicio_partida_multijugador.dart';
|
||||
import '../modelos/partida.dart';
|
||||
import '../modelos/snapshot_partida_online.dart';
|
||||
import '../servicios/servicio_nearby.dart';
|
||||
import '../tema/componentes_farolero.dart';
|
||||
import '../tema/tema_app.dart';
|
||||
import 'pantalla_debate_cliente.dart';
|
||||
import 'pantalla_fin_partida_online.dart';
|
||||
@@ -168,11 +169,14 @@ class _PantallaResultadoOnlineState extends State<PantallaResultadoOnline> {
|
||||
elevation: 0,
|
||||
actions: _acciones(context, l10n),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: resultado == null
|
||||
? _buildEsperaAdivinanza(context, l10n)
|
||||
: _buildResultado(context, l10n, resultado),
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: resultado == null
|
||||
? _buildEsperaAdivinanza(context, l10n)
|
||||
: _buildResultado(context, l10n, resultado),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_animate/flutter_animate.dart';
|
||||
|
||||
import '../tema/componentes_farolero.dart';
|
||||
import '../tema/tema_app.dart';
|
||||
@@ -10,40 +11,27 @@ class PantallaSeleccionModoJuego extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Elegir modo de juego')),
|
||||
extendBodyBehindAppBar: true,
|
||||
appBar: AppBar(title: const Text('Elegir modo')),
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: SafeArea(
|
||||
child: Center(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(24),
|
||||
padding: const EdgeInsets.fromLTRB(20, 24, 20, 28),
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 460),
|
||||
constraints: const BoxConstraints(maxWidth: 470),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.sports_esports,
|
||||
size: 64,
|
||||
color: TemaApp.colorNaranja,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'¿Cómo querés jugar?',
|
||||
style: Theme.of(context).textTheme.headlineMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Elegí primero el tipo de partida para configurar solo lo necesario.',
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 28),
|
||||
const SizedBox(height: 12),
|
||||
const _ModoHero().animate().fadeIn(duration: 320.ms).slideY(begin: -0.12),
|
||||
const SizedBox(height: 34),
|
||||
_ModoCard(
|
||||
icono: Icons.phone_android,
|
||||
titulo: 'Partida en este dispositivo',
|
||||
descripcion:
|
||||
'Todos los jugadores usan este móvil. Acá se agregan los nombres manualmente.',
|
||||
icono: Icons.phone_android_rounded,
|
||||
titulo: 'Un móvil',
|
||||
subtitulo: 'Partida en este dispositivo',
|
||||
descripcion: 'Ideal para jugar todos juntos pasando el móvil. Configuración rápida y directa.',
|
||||
onTap: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
@@ -53,13 +41,13 @@ class PantallaSeleccionModoJuego extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
).animate().fadeIn(delay: 120.ms).slideX(begin: -0.08),
|
||||
const SizedBox(height: 16),
|
||||
_ModoCard(
|
||||
icono: Icons.devices,
|
||||
titulo: 'Partida multidispositivo',
|
||||
descripcion:
|
||||
'Este móvil crea el servidor. Los usuarios se gestionan después en el lobby.',
|
||||
icono: Icons.devices_rounded,
|
||||
titulo: 'Multidispositivo',
|
||||
subtitulo: 'Cada jugador en su móvil',
|
||||
descripcion: 'Crea una sala premium, comparte QR y gestiona usuarios desde el lobby.',
|
||||
destacado: true,
|
||||
onTap: () => Navigator.push(
|
||||
context,
|
||||
@@ -70,7 +58,7 @@ class PantallaSeleccionModoJuego extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
).animate().fadeIn(delay: 200.ms).slideX(begin: 0.08),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -82,9 +70,82 @@ class PantallaSeleccionModoJuego extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _ModoHero extends StatelessWidget {
|
||||
const _ModoHero();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: 230,
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Image.asset(
|
||||
'assets/ui/premium/lantern_radial_glow.png',
|
||||
fit: BoxFit.contain,
|
||||
opacity: const AlwaysStoppedAnimation(0.58),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: 90,
|
||||
height: 90,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
gradient: RadialGradient(
|
||||
colors: [
|
||||
TemaApp.colorDorado.withValues(alpha: 0.95),
|
||||
TemaApp.colorNaranja.withValues(alpha: 0.58),
|
||||
Colors.black.withValues(alpha: 0.76),
|
||||
],
|
||||
),
|
||||
border: Border.all(color: TemaApp.colorDorado, width: 3),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: TemaApp.colorNaranja.withValues(alpha: 0.55),
|
||||
blurRadius: 42,
|
||||
spreadRadius: 5,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: const Icon(Icons.sports_esports_rounded, size: 48, color: Color(0xFF241103)),
|
||||
),
|
||||
const SizedBox(height: 18),
|
||||
Text(
|
||||
'¿Cómo querés jugar?',
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
|
||||
color: TemaApp.colorDorado,
|
||||
fontSize: 32,
|
||||
fontWeight: FontWeight.w900,
|
||||
shadows: [
|
||||
Shadow(color: TemaApp.colorNaranja.withValues(alpha: 0.45), blurRadius: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Elegí el tipo de partida y arrancá sin fricción.',
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color: TemaApp.colorTextoSecundario,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ModoCard extends StatelessWidget {
|
||||
final IconData icono;
|
||||
final String titulo;
|
||||
final String subtitulo;
|
||||
final String descripcion;
|
||||
final bool destacado;
|
||||
final VoidCallback onTap;
|
||||
@@ -92,6 +153,7 @@ class _ModoCard extends StatelessWidget {
|
||||
const _ModoCard({
|
||||
required this.icono,
|
||||
required this.titulo,
|
||||
required this.subtitulo,
|
||||
required this.descripcion,
|
||||
required this.onTap,
|
||||
this.destacado = false,
|
||||
@@ -100,45 +162,86 @@ class _ModoCard extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final color = destacado ? TemaApp.colorNaranja : TemaApp.colorAcento;
|
||||
return Card(
|
||||
color: TemaApp.colorTarjeta,
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderRadius: BorderRadius.circular(28),
|
||||
onTap: onTap,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(18),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 52,
|
||||
height: 52,
|
||||
decoration: BoxDecoration(
|
||||
color: color.withValues(alpha: 0.18),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(color: color.withValues(alpha: 0.7)),
|
||||
),
|
||||
child: Icon(icono, color: color, size: 30),
|
||||
child: Ink(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
const Color(0xFF111C29).withValues(alpha: 0.94),
|
||||
(destacado ? const Color(0xFF2A1620) : const Color(0xFF15111F)).withValues(alpha: 0.92),
|
||||
],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(28),
|
||||
border: Border.all(color: color.withValues(alpha: destacado ? 0.78 : 0.48)),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: color.withValues(alpha: destacado ? 0.26 : 0.14),
|
||||
blurRadius: destacado ? 34 : 22,
|
||||
offset: const Offset(0, 14),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
],
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Image.asset(
|
||||
'assets/ui/premium/card_sheen_overlay.png',
|
||||
fit: BoxFit.cover,
|
||||
opacity: AlwaysStoppedAnimation(destacado ? 0.34 : 0.22),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(titulo, style: Theme.of(context).textTheme.titleLarge),
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
descripcion,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
Container(
|
||||
width: 64,
|
||||
height: 64,
|
||||
decoration: BoxDecoration(
|
||||
color: color.withValues(alpha: 0.18),
|
||||
borderRadius: BorderRadius.circular(22),
|
||||
border: Border.all(color: color.withValues(alpha: 0.72)),
|
||||
),
|
||||
child: Icon(icono, color: color, size: 34),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
titulo.toUpperCase(),
|
||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||
color: destacado ? TemaApp.colorDorado : Colors.white,
|
||||
fontWeight: FontWeight.w900,
|
||||
letterSpacing: 0.8,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 3),
|
||||
Text(
|
||||
subtitulo,
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(color: color),
|
||||
),
|
||||
const SizedBox(height: 7),
|
||||
Text(descripcion, style: Theme.of(context).textTheme.bodyMedium),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Icon(Icons.chevron_right_rounded, color: color, size: 32),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
const Icon(Icons.chevron_right),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,28 +443,19 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(l10n.joinGameTitle)),
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(32),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.bluetooth_searching,
|
||||
EncabezadoFarolero(
|
||||
icono: Icons.bluetooth_searching,
|
||||
titulo: l10n.joinGameTitle,
|
||||
subtitulo: l10n.enterNameToSearch,
|
||||
color: TemaApp.colorAzul,
|
||||
size: 70,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Text(
|
||||
l10n.joinGameTitle,
|
||||
style: Theme.of(context).textTheme.headlineMedium,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
l10n.enterNameToSearch,
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
TextFormField(
|
||||
@@ -481,13 +472,10 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
|
||||
onFieldSubmitted: (_) => _iniciarBusqueda(),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: _iniciarBusqueda,
|
||||
icon: const Icon(Icons.search),
|
||||
label: Text(l10n.searchGames),
|
||||
),
|
||||
BotonFarolero(
|
||||
texto: l10n.searchGames,
|
||||
icono: Icons.search,
|
||||
onPressed: _iniciarBusqueda,
|
||||
),
|
||||
if (_error != null) ...[
|
||||
const SizedBox(height: 16),
|
||||
@@ -525,63 +513,41 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
|
||||
),
|
||||
),
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
children: [
|
||||
// Estado
|
||||
if (_conectando) ...[
|
||||
const CircularProgressIndicator(color: TemaApp.colorAcento),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
'${l10n.connectingTo} ${_salaSeleccionada ?? ""}...',
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
children: [
|
||||
EncabezadoFarolero(
|
||||
icono: _conectando ? Icons.sync : Icons.radar,
|
||||
titulo: _conectando
|
||||
? '${l10n.connectingTo} ${_salaSeleccionada ?? ""}...'
|
||||
: l10n.searchingGames,
|
||||
subtitulo: _conectando
|
||||
? 'Preparando la sala segura'
|
||||
: 'Buscando partidas cercanas por Bluetooth',
|
||||
color: _conectando ? TemaApp.colorAcento : TemaApp.colorNaranja,
|
||||
trailing: SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2.4,
|
||||
color: _conectando
|
||||
? TemaApp.colorAcento
|
||||
: TemaApp.colorNaranja,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
] else ...[
|
||||
// Buscando
|
||||
Row(
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
color: TemaApp.colorNaranja,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Text(
|
||||
l10n.searchingGames,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 18),
|
||||
|
||||
// Lista de hosts encontrados
|
||||
Expanded(
|
||||
child: hosts.isEmpty && !_conectando
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text('📡', style: TextStyle(fontSize: 48)),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
l10n.noGamesFound,
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
l10n.noGamesFoundHint,
|
||||
style: Theme.of(context).textTheme.bodyMedium
|
||||
?.copyWith(color: Colors.grey),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
child: EstadoVacioFarolero(
|
||||
icono: Icons.radar,
|
||||
titulo: l10n.noGamesFound,
|
||||
subtitulo: l10n.noGamesFoundHint,
|
||||
),
|
||||
)
|
||||
: ListView.builder(
|
||||
@@ -627,42 +593,50 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
|
||||
|
||||
Widget _buildHostTile(String endpointId, String nombre) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(bottom: 8),
|
||||
margin: const EdgeInsets.only(bottom: 10),
|
||||
child: Material(
|
||||
color: TemaApp.colorTarjeta,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
onTap: _conectando ? null : () => _conectarAHost(endpointId, nombre),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
const Text('🎭', style: TextStyle(fontSize: 28)),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
nombre,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
Text(
|
||||
'Toca para unirte',
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.bodySmall?.copyWith(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
child: Ink(
|
||||
decoration: TemaApp.decoracionPanel(
|
||||
color: TemaApp.colorTarjeta.withValues(alpha: 0.90),
|
||||
borderColor: TemaApp.colorNaranja.withValues(alpha: 0.42),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.theater_comedy,
|
||||
color: TemaApp.colorNaranja,
|
||||
size: 30,
|
||||
),
|
||||
),
|
||||
const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
size: 16,
|
||||
color: Colors.grey,
|
||||
),
|
||||
],
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
nombre,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
Text(
|
||||
'Toca para unirte',
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
size: 16,
|
||||
color: TemaApp.colorDorado,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -738,26 +712,26 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
|
||||
),
|
||||
),
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
// Estado de conexión
|
||||
const Text('✅', style: TextStyle(fontSize: 64)),
|
||||
const SizedBox(height: 24),
|
||||
Text(
|
||||
l10n.connectedWaiting,
|
||||
style: Theme.of(context).textTheme.headlineMedium,
|
||||
textAlign: TextAlign.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
EncabezadoFarolero(
|
||||
icono: Icons.check_circle,
|
||||
titulo: l10n.connectedWaiting,
|
||||
subtitulo: '${l10n.yourName}: ${_nombreController.text}',
|
||||
color: TemaApp.colorVerde,
|
||||
trailing: const SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2.4,
|
||||
color: TemaApp.colorNaranja,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
'${l10n.yourName}: ${_nombreController.text}',
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
const CircularProgressIndicator(color: TemaApp.colorNaranja),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
l10n.waitingForHost,
|
||||
|
||||
@@ -33,21 +33,15 @@ class _PantallaVerPalabraState extends State<PantallaVerPalabra> {
|
||||
automaticallyImplyLeading: false,
|
||||
),
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
l10n.eachPlayerMustSee,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
l10n.roundNumber(partida.rondaActual),
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color: TemaApp.colorNaranja,
|
||||
),
|
||||
EncabezadoFarolero(
|
||||
icono: Icons.visibility,
|
||||
titulo: l10n.roundNumber(partida.rondaActual),
|
||||
subtitulo: l10n.eachPlayerMustSee,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Expanded(
|
||||
|
||||
@@ -60,6 +60,7 @@ class _PantallaVotacionState extends State<PantallaVotacion> {
|
||||
automaticallyImplyLeading: false,
|
||||
),
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
@@ -68,9 +69,9 @@ class _PantallaVotacionState extends State<PantallaVotacion> {
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: TemaApp.colorTarjeta,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
decoration: TemaApp.decoracionPanel(
|
||||
color: TemaApp.colorTarjeta.withValues(alpha: 0.90),
|
||||
borderColor: TemaApp.colorNaranja.withValues(alpha: 0.38),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
@@ -105,9 +106,17 @@ class _PantallaVotacionState extends State<PantallaVotacion> {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
Text(
|
||||
l10n.whoIsImpostor,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
EncabezadoFarolero(
|
||||
icono: Icons.how_to_vote,
|
||||
titulo: l10n.whoIsImpostor,
|
||||
subtitulo: l10n.selectOnePlayer,
|
||||
color: TemaApp.colorAcento,
|
||||
trailing: Image.asset(
|
||||
'assets/ui/premium/vote_danger_glow.png',
|
||||
width: 42,
|
||||
height: 42,
|
||||
opacity: const AlwaysStoppedAnimation(0.64),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
@@ -178,6 +187,7 @@ class _PantallaVotacionState extends State<PantallaVotacion> {
|
||||
automaticallyImplyLeading: false,
|
||||
),
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(32),
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:farolero/pantallas/pantalla_notas_online.dart';
|
||||
import 'package:farolero/pantallas/pantalla_revision_palabra.dart';
|
||||
import 'package:farolero/pantallas/pantalla_resultado_online.dart';
|
||||
import 'package:farolero/servicios/servicio_nearby.dart';
|
||||
import 'package:farolero/tema/componentes_farolero.dart';
|
||||
import 'package:farolero/tema/tema_app.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
@@ -126,21 +127,26 @@ class _PantallaVotacionClienteState extends State<PantallaVotacionCliente> {
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
l10n.whoDoYouThinkIsTheImpostor,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
_modoMultiVotante
|
||||
EncabezadoFarolero(
|
||||
icono: Icons.how_to_vote,
|
||||
titulo: l10n.whoDoYouThinkIsTheImpostor,
|
||||
subtitulo: _modoMultiVotante
|
||||
? 'Emití un voto por cada jugador que manejás.'
|
||||
: l10n.selectOnePlayer,
|
||||
style: TextStyle(color: TemaApp.colorTextoSecundario),
|
||||
color: TemaApp.colorAcento,
|
||||
trailing: Image.asset(
|
||||
'assets/ui/premium/vote_danger_glow.png',
|
||||
width: 42,
|
||||
height: 42,
|
||||
opacity: const AlwaysStoppedAnimation(0.64),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Expanded(
|
||||
@@ -174,6 +180,7 @@ class _PantallaVotacionClienteState extends State<PantallaVotacionCliente> {
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -240,9 +247,11 @@ class _PantallaVotacionClienteState extends State<PantallaVotacionCliente> {
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
body: FondoFarolero(
|
||||
intenso: true,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
@@ -339,6 +348,7 @@ class _PantallaVotacionClienteState extends State<PantallaVotacionCliente> {
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -20,9 +20,36 @@ class FondoFarolero extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return DecoratedBox(
|
||||
decoration: const BoxDecoration(gradient: TemaApp.gradienteFondo),
|
||||
child: CustomPaint(
|
||||
painter: _FondoFaroleroPainter(intenso: intenso),
|
||||
child: child,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: CustomPaint(painter: _FondoFaroleroPainter(intenso: intenso)),
|
||||
),
|
||||
Positioned(
|
||||
top: intenso ? -180 : -140,
|
||||
left: -220,
|
||||
right: -220,
|
||||
child: IgnorePointer(
|
||||
child: Image.asset(
|
||||
'assets/ui/premium/lantern_radial_glow.png',
|
||||
height: intenso ? 720 : 560,
|
||||
fit: BoxFit.contain,
|
||||
opacity: AlwaysStoppedAnimation(intenso ? 0.56 : 0.34),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned.fill(
|
||||
child: IgnorePointer(
|
||||
child: Image.asset(
|
||||
'assets/ui/premium/sparks_overlay.png',
|
||||
fit: BoxFit.cover,
|
||||
repeat: ImageRepeat.repeat,
|
||||
opacity: AlwaysStoppedAnimation(intenso ? 0.38 : 0.22),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned.fill(child: child),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -49,9 +76,138 @@ class PanelFarolero extends StatelessWidget {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
margin: margin,
|
||||
padding: padding,
|
||||
decoration: TemaApp.decoracionPanel(color: color, borderColor: borderColor),
|
||||
child: child,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Image.asset(
|
||||
'assets/ui/premium/card_sheen_overlay.png',
|
||||
fit: BoxFit.cover,
|
||||
opacity: const AlwaysStoppedAnimation(0.26),
|
||||
),
|
||||
),
|
||||
Padding(padding: padding, child: child),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class EncabezadoFarolero extends StatelessWidget {
|
||||
final IconData icono;
|
||||
final String titulo;
|
||||
final String? subtitulo;
|
||||
final Color color;
|
||||
final Widget? trailing;
|
||||
final EdgeInsetsGeometry padding;
|
||||
|
||||
const EncabezadoFarolero({
|
||||
super.key,
|
||||
required this.icono,
|
||||
required this.titulo,
|
||||
this.subtitulo,
|
||||
this.color = TemaApp.colorNaranja,
|
||||
this.trailing,
|
||||
this.padding = const EdgeInsets.symmetric(horizontal: 16, vertical: 18),
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PanelFarolero(
|
||||
padding: padding,
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 52,
|
||||
height: 52,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
gradient: RadialGradient(
|
||||
colors: [
|
||||
color.withValues(alpha: 0.34),
|
||||
TemaApp.colorSuperficie.withValues(alpha: 0.72),
|
||||
],
|
||||
),
|
||||
border: Border.all(color: color.withValues(alpha: 0.72)),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: color.withValues(alpha: 0.22),
|
||||
blurRadius: 22,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Icon(icono, color: color, size: 30),
|
||||
),
|
||||
const SizedBox(width: 14),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
titulo,
|
||||
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
|
||||
color: TemaApp.colorDorado,
|
||||
fontWeight: FontWeight.w900,
|
||||
),
|
||||
),
|
||||
if (subtitulo != null) ...[
|
||||
const SizedBox(height: 3),
|
||||
Text(
|
||||
subtitulo!,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
if (trailing != null) ...[
|
||||
const SizedBox(width: 12),
|
||||
trailing!,
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class EstadoVacioFarolero extends StatelessWidget {
|
||||
final IconData icono;
|
||||
final String titulo;
|
||||
final String subtitulo;
|
||||
|
||||
const EstadoVacioFarolero({
|
||||
super.key,
|
||||
required this.icono,
|
||||
required this.titulo,
|
||||
required this.subtitulo,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PanelFarolero(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 28),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(icono, color: TemaApp.colorNaranja, size: 46),
|
||||
const SizedBox(height: 14),
|
||||
Text(
|
||||
titulo,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
subtitulo,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -138,17 +294,17 @@ class BotonFarolero extends StatelessWidget {
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
onTap: onPressed,
|
||||
child: Ink(
|
||||
height: 54,
|
||||
height: 58,
|
||||
decoration: BoxDecoration(
|
||||
gradient: habilitado
|
||||
? gradient
|
||||
: const LinearGradient(
|
||||
colors: [TemaApp.colorTarjeta, TemaApp.colorSuperficie],
|
||||
),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
border: Border.all(
|
||||
color: habilitado
|
||||
? TemaApp.colorDorado.withValues(alpha: 0.74)
|
||||
@@ -157,29 +313,46 @@ class BotonFarolero extends StatelessWidget {
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withValues(alpha: 0.34),
|
||||
blurRadius: 14,
|
||||
offset: const Offset(0, 8),
|
||||
blurRadius: 18,
|
||||
offset: const Offset(0, 10),
|
||||
),
|
||||
if (habilitado)
|
||||
BoxShadow(
|
||||
color: TemaApp.colorNaranja.withValues(alpha: 0.16),
|
||||
blurRadius: 22,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Row(
|
||||
child: Stack(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 58,
|
||||
child: Icon(icono, color: foreground, size: 28),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
texto.toUpperCase(),
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color: foreground,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w800,
|
||||
),
|
||||
Positioned.fill(
|
||||
child: Image.asset(
|
||||
'assets/ui/premium/card_sheen_overlay.png',
|
||||
fit: BoxFit.cover,
|
||||
opacity: const AlwaysStoppedAnimation(0.18),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 58),
|
||||
Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 58,
|
||||
child: Icon(icono, color: foreground, size: 28),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
texto.toUpperCase(),
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color: foreground,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w900,
|
||||
letterSpacing: 0.8,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 58),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -254,15 +427,27 @@ class TarjetaPalabraFarolero extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Text(
|
||||
palabra.toUpperCase(),
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.oswald(
|
||||
color: const Color(0xFF1B0C05),
|
||||
fontSize: 42,
|
||||
fontWeight: FontWeight.w900,
|
||||
letterSpacing: 0,
|
||||
),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Image.asset(
|
||||
'assets/ui/premium/word_reveal_glow.png',
|
||||
fit: BoxFit.cover,
|
||||
opacity: const AlwaysStoppedAnimation(0.28),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
palabra.toUpperCase(),
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.oswald(
|
||||
color: const Color(0xFF1B0C05),
|
||||
fontSize: 42,
|
||||
fontWeight: FontWeight.w900,
|
||||
letterSpacing: 0,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -89,8 +89,8 @@ class TemaApp {
|
||||
elevation: 0,
|
||||
margin: EdgeInsets.zero,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: const BorderSide(color: colorBorde),
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
side: BorderSide(color: colorDorado.withValues(alpha: 0.34)),
|
||||
),
|
||||
),
|
||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||
@@ -99,12 +99,13 @@ class TemaApp {
|
||||
foregroundColor: Colors.black,
|
||||
disabledBackgroundColor: colorTarjeta,
|
||||
disabledForegroundColor: colorTextoSecundario,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 15),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
elevation: 0,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(18)),
|
||||
textStyle: GoogleFonts.oswald(
|
||||
fontWeight: FontWeight.w700,
|
||||
fontSize: 16,
|
||||
letterSpacing: 0,
|
||||
fontSize: 17,
|
||||
letterSpacing: 0.6,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -112,8 +113,8 @@ class TemaApp {
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: colorTexto,
|
||||
side: const BorderSide(color: colorBorde),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 15),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(18)),
|
||||
textStyle: GoogleFonts.oswald(
|
||||
fontWeight: FontWeight.w700,
|
||||
fontSize: 16,
|
||||
@@ -125,22 +126,22 @@ class TemaApp {
|
||||
filled: true,
|
||||
fillColor: const Color(0xFF0B1117),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderSide: const BorderSide(color: colorBorde),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderSide: const BorderSide(color: colorBorde),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderSide: const BorderSide(color: colorNaranja),
|
||||
),
|
||||
labelStyle: const TextStyle(color: colorTextoSecundario),
|
||||
hintStyle: const TextStyle(color: colorTextoSecundario),
|
||||
),
|
||||
appBarTheme: AppBarTheme(
|
||||
backgroundColor: colorFondo,
|
||||
backgroundColor: Colors.transparent,
|
||||
foregroundColor: colorNaranja,
|
||||
centerTitle: true,
|
||||
elevation: 0,
|
||||
@@ -199,13 +200,19 @@ class TemaApp {
|
||||
}) {
|
||||
return BoxDecoration(
|
||||
color: color ?? colorTarjeta.withValues(alpha: 0.84),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: borderColor ?? colorBorde),
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
border: Border.all(
|
||||
color: borderColor ?? colorDorado.withValues(alpha: 0.30),
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withValues(alpha: 0.35),
|
||||
blurRadius: 18,
|
||||
offset: const Offset(0, 10),
|
||||
blurRadius: 22,
|
||||
offset: const Offset(0, 12),
|
||||
),
|
||||
BoxShadow(
|
||||
color: colorNaranja.withValues(alpha: 0.10),
|
||||
blurRadius: 24,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user