refactorización de pantallas
This commit is contained in:
@@ -301,5 +301,21 @@
|
|||||||
"type": "String"
|
"type": "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"voteOf": "تصويت {name}",
|
||||||
|
"@voteOf": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"firstTurnInstruction": "يبدأ {name} بقول كلمته.",
|
||||||
|
"@firstTurnInstruction": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,5 +301,21 @@
|
|||||||
"type": "String"
|
"type": "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"voteOf": "Vot de {name}",
|
||||||
|
"@voteOf": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"firstTurnInstruction": "Comença {name} dient la seva paraula.",
|
||||||
|
"@firstTurnInstruction": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,5 +301,21 @@
|
|||||||
"type": "String"
|
"type": "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"voteOf": "Stimme von {name}",
|
||||||
|
"@voteOf": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"firstTurnInstruction": "{name} beginnt und sagt sein/ihr Wort.",
|
||||||
|
"@firstTurnInstruction": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -333,5 +333,21 @@
|
|||||||
"type": "String"
|
"type": "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"voteOf": "Vote from {name}",
|
||||||
|
"@voteOf": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"firstTurnInstruction": "{name} starts by saying their word.",
|
||||||
|
"@firstTurnInstruction": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -369,5 +369,21 @@
|
|||||||
"type": "String"
|
"type": "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"voteOf": "Voto de {name}",
|
||||||
|
"@voteOf": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"firstTurnInstruction": "Empieza {name} diciendo su palabra.",
|
||||||
|
"@firstTurnInstruction": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,5 +301,21 @@
|
|||||||
"type": "String"
|
"type": "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"voteOf": "{name}(r)en botoa",
|
||||||
|
"@voteOf": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"firstTurnInstruction": "{name} hasiko da bere hitza esanez.",
|
||||||
|
"@firstTurnInstruction": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,5 +301,21 @@
|
|||||||
"type": "String"
|
"type": "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"voteOf": "Vote de {name}",
|
||||||
|
"@voteOf": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"firstTurnInstruction": "{name} commence en disant son mot.",
|
||||||
|
"@firstTurnInstruction": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,5 +301,21 @@
|
|||||||
"type": "String"
|
"type": "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"voteOf": "{name} का वोट",
|
||||||
|
"@voteOf": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"firstTurnInstruction": "{name} अपनी शब्द बोलकर शुरू करता है।",
|
||||||
|
"@firstTurnInstruction": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,5 +301,21 @@
|
|||||||
"type": "String"
|
"type": "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"voteOf": "Voto di {name}",
|
||||||
|
"@voteOf": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"firstTurnInstruction": "{name} inizia dicendo la sua parola.",
|
||||||
|
"@firstTurnInstruction": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,5 +301,21 @@
|
|||||||
"type": "String"
|
"type": "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"voteOf": "{name} の投票",
|
||||||
|
"@voteOf": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"firstTurnInstruction": "{name} が自分のワードを言って始めます。",
|
||||||
|
"@firstTurnInstruction": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,5 +301,21 @@
|
|||||||
"type": "String"
|
"type": "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"voteOf": "{name}의 투표",
|
||||||
|
"@voteOf": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"firstTurnInstruction": "{name}님이 자신의 단어를 말하며 시작합니다.",
|
||||||
|
"@firstTurnInstruction": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,5 +301,21 @@
|
|||||||
"type": "String"
|
"type": "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"voteOf": "Stem van {name}",
|
||||||
|
"@voteOf": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"firstTurnInstruction": "{name} begint door het woord te zeggen.",
|
||||||
|
"@firstTurnInstruction": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,5 +301,21 @@
|
|||||||
"type": "String"
|
"type": "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"voteOf": "Głos gracza {name}",
|
||||||
|
"@voteOf": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"firstTurnInstruction": "{name} zaczyna, mówiąc swoje słowo.",
|
||||||
|
"@firstTurnInstruction": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,5 +301,21 @@
|
|||||||
"type": "String"
|
"type": "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"voteOf": "Voto de {name}",
|
||||||
|
"@voteOf": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"firstTurnInstruction": "{name} começa dizendo a sua palavra.",
|
||||||
|
"@firstTurnInstruction": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,5 +301,21 @@
|
|||||||
"type": "String"
|
"type": "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"voteOf": "Голос игрока {name}",
|
||||||
|
"@voteOf": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"firstTurnInstruction": "{name} начинает, называя своё слово.",
|
||||||
|
"@firstTurnInstruction": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,5 +301,21 @@
|
|||||||
"type": "String"
|
"type": "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"voteOf": "{name} için oy",
|
||||||
|
"@voteOf": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"firstTurnInstruction": "{name} kelimesini söyleyerek başlar.",
|
||||||
|
"@firstTurnInstruction": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,5 +301,21 @@
|
|||||||
"type": "String"
|
"type": "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"voteOf": "{name} 的投票",
|
||||||
|
"@voteOf": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"firstTurnInstruction": "{name} 先说出自己的词。",
|
||||||
|
"@firstTurnInstruction": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,5 +301,21 @@
|
|||||||
"type": "String"
|
"type": "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"voteOf": "{name} 的投票",
|
||||||
|
"@voteOf": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"firstTurnInstruction": "{name} 先說出自己的詞。",
|
||||||
|
"@firstTurnInstruction": {
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -520,6 +520,19 @@ abstract class AppLocalizations {
|
|||||||
/// **'Jugadores en debate'**
|
/// **'Jugadores en debate'**
|
||||||
String get playersInDebate;
|
String get playersInDebate;
|
||||||
|
|
||||||
|
|
||||||
|
/// No description provided for @voteOf.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Vote from {name}'**
|
||||||
|
String voteOf(String name);
|
||||||
|
|
||||||
|
/// No description provided for @firstTurnInstruction.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'{name} starts by saying their word.'**
|
||||||
|
String firstTurnInstruction(String name);
|
||||||
|
|
||||||
/// No description provided for @activePlayersInfo.
|
/// No description provided for @activePlayersInfo.
|
||||||
///
|
///
|
||||||
/// In es, this message translates to:
|
/// In es, this message translates to:
|
||||||
|
|||||||
@@ -213,6 +213,16 @@ class AppLocalizationsAr extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get playersInDebate => 'اللاعبون في النقاش';
|
String get playersInDebate => 'اللاعبون في النقاش';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String voteOf(String name) {
|
||||||
|
return "تصويت $name";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String firstTurnInstruction(String name) {
|
||||||
|
return "يبدأ $name بقول كلمته.";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String activePlayersInfo(int active, int impostors) {
|
String activePlayersInfo(int active, int impostors) {
|
||||||
return '$active نشطون • $impostors منتحل(ون) مختبئون';
|
return '$active نشطون • $impostors منتحل(ون) مختبئون';
|
||||||
|
|||||||
@@ -214,6 +214,16 @@ class AppLocalizationsCa extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get playersInDebate => 'Jugadors en debat';
|
String get playersInDebate => 'Jugadors en debat';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String voteOf(String name) {
|
||||||
|
return "Vot de $name";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String firstTurnInstruction(String name) {
|
||||||
|
return "Comença $name dient la seva paraula.";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String activePlayersInfo(int active, int impostors) {
|
String activePlayersInfo(int active, int impostors) {
|
||||||
return '$active actius • $impostors impostor(s) ocults';
|
return '$active actius • $impostors impostor(s) ocults';
|
||||||
|
|||||||
@@ -216,6 +216,16 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get playersInDebate => 'Spieler in der Diskussion';
|
String get playersInDebate => 'Spieler in der Diskussion';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String voteOf(String name) {
|
||||||
|
return "Stimme von $name";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String firstTurnInstruction(String name) {
|
||||||
|
return "$name beginnt und sagt sein/ihr Wort.";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String activePlayersInfo(int active, int impostors) {
|
String activePlayersInfo(int active, int impostors) {
|
||||||
return '$active aktiv • $impostors versteckte(r) Hochstapler';
|
return '$active aktiv • $impostors versteckte(r) Hochstapler';
|
||||||
|
|||||||
@@ -213,6 +213,16 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get playersInDebate => 'Players in discussion';
|
String get playersInDebate => 'Players in discussion';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String voteOf(String name) {
|
||||||
|
return "Vote from $name";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String firstTurnInstruction(String name) {
|
||||||
|
return "$name starts by saying their word.";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String activePlayersInfo(int active, int impostors) {
|
String activePlayersInfo(int active, int impostors) {
|
||||||
return '$active active • $impostors hidden impostor(s)';
|
return '$active active • $impostors hidden impostor(s)';
|
||||||
|
|||||||
@@ -213,6 +213,16 @@ class AppLocalizationsEs extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get playersInDebate => 'Jugadores en debate';
|
String get playersInDebate => 'Jugadores en debate';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String voteOf(String name) {
|
||||||
|
return "Voto de $name";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String firstTurnInstruction(String name) {
|
||||||
|
return "Empieza $name diciendo su palabra.";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String activePlayersInfo(int active, int impostors) {
|
String activePlayersInfo(int active, int impostors) {
|
||||||
return '$active activos • $impostors impostor(es) ocultos';
|
return '$active activos • $impostors impostor(es) ocultos';
|
||||||
|
|||||||
@@ -216,6 +216,16 @@ class AppLocalizationsEu extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get playersInDebate => 'Eztabaidan diren jokalariak';
|
String get playersInDebate => 'Eztabaidan diren jokalariak';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String voteOf(String name) {
|
||||||
|
return "$name(r)en botoa";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String firstTurnInstruction(String name) {
|
||||||
|
return "$name hasiko da bere hitza esanez.";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String activePlayersInfo(int active, int impostors) {
|
String activePlayersInfo(int active, int impostors) {
|
||||||
return '$active aktibo • $impostors inpostore ezkutu';
|
return '$active aktibo • $impostors inpostore ezkutu';
|
||||||
|
|||||||
@@ -214,6 +214,16 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get playersInDebate => 'Joueurs en débat';
|
String get playersInDebate => 'Joueurs en débat';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String voteOf(String name) {
|
||||||
|
return "Vote de $name";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String firstTurnInstruction(String name) {
|
||||||
|
return "$name commence en disant son mot.";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String activePlayersInfo(int active, int impostors) {
|
String activePlayersInfo(int active, int impostors) {
|
||||||
return '$active actifs • $impostors imposteur(s) caché(s)';
|
return '$active actifs • $impostors imposteur(s) caché(s)';
|
||||||
|
|||||||
@@ -213,6 +213,16 @@ class AppLocalizationsHi extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get playersInDebate => 'बहस में खिलाड़ी';
|
String get playersInDebate => 'बहस में खिलाड़ी';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String voteOf(String name) {
|
||||||
|
return "$name का वोट";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String firstTurnInstruction(String name) {
|
||||||
|
return "$name अपनी शब्द बोलकर शुरू करता है।";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String activePlayersInfo(int active, int impostors) {
|
String activePlayersInfo(int active, int impostors) {
|
||||||
return '$active सक्रिय • $impostors धोखेबाज़ छिपे हुए';
|
return '$active सक्रिय • $impostors धोखेबाज़ छिपे हुए';
|
||||||
|
|||||||
@@ -214,6 +214,16 @@ class AppLocalizationsIt extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get playersInDebate => 'Giocatori in discussione';
|
String get playersInDebate => 'Giocatori in discussione';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String voteOf(String name) {
|
||||||
|
return "Voto di $name";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String firstTurnInstruction(String name) {
|
||||||
|
return "$name inizia dicendo la sua parola.";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String activePlayersInfo(int active, int impostors) {
|
String activePlayersInfo(int active, int impostors) {
|
||||||
return '$active attivi • $impostors impostore/i nascosti';
|
return '$active attivi • $impostors impostore/i nascosti';
|
||||||
|
|||||||
@@ -213,6 +213,16 @@ class AppLocalizationsJa extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get playersInDebate => '議論中のプレイヤー';
|
String get playersInDebate => '議論中のプレイヤー';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String voteOf(String name) {
|
||||||
|
return "$name の投票";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String firstTurnInstruction(String name) {
|
||||||
|
return "$name が自分のワードを言って始めます。";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String activePlayersInfo(int active, int impostors) {
|
String activePlayersInfo(int active, int impostors) {
|
||||||
return '$active 人参加中 • $impostors 人のインポスターが潜伏中';
|
return '$active 人参加中 • $impostors 人のインポスターが潜伏中';
|
||||||
|
|||||||
@@ -213,6 +213,16 @@ class AppLocalizationsKo extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get playersInDebate => '토론 중인 플레이어';
|
String get playersInDebate => '토론 중인 플레이어';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String voteOf(String name) {
|
||||||
|
return "$name의 투표";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String firstTurnInstruction(String name) {
|
||||||
|
return "$name님이 자신의 단어를 말하며 시작합니다.";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String activePlayersInfo(int active, int impostors) {
|
String activePlayersInfo(int active, int impostors) {
|
||||||
return '$active명 참여 중 • $impostors명의 임포스터 잠복 중';
|
return '$active명 참여 중 • $impostors명의 임포스터 잠복 중';
|
||||||
|
|||||||
@@ -214,6 +214,16 @@ class AppLocalizationsNl extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get playersInDebate => 'Spelers in debat';
|
String get playersInDebate => 'Spelers in debat';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String voteOf(String name) {
|
||||||
|
return "Stem van $name";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String firstTurnInstruction(String name) {
|
||||||
|
return "$name begint door het woord te zeggen.";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String activePlayersInfo(int active, int impostors) {
|
String activePlayersInfo(int active, int impostors) {
|
||||||
return '$active actief • $impostors verborgen bedrieger(s)';
|
return '$active actief • $impostors verborgen bedrieger(s)';
|
||||||
|
|||||||
@@ -214,6 +214,16 @@ class AppLocalizationsPl extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get playersInDebate => 'Gracze w debacie';
|
String get playersInDebate => 'Gracze w debacie';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String voteOf(String name) {
|
||||||
|
return "Głos gracza $name";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String firstTurnInstruction(String name) {
|
||||||
|
return "$name zaczyna, mówiąc swoje słowo.";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String activePlayersInfo(int active, int impostors) {
|
String activePlayersInfo(int active, int impostors) {
|
||||||
return '$active aktywnych • $impostors ukrytych oszustów';
|
return '$active aktywnych • $impostors ukrytych oszustów';
|
||||||
|
|||||||
@@ -215,6 +215,16 @@ class AppLocalizationsPt extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get playersInDebate => 'Jogadores no debate';
|
String get playersInDebate => 'Jogadores no debate';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String voteOf(String name) {
|
||||||
|
return "Voto de $name";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String firstTurnInstruction(String name) {
|
||||||
|
return "$name começa dizendo a sua palavra.";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String activePlayersInfo(int active, int impostors) {
|
String activePlayersInfo(int active, int impostors) {
|
||||||
return '$active ativos • $impostors impostor(es) ocultos';
|
return '$active ativos • $impostors impostor(es) ocultos';
|
||||||
|
|||||||
@@ -214,6 +214,16 @@ class AppLocalizationsRu extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get playersInDebate => 'Игроки в обсуждении';
|
String get playersInDebate => 'Игроки в обсуждении';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String voteOf(String name) {
|
||||||
|
return "Голос игрока $name";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String firstTurnInstruction(String name) {
|
||||||
|
return "$name начинает, называя своё слово.";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String activePlayersInfo(int active, int impostors) {
|
String activePlayersInfo(int active, int impostors) {
|
||||||
return '$active активных • $impostors скрытый(-х) самозванец(-ев)';
|
return '$active активных • $impostors скрытый(-х) самозванец(-ев)';
|
||||||
|
|||||||
@@ -213,6 +213,16 @@ class AppLocalizationsTr extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get playersInDebate => 'Tartışmadaki oyuncular';
|
String get playersInDebate => 'Tartışmadaki oyuncular';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String voteOf(String name) {
|
||||||
|
return "$name için oy";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String firstTurnInstruction(String name) {
|
||||||
|
return "$name kelimesini söyleyerek başlar.";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String activePlayersInfo(int active, int impostors) {
|
String activePlayersInfo(int active, int impostors) {
|
||||||
return '$active aktif • $impostors gizli sahtekar';
|
return '$active aktif • $impostors gizli sahtekar';
|
||||||
|
|||||||
@@ -213,6 +213,16 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get playersInDebate => '参与讨论的玩家';
|
String get playersInDebate => '参与讨论的玩家';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String voteOf(String name) {
|
||||||
|
return "$name 的投票";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String firstTurnInstruction(String name) {
|
||||||
|
return "$name 先说出自己的词。";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String activePlayersInfo(int active, int impostors) {
|
String activePlayersInfo(int active, int impostors) {
|
||||||
return '$active 名在场 • $impostors 名冒牌者潜伏中';
|
return '$active 名在场 • $impostors 名冒牌者潜伏中';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:farolero/l10n/generated/app_localizations.dart';
|
import 'package:farolero/l10n/generated/app_localizations.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import '../estado/estado_juego.dart';
|
import '../estado/estado_juego.dart';
|
||||||
@@ -30,6 +30,22 @@ class _PantallaAdivinanzaState extends State<PantallaAdivinanza> {
|
|||||||
setState(() => _acierto = resultado);
|
setState(() => _acierto = resultado);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _continuarTrasNoAdivinar(EstadoJuego estado) {
|
||||||
|
final fin = estado.comprobarFinPartida();
|
||||||
|
if (fin) {
|
||||||
|
Navigator.pushReplacement(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (_) => const PantallaFinPartida()),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
estado.siguienteRonda();
|
||||||
|
Navigator.pushReplacement(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (_) => const PantallaDebate()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final l10n = AppLocalizations.of(context)!;
|
final l10n = AppLocalizations.of(context)!;
|
||||||
@@ -44,29 +60,40 @@ class _PantallaAdivinanzaState extends State<PantallaAdivinanza> {
|
|||||||
),
|
),
|
||||||
body: FondoFarolero(
|
body: FondoFarolero(
|
||||||
intenso: true,
|
intenso: true,
|
||||||
|
child: SafeArea(
|
||||||
child: Center(
|
child: Center(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
padding: const EdgeInsets.all(32),
|
padding: const EdgeInsets.all(24),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const ArteGameplayFarolero.fase(height: 132),
|
const ArteGameplayFarolero.fase(height: 132),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
EncabezadoFarolero(
|
TarjetaFaseFarolero(
|
||||||
icono: Icons.theater_comedy,
|
icono: Icons.theater_comedy,
|
||||||
titulo: l10n.impostorCanGuess,
|
titulo: l10n.impostorCanGuess,
|
||||||
subtitulo: l10n.ifCorrectImpostorsWin,
|
subtitulo: l10n.ifCorrectImpostorsWin,
|
||||||
color: TemaApp.colorAcento,
|
color: TemaApp.colorAcento,
|
||||||
trailing: Image.asset(
|
child: _buildContenido(context, l10n, estado, partida.palabraSecreta),
|
||||||
'assets/ui/generated/meta/result_verdict_art.webp',
|
),
|
||||||
width: 42,
|
],
|
||||||
height: 42,
|
|
||||||
opacity: const AlwaysStoppedAnimation(0.64),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 32),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (_acierto == null) ...[
|
Widget _buildContenido(
|
||||||
|
BuildContext context,
|
||||||
|
AppLocalizations l10n,
|
||||||
|
EstadoJuego estado,
|
||||||
|
String palabraSecreta,
|
||||||
|
) {
|
||||||
|
if (_acierto == null) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
TextField(
|
TextField(
|
||||||
controller: _controlador,
|
controller: _controlador,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
@@ -76,167 +103,86 @@ class _PantallaAdivinanzaState extends State<PantallaAdivinanza> {
|
|||||||
textCapitalization: TextCapitalization.sentences,
|
textCapitalization: TextCapitalization.sentences,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: const TextStyle(fontSize: 20),
|
style: const TextStyle(fontSize: 20),
|
||||||
onSubmitted: (_) => _intentarAdivinar(),
|
onChanged: (value) => setState(() {}),
|
||||||
|
onSubmitted: (value) => _intentarAdivinar(),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: OutlinedButton(
|
child: BotonFarolero.oscuro(
|
||||||
onPressed: () {
|
texto: l10n.dontGuess,
|
||||||
// No intenta adivinar, siguiente ronda
|
icono: Icons.skip_next,
|
||||||
final fin = estado.comprobarFinPartida();
|
onPressed: () => _continuarTrasNoAdivinar(estado),
|
||||||
if (fin) {
|
|
||||||
Navigator.pushReplacement(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (_) => const PantallaFinPartida(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
estado.siguienteRonda();
|
|
||||||
Navigator.pushReplacement(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (_) => const PantallaDebate(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Text(l10n.dontGuess),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: ElevatedButton.icon(
|
child: BotonFarolero(
|
||||||
onPressed: _controlador.text.trim().isNotEmpty
|
texto: l10n.guess,
|
||||||
? _intentarAdivinar
|
icono: Icons.send,
|
||||||
: null,
|
onPressed: _controlador.text.trim().isNotEmpty ? _intentarAdivinar : null,
|
||||||
icon: const Icon(Icons.send),
|
|
||||||
label: Text(l10n.guess),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (_acierto == true) ...[
|
final acierto = _acierto == true;
|
||||||
const SizedBox(height: 16),
|
final color = acierto ? TemaApp.colorAcento : TemaApp.colorVerde;
|
||||||
Container(
|
return Column(
|
||||||
|
children: [
|
||||||
|
PanelFarolero(
|
||||||
padding: const EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
decoration: BoxDecoration(
|
borderColor: color,
|
||||||
color: TemaApp.colorAcento.withValues(alpha: 0.3),
|
color: color.withValues(alpha: 0.18),
|
||||||
borderRadius: BorderRadius.circular(16),
|
|
||||||
border: Border.all(color: TemaApp.colorAcento),
|
|
||||||
),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
const Text('🎭🎉', style: TextStyle(fontSize: 48)),
|
Icon(
|
||||||
|
acierto ? Icons.celebration : Icons.cancel,
|
||||||
|
color: color,
|
||||||
|
size: 52,
|
||||||
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
Text(
|
Text(
|
||||||
l10n.correctGuess,
|
acierto ? l10n.correctGuess : l10n.wrongGuess,
|
||||||
style: Theme.of(context)
|
textAlign: TextAlign.center,
|
||||||
.textTheme
|
style: Theme.of(context).textTheme.headlineMedium?.copyWith(color: color),
|
||||||
.headlineMedium
|
|
||||||
?.copyWith(color: TemaApp.colorAcento),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Text(
|
Text(
|
||||||
l10n.theWordWas(partida.palabraSecreta),
|
acierto ? l10n.theWordWas(palabraSecreta) : l10n.gameContinues,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
style: Theme.of(context).textTheme.titleLarge,
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
),
|
),
|
||||||
|
if (acierto) ...[
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Text(
|
Text(
|
||||||
l10n.impostorsWin,
|
l10n.impostorsWin,
|
||||||
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
|
textAlign: TextAlign.center,
|
||||||
color: TemaApp.colorNaranja,
|
style: Theme.of(context).textTheme.bodyLarge?.copyWith(color: TemaApp.colorNaranja),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
SizedBox(
|
BotonFarolero(
|
||||||
width: double.infinity,
|
texto: acierto ? l10n.seeEndResult : l10n.nextRound,
|
||||||
height: 56,
|
icono: acierto ? Icons.emoji_events : Icons.skip_next,
|
||||||
child: ElevatedButton.icon(
|
onPressed: acierto
|
||||||
onPressed: () {
|
? () {
|
||||||
Navigator.pushReplacement(
|
Navigator.pushReplacement(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(builder: (_) => const PantallaFinPartida()),
|
||||||
builder: (_) => const PantallaFinPartida(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
icon: const Icon(Icons.emoji_events),
|
|
||||||
label: Text(l10n.seeEndResult),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
|
|
||||||
if (_acierto == false) ...[
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(24),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: TemaApp.colorVerde.withValues(alpha: 0.3),
|
|
||||||
borderRadius: BorderRadius.circular(16),
|
|
||||||
border: Border.all(color: TemaApp.colorVerde),
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
const Text('❌', style: TextStyle(fontSize: 48)),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
Text(
|
|
||||||
l10n.wrongGuess,
|
|
||||||
style: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.headlineMedium
|
|
||||||
?.copyWith(color: TemaApp.colorVerde),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
Text(
|
|
||||||
l10n.gameContinues,
|
|
||||||
style: Theme.of(context).textTheme.bodyLarge,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 24),
|
|
||||||
SizedBox(
|
|
||||||
width: double.infinity,
|
|
||||||
height: 56,
|
|
||||||
child: ElevatedButton.icon(
|
|
||||||
onPressed: () {
|
|
||||||
final fin = estado.comprobarFinPartida();
|
|
||||||
if (fin) {
|
|
||||||
Navigator.pushReplacement(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (_) => const PantallaFinPartida(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
estado.siguienteRonda();
|
|
||||||
Navigator.pushReplacement(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (_) => const PantallaDebate(),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
: () => _continuarTrasNoAdivinar(estado),
|
||||||
icon: const Icon(Icons.skip_next),
|
|
||||||
label: Text(l10n.nextRound),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import 'package:farolero/l10n/generated/app_localizations.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import '../estado/estado_juego.dart';
|
import '../estado/estado_juego.dart';
|
||||||
import '../tema/componentes_farolero.dart';
|
import '../tema/componentes_farolero.dart';
|
||||||
import '../tema/tema_app.dart';
|
|
||||||
import 'pantalla_notas.dart';
|
import 'pantalla_notas.dart';
|
||||||
import 'pantalla_votacion.dart';
|
import 'pantalla_votacion.dart';
|
||||||
|
|
||||||
@@ -67,9 +66,6 @@ class _PantallaDebateState extends State<PantallaDebate> {
|
|||||||
if (partida == null) return const SizedBox.shrink();
|
if (partida == null) return const SizedBox.shrink();
|
||||||
|
|
||||||
final tieneTemporizador = partida.config.tiempoDebateSegundos != null;
|
final tieneTemporizador = partida.config.tiempoDebateSegundos != null;
|
||||||
final progreso = tieneTemporizador
|
|
||||||
? _segundosRestantes / partida.config.tiempoDebateSegundos!
|
|
||||||
: 0.0;
|
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
@@ -78,167 +74,69 @@ class _PantallaDebateState extends State<PantallaDebate> {
|
|||||||
),
|
),
|
||||||
body: FondoFarolero(
|
body: FondoFarolero(
|
||||||
intenso: true,
|
intenso: true,
|
||||||
|
child: SafeArea(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
const ArteGameplayFarolero.fase(height: 110),
|
const ArteGameplayFarolero.fase(height: 110),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
// Temporizador
|
|
||||||
if (tieneTemporizador) ...[
|
if (tieneTemporizador) ...[
|
||||||
Container(
|
TemporizadorFarolero(
|
||||||
width: double.infinity,
|
etiqueta: _tiempoAgotado ? l10n.timeUp : l10n.timeRemaining,
|
||||||
padding: const EdgeInsets.all(20),
|
tiempo: _formatearTiempo(_segundosRestantes),
|
||||||
decoration: BoxDecoration(
|
agotado: _tiempoAgotado,
|
||||||
color: _tiempoAgotado
|
|
||||||
? TemaApp.colorAcento.withValues(alpha: 0.3)
|
|
||||||
: TemaApp.colorTarjeta,
|
|
||||||
borderRadius: BorderRadius.circular(16),
|
|
||||||
border: _tiempoAgotado
|
|
||||||
? Border.all(color: TemaApp.colorAcento, width: 2)
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
child: Stack(
|
|
||||||
alignment: Alignment.center,
|
|
||||||
children: [
|
|
||||||
Positioned.fill(
|
|
||||||
child: Image.asset(
|
|
||||||
'assets/ui/generated/gameplay/gameplay_phase_emblem.webp',
|
|
||||||
fit: BoxFit.contain,
|
|
||||||
opacity: const AlwaysStoppedAnimation(0.36),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
_tiempoAgotado ? l10n.timeUp : l10n.timeRemaining,
|
|
||||||
style:
|
|
||||||
Theme.of(context).textTheme.titleMedium?.copyWith(
|
|
||||||
color: _tiempoAgotado
|
|
||||||
? TemaApp.colorAcento
|
|
||||||
: TemaApp.colorTextoSecundario,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
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,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
],
|
],
|
||||||
|
|
||||||
// Jugadores activos
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Card(
|
child: TarjetaFaseFarolero(
|
||||||
child: Padding(
|
icono: Icons.forum,
|
||||||
padding: const EdgeInsets.all(16),
|
titulo: l10n.playersInDebate,
|
||||||
child: Column(
|
subtitulo: l10n.activePlayersInfo(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
partida.jugadoresActivos.length,
|
||||||
children: [
|
partida.impostoresActivos.length,
|
||||||
Text(
|
|
||||||
l10n.playersInDebate,
|
|
||||||
style: Theme.of(context).textTheme.titleLarge,
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
child: Expanded(
|
||||||
Text(
|
child: ListView.separated(
|
||||||
l10n.activePlayersInfo(partida.jugadoresActivos.length, partida.impostoresActivos.length),
|
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
Expanded(
|
|
||||||
child: ListView.builder(
|
|
||||||
itemCount: partida.jugadores.length,
|
itemCount: partida.jugadores.length,
|
||||||
|
separatorBuilder: (context, index) => const SizedBox(height: 8),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final j = partida.jugadores[index];
|
final jugador = partida.jugadores[index];
|
||||||
return ListTile(
|
return EstadoJugadorFarolero(
|
||||||
leading: CircleAvatar(
|
nombre: '${index + 1}. ${jugador.nombre}',
|
||||||
backgroundColor: j.eliminado
|
subtitulo: jugador.eliminado ? l10n.eliminated : null,
|
||||||
? Colors.grey
|
icono: jugador.eliminado ? Icons.person_off : Icons.record_voice_over,
|
||||||
: TemaApp.colorAcento,
|
destacado: !jugador.eliminado,
|
||||||
child: Text(
|
completado: !jugador.eliminado,
|
||||||
j.eliminado ? '💀' : '${index + 1}',
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.white, fontSize: 14),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
title: Text(
|
|
||||||
j.nombre,
|
|
||||||
style: TextStyle(
|
|
||||||
decoration: j.eliminado
|
|
||||||
? TextDecoration.lineThrough
|
|
||||||
: null,
|
|
||||||
color: j.eliminado
|
|
||||||
? TemaApp.colorTextoSecundario
|
|
||||||
: TemaApp.colorTexto,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
subtitle: j.eliminado
|
|
||||||
? Text(l10n.eliminated)
|
|
||||||
: null,
|
|
||||||
dense: true,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
// Botones
|
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: OutlinedButton.icon(
|
child: BotonFarolero.oscuro(
|
||||||
|
texto: l10n.notes,
|
||||||
|
icono: Icons.edit_note,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(builder: (_) => const PantallaNotas()),
|
||||||
builder: (_) => const PantallaNotas(),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
icon: const Text('📝', style: TextStyle(fontSize: 18)),
|
|
||||||
label: Text(l10n.notes),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: ElevatedButton.icon(
|
child: BotonFarolero(
|
||||||
|
texto: l10n.goToVoting,
|
||||||
|
icono: Icons.how_to_vote,
|
||||||
onPressed: _irAVotacion,
|
onPressed: _irAVotacion,
|
||||||
icon: const Text('🗳️', style: TextStyle(fontSize: 18)),
|
|
||||||
label: Text(l10n.goToVoting),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -247,6 +145,7 @@ class _PantallaDebateState extends State<PantallaDebate> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:farolero/l10n/generated/app_localizations.dart';
|
import 'package:farolero/l10n/generated/app_localizations.dart';
|
||||||
import 'package:farolero/modelos/inicio_partida_multijugador.dart';
|
import 'package:farolero/modelos/inicio_partida_multijugador.dart';
|
||||||
@@ -11,8 +11,6 @@ import 'package:farolero/tema/componentes_farolero.dart';
|
|||||||
import 'package:farolero/tema/tema_app.dart';
|
import 'package:farolero/tema/tema_app.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
/// Pantalla que ve el jugador durante la fase de debate (multidispositivo).
|
|
||||||
/// El cliente recibe el cambio de fase via Nearby y se navega aquí.
|
|
||||||
class PantallaDebateCliente extends StatefulWidget {
|
class PantallaDebateCliente extends StatefulWidget {
|
||||||
final int? tiempoDebateSegundos;
|
final int? tiempoDebateSegundos;
|
||||||
final String? primerTurnoNombre;
|
final String? primerTurnoNombre;
|
||||||
@@ -87,9 +85,7 @@ class _PantallaDebateClienteState extends State<PantallaDebateCliente> {
|
|||||||
void dispose() {
|
void dispose() {
|
||||||
_timer?.cancel();
|
_timer?.cancel();
|
||||||
final listener = _listener;
|
final listener = _listener;
|
||||||
if (listener != null) {
|
if (listener != null) _nearby?.removeMensajeListener(listener);
|
||||||
_nearby?.removeMensajeListener(listener);
|
|
||||||
}
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,141 +156,70 @@ class _PantallaDebateClienteState extends State<PantallaDebateCliente> {
|
|||||||
),
|
),
|
||||||
body: FondoFarolero(
|
body: FondoFarolero(
|
||||||
intenso: true,
|
intenso: true,
|
||||||
child: Padding(
|
child: SafeArea(
|
||||||
|
top: false,
|
||||||
|
child: SingleChildScrollView(
|
||||||
padding: const EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
const ArteGameplayFarolero.fase(height: 124),
|
const ArteGameplayFarolero.fase(height: 124),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 12),
|
||||||
const Spacer(),
|
TarjetaFaseFarolero(
|
||||||
|
icono: Icons.forum,
|
||||||
// Timer
|
titulo: l10n.debate,
|
||||||
|
subtitulo: l10n.debateInstructions,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
if (widget.tiempoDebateSegundos != null) ...[
|
if (widget.tiempoDebateSegundos != null) ...[
|
||||||
Container(
|
TemporizadorFarolero(
|
||||||
padding: const EdgeInsets.all(32),
|
etiqueta: _segundosRestantes == 0
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: _segundosRestantes == 0
|
|
||||||
? TemaApp.colorAcento.withValues(alpha: 0.3)
|
|
||||||
: TemaApp.colorTarjeta,
|
|
||||||
borderRadius: BorderRadius.circular(24),
|
|
||||||
),
|
|
||||||
child: Stack(
|
|
||||||
alignment: Alignment.center,
|
|
||||||
children: [
|
|
||||||
Positioned.fill(
|
|
||||||
child: Image.asset(
|
|
||||||
'assets/ui/generated/gameplay/gameplay_phase_emblem.webp',
|
|
||||||
fit: BoxFit.contain,
|
|
||||||
opacity: const AlwaysStoppedAnimation(0.42),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
_segundosRestantes == 0
|
|
||||||
? l10n.timeUp
|
? l10n.timeUp
|
||||||
: l10n.timeRemaining,
|
: l10n.timeRemaining,
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
tiempo: _formatearTiempo(_segundosRestantes),
|
||||||
|
agotado: _segundosRestantes == 0,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 16),
|
||||||
Text(
|
|
||||||
_formatearTiempo(_segundosRestantes),
|
|
||||||
style:
|
|
||||||
Theme.of(context).textTheme.displayMedium?.copyWith(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: _segundosRestantes == 0
|
|
||||||
? TemaApp.colorAcento
|
|
||||||
: TemaApp.colorTexto,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 32),
|
|
||||||
] else ...[
|
] else ...[
|
||||||
Text(
|
Text(
|
||||||
l10n.debatePhaseActive,
|
l10n.debatePhaseActive,
|
||||||
style: Theme.of(context).textTheme.headlineMedium,
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
],
|
],
|
||||||
|
|
||||||
// Instrucciones
|
|
||||||
if (widget.primerTurnoNombre != null) ...[
|
if (widget.primerTurnoNombre != null) ...[
|
||||||
Container(
|
EstadoJugadorFarolero(
|
||||||
width: double.infinity,
|
nombre: l10n.firstTurnInstruction(
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: TemaApp.colorNaranja.withValues(alpha: 0.18),
|
|
||||||
borderRadius: BorderRadius.circular(16),
|
|
||||||
border: Border.all(
|
|
||||||
color: TemaApp.colorNaranja.withValues(alpha: 0.65),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(
|
|
||||||
Icons.record_voice_over,
|
|
||||||
color: TemaApp.colorNaranja,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
widget.primerTurnoNombre!,
|
widget.primerTurnoNombre!,
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
|
||||||
),
|
),
|
||||||
|
destacado: true,
|
||||||
|
completado: true,
|
||||||
|
icono: Icons.record_voice_over,
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
],
|
],
|
||||||
),
|
BotonFarolero.secundario(
|
||||||
),
|
texto: _votacionSolicitada
|
||||||
const SizedBox(height: 16),
|
? l10n.votacionSolicitada
|
||||||
],
|
: l10n.solicitarVotacion,
|
||||||
|
icono: _votacionSolicitada
|
||||||
Text(
|
? Icons.hourglass_empty
|
||||||
l10n.debateInstructions,
|
: Icons.how_to_vote,
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: TextStyle(
|
|
||||||
color: TemaApp.colorTextoSecundario,
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
const Spacer(),
|
|
||||||
|
|
||||||
// Botón solicitar votación
|
|
||||||
SizedBox(
|
|
||||||
width: double.infinity,
|
|
||||||
height: 56,
|
|
||||||
child: ElevatedButton.icon(
|
|
||||||
onPressed: _votacionSolicitada
|
onPressed: _votacionSolicitada
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
setState(() => _votacionSolicitada = true);
|
setState(() => _votacionSolicitada = true);
|
||||||
widget.onSolicitarVotacion();
|
widget.onSolicitarVotacion();
|
||||||
},
|
},
|
||||||
icon: Icon(_votacionSolicitada ? Icons.hourglass_empty : Icons.how_to_vote),
|
|
||||||
label: Text(
|
|
||||||
_votacionSolicitada
|
|
||||||
? l10n.votacionSolicitada
|
|
||||||
: l10n.solicitarVotacion,
|
|
||||||
),
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
backgroundColor: _votacionSolicitada
|
|
||||||
? TemaApp.colorTarjeta
|
|
||||||
: TemaApp.colorAcento,
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
textStyle: const TextStyle(fontSize: 16),
|
|
||||||
),
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,12 +7,14 @@ import '../estado/estado_juego.dart';
|
|||||||
import '../modelos/gamificacion_usuario.dart';
|
import '../modelos/gamificacion_usuario.dart';
|
||||||
import '../modelos/inicio_partida_multijugador.dart';
|
import '../modelos/inicio_partida_multijugador.dart';
|
||||||
import '../modelos/jugador.dart';
|
import '../modelos/jugador.dart';
|
||||||
|
import '../modelos/palabra.dart';
|
||||||
import '../modelos/partida.dart';
|
import '../modelos/partida.dart';
|
||||||
import '../modelos/snapshot_partida_online.dart';
|
import '../modelos/snapshot_partida_online.dart';
|
||||||
import '../servicios/servicio_historial_partidas.dart';
|
import '../servicios/servicio_historial_partidas.dart';
|
||||||
import '../servicios/servicio_nearby.dart';
|
import '../servicios/servicio_nearby.dart';
|
||||||
import '../servicios/servicio_perfil_usuario.dart';
|
import '../servicios/servicio_perfil_usuario.dart';
|
||||||
import '../tema/componentes_farolero.dart';
|
import '../tema/componentes_farolero.dart';
|
||||||
|
import '../tema/componentes_resultado_farolero.dart';
|
||||||
import '../tema/tema_app.dart';
|
import '../tema/tema_app.dart';
|
||||||
import 'pantalla_notas_online.dart';
|
import 'pantalla_notas_online.dart';
|
||||||
import 'pantalla_revision_palabra.dart';
|
import 'pantalla_revision_palabra.dart';
|
||||||
@@ -279,10 +281,13 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
|
|||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: OutlinedButton.icon(
|
child: SizedBox(
|
||||||
|
width: 260,
|
||||||
|
child: BotonFarolero.oscuro(
|
||||||
|
texto: AppLocalizations.of(context)!.assumeOnThisPhone,
|
||||||
|
icono: Icons.person_add_alt_1,
|
||||||
onPressed: () => nearby.asumirUsuariosDesconectados(),
|
onPressed: () => nearby.asumirUsuariosDesconectados(),
|
||||||
icon: const Icon(Icons.person_add_alt_1),
|
),
|
||||||
label: Text(AppLocalizations.of(context)!.assumeOnThisPhone),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -404,68 +409,36 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
|
|||||||
bool todosListos,
|
bool todosListos,
|
||||||
ServicioNearby nearby,
|
ServicioNearby nearby,
|
||||||
) {
|
) {
|
||||||
return Card(
|
return TarjetaFaseFarolero(
|
||||||
child: Padding(
|
icono: Icons.visibility,
|
||||||
padding: const EdgeInsets.all(16),
|
titulo: l10n.waitingPlayersSeeWord,
|
||||||
|
subtitulo: l10n.connectedPlayers,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
Text(
|
|
||||||
l10n.waitingPlayersSeeWord,
|
|
||||||
style: Theme.of(context).textTheme.titleLarge,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Text(
|
|
||||||
l10n.connectedPlayers,
|
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
_buildJugadorTile(nearby.miNombre ?? 'Host', true, _hostListo),
|
_buildJugadorTile(nearby.miNombre ?? 'Host', true, _hostListo),
|
||||||
...nearby.jugadores.map(
|
...nearby.jugadores.map(
|
||||||
(j) => _buildJugadorTile(
|
(jugador) => _buildJugadorTile(
|
||||||
j.nombre,
|
jugador.nombre,
|
||||||
false,
|
false,
|
||||||
_clientesListos[j.endpointId] ?? false,
|
_clientesListos[jugador.endpointId] ?? false,
|
||||||
),
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
// Botón para que el host vea su palabra
|
|
||||||
SizedBox(
|
|
||||||
width: double.infinity,
|
|
||||||
child: ElevatedButton.icon(
|
|
||||||
onPressed: () => _mostrarPalabraHost(context),
|
|
||||||
icon: const Icon(Icons.visibility),
|
|
||||||
label: Text(l10n.seeYourWord),
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
backgroundColor: TemaApp.colorNaranja,
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
if (todosListos)
|
BotonFarolero(
|
||||||
Container(
|
texto: l10n.seeYourWord,
|
||||||
padding: const EdgeInsets.all(12),
|
icono: Icons.visibility,
|
||||||
decoration: BoxDecoration(
|
onPressed: () => _mostrarPalabraHost(context),
|
||||||
color: TemaApp.colorVerde.withValues(alpha: 0.2),
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
),
|
),
|
||||||
child: Row(
|
if (todosListos) ...[
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
const SizedBox(height: 12),
|
||||||
children: [
|
EstadoJugadorFarolero(
|
||||||
const Icon(Icons.check_circle, color: TemaApp.colorVerde),
|
nombre: l10n.allSeenStartDebate,
|
||||||
const SizedBox(width: 8),
|
completado: true,
|
||||||
Text(
|
icono: Icons.check_circle,
|
||||||
l10n.allSeenStartDebate,
|
|
||||||
style: const TextStyle(color: TemaApp.colorVerde),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,67 +536,33 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
|
|||||||
final estado = context.read<EstadoJuego>();
|
final estado = context.read<EstadoJuego>();
|
||||||
final tiempo = estado.partida?.config.tiempoDebateSegundos;
|
final tiempo = estado.partida?.config.tiempoDebateSegundos;
|
||||||
|
|
||||||
return Card(
|
return TarjetaFaseFarolero(
|
||||||
child: Padding(
|
icono: Icons.forum,
|
||||||
padding: const EdgeInsets.all(16),
|
titulo: l10n.debate,
|
||||||
|
subtitulo: l10n.debateInstructions,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
if (tiempo != null) ...[
|
if (tiempo != null) ...[
|
||||||
Text(l10n.debate, style: Theme.of(context).textTheme.titleLarge),
|
TemporizadorFarolero(
|
||||||
const SizedBox(height: 16),
|
etiqueta: _segundosRestantes == 0
|
||||||
Container(
|
|
||||||
width: double.infinity,
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: _segundosRestantes == 0
|
|
||||||
? TemaApp.colorAcento.withValues(alpha: 0.3)
|
|
||||||
: TemaApp.colorTarjeta,
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
_segundosRestantes == 0
|
|
||||||
? l10n.timeUp
|
? l10n.timeUp
|
||||||
: l10n.timeRemaining,
|
: l10n.timeRemaining,
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
tiempo: _formatearTiempo(_segundosRestantes),
|
||||||
),
|
agotado: _segundosRestantes == 0,
|
||||||
Text(
|
|
||||||
_formatearTiempo(_segundosRestantes),
|
|
||||||
style: Theme.of(context).textTheme.headlineLarge,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
],
|
],
|
||||||
_buildPrimerTurno(context),
|
_buildPrimerTurno(context),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(
|
Text(l10n.activePlayers, style: Theme.of(context).textTheme.titleMedium),
|
||||||
l10n.activePlayers,
|
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Expanded(
|
_buildJugadorTile(nearby.miNombre ?? 'Host', true, true),
|
||||||
child: ListView.builder(
|
...nearby.jugadores.map(
|
||||||
itemCount: nearby.jugadores.length + 1,
|
(jugador) => _buildJugadorTile(jugador.nombre, false, true),
|
||||||
itemBuilder: (context, index) {
|
|
||||||
if (index == 0) {
|
|
||||||
return _buildJugadorTile(
|
|
||||||
nearby.miNombre ?? 'Host',
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
final j = nearby.jugadores[index - 1];
|
|
||||||
return _buildJugadorTile(j.nombre, false, true);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -644,7 +583,7 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
|
|||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Empieza $nombre diciendo su palabra.',
|
AppLocalizations.of(context)!.firstTurnInstruction(nombre),
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -664,90 +603,43 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
|
|||||||
final votosEmitidos = estado.votos.length;
|
final votosEmitidos = estado.votos.length;
|
||||||
final progreso = totalVotos == 0 ? 0.0 : votosEmitidos / totalVotos;
|
final progreso = totalVotos == 0 ? 0.0 : votosEmitidos / totalVotos;
|
||||||
|
|
||||||
return Card(
|
return TarjetaFaseFarolero(
|
||||||
child: Padding(
|
icono: Icons.how_to_vote,
|
||||||
padding: const EdgeInsets.all(16),
|
titulo: l10n.voting,
|
||||||
|
subtitulo: l10n.votesProgress(votosEmitidos, totalVotos),
|
||||||
|
color: TemaApp.colorAcento,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(l10n.voting, style: Theme.of(context).textTheme.titleLarge),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Container(
|
|
||||||
width: double.infinity,
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: TemaApp.colorTarjeta,
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Text(l10n.votesProgress(votosEmitidos, totalVotos)),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
ClipRRect(
|
ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(999),
|
||||||
child: LinearProgressIndicator(
|
child: LinearProgressIndicator(
|
||||||
value: progreso.clamp(0.0, 1.0).toDouble(),
|
value: progreso.clamp(0.0, 1.0).toDouble(),
|
||||||
backgroundColor: TemaApp.colorSuperficie,
|
minHeight: 14,
|
||||||
valueColor: const AlwaysStoppedAnimation(
|
backgroundColor: Colors.black.withValues(alpha: 0.35),
|
||||||
TemaApp.colorAcento,
|
valueColor: const AlwaysStoppedAnimation(TemaApp.colorAcento),
|
||||||
),
|
|
||||||
minHeight: 8,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
SizedBox(
|
|
||||||
width: double.infinity,
|
|
||||||
child: OutlinedButton.icon(
|
|
||||||
onPressed: _hostYaVoto(context) ? null : () => _abrirVotacionHost(context),
|
|
||||||
icon: const Icon(Icons.how_to_vote),
|
|
||||||
label: Text(
|
|
||||||
_hostYaVoto(context)
|
|
||||||
? l10n.playersVoted
|
|
||||||
: l10n.confirmVote,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(
|
if (!_hostYaVoto(context))
|
||||||
l10n.playersVoted,
|
BotonFarolero.secundario(
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
texto: l10n.votar,
|
||||||
|
icono: Icons.how_to_vote,
|
||||||
|
onPressed: () => _abrirVotacionHost(context),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
if (!_hostYaVoto(context)) const SizedBox(height: 16),
|
||||||
Expanded(
|
...partida.jugadoresActivos.map((jugador) {
|
||||||
child: ListView.builder(
|
|
||||||
itemCount: partida.jugadoresActivos.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final jugador = partida.jugadoresActivos[index];
|
|
||||||
final haVotado = estado.votos.containsKey(jugador.id);
|
final haVotado = estado.votos.containsKey(jugador.id);
|
||||||
return _buildJugadorTile(jugador.nombre, false, haVotado);
|
return _buildJugadorTile(jugador.nombre, false, haVotado);
|
||||||
},
|
}),
|
||||||
),
|
|
||||||
),
|
|
||||||
if (todosVotaron)
|
if (todosVotaron)
|
||||||
Container(
|
EstadoJugadorFarolero(
|
||||||
padding: const EdgeInsets.all(12),
|
nombre: l10n.allVoted,
|
||||||
decoration: BoxDecoration(
|
completado: true,
|
||||||
color: TemaApp.colorVerde.withValues(alpha: 0.2),
|
icono: Icons.check_circle,
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.check_circle, color: TemaApp.colorVerde),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
Text(
|
|
||||||
l10n.allVoted,
|
|
||||||
style: const TextStyle(color: TemaApp.colorVerde),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -760,132 +652,11 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
|
|||||||
return Center(child: Text(l10n.noResult));
|
return Center(child: Text(l10n.noResult));
|
||||||
}
|
}
|
||||||
|
|
||||||
final conteo = <String, int>{};
|
return SingleChildScrollView(
|
||||||
for (final votadoId in resultado.votos.values) {
|
padding: const EdgeInsets.only(bottom: 8),
|
||||||
conteo[votadoId] = (conteo[votadoId] ?? 0) + 1;
|
child: ResultadoRondaFarolero(
|
||||||
}
|
resultado: resultado,
|
||||||
final maxVotos = conteo.values.isEmpty
|
jugadores: partida.jugadores,
|
||||||
? 1
|
|
||||||
: conteo.values.reduce((a, b) => a > b ? a : b);
|
|
||||||
final ranking = conteo.entries.toList()
|
|
||||||
..sort((a, b) => b.value.compareTo(a.value));
|
|
||||||
|
|
||||||
return Card(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(l10n.result, style: Theme.of(context).textTheme.titleLarge),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
Container(
|
|
||||||
width: double.infinity,
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
decoration: TemaApp.decoracionPanel(
|
|
||||||
color: resultado.eraImpostor
|
|
||||||
? TemaApp.colorVerde.withValues(alpha: 0.18)
|
|
||||||
: TemaApp.colorAcento.withValues(alpha: 0.18),
|
|
||||||
borderColor: resultado.eraImpostor
|
|
||||||
? TemaApp.colorVerde
|
|
||||||
: TemaApp.colorAcento,
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
resultado.eliminadoNombre,
|
|
||||||
style: Theme.of(context).textTheme.headlineMedium,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 6),
|
|
||||||
Text(
|
|
||||||
resultado.eraImpostor
|
|
||||||
? l10n.wasImpostor
|
|
||||||
: l10n.wasInnocent,
|
|
||||||
style: TextStyle(
|
|
||||||
color: resultado.eraImpostor
|
|
||||||
? TemaApp.colorVerde
|
|
||||||
: TemaApp.colorAcento,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Text(l10n.votesThisRound,
|
|
||||||
style: Theme.of(context).textTheme.titleMedium),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
Expanded(
|
|
||||||
child: ListView(
|
|
||||||
children: [
|
|
||||||
...ranking.map((entry) {
|
|
||||||
final jugador = partida.jugadores.firstWhere(
|
|
||||||
(j) => j.id == entry.key,
|
|
||||||
orElse: () => partida.jugadores.first,
|
|
||||||
);
|
|
||||||
return _buildBarraResultado(
|
|
||||||
context,
|
|
||||||
nombre: jugador.nombre,
|
|
||||||
votos: entry.value,
|
|
||||||
maxVotos: maxVotos,
|
|
||||||
destacado: entry.key == resultado.eliminadoId,
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
const Divider(height: 24),
|
|
||||||
...resultado.votos.entries.map((entry) {
|
|
||||||
final votante = partida.jugadores.firstWhere(
|
|
||||||
(j) => j.id == entry.key,
|
|
||||||
orElse: () => partida.jugadores.first,
|
|
||||||
);
|
|
||||||
final votado = partida.jugadores.firstWhere(
|
|
||||||
(j) => j.id == entry.value,
|
|
||||||
orElse: () => partida.jugadores.first,
|
|
||||||
);
|
|
||||||
return ListTile(
|
|
||||||
dense: true,
|
|
||||||
leading: const Icon(Icons.how_to_vote),
|
|
||||||
title: Text('${votante.nombre} → ${votado.nombre}'),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildBarraResultado(
|
|
||||||
BuildContext context, {
|
|
||||||
required String nombre,
|
|
||||||
required int votos,
|
|
||||||
required int maxVotos,
|
|
||||||
required bool destacado,
|
|
||||||
}) {
|
|
||||||
final color = destacado ? TemaApp.colorAcento : TemaApp.colorNaranja;
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: 12),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Expanded(child: Text(nombre)),
|
|
||||||
Text('$votos',
|
|
||||||
style: TextStyle(color: color, fontWeight: FontWeight.bold)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 6),
|
|
||||||
ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(999),
|
|
||||||
child: LinearProgressIndicator(
|
|
||||||
value: (votos / maxVotos).clamp(0.0, 1.0).toDouble(),
|
|
||||||
minHeight: 10,
|
|
||||||
backgroundColor: TemaApp.colorSuperficie,
|
|
||||||
valueColor: AlwaysStoppedAnimation(color),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -895,102 +666,63 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
|
|||||||
final ultimo = partida?.historialVotaciones.isNotEmpty == true
|
final ultimo = partida?.historialVotaciones.isNotEmpty == true
|
||||||
? partida!.historialVotaciones.last
|
? partida!.historialVotaciones.last
|
||||||
: null;
|
: null;
|
||||||
return Card(
|
return TarjetaFaseFarolero(
|
||||||
child: Padding(
|
icono: Icons.psychology,
|
||||||
padding: const EdgeInsets.all(20),
|
titulo: l10n.impostorGuessTitle,
|
||||||
child: Column(
|
subtitulo: ultimo == null
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.psychology, size: 56, color: TemaApp.colorNaranja),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Text(
|
|
||||||
l10n.impostorGuessTitle,
|
|
||||||
style: Theme.of(context).textTheme.headlineSmall,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
Text(
|
|
||||||
ultimo == null
|
|
||||||
? l10n.impostorCanGuess
|
? l10n.impostorCanGuess
|
||||||
: '${ultimo.eliminadoNombre}: ${l10n.impostorCanGuess}',
|
: '${ultimo.eliminadoNombre}: ${l10n.impostorCanGuess}',
|
||||||
textAlign: TextAlign.center,
|
color: TemaApp.colorNaranja,
|
||||||
),
|
child: const ArteGameplayFarolero.resultado(height: 132),
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildFaseFinOnline(BuildContext context, AppLocalizations l10n) {
|
Widget _buildFaseFinOnline(BuildContext context, AppLocalizations l10n) {
|
||||||
final partida = context.watch<EstadoJuego>().partida;
|
final partida = context.watch<EstadoJuego>().partida;
|
||||||
final ganaronJugadores = partida?.ganador == 'jugadores';
|
if (partida == null) return Center(child: Text(l10n.noResult));
|
||||||
return Card(
|
|
||||||
child: Padding(
|
final ganaronJugadores = partida.ganador == 'jugadores';
|
||||||
padding: const EdgeInsets.all(24),
|
final color = ganaronJugadores ? TemaApp.colorVerde : TemaApp.colorAcento;
|
||||||
|
final impostores = partida.jugadores.where((j) => j.esImpostor).toList();
|
||||||
|
|
||||||
|
return SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.only(bottom: 8),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
children: [
|
||||||
Text(
|
HeroFinalPartidaFarolero(
|
||||||
ganaronJugadores ? '🎉' : '🎭',
|
encabezado: l10n.gameOver,
|
||||||
style: const TextStyle(fontSize: 64),
|
titulo: ganaronJugadores ? l10n.playersWin : l10n.impostorsWin,
|
||||||
),
|
icono: ganaronJugadores ? Icons.emoji_events : Icons.theater_comedy,
|
||||||
const SizedBox(height: 16),
|
color: color,
|
||||||
Text(
|
|
||||||
ganaronJugadores ? l10n.playersWin : l10n.impostorsWin,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: Theme.of(context).textTheme.headlineMedium,
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
Text(
|
if (_progresoGamificacion == null)
|
||||||
partida == null ? '' : l10n.theWordWas(partida.palabraSecreta),
|
const TarjetaRecompensaCargandoPremium()
|
||||||
textAlign: TextAlign.center,
|
else
|
||||||
|
TarjetaProgresoGamificacionPremium(
|
||||||
|
progreso: _progresoGamificacion!,
|
||||||
),
|
),
|
||||||
if (_progresoGamificacion != null) ...[
|
const SizedBox(height: 18),
|
||||||
const SizedBox(height: 16),
|
TarjetaSecretoPremium(
|
||||||
_buildProgresoGamificacion(context, _progresoGamificacion!),
|
palabra: partida.palabraSecreta,
|
||||||
],
|
categoria: BancoPalabras.nombreBonitoCategoria(
|
||||||
],
|
partida.categoriaReal,
|
||||||
|
l10n,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
const SizedBox(height: 18),
|
||||||
}
|
TarjetaImpostoresPremium(
|
||||||
|
titulo: impostores.length == 1
|
||||||
Widget _buildProgresoGamificacion(
|
? l10n.theImpostorWas
|
||||||
BuildContext context,
|
: l10n.theImpostorsWere,
|
||||||
ProgresoGamificacionUsuario progreso,
|
impostores: impostores,
|
||||||
) {
|
|
||||||
final nuevas = progreso.nuevasMedallas;
|
|
||||||
return PanelFarolero(
|
|
||||||
padding: const EdgeInsets.all(14),
|
|
||||||
color: TemaApp.colorSuperficie.withValues(alpha: 0.82),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text('Tu progreso', style: Theme.of(context).textTheme.titleMedium),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
const Text('🔥', style: TextStyle(fontSize: 22)),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
Expanded(
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(6),
|
|
||||||
child: LinearProgressIndicator(
|
|
||||||
value: progreso.despues.fuego / 100,
|
|
||||||
minHeight: 8,
|
|
||||||
color: TemaApp.colorNaranja,
|
|
||||||
backgroundColor: Colors.black.withValues(alpha: 0.35),
|
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 18),
|
||||||
|
if (partida.historialVotaciones.isNotEmpty)
|
||||||
|
TarjetaHistorialVotosPremium(
|
||||||
|
historial: partida.historialVotaciones,
|
||||||
|
jugadores: partida.jugadores,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
Text('${progreso.despues.fuego}%'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
if (nuevas.isNotEmpty) ...[
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
MedallasCompactasFarolero(ids: nuevas, max: nuevas.length),
|
|
||||||
],
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -1046,28 +778,11 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildJugadorTile(String nombre, bool esHost, bool listo) {
|
Widget _buildJugadorTile(String nombre, bool esHost, bool listo) {
|
||||||
return Container(
|
return EstadoJugadorFarolero(
|
||||||
margin: const EdgeInsets.only(bottom: 8),
|
nombre: nombre,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
destacado: esHost,
|
||||||
decoration: BoxDecoration(
|
completado: listo,
|
||||||
color: listo
|
icono: esHost ? Icons.phone_android : Icons.devices,
|
||||||
? TemaApp.colorVerde.withValues(alpha: 0.2)
|
|
||||||
: TemaApp.colorTarjeta,
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
esHost ? Icons.phone_android : Icons.devices,
|
|
||||||
color: esHost ? TemaApp.colorDorado : TemaApp.colorNaranja,
|
|
||||||
size: 22,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
Expanded(child: Text(nombre)),
|
|
||||||
if (listo)
|
|
||||||
const Icon(Icons.check_circle, color: TemaApp.colorVerde, size: 20),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1080,60 +795,36 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
|
|||||||
) {
|
) {
|
||||||
switch (fase) {
|
switch (fase) {
|
||||||
case FaseJuego.verPalabra:
|
case FaseJuego.verPalabra:
|
||||||
return SizedBox(
|
return BotonFarolero(
|
||||||
width: double.infinity,
|
texto: todosListos ? l10n.allSeenStartDebate : l10n.waitingPlayersSeeWord,
|
||||||
height: 56,
|
icono: Icons.forum,
|
||||||
child: ElevatedButton.icon(
|
onPressed: todosListos ? () => _avanzarAFase(FaseJuego.debate) : null,
|
||||||
onPressed: todosListos
|
|
||||||
? () => _avanzarAFase(FaseJuego.debate)
|
|
||||||
: null,
|
|
||||||
icon: const Icon(Icons.forum),
|
|
||||||
label: Text(
|
|
||||||
todosListos
|
|
||||||
? l10n.allSeenStartDebate
|
|
||||||
: l10n.waitingPlayersSeeWord,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
case FaseJuego.debate:
|
case FaseJuego.debate:
|
||||||
return SizedBox(
|
return BotonFarolero.secundario(
|
||||||
width: double.infinity,
|
texto: l10n.goToVoting,
|
||||||
height: 56,
|
icono: Icons.how_to_vote,
|
||||||
child: ElevatedButton.icon(
|
|
||||||
onPressed: () => _avanzarAFase(FaseJuego.votacion),
|
onPressed: () => _avanzarAFase(FaseJuego.votacion),
|
||||||
icon: const Icon(Icons.how_to_vote),
|
|
||||||
label: Text(l10n.goToVoting),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
case FaseJuego.votacion:
|
case FaseJuego.votacion:
|
||||||
return SizedBox(
|
return BotonFarolero(
|
||||||
width: double.infinity,
|
texto: todosVotaron ? l10n.revealResult : l10n.waitingVoting,
|
||||||
height: 56,
|
icono: Icons.visibility,
|
||||||
child: ElevatedButton.icon(
|
onPressed: todosVotaron ? () => _avanzarAFase(FaseJuego.resultado) : null,
|
||||||
onPressed: todosVotaron
|
|
||||||
? () => _avanzarAFase(FaseJuego.resultado)
|
|
||||||
: null,
|
|
||||||
icon: const Icon(Icons.visibility),
|
|
||||||
label: Text(todosVotaron ? l10n.revealResult : l10n.waitingVoting),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
case FaseJuego.resultado:
|
case FaseJuego.resultado:
|
||||||
return _buildAccionesResultado(context, l10n);
|
return _buildAccionesResultado(context, l10n);
|
||||||
case FaseJuego.adivinanza:
|
case FaseJuego.adivinanza:
|
||||||
return _buildAccionesAdivinanza(context, l10n);
|
return _buildAccionesAdivinanza(context, l10n);
|
||||||
case FaseJuego.finPartida:
|
case FaseJuego.finPartida:
|
||||||
return SizedBox(
|
return BotonFarolero.oscuro(
|
||||||
width: double.infinity,
|
texto: l10n.mainMenu,
|
||||||
height: 56,
|
icono: Icons.home,
|
||||||
child: OutlinedButton.icon(
|
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final nearby = context.read<ServicioNearby>();
|
final nearby = context.read<ServicioNearby>();
|
||||||
await nearby.desconectar();
|
await nearby.desconectar();
|
||||||
widget.onPartidaFin();
|
widget.onPartidaFin();
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.home),
|
|
||||||
label: Text(l10n.mainMenu),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
@@ -1149,80 +840,58 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
|
|||||||
if (partida == null || resultado == null) return const SizedBox.shrink();
|
if (partida == null || resultado == null) return const SizedBox.shrink();
|
||||||
|
|
||||||
if (_hayFinTrasVotacion(partida)) {
|
if (_hayFinTrasVotacion(partida)) {
|
||||||
return SizedBox(
|
return BotonFarolero(
|
||||||
width: double.infinity,
|
texto: l10n.seeEndResult,
|
||||||
height: 56,
|
icono: Icons.emoji_events,
|
||||||
child: ElevatedButton.icon(
|
|
||||||
onPressed: () => _finalizarPartidaOnline(context),
|
onPressed: () => _finalizarPartidaOnline(context),
|
||||||
icon: const Icon(Icons.emoji_events),
|
|
||||||
label: Text(l10n.seeEndResult),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resultado.eraImpostor) {
|
if (resultado.eraImpostor) {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
BotonFarolero.oscuro(
|
||||||
width: double.infinity,
|
texto: l10n.impostorGuessWord,
|
||||||
height: 56,
|
icono: Icons.psychology,
|
||||||
child: OutlinedButton.icon(
|
|
||||||
onPressed: () => _iniciarAdivinanzaOnline(context),
|
onPressed: () => _iniciarAdivinanzaOnline(context),
|
||||||
icon: const Icon(Icons.psychology),
|
|
||||||
label: Text(l10n.impostorGuessWord),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
SizedBox(
|
BotonFarolero(
|
||||||
width: double.infinity,
|
texto: l10n.nextRound,
|
||||||
height: 56,
|
icono: Icons.skip_next,
|
||||||
child: ElevatedButton.icon(
|
|
||||||
onPressed: () => _siguienteRondaOnline(context),
|
onPressed: () => _siguienteRondaOnline(context),
|
||||||
icon: const Icon(Icons.skip_next),
|
|
||||||
label: Text(l10n.nextRound),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SizedBox(
|
return BotonFarolero(
|
||||||
width: double.infinity,
|
texto: l10n.nextRound,
|
||||||
height: 56,
|
icono: Icons.skip_next,
|
||||||
child: ElevatedButton.icon(
|
|
||||||
onPressed: () => _siguienteRondaOnline(context),
|
onPressed: () => _siguienteRondaOnline(context),
|
||||||
icon: const Icon(Icons.skip_next),
|
|
||||||
label: Text(l10n.nextRound),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildAccionesAdivinanza(BuildContext context, AppLocalizations l10n) {
|
Widget _buildAccionesAdivinanza(BuildContext context, AppLocalizations l10n) {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
BotonFarolero(
|
||||||
width: double.infinity,
|
texto: l10n.guess,
|
||||||
height: 56,
|
icono: Icons.check_circle,
|
||||||
child: ElevatedButton.icon(
|
|
||||||
onPressed: () => _resolverAdivinanzaOnline(context),
|
onPressed: () => _resolverAdivinanzaOnline(context),
|
||||||
icon: const Icon(Icons.check_circle),
|
|
||||||
label: Text(l10n.guess),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
SizedBox(
|
BotonFarolero.oscuro(
|
||||||
width: double.infinity,
|
texto: l10n.dontGuess,
|
||||||
height: 56,
|
icono: Icons.skip_next,
|
||||||
child: OutlinedButton.icon(
|
|
||||||
onPressed: () => _siguienteRondaOnline(context),
|
onPressed: () => _siguienteRondaOnline(context),
|
||||||
icon: const Icon(Icons.skip_next),
|
|
||||||
label: Text(l10n.dontGuess),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _finalizarPartidaOnline
|
||||||
|
|
||||||
Future<void> _finalizarPartidaOnline(BuildContext context) async {
|
Future<void> _finalizarPartidaOnline(BuildContext context) async {
|
||||||
final estado = context.read<EstadoJuego>();
|
final estado = context.read<EstadoJuego>();
|
||||||
final nearby = context.read<ServicioNearby>();
|
final nearby = context.read<ServicioNearby>();
|
||||||
@@ -1441,7 +1110,12 @@ class _PantallaRevelarPalabraHostState
|
|||||||
if (widget.esImpostor && widget.pistaActiva) ...[
|
if (widget.esImpostor && widget.pistaActiva) ...[
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
Text(
|
Text(
|
||||||
'Categoría: ${widget.categoria}',
|
l10n.clueCategory(
|
||||||
|
BancoPalabras.nombreBonitoCategoria(
|
||||||
|
widget.categoria,
|
||||||
|
l10n,
|
||||||
|
),
|
||||||
|
),
|
||||||
style: Theme.of(context).textTheme.bodyLarge
|
style: Theme.of(context).textTheme.bodyLarge
|
||||||
?.copyWith(color: TemaApp.colorNaranja),
|
?.copyWith(color: TemaApp.colorNaranja),
|
||||||
),
|
),
|
||||||
@@ -1450,7 +1124,11 @@ class _PantallaRevelarPalabraHostState
|
|||||||
)
|
)
|
||||||
: Column(
|
: Column(
|
||||||
children: [
|
children: [
|
||||||
const Text('🔒', style: TextStyle(fontSize: 48)),
|
const Icon(
|
||||||
|
Icons.lock,
|
||||||
|
color: TemaApp.colorDorado,
|
||||||
|
size: 48,
|
||||||
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(
|
Text(
|
||||||
l10n.holdToSeeWord,
|
l10n.holdToSeeWord,
|
||||||
@@ -1496,21 +1174,15 @@ class _PantallaRevelarPalabraHostState
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
SizedBox(
|
BotonFarolero(
|
||||||
width: double.infinity,
|
texto: _haRevelado ? l10n.iveSeenIt : l10n.tapToSee,
|
||||||
height: 56,
|
icono: Icons.check,
|
||||||
child: ElevatedButton.icon(
|
|
||||||
onPressed: _haRevelado
|
onPressed: _haRevelado
|
||||||
? () {
|
? () {
|
||||||
widget.onVisto();
|
widget.onVisto();
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
icon: const Icon(Icons.check),
|
|
||||||
label: Text(
|
|
||||||
_haRevelado ? l10n.iveSeenIt : l10n.tapToSee,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import 'package:farolero/tema/componentes_farolero.dart';
|
|||||||
import 'package:farolero/tema/tema_app.dart';
|
import 'package:farolero/tema/tema_app.dart';
|
||||||
|
|
||||||
/// Pantalla que ve cada jugador cuando recibe su palabra (modo multidispositivo).
|
/// Pantalla que ve cada jugador cuando recibe su palabra (modo multidispositivo).
|
||||||
/// El cliente recibe la palabra via ServicioNearby y se navega aquí.
|
/// El cliente recibe la palabra vía ServicioNearby y se navega aquí.
|
||||||
/// NO es la pantalla del host.
|
/// NO es la pantalla del host.
|
||||||
class PantallaPalabraCliente extends StatefulWidget {
|
class PantallaPalabraCliente extends StatefulWidget {
|
||||||
final String palabra;
|
final String palabra;
|
||||||
@@ -166,23 +166,11 @@ class _PantallaPalabraClienteState extends State<PantallaPalabraCliente> {
|
|||||||
),
|
),
|
||||||
|
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
|
|
||||||
// Botón confirmar
|
// Botón confirmar
|
||||||
SizedBox(
|
BotonFarolero(
|
||||||
width: double.infinity,
|
texto: _haRevelado ? l10n.iveSeenIt : l10n.tapToSee,
|
||||||
height: 56,
|
icono: Icons.check,
|
||||||
child: ElevatedButton.icon(
|
|
||||||
onPressed: _haRevelado ? widget.onVisto : null,
|
onPressed: _haRevelado ? widget.onVisto : null,
|
||||||
icon: const Icon(Icons.check),
|
|
||||||
label: Text(
|
|
||||||
_haRevelado ? l10n.iveSeenIt : l10n.tapToSee,
|
|
||||||
),
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
backgroundColor: TemaApp.colorAcento,
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
textStyle: const TextStyle(fontSize: 16),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -130,18 +130,12 @@ class _PantallaPalabrasClienteState extends State<PantallaPalabrasCliente> {
|
|||||||
style: TextStyle(color: TemaApp.colorTextoSecundario),
|
style: TextStyle(color: TemaApp.colorTextoSecundario),
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
SizedBox(
|
BotonFarolero(
|
||||||
width: double.infinity,
|
texto: _actualRevelado
|
||||||
height: 56,
|
|
||||||
child: ElevatedButton.icon(
|
|
||||||
onPressed: _actualRevelado ? _continuar : null,
|
|
||||||
icon: Icon(_esUltimo ? Icons.check : Icons.arrow_forward),
|
|
||||||
label: Text(
|
|
||||||
_actualRevelado
|
|
||||||
? (_esUltimo ? l10n.iveSeenIt : l10n.next)
|
? (_esUltimo ? l10n.iveSeenIt : l10n.next)
|
||||||
: l10n.tapToSee,
|
: l10n.tapToSee,
|
||||||
),
|
icono: _esUltimo ? Icons.check : Icons.arrow_forward,
|
||||||
),
|
onPressed: _actualRevelado ? _continuar : null,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -223,7 +223,9 @@ class _PantallaResultadoOnlineState extends State<PantallaResultadoOnline> {
|
|||||||
AppLocalizations l10n,
|
AppLocalizations l10n,
|
||||||
) {
|
) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Card(
|
child: PanelFarolero(
|
||||||
|
margin: const EdgeInsets.all(16),
|
||||||
|
borderColor: TemaApp.colorNaranja.withValues(alpha: 0.48),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
|||||||
@@ -29,15 +29,12 @@ Future<void> mostrarRevisionPalabraOnline({
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
...jugadoresControlados.map(
|
...jugadoresControlados.map(
|
||||||
(jugador) => Card(
|
(jugador) => EstadoJugadorFarolero(
|
||||||
color: TemaApp.colorTarjeta,
|
nombre: jugador.nombre,
|
||||||
child: ListTile(
|
icono: Icons.visibility,
|
||||||
leading: const Icon(Icons.visibility),
|
|
||||||
title: Text(jugador.nombre),
|
|
||||||
onTap: () => Navigator.pop(sheetContext, jugador),
|
onTap: () => Navigator.pop(sheetContext, jugador),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -121,13 +118,10 @@ class _DialogoRevisionPalabra extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
SizedBox(
|
BotonFarolero.secundario(
|
||||||
width: double.infinity,
|
texto: l10n.back,
|
||||||
child: ElevatedButton.icon(
|
icono: Icons.check,
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(context),
|
||||||
icon: const Icon(Icons.check),
|
|
||||||
label: Text(l10n.back),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:farolero/l10n/generated/app_localizations.dart';
|
import 'package:farolero/l10n/generated/app_localizations.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import '../estado/estado_juego.dart';
|
import '../estado/estado_juego.dart';
|
||||||
@@ -24,8 +24,7 @@ class _PantallaVerPalabraState extends State<PantallaVerPalabra> {
|
|||||||
final partida = estado.partida;
|
final partida = estado.partida;
|
||||||
if (partida == null) return const SizedBox.shrink();
|
if (partida == null) return const SizedBox.shrink();
|
||||||
|
|
||||||
final todosHanVisto =
|
final todosHanVisto = partida.jugadores.every((j) => _hanVisto.contains(j.id));
|
||||||
partida.jugadores.every((j) => _hanVisto.contains(j.id));
|
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
@@ -34,82 +33,58 @@ class _PantallaVerPalabraState extends State<PantallaVerPalabra> {
|
|||||||
),
|
),
|
||||||
body: FondoFarolero(
|
body: FondoFarolero(
|
||||||
intenso: true,
|
intenso: true,
|
||||||
|
child: SafeArea(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
const ArteGameplayFarolero.fase(height: 110),
|
const ArteGameplayFarolero.fase(height: 110),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
EncabezadoFarolero(
|
TarjetaFaseFarolero(
|
||||||
icono: Icons.visibility,
|
icono: Icons.visibility,
|
||||||
titulo: l10n.roundNumber(partida.rondaActual),
|
titulo: l10n.roundNumber(partida.rondaActual),
|
||||||
subtitulo: l10n.eachPlayerMustSee,
|
subtitulo: l10n.eachPlayerMustSee,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ListView.builder(
|
child: ListView.separated(
|
||||||
itemCount: partida.jugadores.length,
|
itemCount: partida.jugadores.length,
|
||||||
|
separatorBuilder: (context, index) => const SizedBox(height: 10),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final jugador = partida.jugadores[index];
|
final jugador = partida.jugadores[index];
|
||||||
final haVisto = _hanVisto.contains(jugador.id);
|
final haVisto = _hanVisto.contains(jugador.id);
|
||||||
return Card(
|
return EstadoJugadorFarolero(
|
||||||
color: haVisto
|
nombre: '${index + 1}. ${jugador.nombre}',
|
||||||
? TemaApp.colorVerde.withValues(alpha: 0.2)
|
subtitulo: haVisto ? l10n.alreadySeen : l10n.tapToSee,
|
||||||
: TemaApp.colorTarjeta,
|
icono: haVisto ? Icons.check_circle : Icons.visibility,
|
||||||
child: ListTile(
|
destacado: haVisto,
|
||||||
leading: CircleAvatar(
|
completado: haVisto,
|
||||||
backgroundColor: haVisto
|
onTap: haVisto ? null : () => _mostrarPalabra(context, jugador.id),
|
||||||
? TemaApp.colorVerde
|
|
||||||
: TemaApp.colorAcento,
|
|
||||||
child: Text(
|
|
||||||
haVisto ? '✓' : '${index + 1}',
|
|
||||||
style:
|
|
||||||
const TextStyle(color: Colors.white),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
title: Text(jugador.nombre),
|
|
||||||
subtitle: Text(
|
|
||||||
haVisto ? l10n.alreadySeen : l10n.tapToSee,
|
|
||||||
),
|
|
||||||
trailing: haVisto
|
|
||||||
? const Icon(Icons.check_circle,
|
|
||||||
color: TemaApp.colorVerde)
|
|
||||||
: const Icon(Icons.visibility,
|
|
||||||
color: TemaApp.colorTextoSecundario),
|
|
||||||
onTap: haVisto
|
|
||||||
? null
|
|
||||||
: () => _mostrarPalabra(context, jugador.id),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
SizedBox(
|
BotonFarolero(
|
||||||
width: double.infinity,
|
texto: todosHanVisto
|
||||||
height: 56,
|
? l10n.allSeenStartDebate
|
||||||
child: ElevatedButton.icon(
|
: l10n.playersRemaining(partida.jugadores.length - _hanVisto.length),
|
||||||
|
icono: Icons.forum,
|
||||||
onPressed: todosHanVisto
|
onPressed: todosHanVisto
|
||||||
? () {
|
? () {
|
||||||
estado.iniciarDebate();
|
estado.iniciarDebate();
|
||||||
Navigator.pushReplacement(
|
Navigator.pushReplacement(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(builder: (_) => const PantallaDebate()),
|
||||||
builder: (_) => const PantallaDebate(),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
icon: const Icon(Icons.forum),
|
|
||||||
label: Text(todosHanVisto
|
|
||||||
? l10n.allSeenStartDebate
|
|
||||||
: l10n.playersRemaining(partida.jugadores.length - _hanVisto.length)),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,8 +129,7 @@ class _PantallaRevelarPalabra extends StatefulWidget {
|
|||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<_PantallaRevelarPalabra> createState() =>
|
State<_PantallaRevelarPalabra> createState() => _PantallaRevelarPalabraState();
|
||||||
_PantallaRevelarPalabraState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PantallaRevelarPalabraState extends State<_PantallaRevelarPalabra> {
|
class _PantallaRevelarPalabraState extends State<_PantallaRevelarPalabra> {
|
||||||
@@ -165,66 +139,48 @@ class _PantallaRevelarPalabraState extends State<_PantallaRevelarPalabra> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final l10n = AppLocalizations.of(context)!;
|
final l10n = AppLocalizations.of(context)!;
|
||||||
|
final colorEstado = widget.esImpostor ? TemaApp.colorAcento : TemaApp.colorVerde;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(title: Text(widget.nombre)),
|
appBar: AppBar(title: Text(widget.nombre)),
|
||||||
body: FondoFarolero(
|
body: FondoFarolero(
|
||||||
intenso: true,
|
intenso: true,
|
||||||
child: Center(
|
child: SafeArea(
|
||||||
child: Padding(
|
child: SingleChildScrollView(
|
||||||
padding: const EdgeInsets.all(32),
|
padding: const EdgeInsets.all(24),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
children: [
|
||||||
const ArteGameplayFarolero.fase(height: 128),
|
const ArteGameplayFarolero.fase(height: 128),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
Text(
|
TarjetaFaseFarolero(
|
||||||
widget.nombre,
|
icono: widget.esImpostor ? Icons.theater_comedy : Icons.search,
|
||||||
style: Theme.of(context).textTheme.headlineMedium,
|
titulo: widget.nombre,
|
||||||
|
subtitulo: l10n.holdToSeeWord,
|
||||||
|
color: colorEstado,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 32),
|
const SizedBox(height: 18),
|
||||||
|
|
||||||
// Zona de revelación
|
|
||||||
AnimatedContainer(
|
AnimatedContainer(
|
||||||
duration: const Duration(milliseconds: 200),
|
duration: const Duration(milliseconds: 200),
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
padding: const EdgeInsets.all(32),
|
padding: const EdgeInsets.all(24),
|
||||||
decoration: BoxDecoration(
|
decoration: TemaApp.decoracionPanel(
|
||||||
color: _manteniendo
|
color: (_manteniendo ? colorEstado : TemaApp.colorTarjeta).withValues(alpha: _manteniendo ? 0.22 : 0.92),
|
||||||
? (widget.esImpostor
|
borderColor: _manteniendo ? colorEstado : TemaApp.colorBorde,
|
||||||
? TemaApp.colorAcento.withValues(alpha: 0.3)
|
radius: 24,
|
||||||
: TemaApp.colorVerde.withValues(alpha: 0.3))
|
|
||||||
: TemaApp.colorTarjeta,
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
border: Border.all(
|
|
||||||
color: _manteniendo
|
|
||||||
? (widget.esImpostor
|
|
||||||
? TemaApp.colorAcento
|
|
||||||
: TemaApp.colorVerde)
|
|
||||||
: Colors.transparent,
|
|
||||||
width: 2,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: _manteniendo
|
child: _manteniendo
|
||||||
? Column(
|
? Column(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Icon(
|
||||||
widget.esImpostor ? '🎭' : '🔍',
|
widget.esImpostor ? Icons.theater_comedy : Icons.search,
|
||||||
style: const TextStyle(fontSize: 48),
|
color: colorEstado,
|
||||||
|
size: 52,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(
|
Text(
|
||||||
widget.esImpostor
|
widget.esImpostor ? l10n.youAreImpostor : l10n.yourWordIs,
|
||||||
? l10n.youAreImpostor
|
textAlign: TextAlign.center,
|
||||||
: l10n.yourWordIs,
|
style: Theme.of(context).textTheme.titleLarge?.copyWith(color: colorEstado),
|
||||||
style: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.titleLarge
|
|
||||||
?.copyWith(
|
|
||||||
color: widget.esImpostor
|
|
||||||
? TemaApp.colorAcento
|
|
||||||
: TemaApp.colorVerde,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
if (!widget.esImpostor) ...[
|
if (!widget.esImpostor) ...[
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
@@ -234,19 +190,15 @@ class _PantallaRevelarPalabraState extends State<_PantallaRevelarPalabra> {
|
|||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
Text(
|
Text(
|
||||||
l10n.clueCategory(BancoPalabras.nombreBonitoCategoria(widget.categoria, l10n)),
|
l10n.clueCategory(BancoPalabras.nombreBonitoCategoria(widget.categoria, l10n)),
|
||||||
style: Theme.of(context)
|
textAlign: TextAlign.center,
|
||||||
.textTheme
|
style: Theme.of(context).textTheme.bodyLarge?.copyWith(color: TemaApp.colorNaranja),
|
||||||
.bodyLarge
|
|
||||||
?.copyWith(
|
|
||||||
color: TemaApp.colorNaranja,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: Column(
|
: Column(
|
||||||
children: [
|
children: [
|
||||||
const Text('🔒', style: TextStyle(fontSize: 48)),
|
const Icon(Icons.lock, color: TemaApp.colorDorado, size: 52),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(
|
Text(
|
||||||
l10n.holdToSeeWord,
|
l10n.holdToSeeWord,
|
||||||
@@ -257,23 +209,20 @@ class _PantallaRevelarPalabraState extends State<_PantallaRevelarPalabra> {
|
|||||||
Text(
|
Text(
|
||||||
l10n.makeSureNoOneLooks,
|
l10n.makeSureNoOneLooks,
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
|
|
||||||
// Botón mantener pulsado
|
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onLongPressStart: (_) {
|
onLongPressStart: (details) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_manteniendo = true;
|
_manteniendo = true;
|
||||||
_visto = true;
|
_visto = true;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onLongPressEnd: (_) {
|
onLongPressEnd: (details) => setState(() => _manteniendo = false),
|
||||||
setState(() => _manteniendo = false);
|
|
||||||
},
|
|
||||||
child: Container(
|
child: Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: 64,
|
height: 64,
|
||||||
@@ -283,13 +232,11 @@ class _PantallaRevelarPalabraState extends State<_PantallaRevelarPalabra> {
|
|||||||
? [TemaApp.colorNaranja, TemaApp.colorAcento]
|
? [TemaApp.colorNaranja, TemaApp.colorAcento]
|
||||||
: [TemaApp.colorAcento, TemaApp.colorAcento],
|
: [TemaApp.colorAcento, TemaApp.colorAcento],
|
||||||
),
|
),
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(18),
|
||||||
),
|
),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
_manteniendo
|
_manteniendo ? l10n.showingWord : l10n.holdToSee,
|
||||||
? l10n.showingWord
|
|
||||||
: l10n.holdToSee,
|
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
@@ -300,18 +247,14 @@ class _PantallaRevelarPalabraState extends State<_PantallaRevelarPalabra> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
|
|
||||||
if (_visto)
|
if (_visto)
|
||||||
SizedBox(
|
BotonFarolero.secundario(
|
||||||
width: double.infinity,
|
texto: l10n.seenMyWord,
|
||||||
child: OutlinedButton.icon(
|
icono: Icons.check,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
widget.onVisto();
|
widget.onVisto();
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.check),
|
|
||||||
label: Text(l10n.seenMyWord),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -25,12 +25,6 @@ class _PantallaVotacionState extends State<PantallaVotacion> {
|
|||||||
final activos = partida.jugadoresActivos;
|
final activos = partida.jugadoresActivos;
|
||||||
final todosVotaron = estado.todosHanVotado();
|
final todosVotaron = estado.todosHanVotado();
|
||||||
|
|
||||||
// Modo un solo móvil
|
|
||||||
if (!partida.config.modoMultimovil) {
|
|
||||||
return _construirVotacionUnMovil(context, estado, partida, activos, todosVotaron);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modo multimóvil sería similar pero controlado por Nearby
|
|
||||||
return _construirVotacionUnMovil(context, estado, partida, activos, todosVotaron);
|
return _construirVotacionUnMovil(context, estado, partida, activos, todosVotaron);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,10 +35,7 @@ class _PantallaVotacionState extends State<PantallaVotacion> {
|
|||||||
List activos,
|
List activos,
|
||||||
bool todosVotaron,
|
bool todosVotaron,
|
||||||
) {
|
) {
|
||||||
// Encontrar el siguiente votante que no haya votado
|
final sinVotar = activos.where((j) => !estado.votos.containsKey(j.id)).toList();
|
||||||
final sinVotar = activos
|
|
||||||
.where((j) => !estado.votos.containsKey(j.id))
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
if (todosVotaron) {
|
if (todosVotaron) {
|
||||||
return _construirTodosVotaron(context, estado);
|
return _construirTodosVotaron(context, estado);
|
||||||
@@ -61,122 +52,68 @@ class _PantallaVotacionState extends State<PantallaVotacion> {
|
|||||||
),
|
),
|
||||||
body: FondoFarolero(
|
body: FondoFarolero(
|
||||||
intenso: true,
|
intenso: true,
|
||||||
|
child: SafeArea(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
const ArteGameplayFarolero.fase(height: 108),
|
const ArteGameplayFarolero.fase(height: 108),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
// Progreso de votos
|
TarjetaFaseFarolero(
|
||||||
Container(
|
icono: Icons.how_to_vote,
|
||||||
width: double.infinity,
|
titulo: l10n.voteOf(votanteActual.nombre),
|
||||||
padding: const EdgeInsets.all(16),
|
subtitulo: l10n.votesProgress(estado.votos.length, activos.length),
|
||||||
decoration: TemaApp.decoracionPanel(
|
color: TemaApp.colorAcento,
|
||||||
color: TemaApp.colorTarjeta.withValues(alpha: 0.90),
|
child: ClipRRect(
|
||||||
borderColor: TemaApp.colorNaranja.withValues(alpha: 0.38),
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
l10n.turnToVote,
|
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 4),
|
|
||||||
Text(
|
|
||||||
votanteActual.nombre,
|
|
||||||
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
|
|
||||||
color: TemaApp.colorNaranja,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
Text(
|
|
||||||
l10n.votesProgress(estado.votos.length, activos.length),
|
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 4),
|
|
||||||
ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(4),
|
||||||
child: LinearProgressIndicator(
|
child: LinearProgressIndicator(
|
||||||
value: estado.votos.length / activos.length,
|
value: estado.votos.length / activos.length,
|
||||||
backgroundColor: TemaApp.colorSuperficie,
|
backgroundColor: TemaApp.colorSuperficie,
|
||||||
valueColor: const AlwaysStoppedAnimation(TemaApp.colorAcento),
|
valueColor: const AlwaysStoppedAnimation(TemaApp.colorAcento),
|
||||||
minHeight: 6,
|
minHeight: 7,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
Expanded(
|
||||||
EncabezadoFarolero(
|
child: TarjetaFaseFarolero(
|
||||||
icono: Icons.how_to_vote,
|
icono: Icons.person_search,
|
||||||
titulo: l10n.whoIsImpostor,
|
titulo: l10n.whoIsImpostor,
|
||||||
subtitulo: l10n.selectOnePlayer,
|
subtitulo: l10n.selectOnePlayer,
|
||||||
color: TemaApp.colorAcento,
|
color: TemaApp.colorNaranja,
|
||||||
trailing: Image.asset(
|
child: Expanded(
|
||||||
'assets/ui/generated/meta/result_verdict_art.webp',
|
child: ListView.separated(
|
||||||
width: 42,
|
|
||||||
height: 42,
|
|
||||||
opacity: const AlwaysStoppedAnimation(0.64),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
|
|
||||||
// Lista de candidatos
|
|
||||||
Expanded(
|
|
||||||
child: ListView.builder(
|
|
||||||
itemCount: puedenRecibir.length,
|
itemCount: puedenRecibir.length,
|
||||||
|
separatorBuilder: (context, index) => const SizedBox(height: 8),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final candidato = puedenRecibir[index];
|
final candidato = puedenRecibir[index];
|
||||||
final seleccionado = _seleccionado == candidato.id;
|
final seleccionado = _seleccionado == candidato.id;
|
||||||
return Card(
|
return SelectorVotoFarolero(
|
||||||
color: seleccionado
|
nombre: '${index + 1}. ${candidato.nombre}',
|
||||||
? TemaApp.colorAcento.withValues(alpha: 0.3)
|
seleccionado: seleccionado,
|
||||||
: TemaApp.colorTarjeta,
|
onTap: () => setState(() => _seleccionado = candidato.id),
|
||||||
child: ListTile(
|
|
||||||
leading: CircleAvatar(
|
|
||||||
backgroundColor: seleccionado
|
|
||||||
? TemaApp.colorAcento
|
|
||||||
: TemaApp.colorSuperficie,
|
|
||||||
child: Text('${index + 1}',
|
|
||||||
style: const TextStyle(color: Colors.white)),
|
|
||||||
),
|
|
||||||
title: Text(candidato.nombre),
|
|
||||||
trailing: seleccionado
|
|
||||||
? const Icon(Icons.check_circle,
|
|
||||||
color: TemaApp.colorAcento)
|
|
||||||
: const Icon(Icons.radio_button_unchecked),
|
|
||||||
onTap: () {
|
|
||||||
setState(() => _seleccionado = candidato.id);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
BotonFarolero(
|
||||||
SizedBox(
|
texto: l10n.confirmVote,
|
||||||
width: double.infinity,
|
icono: Icons.how_to_vote,
|
||||||
height: 56,
|
|
||||||
child: ElevatedButton.icon(
|
|
||||||
onPressed: _seleccionado != null
|
onPressed: _seleccionado != null
|
||||||
? () {
|
? () {
|
||||||
estado.registrarVoto(
|
estado.registrarVoto(votanteActual.id, _seleccionado!);
|
||||||
votanteActual.id, _seleccionado!);
|
setState(() => _seleccionado = null);
|
||||||
setState(() {
|
|
||||||
_seleccionado = null;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
icon: const Icon(Icons.how_to_vote),
|
|
||||||
label: Text(l10n.confirmVote),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,49 +127,44 @@ class _PantallaVotacionState extends State<PantallaVotacion> {
|
|||||||
),
|
),
|
||||||
body: FondoFarolero(
|
body: FondoFarolero(
|
||||||
intenso: true,
|
intenso: true,
|
||||||
|
child: SafeArea(
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Padding(
|
child: SingleChildScrollView(
|
||||||
padding: const EdgeInsets.all(32),
|
padding: const EdgeInsets.all(24),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
const ArteGameplayFarolero.fase(height: 132),
|
const ArteGameplayFarolero.fase(height: 132),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
Text(
|
TarjetaFaseFarolero(
|
||||||
l10n.allVoted,
|
icono: Icons.check_circle,
|
||||||
style: Theme.of(context).textTheme.headlineMedium,
|
titulo: l10n.allVoted,
|
||||||
|
subtitulo: l10n.tapToReveal,
|
||||||
|
color: TemaApp.colorVerde,
|
||||||
|
child: const SizedBox.shrink(),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 28),
|
||||||
Text(
|
BotonFarolero(
|
||||||
l10n.tapToReveal,
|
texto: l10n.revealResult,
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
icono: Icons.visibility,
|
||||||
),
|
|
||||||
const SizedBox(height: 32),
|
|
||||||
SizedBox(
|
|
||||||
width: double.infinity,
|
|
||||||
height: 56,
|
|
||||||
child: ElevatedButton.icon(
|
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
final resultado = estado.procesarVotacion();
|
final resultado = estado.procesarVotacion();
|
||||||
if (resultado != null) {
|
if (resultado != null) {
|
||||||
Navigator.pushReplacement(
|
Navigator.pushReplacement(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) =>
|
builder: (_) => PantallaResultado(resultado: resultado),
|
||||||
PantallaResultado(resultado: resultado),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.visibility),
|
|
||||||
label: Text(l10n.revealResult),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,21 +183,12 @@ class _PantallaVotacionClienteState extends State<PantallaVotacionCliente> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
SizedBox(
|
BotonFarolero.secundario(
|
||||||
width: double.infinity,
|
texto: l10n.votar,
|
||||||
height: 56,
|
icono: Icons.how_to_vote,
|
||||||
child: ElevatedButton.icon(
|
|
||||||
onPressed: _votacionCompleta
|
onPressed: _votacionCompleta
|
||||||
? () => widget.onVotos(Map.unmodifiable(_votosPorVotante))
|
? () => widget.onVotos(Map.unmodifiable(_votosPorVotante))
|
||||||
: null,
|
: null,
|
||||||
icon: const Icon(Icons.how_to_vote),
|
|
||||||
label: Text(l10n.votar),
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
backgroundColor: TemaApp.colorAcento,
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
textStyle: const TextStyle(fontSize: 16),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -232,16 +223,15 @@ class _PantallaVotacionClienteState extends State<PantallaVotacionCliente> {
|
|||||||
BuildContext context,
|
BuildContext context,
|
||||||
JugadorInicioPartida votante,
|
JugadorInicioPartida votante,
|
||||||
) {
|
) {
|
||||||
return Card(
|
return PanelFarolero(
|
||||||
color: TemaApp.colorSuperficie,
|
|
||||||
margin: const EdgeInsets.only(bottom: 16),
|
margin: const EdgeInsets.only(bottom: 16),
|
||||||
child: Padding(
|
padding: const EdgeInsets.all(14),
|
||||||
padding: const EdgeInsets.all(12),
|
borderColor: TemaApp.colorAcento.withValues(alpha: 0.48),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Voto de ${votante.nombre}',
|
AppLocalizations.of(context)!.voteOf(votante.nombre),
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
@@ -259,7 +249,6 @@ class _PantallaVotacionClienteState extends State<PantallaVotacionCliente> {
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,29 +258,10 @@ class _PantallaVotacionClienteState extends State<PantallaVotacionCliente> {
|
|||||||
required bool selected,
|
required bool selected,
|
||||||
required VoidCallback onTap,
|
required VoidCallback onTap,
|
||||||
}) {
|
}) {
|
||||||
return Card(
|
return SelectorVotoFarolero(
|
||||||
color: selected
|
nombre: '${index + 1}. ${jugador.nombre}',
|
||||||
? TemaApp.colorAcento.withValues(alpha: 0.3)
|
seleccionado: selected,
|
||||||
: TemaApp.colorTarjeta,
|
|
||||||
margin: const EdgeInsets.only(bottom: 8),
|
|
||||||
child: ListTile(
|
|
||||||
leading: CircleAvatar(
|
|
||||||
backgroundColor: selected
|
|
||||||
? TemaApp.colorAcento
|
|
||||||
: TemaApp.colorAcento.withValues(alpha: 0.3),
|
|
||||||
child: Text(
|
|
||||||
'${index + 1}',
|
|
||||||
style: TextStyle(
|
|
||||||
color: selected ? Colors.white : TemaApp.colorTexto,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
title: Text(jugador.nombre),
|
|
||||||
trailing: selected
|
|
||||||
? const Icon(Icons.check_circle, color: TemaApp.colorAcento)
|
|
||||||
: null,
|
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -335,6 +335,253 @@ class BotonFarolero extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TarjetaFaseFarolero extends StatelessWidget {
|
||||||
|
final IconData icono;
|
||||||
|
final String titulo;
|
||||||
|
final String? subtitulo;
|
||||||
|
final Color color;
|
||||||
|
final Widget child;
|
||||||
|
final EdgeInsetsGeometry padding;
|
||||||
|
|
||||||
|
const TarjetaFaseFarolero({
|
||||||
|
super.key,
|
||||||
|
required this.icono,
|
||||||
|
required this.titulo,
|
||||||
|
this.subtitulo,
|
||||||
|
this.color = TemaApp.colorNaranja,
|
||||||
|
this.child = const SizedBox.shrink(),
|
||||||
|
this.padding = const EdgeInsets.all(18),
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return PanelFarolero(
|
||||||
|
padding: padding,
|
||||||
|
borderColor: color.withValues(alpha: 0.48),
|
||||||
|
color: TemaApp.colorSuperficie.withValues(alpha: 0.84),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 54,
|
||||||
|
height: 54,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
gradient: RadialGradient(
|
||||||
|
colors: [
|
||||||
|
color.withValues(alpha: 0.42),
|
||||||
|
Colors.black.withValues(alpha: 0.62),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
border: Border.all(color: color.withValues(alpha: 0.72)),
|
||||||
|
),
|
||||||
|
child: Icon(icono, color: color, size: 30),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 14),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
titulo,
|
||||||
|
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||||
|
color: TemaApp.colorDorado,
|
||||||
|
fontWeight: FontWeight.w900,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (subtitulo != null) ...[
|
||||||
|
const SizedBox(height: 3),
|
||||||
|
Text(
|
||||||
|
subtitulo!,
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
|
color: TemaApp.colorTextoSecundario,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
child,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EstadoJugadorFarolero extends StatelessWidget {
|
||||||
|
final String nombre;
|
||||||
|
final bool destacado;
|
||||||
|
final bool completado;
|
||||||
|
final IconData icono;
|
||||||
|
final String? subtitulo;
|
||||||
|
final VoidCallback? onTap;
|
||||||
|
|
||||||
|
const EstadoJugadorFarolero({
|
||||||
|
super.key,
|
||||||
|
required this.nombre,
|
||||||
|
this.destacado = false,
|
||||||
|
this.completado = false,
|
||||||
|
this.icono = Icons.person,
|
||||||
|
this.subtitulo,
|
||||||
|
this.onTap,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final color = completado ? TemaApp.colorVerde : TemaApp.colorNaranja;
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 10),
|
||||||
|
child: Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: InkWell(
|
||||||
|
borderRadius: BorderRadius.circular(18),
|
||||||
|
onTap: onTap,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: completado
|
||||||
|
? TemaApp.colorVerde.withValues(alpha: 0.14)
|
||||||
|
: TemaApp.colorTarjeta.withValues(alpha: 0.84),
|
||||||
|
borderRadius: BorderRadius.circular(18),
|
||||||
|
border: Border.all(
|
||||||
|
color: destacado
|
||||||
|
? TemaApp.colorDorado.withValues(alpha: 0.72)
|
||||||
|
: color.withValues(alpha: completado ? 0.54 : 0.28),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 42,
|
||||||
|
height: 42,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
color: color.withValues(alpha: 0.16),
|
||||||
|
border: Border.all(color: color.withValues(alpha: 0.72)),
|
||||||
|
),
|
||||||
|
child: Icon(icono, color: color, size: 24),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
nombre,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||||
|
fontWeight: destacado ? FontWeight.w900 : FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (subtitulo != null) ...[
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
Text(
|
||||||
|
subtitulo!,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||||
|
color: TemaApp.colorTextoSecundario,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Icon(
|
||||||
|
completado ? Icons.check_circle : Icons.hourglass_bottom,
|
||||||
|
color: completado ? TemaApp.colorVerde : TemaApp.colorTextoSecundario,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SelectorVotoFarolero extends StatelessWidget {
|
||||||
|
final String nombre;
|
||||||
|
final bool seleccionado;
|
||||||
|
final VoidCallback onTap;
|
||||||
|
|
||||||
|
const SelectorVotoFarolero({
|
||||||
|
super.key,
|
||||||
|
required this.nombre,
|
||||||
|
required this.seleccionado,
|
||||||
|
required this.onTap,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return EstadoJugadorFarolero(
|
||||||
|
nombre: nombre,
|
||||||
|
destacado: seleccionado,
|
||||||
|
completado: seleccionado,
|
||||||
|
icono: seleccionado ? Icons.check : Icons.person_search,
|
||||||
|
onTap: onTap,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TemporizadorFarolero extends StatelessWidget {
|
||||||
|
final String etiqueta;
|
||||||
|
final String tiempo;
|
||||||
|
final bool agotado;
|
||||||
|
|
||||||
|
const TemporizadorFarolero({
|
||||||
|
super.key,
|
||||||
|
required this.etiqueta,
|
||||||
|
required this.tiempo,
|
||||||
|
this.agotado = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final color = agotado ? TemaApp.colorAcento : TemaApp.colorNaranja;
|
||||||
|
return PanelFarolero(
|
||||||
|
padding: const EdgeInsets.all(22),
|
||||||
|
borderColor: color.withValues(alpha: 0.62),
|
||||||
|
color: color.withValues(alpha: agotado ? 0.18 : 0.10),
|
||||||
|
child: Stack(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
children: [
|
||||||
|
Image.asset(
|
||||||
|
'assets/ui/generated/gameplay/gameplay_phase_emblem.webp',
|
||||||
|
height: 132,
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
opacity: const AlwaysStoppedAnimation(0.34),
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
etiqueta,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
tiempo,
|
||||||
|
style: Theme.of(context).textTheme.displaySmall?.copyWith(
|
||||||
|
color: color,
|
||||||
|
fontWeight: FontWeight.w900,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class MarcoBotonFaroleroPainter extends CustomPainter {
|
class MarcoBotonFaroleroPainter extends CustomPainter {
|
||||||
final LinearGradient gradient;
|
final LinearGradient gradient;
|
||||||
final bool destacado;
|
final bool destacado;
|
||||||
|
|||||||
Reference in New Issue
Block a user