From e46ad49e096810d1ed0266a0ca079f55ca15844e Mon Sep 17 00:00:00 2001 From: dan63047 Date: Thu, 5 Dec 2024 17:13:08 +0300 Subject: [PATCH] News widget was redone for the sake of i18n --- lib/gen/strings.g.dart | 124 ++++++++++++++--------- lib/views/destination_leaderboards.dart | 1 - lib/views/main_view.dart | 1 + lib/views/sprint_and_blitz_averages.dart | 3 - lib/widgets/news_thingy.dart | 41 ++++---- res/i18n/strings.i18n.json | 28 ++--- 6 files changed, 110 insertions(+), 88 deletions(-) diff --git a/lib/gen/strings.g.dart b/lib/gen/strings.g.dart index 9d66050..451ab11 100644 --- a/lib/gen/strings.g.dart +++ b/lib/gen/strings.g.dart @@ -4,9 +4,9 @@ /// To regenerate, run: `dart run slang` /// /// Locales: 1 -/// Strings: 756 +/// Strings: 750 /// -/// Built on 2024-12-02 at 19:52 UTC +/// Built on 2024-12-04 at 18:43 UTC // coverage:ignore-file // ignore_for_file: type=lint @@ -209,8 +209,8 @@ class Translations implements BaseTranslations { String get news => 'News'; late final _StringsMatchResultEn matchResult = _StringsMatchResultEn._(_root); late final _StringsDistinguishmentsEn distinguishments = _StringsDistinguishmentsEn._(_root); - late final _StringsNewsEntrysEn newsEntrys = _StringsNewsEntrysEn._(_root); - late final _StringsNewsPartsEn newsParts = _StringsNewsPartsEn._(_root); + late final _StringsNewsEntriesEn newsEntries = _StringsNewsEntriesEn._(_root); + String rankupMiddle({required Object r}) => '${r} rank'; String get copyUserID => 'Click to copy user ID'; String get searchHint => 'Username or ID'; String get navMenu => 'Navigation menu'; @@ -577,36 +577,47 @@ class _StringsDistinguishmentsEn { String twcYear({required Object year}) => '${year} TETR.IO World Championship'; } -// Path: newsEntrys -class _StringsNewsEntrysEn { - _StringsNewsEntrysEn._(this._root); +// Path: newsEntries +class _StringsNewsEntriesEn { + _StringsNewsEntriesEn._(this._root); final Translations _root; // ignore: unused_field // Translations - String leaderboard({required Object rank, required Object gametype}) => 'Got № ${rank} on ${gametype}'; -} - -// Path: newsParts -class _StringsNewsPartsEn { - _StringsNewsPartsEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - String get leaderboardStart => 'Got '; - String get leaderboardMiddle => 'on '; - String get personalbest => 'Got a new PB in '; - String get personalbestMiddle => 'of '; - String get badgeStart => 'Obtained a '; - String get badgeEnd => 'badge'; - String get rankupStart => 'Obtained '; - String rankupMiddle({required Object r}) => '${r} rank '; - String get rankupEnd => 'in Tetra League'; - String get tetoSupporter => 'TETR.IO supporter'; - String get supporterStart => 'Become a '; - String get supporterGiftStart => 'Received the gift of '; - String unknownNews({required Object type}) => 'Unknown news of type ${type}'; + TextSpan leaderboard({required InlineSpan rank, required InlineSpan gametype}) => TextSpan(children: [ + const TextSpan(text: 'Got № '), + rank, + const TextSpan(text: ' in '), + gametype, + ]); + TextSpan personalbest({required InlineSpan gametype, required InlineSpan pb}) => TextSpan(children: [ + const TextSpan(text: 'Got a new PB in '), + gametype, + const TextSpan(text: ' of '), + pb, + ]); + TextSpan badge({required InlineSpan badge}) => TextSpan(children: [ + const TextSpan(text: 'Obtained a '), + badge, + const TextSpan(text: ' badge'), + ]); + TextSpan rankup({required InlineSpan rank}) => TextSpan(children: [ + const TextSpan(text: 'Obtained '), + rank, + const TextSpan(text: ' in Tetra League'), + ]); + TextSpan supporter({required InlineSpanBuilder s}) => TextSpan(children: [ + const TextSpan(text: 'Became a '), + s('TETR.IO supporter'), + ]); + TextSpan supporter_gift({required InlineSpanBuilder s}) => TextSpan(children: [ + const TextSpan(text: 'Received the gift of '), + s('TETR.IO supporter'), + ]); + TextSpan unknown({required InlineSpan type}) => TextSpan(children: [ + const TextSpan(text: 'Unknown news of type '), + type, + ]); } // Path: snackBarMessages @@ -1064,7 +1075,7 @@ class _StringsStatsEn { String get sent => 'Sent'; String get received => 'Received'; String get placement => 'Placement'; - String get peak => 'peak'; + String get peak => 'Peak'; String qpWithMods({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, one: 'With 1 mod', two: 'With ${n} mods', @@ -1719,20 +1730,41 @@ extension on Translations { case 'distinguishments.noFooter': return 'Footer is missing'; case 'distinguishments.twc': return 'TETR.IO World Champion'; case 'distinguishments.twcYear': return ({required Object year}) => '${year} TETR.IO World Championship'; - case 'newsEntrys.leaderboard': return ({required Object rank, required Object gametype}) => 'Got № ${rank} on ${gametype}'; - case 'newsParts.leaderboardStart': return 'Got '; - case 'newsParts.leaderboardMiddle': return 'on '; - case 'newsParts.personalbest': return 'Got a new PB in '; - case 'newsParts.personalbestMiddle': return 'of '; - case 'newsParts.badgeStart': return 'Obtained a '; - case 'newsParts.badgeEnd': return 'badge'; - case 'newsParts.rankupStart': return 'Obtained '; - case 'newsParts.rankupMiddle': return ({required Object r}) => '${r} rank '; - case 'newsParts.rankupEnd': return 'in Tetra League'; - case 'newsParts.tetoSupporter': return 'TETR.IO supporter'; - case 'newsParts.supporterStart': return 'Become a '; - case 'newsParts.supporterGiftStart': return 'Received the gift of '; - case 'newsParts.unknownNews': return ({required Object type}) => 'Unknown news of type ${type}'; + case 'newsEntries.leaderboard': return ({required InlineSpan rank, required InlineSpan gametype}) => TextSpan(children: [ + const TextSpan(text: 'Got № '), + rank, + const TextSpan(text: ' in '), + gametype, + ]); + case 'newsEntries.personalbest': return ({required InlineSpan gametype, required InlineSpan pb}) => TextSpan(children: [ + const TextSpan(text: 'Got a new PB in '), + gametype, + const TextSpan(text: ' of '), + pb, + ]); + case 'newsEntries.badge': return ({required InlineSpan badge}) => TextSpan(children: [ + const TextSpan(text: 'Obtained a '), + badge, + const TextSpan(text: ' badge'), + ]); + case 'newsEntries.rankup': return ({required InlineSpan rank}) => TextSpan(children: [ + const TextSpan(text: 'Obtained '), + rank, + const TextSpan(text: ' in Tetra League'), + ]); + case 'newsEntries.supporter': return ({required InlineSpanBuilder s}) => TextSpan(children: [ + const TextSpan(text: 'Became a '), + s('TETR.IO supporter'), + ]); + case 'newsEntries.supporter_gift': return ({required InlineSpanBuilder s}) => TextSpan(children: [ + const TextSpan(text: 'Received the gift of '), + s('TETR.IO supporter'), + ]); + case 'newsEntries.unknown': return ({required InlineSpan type}) => TextSpan(children: [ + const TextSpan(text: 'Unknown news of type '), + type, + ]); + case 'rankupMiddle': return ({required Object r}) => '${r} rank'; case 'copyUserID': return 'Click to copy user ID'; case 'searchHint': return 'Username or ID'; case 'navMenu': return 'Navigation menu'; @@ -2068,7 +2100,7 @@ extension on Translations { case 'stats.sent': return 'Sent'; case 'stats.received': return 'Received'; case 'stats.placement': return 'Placement'; - case 'stats.peak': return 'peak'; + case 'stats.peak': return 'Peak'; case 'stats.qpWithMods': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, one: 'With 1 mod', two: 'With ${n} mods', diff --git a/lib/views/destination_leaderboards.dart b/lib/views/destination_leaderboards.dart index 8a5187d..2b4780e 100644 --- a/lib/views/destination_leaderboards.dart +++ b/lib/views/destination_leaderboards.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:ffi'; import 'dart:math'; import 'package:flutter/material.dart'; import 'package:tetra_stats/data_objects/tetrio_constants.dart'; diff --git a/lib/views/main_view.dart b/lib/views/main_view.dart index 454fc1b..164fc0d 100644 --- a/lib/views/main_view.dart +++ b/lib/views/main_view.dart @@ -140,6 +140,7 @@ class _MainState extends State with TickerProviderStateMixin { void dispose() { controller.dispose(); _searchController.dispose(); + _backgroundUpdate.cancel(); super.dispose(); } diff --git a/lib/views/sprint_and_blitz_averages.dart b/lib/views/sprint_and_blitz_averages.dart index aeff773..df115fa 100644 --- a/lib/views/sprint_and_blitz_averages.dart +++ b/lib/views/sprint_and_blitz_averages.dart @@ -1,12 +1,9 @@ -import 'dart:io'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:tetra_stats/data_objects/tetrio_constants.dart'; import 'package:tetra_stats/gen/strings.g.dart'; import 'package:tetra_stats/utils/relative_timestamps.dart'; import 'package:tetra_stats/utils/text_shadow.dart'; -import 'package:window_manager/window_manager.dart'; late String oldWindowTitle; final DateFormat dateFormat = DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode); diff --git a/lib/widgets/news_thingy.dart b/lib/widgets/news_thingy.dart index 3914990..ee32ebf 100644 --- a/lib/widgets/news_thingy.dart +++ b/lib/widgets/news_thingy.dart @@ -20,11 +20,11 @@ class NewsThingy extends StatelessWidget{ title: RichText( text: TextSpan( style: const TextStyle(fontFamily: 'Eurostile Round', fontSize: 16, color: Colors.white), - text: t.newsParts.leaderboardStart, children: [ - TextSpan(text: "№${news.data["rank"]} ", style: const TextStyle(fontWeight: FontWeight.bold)), - TextSpan(text: t.newsParts.leaderboardMiddle), - TextSpan(text: "№${t.gamemodes[news.data["gametype"]]}", style: const TextStyle(fontWeight: FontWeight.bold)), + t.newsEntries.leaderboard( + rank: TextSpan(text: news.data["rank"], style: const TextStyle(fontWeight: FontWeight.bold)), + gametype: TextSpan(text: t.gamemodes[news.data["gametype"]], style: const TextStyle(fontWeight: FontWeight.bold)) + ) ] ) ), @@ -35,11 +35,10 @@ class NewsThingy extends StatelessWidget{ title: RichText( text: TextSpan( style: const TextStyle(fontFamily: 'Eurostile Round', fontSize: 16, color: Colors.white), - text: t.newsParts.personalbest, children: [ - TextSpan(text: "${t.gamemodes[news.data["gametype"]]} ", style: const TextStyle(fontWeight: FontWeight.bold)), - TextSpan(text: t.newsParts.personalbestMiddle), - TextSpan(text: switch (news.data["gametype"]){ + t.newsEntries.personalbest( + gametype: TextSpan(text: t.gamemodes[news.data["gametype"]], style: const TextStyle(fontWeight: FontWeight.bold)), + pb: TextSpan(text: switch (news.data["gametype"]){ "blitz" => NumberFormat.decimalPattern().format(news.data["result"]), "40l" => get40lTime((news.data["result"]*1000).floor()), "5mblast" => get40lTime((news.data["result"]*1000).floor()), @@ -48,7 +47,8 @@ class NewsThingy extends StatelessWidget{ _ => "unknown" }, style: const TextStyle(fontWeight: FontWeight.bold) - ), + ) + ) ] ) ), @@ -67,10 +67,8 @@ class NewsThingy extends StatelessWidget{ title: RichText( text: TextSpan( style: const TextStyle(fontFamily: 'Eurostile Round', fontSize: 16, color: Colors.white), - text: t.newsParts.badgeStart, children: [ - TextSpan(text: "${news.data["label"]} ", style: const TextStyle(fontWeight: FontWeight.bold)), - TextSpan(text: t.newsParts.badgeEnd) + t.newsEntries.badge(badge: TextSpan(text: news.data["label"], style: const TextStyle(fontWeight: FontWeight.bold))) ] ) ), @@ -89,10 +87,8 @@ class NewsThingy extends StatelessWidget{ title: RichText( text: TextSpan( style: const TextStyle(fontFamily: 'Eurostile Round', fontSize: 16, color: Colors.white), - text: t.newsParts.rankupStart, children: [ - TextSpan(text: t.newsParts.rankupMiddle(r: news.data["rank"].toString().toUpperCase()), style: const TextStyle(fontWeight: FontWeight.bold)), - TextSpan(text: t.newsParts.rankupEnd) + t.newsEntries.rankup(rank: TextSpan(text: t.rankupMiddle(r: news.data["rank"].toString().toUpperCase()), style: const TextStyle(fontWeight: FontWeight.bold))) ] ) ), @@ -111,9 +107,8 @@ class NewsThingy extends StatelessWidget{ title: RichText( text: TextSpan( style: const TextStyle(fontFamily: 'Eurostile Round', fontSize: 16, color: Colors.white), - text: t.newsParts.supporterStart, children: [ - TextSpan(text: t.newsParts.tetoSupporter, style: const TextStyle(fontWeight: FontWeight.bold)) + t.newsEntries.supporter(s: (p0) => TextSpan(text: p0, style: const TextStyle(fontWeight: FontWeight.bold))) ] ) ), @@ -132,9 +127,8 @@ class NewsThingy extends StatelessWidget{ title: RichText( text: TextSpan( style: const TextStyle(fontFamily: 'Eurostile Round', fontSize: 16, color: Colors.white), - text: t.newsParts.supporterGiftStart, children: [ - TextSpan(text: t.newsParts.tetoSupporter, style: const TextStyle(fontWeight: FontWeight.bold)) + t.newsEntries.supporter_gift(s: (p0) => TextSpan(text: p0, style: const TextStyle(fontWeight: FontWeight.bold))) ] ) ), @@ -150,7 +144,14 @@ class NewsThingy extends StatelessWidget{ ); default: // if type is unknown return ListTile( - title: Text(t.newsParts.unknownNews(type: news.type)), + title: RichText( + text: TextSpan( + style: const TextStyle(fontFamily: 'Eurostile Round', fontSize: 16, color: Colors.white), + children: [ + t.newsEntries.unknown(type: TextSpan(text: news.type, style: const TextStyle(fontWeight: FontWeight.bold))) + ] + ) + ), subtitle: Text(timestamp(news.timestamp)), ); } diff --git a/res/i18n/strings.i18n.json b/res/i18n/strings.i18n.json index a9fec22..1aec28c 100644 --- a/res/i18n/strings.i18n.json +++ b/res/i18n/strings.i18n.json @@ -91,24 +91,16 @@ "twc": "TETR.IO World Champion", "twcYear": "$year TETR.IO World Championship" }, - "newsEntrys":{ - "leaderboard": "Got № $rank on $gametype" - }, - "newsParts":{ - "leaderboardStart": "Got ", - "leaderboardMiddle": "on ", - "personalbest": "Got a new PB in ", - "personalbestMiddle": "of ", - "badgeStart": "Obtained a ", - "badgeEnd": "badge", - "rankupStart": "Obtained ", - "rankupMiddle": "${r} rank ", - "rankupEnd": "in Tetra League", - "tetoSupporter": "TETR.IO supporter", - "supporterStart": "Become a ", - "supporterGiftStart": "Received the gift of ", - "unknownNews": "Unknown news of type ${type}" + "newsEntries":{ + "leaderboard(rich)": "Got № $rank in $gametype", + "personalbest(rich)": "Got a new PB in $gametype of $pb", + "badge(rich)": "Obtained a $badge badge", + "rankup(rich)": "Obtained $rank in Tetra League", + "supporter(rich)": "Became a ${s(TETR.IO supporter)}", + "supporter_gift(rich)": "Received the gift of ${s(TETR.IO supporter)}", + "unknown(rich)": "Unknown news of type $type" }, + "rankupMiddle": "${r} rank", "copyUserID": "Click to copy user ID", "searchHint": "Username or ID", "navMenu": "Navigation menu", @@ -565,7 +557,7 @@ "sent": "Sent", "received": "Received", "placement": "Placement", - "peak": "peak", + "peak": "Peak", "qpWithMods(plural)": { "one": "With 1 mod", "two": "With $n mods",