From d15ef31b9576fd0a90ee36e7e1c3cc6d8f95aab9 Mon Sep 17 00:00:00 2001 From: Mikael de Verdier Date: Tue, 25 Aug 2026 00:00:27 +0200 Subject: [PATCH 1/9] improved submissionsBarChart to always show only endpoints regardless of transformation; minor improvements --- .../enclose_moose_level_page.dart | 26 ++++++++++++------- .../helper_widgets/submissions_bar_chart.dart | 20 +++++++++----- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/lib/screens/games/enclose_moose/enclose_moose_level_page.dart b/lib/screens/games/enclose_moose/enclose_moose_level_page.dart index e1a68159..78891993 100644 --- a/lib/screens/games/enclose_moose/enclose_moose_level_page.dart +++ b/lib/screens/games/enclose_moose/enclose_moose_level_page.dart @@ -677,21 +677,27 @@ class _EncloseMooseLevelState extends State with TickerPr void _tapTile(EncloseGridTile tile) async { /* // Useful for debug! - final builder = EncloseMooseLevelReadBuilder(); - builder.levelId = 10; - builder.nameSv = "debug"; - builder.nameEn = "debug"; - builder.encodedGrid = ""; - builder.wallBudget = 10; + final builder = _usedLevel.toBuilder(); + builder.optimalScore = 45; + builder.optimalSolution = SetBuilder(); + builder.optimalIsUnique = true; + builder.scoreDistribution = MapBuilder({ + "1": 3, + "2": 1, + "17": 2, + "22": 1, + "41": 3, + "45": 4 + }); builder.playerSubmission = EncloseMooseSubmissionReadBuilder(); - builder.playerSubmission.levelId = 10; + builder.playerSubmission.levelId = _usedLevel.levelId; builder.playerSubmission.submissionTime = DateTime.now(); builder.playerSubmission.playerId = 0; - builder.playerSubmission.playerScore = 10; - builder.releaseDate = Date.now(); - builder.optimalScore = 54; + builder.playerSubmission.playerScore = 45; _usedLevel = builder.build(); + + showDialog(context: context, builder: _buildSubmitDialog()); */ if (_grid.wallsLeft == 0 && tile.isGrass) { diff --git a/lib/screens/games/enclose_moose/helper_widgets/submissions_bar_chart.dart b/lib/screens/games/enclose_moose/helper_widgets/submissions_bar_chart.dart index 7c4df20b..cef391c2 100644 --- a/lib/screens/games/enclose_moose/helper_widgets/submissions_bar_chart.dart +++ b/lib/screens/games/enclose_moose/helper_widgets/submissions_bar_chart.dart @@ -68,10 +68,15 @@ class _SubmissionsBarChartState extends State with SingleTi ]), builder: (context, child) { - final scale = _chartTransformationController.value.getMaxScaleOnAxis(); + final transformationMatrix = _chartTransformationController.value; + final scale = transformationMatrix.getMaxScaleOnAxis(); + final translation = transformationMatrix.getTranslation().x.abs(); + final barWidth = scale * (constraints.maxWidth * 0.7 - 75) / amountBars; final currentAlpha = (255 * _tooltipAnimationController.value).toInt(); + final amountShownBars = amountBars / scale; + return BarChart( BarChartData( borderData: FlBorderData(show: false), @@ -126,13 +131,14 @@ class _SubmissionsBarChartState extends State with SingleTi ), sideTitles: SideTitles( showTitles: true, - interval: scale == 1 ? 1 : amountBars / scale, + // interval: scale == 1 ? 1 : amountBars / scale, + interval: 1, reservedSize: 28, - getTitlesWidget: (value, meta) { - if (scale == 1 && value != minScore && value != widget.optimalScore) return const SizedBox.shrink(); // Because the axis is categorical we can't use interval and instead have to use this - - final usedInterval = amountBars ~/ scale; // Evenly space labels so that at least one is always showing - if ((value.toInt() - minScore) % usedInterval != 0 && value != minScore && value != widget.optimalScore) return const SizedBox.shrink(); + getTitlesWidget: (value, meta) { // Why is meta.min == 0 and meta.max == 1 always? They have the tools to calculate the max and min (they do it because they only call getTitlesWidget for bars that are in frame...) + final barsTranslated = (amountBars / (meta.parentAxisSize / translation)); // Don't really understand why meta.parentAxisSize != constraints.maxWidth cause then this would just be translation / barWidth + final minShown = (minScore + barsTranslated).roundToDouble(); // This should maybe be a ceil because sometimes this one is out of frame but it's so ugly! + final maxShown = (minScore + barsTranslated + amountShownBars - 1).roundToDouble(); // Same thing here but with floor. + if (value != minShown && value != maxShown) return const SizedBox.shrink(); return SideTitleWidget( space: 5, From 8b719cb02aab24852a4e73445b4fc61b399c7f5f Mon Sep 17 00:00:00 2001 From: Mikael de Verdier Date: Tue, 25 Aug 2026 01:21:55 +0200 Subject: [PATCH 2/9] localized enclose.moose --- lib/l10n/app_en.arb | 30 +++- lib/l10n/app_localizations.dart | 156 ++++++++++++++++++ lib/l10n/app_localizations_en.dart | 81 +++++++++ lib/l10n/app_localizations_sv.dart | 80 +++++++++ lib/l10n/app_sv.arb | 30 +++- .../enclose_moose_level_page.dart | 79 ++++----- .../helper_widgets/submissions_bar_chart.dart | 17 +- 7 files changed, 425 insertions(+), 48 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index a3bcd8fe..62c7576e 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -565,6 +565,32 @@ "missions": "MISSIONS", "unlimited": "Unlimited", "eventNoSignup": "No signup required", - "eventHasLottery": "Spots decided by lottery" - + "eventHasLottery": "Spots decided by lottery", + + "encloseDay": "Day", + "encloseBonus": "Bonus", + "encloseWalls": "Walls", + "encloseSubmit": "Submit", + "encloseScore": "Score", + "encloseOptimal": "Optimal", + "encloseYourSolution": "Your solution", + "encloseYourBest": "Your best", + "encloseIfEnclosed": "if in enclosure", + "enclosePreviousDays": "Previous days", + "encloseBonusLevels": "Bonus levels", + "encloseHowToPlay": "How to play", + "encloseInstruction": "The objective is to build an enclosure for the moose by placing walls (tapping) on the grid. The moose can not move over the water or diagonally. The more grass tiles in your enclosure, the higher your score. You only have a limited amount of walls so use them wisely", + "enclosePerfect": "PERFECT!!!", + "enclosePrettyGood": "Pretty good!", + "encloseNotBad": "Not bad!", + "encloseNotTheWorst": "I've seen worse!", + "encloseComeOn": "Come on...", + "encloseBetterThan": "You scored as good or better than", + "enclosePercentOfPlayers": "% of players", + "encloseYourScore": "Your score", + "encloseSubmitErrorTitle": "A problem occurred with your submission", + "encloseSubmitErrorText": "Please try again later\n\nThe reason was", + "encloseOptimalScore": "Optimal score", + "encloseOccurrences": "Occurrences", + "encloseOccurrence": "Occurrence" } diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index c346dbdc..bb1f35a1 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -3187,6 +3187,162 @@ abstract class AppLocalizations { /// In sv, this message translates to: /// **'Platser lottas'** String get eventHasLottery; + + /// No description provided for @encloseDay. + /// + /// In sv, this message translates to: + /// **'Dag'** + String get encloseDay; + + /// No description provided for @encloseBonus. + /// + /// In sv, this message translates to: + /// **'Bonus'** + String get encloseBonus; + + /// No description provided for @encloseWalls. + /// + /// In sv, this message translates to: + /// **'Väggar'** + String get encloseWalls; + + /// No description provided for @encloseSubmit. + /// + /// In sv, this message translates to: + /// **'Skicka in'** + String get encloseSubmit; + + /// No description provided for @encloseScore. + /// + /// In sv, this message translates to: + /// **'Poäng'** + String get encloseScore; + + /// No description provided for @encloseOptimal. + /// + /// In sv, this message translates to: + /// **'Optimal'** + String get encloseOptimal; + + /// No description provided for @encloseYourSolution. + /// + /// In sv, this message translates to: + /// **'Din lösning'** + String get encloseYourSolution; + + /// No description provided for @encloseYourBest. + /// + /// In sv, this message translates to: + /// **'Ditt bästa'** + String get encloseYourBest; + + /// No description provided for @encloseIfEnclosed. + /// + /// In sv, this message translates to: + /// **'om i hagen'** + String get encloseIfEnclosed; + + /// No description provided for @enclosePreviousDays. + /// + /// In sv, this message translates to: + /// **'Tidigare dagar'** + String get enclosePreviousDays; + + /// No description provided for @encloseBonusLevels. + /// + /// In sv, this message translates to: + /// **'Bonusnivåer'** + String get encloseBonusLevels; + + /// No description provided for @encloseHowToPlay. + /// + /// In sv, this message translates to: + /// **'Hur man spelar'** + String get encloseHowToPlay; + + /// No description provided for @encloseInstruction. + /// + /// In sv, this message translates to: + /// **'Målet är att bygga en så stor hage som möjligt åt älgen genom att placera väggar (klicka) i rutnätet. Älgen kan inte röra sig över vatten eller diagonalt. Ju mer gräs i din hage, desto högre din poäng. Du har ett begränsat antal väggar så använd dem vist'** + String get encloseInstruction; + + /// No description provided for @enclosePerfect. + /// + /// In sv, this message translates to: + /// **'PERFEKT!!!'** + String get enclosePerfect; + + /// No description provided for @enclosePrettyGood. + /// + /// In sv, this message translates to: + /// **'Ganska bra!'** + String get enclosePrettyGood; + + /// No description provided for @encloseNotBad. + /// + /// In sv, this message translates to: + /// **'Inte illa!'** + String get encloseNotBad; + + /// No description provided for @encloseNotTheWorst. + /// + /// In sv, this message translates to: + /// **'Jag har sett värre!'** + String get encloseNotTheWorst; + + /// No description provided for @encloseComeOn. + /// + /// In sv, this message translates to: + /// **'Kom igen...'** + String get encloseComeOn; + + /// No description provided for @encloseBetterThan. + /// + /// In sv, this message translates to: + /// **'Du fick lika bra eller bättre än'** + String get encloseBetterThan; + + /// No description provided for @enclosePercentOfPlayers. + /// + /// In sv, this message translates to: + /// **'% av spelare'** + String get enclosePercentOfPlayers; + + /// No description provided for @encloseYourScore. + /// + /// In sv, this message translates to: + /// **'Din poäng'** + String get encloseYourScore; + + /// No description provided for @encloseSubmitErrorTitle. + /// + /// In sv, this message translates to: + /// **'Ett problem uppstod med att skicka in ditt svar'** + String get encloseSubmitErrorTitle; + + /// No description provided for @encloseSubmitErrorText. + /// + /// In sv, this message translates to: + /// **'Försök igen senare\n\nAnledningen var'** + String get encloseSubmitErrorText; + + /// No description provided for @encloseOptimalScore. + /// + /// In sv, this message translates to: + /// **'Optimal poäng'** + String get encloseOptimalScore; + + /// No description provided for @encloseOccurrences. + /// + /// In sv, this message translates to: + /// **'Förekomster'** + String get encloseOccurrences; + + /// No description provided for @encloseOccurrence. + /// + /// In sv, this message translates to: + /// **'Förekomst'** + String get encloseOccurrence; } class _AppLocalizationsDelegate diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 54b14ccd..0c2126be 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -1693,4 +1693,85 @@ class AppLocalizationsEn extends AppLocalizations { @override String get eventHasLottery => 'Spots decided by lottery'; + + @override + String get encloseDay => 'Day'; + + @override + String get encloseBonus => 'Bonus'; + + @override + String get encloseWalls => 'Walls'; + + @override + String get encloseSubmit => 'Submit'; + + @override + String get encloseScore => 'Score'; + + @override + String get encloseOptimal => 'Optimal'; + + @override + String get encloseYourSolution => 'Your solution'; + + @override + String get encloseYourBest => 'Your best'; + + @override + String get encloseIfEnclosed => 'if in enclosure'; + + @override + String get enclosePreviousDays => 'Previous days'; + + @override + String get encloseBonusLevels => 'Bonus levels'; + + @override + String get encloseHowToPlay => 'How to play'; + + @override + String get encloseInstruction => + 'The objective is to build an enclosure for the moose by placing walls (tapping) on the grid. The moose can not move over the water or diagonally. The more grass tiles in your enclosure, the higher your score. You only have a limited amount of walls so use them wisely'; + + @override + String get enclosePerfect => 'PERFECT!!!'; + + @override + String get enclosePrettyGood => 'Pretty good!'; + + @override + String get encloseNotBad => 'Not bad!'; + + @override + String get encloseNotTheWorst => 'I\'ve seen worse!'; + + @override + String get encloseComeOn => 'Come on...'; + + @override + String get encloseBetterThan => 'You scored as good or better than'; + + @override + String get enclosePercentOfPlayers => '% of players'; + + @override + String get encloseYourScore => 'Your score'; + + @override + String get encloseSubmitErrorTitle => + 'A problem occurred with your submission'; + + @override + String get encloseSubmitErrorText => + 'Please try again later\n\nThe reason was'; + + @override + String get encloseOptimalScore => 'Optimal score'; + + @override + String get encloseOccurrences => 'Occurrences'; + + @override + String get encloseOccurrence => 'Occurrence'; } diff --git a/lib/l10n/app_localizations_sv.dart b/lib/l10n/app_localizations_sv.dart index 41fc64a0..9f34dee3 100644 --- a/lib/l10n/app_localizations_sv.dart +++ b/lib/l10n/app_localizations_sv.dart @@ -1683,4 +1683,84 @@ class AppLocalizationsSv extends AppLocalizations { @override String get eventHasLottery => 'Platser lottas'; + + @override + String get encloseDay => 'Dag'; + + @override + String get encloseBonus => 'Bonus'; + + @override + String get encloseWalls => 'Väggar'; + + @override + String get encloseSubmit => 'Skicka in'; + + @override + String get encloseScore => 'Poäng'; + + @override + String get encloseOptimal => 'Optimal'; + + @override + String get encloseYourSolution => 'Din lösning'; + + @override + String get encloseYourBest => 'Ditt bästa'; + + @override + String get encloseIfEnclosed => 'om i hagen'; + + @override + String get enclosePreviousDays => 'Tidigare dagar'; + + @override + String get encloseBonusLevels => 'Bonusnivåer'; + + @override + String get encloseHowToPlay => 'Hur man spelar'; + + @override + String get encloseInstruction => + 'Målet är att bygga en så stor hage som möjligt åt älgen genom att placera väggar (klicka) i rutnätet. Älgen kan inte röra sig över vatten eller diagonalt. Ju mer gräs i din hage, desto högre din poäng. Du har ett begränsat antal väggar så använd dem vist'; + + @override + String get enclosePerfect => 'PERFEKT!!!'; + + @override + String get enclosePrettyGood => 'Ganska bra!'; + + @override + String get encloseNotBad => 'Inte illa!'; + + @override + String get encloseNotTheWorst => 'Jag har sett värre!'; + + @override + String get encloseComeOn => 'Kom igen...'; + + @override + String get encloseBetterThan => 'Du fick lika bra eller bättre än'; + + @override + String get enclosePercentOfPlayers => '% av spelare'; + + @override + String get encloseYourScore => 'Din poäng'; + + @override + String get encloseSubmitErrorTitle => + 'Ett problem uppstod med att skicka in ditt svar'; + + @override + String get encloseSubmitErrorText => 'Försök igen senare\n\nAnledningen var'; + + @override + String get encloseOptimalScore => 'Optimal poäng'; + + @override + String get encloseOccurrences => 'Förekomster'; + + @override + String get encloseOccurrence => 'Förekomst'; } diff --git a/lib/l10n/app_sv.arb b/lib/l10n/app_sv.arb index df351f45..bcc630f3 100644 --- a/lib/l10n/app_sv.arb +++ b/lib/l10n/app_sv.arb @@ -567,6 +567,32 @@ "missions": "UPPDRAG", "unlimited": "Oändligt", "eventNoSignup": "Ingen anmälan behövs", - "eventHasLottery": "Platser lottas" - + "eventHasLottery": "Platser lottas", + + "encloseDay": "Dag", + "encloseBonus": "Bonus", + "encloseWalls": "Väggar", + "encloseSubmit": "Skicka in", + "encloseScore": "Poäng", + "encloseOptimal": "Optimal", + "encloseYourSolution": "Din lösning", + "encloseYourBest": "Ditt bästa", + "encloseIfEnclosed": "om i hagen", + "enclosePreviousDays": "Tidigare dagar", + "encloseBonusLevels": "Bonusnivåer", + "encloseHowToPlay": "Hur man spelar", + "encloseInstruction": "Målet är att bygga en så stor hage som möjligt åt älgen genom att placera väggar (klicka) i rutnätet. Älgen kan inte röra sig över vatten eller diagonalt. Ju mer gräs i din hage, desto högre din poäng. Du har ett begränsat antal väggar så använd dem vist", + "enclosePerfect": "PERFEKT!!!", + "enclosePrettyGood": "Ganska bra!", + "encloseNotBad": "Inte illa!", + "encloseNotTheWorst": "Jag har sett värre!", + "encloseComeOn": "Kom igen...", + "encloseBetterThan": "Du fick lika bra eller bättre än", + "enclosePercentOfPlayers": "% av spelare", + "encloseYourScore": "Din poäng", + "encloseSubmitErrorTitle": "Ett problem uppstod med att skicka in ditt svar", + "encloseSubmitErrorText": "Försök igen senare\n\nAnledningen var", + "encloseOptimalScore": "Optimal poäng", + "encloseOccurrences": "Förekomster", + "encloseOccurrence": "Förekomst" } diff --git a/lib/screens/games/enclose_moose/enclose_moose_level_page.dart b/lib/screens/games/enclose_moose/enclose_moose_level_page.dart index 78891993..63b4aae4 100644 --- a/lib/screens/games/enclose_moose/enclose_moose_level_page.dart +++ b/lib/screens/games/enclose_moose/enclose_moose_level_page.dart @@ -161,7 +161,7 @@ class _EncloseMooseLevelState extends State with TickerPr WigglingWidget( controller: _idleController, child: OutlinedText( - text: _usedLevel.dayIndex != null ? "Day ${_usedLevel.dayIndex}" : "Bonus", + text: _usedLevel.dayIndex != null ? "${t.encloseDay} ${_usedLevel.dayIndex}" : t.encloseBonus, style: const TextStyle( color: Colors.white, fontSize: 25, @@ -503,7 +503,7 @@ class _EncloseMooseLevelState extends State with TickerPr child: HighlightedText( showHighlight: (_openCallCounter.getCount("walls") ?? 0) != 0, child: OutlinedText( - text: "Walls: ${_grid.wallsLeft}/${_grid.wallBudget}", + text: "${t.encloseWalls}: ${_grid.wallsLeft}/${_grid.wallBudget}", style: const TextStyle( fontSize: 25, fontFamily: "Schoolbell" @@ -527,9 +527,9 @@ class _EncloseMooseLevelState extends State with TickerPr ) ), onPressed: _submitSolution, - child: const OutlinedText( - text: "Submit", - style: TextStyle( + child: OutlinedText( + text: t.encloseSubmit, + style: const TextStyle( color: Colors.white, fontSize: 25, fontFamily: "Schoolbell" @@ -547,7 +547,7 @@ class _EncloseMooseLevelState extends State with TickerPr child: HighlightedText( showHighlight: (_openCallCounter.getCount("score") ?? 0) != 0, child: OutlinedText( - text: "Score: ${_grid.score ?? "N/A"}", + text: "${t.encloseScore}: ${_grid.score ?? "N/A"}", style: const TextStyle( fontSize: 25, fontFamily: "Schoolbell" @@ -577,7 +577,7 @@ class _EncloseMooseLevelState extends State with TickerPr visualDensity: VisualDensity.compact ), label: OutlinedText( - text: "Optimal: ${_usedLevel.optimalScore}", + text: "${t.encloseOptimal}: ${_usedLevel.optimalScore}", style: const TextStyle( // color: Colors.white, fontSize: 20, @@ -605,7 +605,7 @@ class _EncloseMooseLevelState extends State with TickerPr visualDensity: VisualDensity.compact ), label: OutlinedText( - text: _hasSubmitted ? "Your solution: ${_usedLevel.playerSubmission!.playerScore}" : "Your best: $_bestSolutionScore", + text: _hasSubmitted ? "${t.encloseYourSolution}: ${_usedLevel.playerSubmission!.playerScore}" : "${t.encloseYourBest}: $_bestSolutionScore", style: const TextStyle( // color: Colors.white, fontSize: 20, @@ -740,7 +740,8 @@ class _EncloseMooseLevelState extends State with TickerPr if (tile.isBonus) { final bonusScore = tile.bonusScore; if (bonusScore != 0) { - _tooltipCallCounter.increment(tile, (bonusScore > 0 ? "+" : "") + "$bonusScore if enclosed"); + final t = AppLocalizations.of(context)!; + _tooltipCallCounter.increment(tile, (bonusScore > 0 ? "+" : "") + "$bonusScore ${t.encloseIfEnclosed}"); } } } @@ -820,10 +821,10 @@ class _EncloseMooseLevelState extends State with TickerPr Column( children: [ if (_dailies.isNotEmpty) - const Text( - "Previous days", + Text( + t.enclosePreviousDays, textAlign: TextAlign.center, - style: TextStyle( + style: const TextStyle( fontSize: 25, fontFamily: "Schoolbell" ) @@ -840,12 +841,10 @@ class _EncloseMooseLevelState extends State with TickerPr title: Text.rich( TextSpan( children: [ - TextSpan( - text: "Day ${level.dayIndex}" - ), + TextSpan(text: "${t.encloseDay} ${level.dayIndex}"), TextSpan( - text: " (${Time.format(level.releaseDate.toDateTime(), "%d %M %Y", locale: "en")})", + text: " (${Time.format(level.releaseDate.toDateTime(), "%d %M %Y", locale: t.localeName)})", style: TextStyle( color: Theme.of(context).primaryColor ) @@ -871,10 +870,10 @@ class _EncloseMooseLevelState extends State with TickerPr Column( children: [ if (_nonDailies.isNotEmpty) - const Text( - "Bonus levels", + Text( + t.encloseBonusLevels, textAlign: TextAlign.center, - style: TextStyle( + style: const TextStyle( fontSize: 25, fontFamily: "Schoolbell" ) @@ -912,20 +911,22 @@ class _EncloseMooseLevelState extends State with TickerPr } Widget Function(BuildContext) _buildHelpDialog() { - return (context) => const SimpleDialog( + final t = AppLocalizations.of(context)!; + + return (context) => SimpleDialog( contentPadding: const EdgeInsets.all(16), title: Text( - "How to play", + t.encloseHowToPlay, textAlign: TextAlign.center, - style: TextStyle( + style: const TextStyle( fontSize: 25, fontFamily: "Schoolbell" ) ), children: [ Text( - "The objective is to build an enclosure for the moose by placing walls (tapping) on the grid. The moose can not move over the water. The more grass tiles in your enclosure, the higher your score. You only have a limited amount of walls so use them wisely.", - style: TextStyle( + t.encloseInstruction, + style: const TextStyle( fontSize: 18, fontFamily: "Schoolbell" ) @@ -935,6 +936,8 @@ class _EncloseMooseLevelState extends State with TickerPr } Widget Function(BuildContext) _buildSubmitDialog() { + final t = AppLocalizations.of(context)!; + final Map scoreDistribution = {}; for (final entry in _usedLevel.scoreDistribution!.entries) { scoreDistribution[int.parse(entry.key)] = entry.value; @@ -960,15 +963,15 @@ class _EncloseMooseLevelState extends State with TickerPr String grade; if (_usedLevel.playerSubmission!.playerScore == _usedLevel.optimalScore) { - grade = "PERFECT!!! 💎"; + grade = "${t.enclosePerfect} 💎"; } else if (percentile >= 0.75) { - grade = "Pretty good! ✅"; + grade = "${t.enclosePrettyGood} ✅"; } else if (percentile >= 0.5) { - grade = "Not bad! ✅"; + grade = "${t.encloseNotBad} ✅"; } else if (percentile >= 0.25) { - grade = "Not the worst! ✅"; + grade = "${t.encloseNotTheWorst} ✅"; } else { - grade = "Come on... ✅"; + grade = "${t.encloseComeOn} ✅"; } return (context) => SimpleDialog( @@ -993,7 +996,7 @@ class _EncloseMooseLevelState extends State with TickerPr TextSpan( children: [ TextSpan( - text: "You scored as good or better than ", + text: "${t.encloseBetterThan} ", style: const TextStyle( fontSize: 20, fontFamily: "Schoolbell" @@ -1010,7 +1013,7 @@ class _EncloseMooseLevelState extends State with TickerPr ), TextSpan( - text: "% of players", + text: t.enclosePercentOfPlayers, style: const TextStyle( fontSize: 20, fontFamily: "Schoolbell" @@ -1025,7 +1028,7 @@ class _EncloseMooseLevelState extends State with TickerPr TextSpan( children: [ TextSpan( - text: "Your score: ", + text: "${t.encloseYourScore}: ", style: const TextStyle( fontSize: 20, fontFamily: "Schoolbell" @@ -1049,7 +1052,7 @@ class _EncloseMooseLevelState extends State with TickerPr TextSpan( children: [ TextSpan( - text: "Optimal: ", + text: "${t.encloseOptimalScore}: ", style: const TextStyle( fontSize: 20, fontFamily: "Schoolbell" @@ -1086,19 +1089,21 @@ class _EncloseMooseLevelState extends State with TickerPr } Widget Function(BuildContext) _buildSubmitErrorDialog(String errorMessage) { + final t = AppLocalizations.of(context)!; + return (context) => SimpleDialog( contentPadding: const EdgeInsets.all(16), - title: const Text( - "There was an error with your submission", + title: Text( + t.encloseSubmitErrorTitle, textAlign: TextAlign.center, - style: TextStyle( + style: const TextStyle( fontSize: 25, fontFamily: "Schoolbell" ) ), children: [ Text( - "Please try again later.\n\nResponse was: \"$errorMessage\"", + "${t.encloseSubmitErrorText} \"$errorMessage\"", style: const TextStyle( fontSize: 18, fontFamily: "Schoolbell" diff --git a/lib/screens/games/enclose_moose/helper_widgets/submissions_bar_chart.dart b/lib/screens/games/enclose_moose/helper_widgets/submissions_bar_chart.dart index cef391c2..94b89072 100644 --- a/lib/screens/games/enclose_moose/helper_widgets/submissions_bar_chart.dart +++ b/lib/screens/games/enclose_moose/helper_widgets/submissions_bar_chart.dart @@ -1,6 +1,7 @@ import "dart:math" as math; import "package:flutter/material.dart"; import "package:fl_chart/fl_chart.dart"; +import "package:fsek_mobile/l10n/app_localizations.dart"; class SubmissionsBarChart extends StatefulWidget { const SubmissionsBarChart({ @@ -52,6 +53,8 @@ class _SubmissionsBarChartState extends State with SingleTi @override Widget build(BuildContext context) { + final t = AppLocalizations.of(context)!; + final barColorDict = { widget.playerScore: Theme.of(context).primaryColor, // A bit weird on themeN where primaryColor is green widget.optimalScore: Colors.green[800] @@ -93,7 +96,7 @@ class _SubmissionsBarChartState extends State with SingleTi getTooltipColor: (group) => (barColorDict[group.x] ?? defaultBarColor).withAlpha(currentAlpha), getTooltipItem: (group, groupIndex, rod, rodIndex) { return BarTooltipItem( - "Score: ${entries[groupIndex].key}\nOccurrences: ${rod.toY.toInt()}", + "${t.encloseScore}: ${entries[groupIndex].key}\n${t.encloseOccurrences}: ${rod.toY.toInt()}", TextStyle( color: Colors.white.withAlpha(currentAlpha), fontSize: 18, @@ -122,9 +125,9 @@ class _SubmissionsBarChartState extends State with SingleTi ), bottomTitles: AxisTitles( axisNameSize: 30, - axisNameWidget: const Text( - "Score", - style: TextStyle( + axisNameWidget: Text( + t.encloseScore, + style: const TextStyle( fontSize: 20, fontFamily: "Schoolbell" ) @@ -156,9 +159,9 @@ class _SubmissionsBarChartState extends State with SingleTi ), leftTitles: AxisTitles( axisNameSize: 30, - axisNameWidget: const Text( - "Occurrence", - style: TextStyle( + axisNameWidget: Text( + t.encloseOccurrence, + style: const TextStyle( fontSize: 20, fontFamily: "Schoolbell" ) From 4d0a50887093d11daf07d59e642bf4407f9b8819 Mon Sep 17 00:00:00 2001 From: Mikael de Verdier Date: Fri, 28 Aug 2026 01:24:36 +0200 Subject: [PATCH 3/9] =?UTF-8?q?fixed=20one=20voiceline;=20changed=20transl?= =?UTF-8?q?ation=20of=20walls=20from=20v=C3=A4ggar=20to=20murar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/l10n/app_localizations.dart | 4 ++-- lib/l10n/app_localizations_sv.dart | 4 ++-- lib/l10n/app_sv.arb | 4 ++-- lib/screens/games/enclose_moose/asset_handler.dart | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index bb1f35a1..d0c22d1d 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -3203,7 +3203,7 @@ abstract class AppLocalizations { /// No description provided for @encloseWalls. /// /// In sv, this message translates to: - /// **'Väggar'** + /// **'Murar'** String get encloseWalls; /// No description provided for @encloseSubmit. @@ -3263,7 +3263,7 @@ abstract class AppLocalizations { /// No description provided for @encloseInstruction. /// /// In sv, this message translates to: - /// **'Målet är att bygga en så stor hage som möjligt åt älgen genom att placera väggar (klicka) i rutnätet. Älgen kan inte röra sig över vatten eller diagonalt. Ju mer gräs i din hage, desto högre din poäng. Du har ett begränsat antal väggar så använd dem vist'** + /// **'Målet är att bygga en så stor hage som möjligt åt älgen genom att placera murar (klicka) i rutnätet. Älgen kan inte röra sig över vatten eller diagonalt. Ju mer gräs i din hage, desto högre din poäng. Du har ett begränsat antal murar så använd dem vist'** String get encloseInstruction; /// No description provided for @enclosePerfect. diff --git a/lib/l10n/app_localizations_sv.dart b/lib/l10n/app_localizations_sv.dart index 9f34dee3..1716d76e 100644 --- a/lib/l10n/app_localizations_sv.dart +++ b/lib/l10n/app_localizations_sv.dart @@ -1691,7 +1691,7 @@ class AppLocalizationsSv extends AppLocalizations { String get encloseBonus => 'Bonus'; @override - String get encloseWalls => 'Väggar'; + String get encloseWalls => 'Murar'; @override String get encloseSubmit => 'Skicka in'; @@ -1722,7 +1722,7 @@ class AppLocalizationsSv extends AppLocalizations { @override String get encloseInstruction => - 'Målet är att bygga en så stor hage som möjligt åt älgen genom att placera väggar (klicka) i rutnätet. Älgen kan inte röra sig över vatten eller diagonalt. Ju mer gräs i din hage, desto högre din poäng. Du har ett begränsat antal väggar så använd dem vist'; + 'Målet är att bygga en så stor hage som möjligt åt älgen genom att placera murar (klicka) i rutnätet. Älgen kan inte röra sig över vatten eller diagonalt. Ju mer gräs i din hage, desto högre din poäng. Du har ett begränsat antal murar så använd dem vist'; @override String get enclosePerfect => 'PERFEKT!!!'; diff --git a/lib/l10n/app_sv.arb b/lib/l10n/app_sv.arb index bcc630f3..b29d0bba 100644 --- a/lib/l10n/app_sv.arb +++ b/lib/l10n/app_sv.arb @@ -571,7 +571,7 @@ "encloseDay": "Dag", "encloseBonus": "Bonus", - "encloseWalls": "Väggar", + "encloseWalls": "Murar", "encloseSubmit": "Skicka in", "encloseScore": "Poäng", "encloseOptimal": "Optimal", @@ -581,7 +581,7 @@ "enclosePreviousDays": "Tidigare dagar", "encloseBonusLevels": "Bonusnivåer", "encloseHowToPlay": "Hur man spelar", - "encloseInstruction": "Målet är att bygga en så stor hage som möjligt åt älgen genom att placera väggar (klicka) i rutnätet. Älgen kan inte röra sig över vatten eller diagonalt. Ju mer gräs i din hage, desto högre din poäng. Du har ett begränsat antal väggar så använd dem vist", + "encloseInstruction": "Målet är att bygga en så stor hage som möjligt åt älgen genom att placera murar (klicka) i rutnätet. Älgen kan inte röra sig över vatten eller diagonalt. Ju mer gräs i din hage, desto högre din poäng. Du har ett begränsat antal murar så använd dem vist", "enclosePerfect": "PERFEKT!!!", "enclosePrettyGood": "Ganska bra!", "encloseNotBad": "Inte illa!", diff --git a/lib/screens/games/enclose_moose/asset_handler.dart b/lib/screens/games/enclose_moose/asset_handler.dart index c0fe00c1..bc68494e 100644 --- a/lib/screens/games/enclose_moose/asset_handler.dart +++ b/lib/screens/games/enclose_moose/asset_handler.dart @@ -235,7 +235,7 @@ class AssetHandler { ("I'll sneak away like sooo... Moohoho", "${baseAudioPath}sneak_away_like_so.mp3"), ("I'll sneak away like sooo... Moohoho", "${baseAudioPath}sneak_away_like_so.mp3"), ("I will first go THIS way and then I will go THAT way and then I'm free!", "${baseAudioPath}this_way_that_way_2.mp3"), - ("I will go THIS way and then I will go THAT way and then I'm gonna be free!", "${baseAudioPath}this_way_that_way.mp3"), + ("I will go THIS way and then I will go THAT way and then I will be free!", "${baseAudioPath}this_way_that_way.mp3"), ("You can't enclose me, I'm a moose!", "${baseAudioPath}you_cant_enclose_me.mp3") ]; const enclosedVoicelines = [ From 2f0a6b74c2d197b7073891e2de8ee79cdeac8fad Mon Sep 17 00:00:00 2001 From: Mikael de Verdier Date: Fri, 28 Aug 2026 01:37:13 +0200 Subject: [PATCH 4/9] removed border (grid lines) from water tiles; made grid lines slightly more visible (but thinner) --- .../games/enclose_moose/enclose_moose_level_page.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/screens/games/enclose_moose/enclose_moose_level_page.dart b/lib/screens/games/enclose_moose/enclose_moose_level_page.dart index 63b4aae4..035375d6 100644 --- a/lib/screens/games/enclose_moose/enclose_moose_level_page.dart +++ b/lib/screens/games/enclose_moose/enclose_moose_level_page.dart @@ -322,9 +322,9 @@ class _EncloseMooseLevelState extends State with TickerPr return Container( decoration: BoxDecoration( - border: Border.all( - color: Colors.green[900]!, - width: cellSize / 100 + border: tile.isWater ? null : Border.all( + color: const Color.fromARGB(255, 36, 124, 42), + width: 0, // thinnest possible // cellSize / 100 // Would prefer this to depend on cellSize but looks weird for a nonzero value next to water ) ), child: OverflowBox( From ebaab82d7c2a8db95a3384701f194eb0878542a6 Mon Sep 17 00:00:00 2001 From: Mikael de Verdier Date: Sun, 30 Aug 2026 01:22:23 +0200 Subject: [PATCH 5/9] doubled forwards animationduration for wall --- lib/screens/games/enclose_moose/tile_widget.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/screens/games/enclose_moose/tile_widget.dart b/lib/screens/games/enclose_moose/tile_widget.dart index 572e0bbb..d75ab585 100644 --- a/lib/screens/games/enclose_moose/tile_widget.dart +++ b/lib/screens/games/enclose_moose/tile_widget.dart @@ -101,7 +101,8 @@ class TileWidget extends StatelessWidget { vsync: vsync, shouldAnimate: tile.type == EncloseGridCellType.wall, animationFrames: AssetHandler.getAnimationFrames(EncloseGridCellType.wall), - animationReverseFrameDuration: const Duration(milliseconds: 20), + animationFrameDuration: _wheatFrameDuration, + animationReverseFrameDuration: _wheatFrameDuration * 0.5, endIdleFrames: AssetHandler.getIdleFrames(EncloseGridCellType.wall), idleController: idleController ), From 6037fefd8217cca3bafbab04dabf3d34b9f37a99 Mon Sep 17 00:00:00 2001 From: Mikael de Verdier Date: Tue, 1 Sep 2026 19:30:16 +0200 Subject: [PATCH 6/9] fixed a bug that made the 'your solution' button not disappear on click --- lib/screens/games/enclose_moose/enclose_moose_level_page.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/screens/games/enclose_moose/enclose_moose_level_page.dart b/lib/screens/games/enclose_moose/enclose_moose_level_page.dart index 035375d6..535732dc 100644 --- a/lib/screens/games/enclose_moose/enclose_moose_level_page.dart +++ b/lib/screens/games/enclose_moose/enclose_moose_level_page.dart @@ -784,6 +784,8 @@ class _EncloseMooseLevelState extends State with TickerPr } void _changeToSolution(Iterable solution) { + final oldScore = _grid.score; + _grid.reset(doUpdate: false); for (final flatIndex in solution) { @@ -792,6 +794,7 @@ class _EncloseMooseLevelState extends State with TickerPr } _grid.updateEnclosure(); + updateScore(oldScore); } Widget Function(BuildContext) _buildDayChooserDialog() { From 6e6d914c77a2800bfa3b63753538aaafe6e070fb Mon Sep 17 00:00:00 2001 From: Mikael de Verdier Date: Tue, 1 Sep 2026 19:41:51 +0200 Subject: [PATCH 7/9] made though bubble and escapePath arrow a bit more opaque --- lib/screens/games/enclose_moose/enclose_moose_level_page.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/screens/games/enclose_moose/enclose_moose_level_page.dart b/lib/screens/games/enclose_moose/enclose_moose_level_page.dart index 535732dc..14a589fb 100644 --- a/lib/screens/games/enclose_moose/enclose_moose_level_page.dart +++ b/lib/screens/games/enclose_moose/enclose_moose_level_page.dart @@ -444,7 +444,7 @@ class _EncloseMooseLevelState extends State with TickerPr cellSize: cellSize, extraLength: cellSize, extraDirection: _grid.escapeDirection, - lineColor: Colors.white.withAlpha(200), + lineColor: Colors.white.withAlpha(220), idleController: _idleController, frequency: 2 ) @@ -458,7 +458,7 @@ class _EncloseMooseLevelState extends State with TickerPr child: AnimatedThoughtBubble( isVisible: (_openCallCounter.getCount("thinking") ?? 0) != 0, text: _mooseThought, - color: Colors.white.withAlpha(200), + color: Colors.white.withAlpha(220), idleController: _idleController ) ) From 8560400a9fe637b84967155174c0c53ec96e1ca5 Mon Sep 17 00:00:00 2001 From: Mikael de Verdier Date: Wed, 2 Sep 2026 16:17:41 +0200 Subject: [PATCH 8/9] fixed release and concurrency bug with moose voiceline --- .../games/enclose_moose/enclose_moose_level_page.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/screens/games/enclose_moose/enclose_moose_level_page.dart b/lib/screens/games/enclose_moose/enclose_moose_level_page.dart index 14a589fb..34af81a9 100644 --- a/lib/screens/games/enclose_moose/enclose_moose_level_page.dart +++ b/lib/screens/games/enclose_moose/enclose_moose_level_page.dart @@ -726,8 +726,7 @@ class _EncloseMooseLevelState extends State with TickerPr if (tile.isMoose) { final mooseVoiceline = AssetHandler.getMooseVoiceline(_grid.escapePath == null); _mooseThought = mooseVoiceline.$1; - _audioPlayer.release(); // Doesn't otherwise happen if the same voiceline is chosen - _audioPlayer.play(AssetSource(mooseVoiceline.$2)); + _playVoicelineAudio(AssetSource(mooseVoiceline.$2)); final voicelineDuration = await _audioPlayer.onDurationChanged.first; if (_grid.escapePath != null) { @@ -746,6 +745,11 @@ class _EncloseMooseLevelState extends State with TickerPr } } + Future _playVoicelineAudio(AssetSource voiceline) async { // for some reason has to be a seperate function to avoid a bug where the audio played but the though bubble didn't show + await _audioPlayer.stop(); // Doesn't otherwise happen if the same voiceline is chosen + await _audioPlayer.play(voiceline); + } + Future _submitSolution() async { if (_bestSolution != null) { _changeToSolution(_bestSolution!); From 5e272de19466510e6177570bb2a9bb54b19f9bd2 Mon Sep 17 00:00:00 2001 From: Mikael de Verdier Date: Thu, 3 Sep 2026 18:05:15 +0200 Subject: [PATCH 9/9] added fittedBoxes (scale down) in some places to avoid overflow on small screens (mostly enclose.moose but also the navigation bottom bar buttons) --- .../enclose_moose_level_page.dart | 421 ++++++++++-------- .../helper_widgets/outlined_text.dart | 2 +- lib/widgets/bottom_app_bar.dart | 11 +- 3 files changed, 243 insertions(+), 191 deletions(-) diff --git a/lib/screens/games/enclose_moose/enclose_moose_level_page.dart b/lib/screens/games/enclose_moose/enclose_moose_level_page.dart index 34af81a9..b908c7e3 100644 --- a/lib/screens/games/enclose_moose/enclose_moose_level_page.dart +++ b/lib/screens/games/enclose_moose/enclose_moose_level_page.dart @@ -107,42 +107,29 @@ class _EncloseMooseLevelState extends State with TickerPr crossAxisAlignment: CrossAxisAlignment.center, children: [ Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - WigglingWidget( - controller: _idleController, - child: IconButton( - onPressed: () { - showDialog(context: context, builder: _buildDayChooserDialog()); - }, - icon: const Icon(Icons.calendar_month_rounded), - color: Colors.white - ) - ), - - Visibility( - visible: _hasSubmitted, - maintainState: true, - maintainAnimation: true, - maintainSize: true, - child: WigglingWidget( - controller: _idleController, - child: IconButton( - onPressed: () { - showDialog(context: context, builder: _buildSubmitDialog()); - }, - icon: const Icon(Icons.leaderboard_outlined), - color: Colors.white + Flexible( + child: FittedBox( + fit: BoxFit.scaleDown, + child: WigglingWidget( + controller: _idleController, + child: IconButton( + onPressed: () { + showDialog(context: context, builder: _buildDayChooserDialog()); + }, + icon: const Icon(Icons.calendar_month_rounded), + color: Colors.white + ) ) ) ), - - const Spacer(), - - Row( - children: [ - Visibility( - visible: widget.availableLevels.first != _usedLevel, + + Flexible( + child: FittedBox( + fit: BoxFit.scaleDown, + child: Visibility( + visible: _hasSubmitted, maintainState: true, maintainAnimation: true, maintainSize: true, @@ -150,66 +137,105 @@ class _EncloseMooseLevelState extends State with TickerPr controller: _idleController, child: IconButton( onPressed: () { - widget.pageController.jumpToPage(widget.pageController.page!.toInt() - 1); + showDialog(context: context, builder: _buildSubmitDialog()); }, - icon: const Icon(Icons.chevron_left), + icon: const Icon(Icons.leaderboard_outlined), color: Colors.white ) ) - ), + ) + ) + ), - WigglingWidget( - controller: _idleController, - child: OutlinedText( - text: _usedLevel.dayIndex != null ? "${t.encloseDay} ${_usedLevel.dayIndex}" : t.encloseBonus, - style: const TextStyle( - color: Colors.white, - fontSize: 25, - fontFamily: "Schoolbell" - ) - ) - ), + // const Spacer(), - Visibility( - visible: widget.availableLevels.last != _usedLevel, - maintainState: true, - maintainAnimation: true, - maintainSize: true, - child: WigglingWidget( - controller: _idleController, - child: IconButton( - onPressed: () { - widget.pageController.jumpToPage(widget.pageController.page!.toInt() + 1); - }, - icon: const Icon(Icons.chevron_right), - color: Colors.white - ) - ) - ), - ] + Flexible( + flex: 4, + child: FittedBox( + fit: BoxFit.scaleDown, + child: Row( + children: [ + Visibility( + visible: widget.availableLevels.first != _usedLevel, + maintainState: true, + maintainAnimation: true, + maintainSize: true, + child: WigglingWidget( + controller: _idleController, + child: IconButton( + onPressed: () { + widget.pageController.jumpToPage(widget.pageController.page!.toInt() - 1); + }, + icon: const Icon(Icons.chevron_left), + color: Colors.white + ) + ) + ), + + WigglingWidget( + controller: _idleController, + child: OutlinedText( + text: _usedLevel.dayIndex != null ? "${t.encloseDay} ${_usedLevel.dayIndex}" : t.encloseBonus, + style: const TextStyle( + color: Colors.white, + fontSize: 25, + fontFamily: "Schoolbell" + ) + ) + ), + + Visibility( + visible: widget.availableLevels.last != _usedLevel, + maintainState: true, + maintainAnimation: true, + maintainSize: true, + child: WigglingWidget( + controller: _idleController, + child: IconButton( + onPressed: () { + widget.pageController.jumpToPage(widget.pageController.page!.toInt() + 1); + }, + icon: const Icon(Icons.chevron_right), + color: Colors.white + ) + ) + ), + ] + ) + ) ), - Spacer(), + // const Spacer(), - WigglingWidget( - controller: _idleController, - child: IconButton( - onPressed: () { - _grid.reset(); - }, - icon: const Icon(Icons.restart_alt_outlined), - color: Colors.white + Flexible( + child: FittedBox( + fit: BoxFit.scaleDown, + child: WigglingWidget( + controller: _idleController, + child: IconButton( + onPressed: () { + _grid.reset(); + }, + icon: const Icon(Icons.restart_alt_outlined), + color: Colors.white + ) + ) ) ), - WigglingWidget( - controller: _idleController, - child: IconButton( - onPressed: () { - showDialog(context: context, builder: _buildHelpDialog()); - }, - icon: const Icon(Icons.question_mark_outlined), - color: Colors.white + Flexible( + child: FittedBox( + fit: BoxFit.scaleDown, + child: WigglingWidget( + controller: _idleController, + child: IconButton( + onPressed: () { + showDialog(context: context, builder: _buildHelpDialog()); + }, + icon: const Icon(Icons.question_mark_outlined), + color: Colors.white + ) + ) ) ), ] @@ -240,23 +266,25 @@ class _EncloseMooseLevelState extends State with TickerPr ) ), - title: WigglingWidget( - controller: _idleController, - child: Text.rich( - TextSpan( - children: "enclose.moose".characters.map((char) => WidgetSpan( // Could consider making all text like this - child: WigglingWidget( - controller: _idleController, - child: OutlinedText( - text: char, - style: const TextStyle( - color: Colors.white, - fontSize: 45, - fontFamily: "Schoolbell" + title: FittedBox( + child: WigglingWidget( + controller: _idleController, + child: Text.rich( + TextSpan( + children: "enclose.moose".characters.map((char) => WidgetSpan( // Could consider making all text like this + child: WigglingWidget( + controller: _idleController, + child: OutlinedText( + text: char, + style: const TextStyle( + color: Colors.white, + fontSize: 45, + fontFamily: "Schoolbell" + ) ) ) - ) - )).toList() + )).toList() + ) ) ) ) @@ -496,61 +524,72 @@ class _EncloseMooseLevelState extends State with TickerPr child: Column( children: [ Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - WigglingWidget( - controller: _idleController, - child: HighlightedText( - showHighlight: (_openCallCounter.getCount("walls") ?? 0) != 0, - child: OutlinedText( - text: "${t.encloseWalls}: ${_grid.wallsLeft}/${_grid.wallBudget}", - style: const TextStyle( - fontSize: 25, - fontFamily: "Schoolbell" + Flexible( + child: FittedBox( + fit: BoxFit.scaleDown, + child: WigglingWidget( + controller: _idleController, + child: HighlightedText( + showHighlight: (_openCallCounter.getCount("walls") ?? 0) != 0, + child: OutlinedText( + text: "${t.encloseWalls}: ${_grid.wallsLeft}/${_grid.wallBudget}", + style: const TextStyle( + fontSize: 25, + fontFamily: "Schoolbell" + ) + ) ) ) ) ), - Spacer(), - - Visibility( - visible: !_hasSubmitted && _grid.escapePath == null, - maintainState: true, - maintainAnimation: true, - maintainSize: true, - child: WigglingWidget( - child: TextButton( - style: TextButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5), - ) - ), - onPressed: _submitSolution, - child: OutlinedText( - text: t.encloseSubmit, - style: const TextStyle( - color: Colors.white, - fontSize: 25, - fontFamily: "Schoolbell" - ) + Flexible( + child: FittedBox( + fit: BoxFit.scaleDown, + child: Visibility( + visible: !_hasSubmitted && _grid.escapePath == null, + maintainState: true, + maintainAnimation: true, + maintainSize: true, + child: WigglingWidget( + child: TextButton( + style: TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ) + ), + onPressed: _submitSolution, + child: OutlinedText( + text: t.encloseSubmit, + style: const TextStyle( + color: Colors.white, + fontSize: 25, + fontFamily: "Schoolbell" + ) + ) + ), + controller: _idleController ) - ), - controller: _idleController + ) ) ), - Spacer(), - - WigglingWidget( - controller: _idleController, - child: HighlightedText( - showHighlight: (_openCallCounter.getCount("score") ?? 0) != 0, - child: OutlinedText( - text: "${t.encloseScore}: ${_grid.score ?? "N/A"}", - style: const TextStyle( - fontSize: 25, - fontFamily: "Schoolbell" + Flexible( + child: FittedBox( + fit: BoxFit.scaleDown, + child: WigglingWidget( + controller: _idleController, + child: HighlightedText( + showHighlight: (_openCallCounter.getCount("score") ?? 0) != 0, + child: OutlinedText( + text: "${t.encloseScore}: ${_grid.score ?? "N/A"}", + style: const TextStyle( + fontSize: 25, + fontFamily: "Schoolbell" + ) + ) ) ) ) @@ -561,58 +600,68 @@ class _EncloseMooseLevelState extends State with TickerPr Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Visibility( - visible: _hasSubmitted && _grid.score != _usedLevel.optimalScore, - maintainState: true, - maintainAnimation: true, - maintainSize: true, - child: WigglingWidget( - controller: _idleController, - child: OutlinedButton.icon( - onPressed: () { - _changeToSolution(_usedLevel.optimalSolution!); - }, - style: OutlinedButton.styleFrom( - backgroundColor: Color(0xFF15542D).withAlpha(200), // Colors.black.withAlpha(55), - visualDensity: VisualDensity.compact - ), - label: OutlinedText( - text: "${t.encloseOptimal}: ${_usedLevel.optimalScore}", - style: const TextStyle( - // color: Colors.white, - fontSize: 20, - fontFamily: "Schoolbell" + Flexible( + child: FittedBox( + fit: BoxFit.scaleDown, + child: Visibility( + visible: _hasSubmitted && _grid.score != _usedLevel.optimalScore, + maintainState: true, + maintainAnimation: true, + maintainSize: true, + child: WigglingWidget( + controller: _idleController, + child: OutlinedButton.icon( + onPressed: () { + _changeToSolution(_usedLevel.optimalSolution!); + }, + style: OutlinedButton.styleFrom( + backgroundColor: Color(0xFF15542D).withAlpha(200), // Colors.black.withAlpha(55), + visualDensity: VisualDensity.compact + ), + label: OutlinedText( + text: "${t.encloseOptimal}: ${_usedLevel.optimalScore}", + style: const TextStyle( + // color: Colors.white, + fontSize: 20, + fontFamily: "Schoolbell" + ) + ), + icon: const Icon(Icons.star_sharp) ) - ), - icon: const Icon(Icons.star_sharp) + ) ) ) ), - Visibility( - visible: isNotShowingYours || !isCurrentBest, - maintainState: true, - maintainAnimation: true, - maintainSize: true, - child: WigglingWidget( - controller: _idleController, - child: OutlinedButton.icon( - onPressed: () { - _changeToSolution(_hasSubmitted ? _usedLevel.playerSubmission!.playerSolution : _bestSolution!); - }, - style: OutlinedButton.styleFrom( - backgroundColor: Color(0xFF15542D).withAlpha(200), // Colors.black.withAlpha(55), - visualDensity: VisualDensity.compact - ), - label: OutlinedText( - text: _hasSubmitted ? "${t.encloseYourSolution}: ${_usedLevel.playerSubmission!.playerScore}" : "${t.encloseYourBest}: $_bestSolutionScore", - style: const TextStyle( - // color: Colors.white, - fontSize: 20, - fontFamily: "Schoolbell" + Flexible( + child: FittedBox( + fit: BoxFit.scaleDown, + child: Visibility( + visible: isNotShowingYours || !isCurrentBest, + maintainState: true, + maintainAnimation: true, + maintainSize: true, + child: WigglingWidget( + controller: _idleController, + child: OutlinedButton.icon( + onPressed: () { + _changeToSolution(_hasSubmitted ? _usedLevel.playerSubmission!.playerSolution : _bestSolution!); + }, + style: OutlinedButton.styleFrom( + backgroundColor: Color(0xFF15542D).withAlpha(200), // Colors.black.withAlpha(55), + visualDensity: VisualDensity.compact + ), + label: OutlinedText( + text: _hasSubmitted ? "${t.encloseYourSolution}: ${_usedLevel.playerSubmission!.playerScore}" : "${t.encloseYourBest}: $_bestSolutionScore", + style: const TextStyle( + // color: Colors.white, + fontSize: 20, + fontFamily: "Schoolbell" + ) + ), + icon: const Icon(Icons.keyboard_return_outlined) ) - ), - icon: const Icon(Icons.keyboard_return_outlined) + ) ) ) ), diff --git a/lib/screens/games/enclose_moose/helper_widgets/outlined_text.dart b/lib/screens/games/enclose_moose/helper_widgets/outlined_text.dart index bd33cc0e..54b1baf7 100644 --- a/lib/screens/games/enclose_moose/helper_widgets/outlined_text.dart +++ b/lib/screens/games/enclose_moose/helper_widgets/outlined_text.dart @@ -5,7 +5,7 @@ class OutlinedText extends StatefulWidget { super.key, required this.text, this.style, - this.strokeWidth = 1.5, + this.strokeWidth = 1.5, // could make this default depend on font size this.strokeColor = Colors.black, this.textAlign }); diff --git a/lib/widgets/bottom_app_bar.dart b/lib/widgets/bottom_app_bar.dart index ac0a0599..308497e1 100644 --- a/lib/widgets/bottom_app_bar.dart +++ b/lib/widgets/bottom_app_bar.dart @@ -182,10 +182,13 @@ class FsekAppBarState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(item.iconData, color: color, size: widget.iconSize), - Text( - item.text!, - style: TextStyle(color: color), - softWrap: false, + FittedBox( + fit: BoxFit.scaleDown, + child: Text( + item.text!, + style: TextStyle(color: color), + softWrap: false, + ) ) ], ),