From 64df2ec80b574d45a99cf565c8e50d2fe5822c82 Mon Sep 17 00:00:00 2001 From: dan63047 Date: Mon, 1 Jan 2024 20:26:09 +0300 Subject: [PATCH] Now user redirects only from ch.tetr.io/u/* + redesign of StatSell --- android/app/src/main/AndroidManifest.xml | 2 +- lib/gen/strings.g.dart | 65 ++++++++++++------------ lib/views/main_view.dart | 33 +++++++----- lib/widgets/stat_sell_num.dart | 24 ++++++--- lib/widgets/tl_thingy.dart | 5 +- res/i18n/strings.i18n.json | 1 + res/i18n/strings_ru.i18n.json | 1 + 7 files changed, 76 insertions(+), 55 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 309d1a5..f9c9c75 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -28,7 +28,7 @@ - + diff --git a/lib/gen/strings.g.dart b/lib/gen/strings.g.dart index 349c4ab..f6e2244 100644 --- a/lib/gen/strings.g.dart +++ b/lib/gen/strings.g.dart @@ -4,9 +4,9 @@ /// To regenerate, run: `dart run slang` /// /// Locales: 2 -/// Strings: 986 (493 per locale) +/// Strings: 988 (494 per locale) /// -/// Built on 2023-11-08 at 22:09 UTC +/// Built on 2024-01-01 at 16:00 UTC // coverage:ignore-file // ignore_for_file: type=lint @@ -24,8 +24,8 @@ const AppLocale _baseLocale = AppLocale.en; /// - LocaleSettings.setLocale(AppLocale.en) // set locale /// - Locale locale = AppLocale.en.flutterLocale // get flutter locale from enum /// - if (LocaleSettings.currentLocale == AppLocale.en) // locale check -enum AppLocale with BaseAppLocale { - en(languageCode: 'en', build: _StringsEn.build), +enum AppLocale with BaseAppLocale { + en(languageCode: 'en', build: Translations.build), ru(languageCode: 'ru', build: _StringsRu.build); const AppLocale({required this.languageCode, this.scriptCode, this.countryCode, required this.build}); // ignore: unused_element @@ -33,10 +33,10 @@ enum AppLocale with BaseAppLocale { @override final String languageCode; @override final String? scriptCode; @override final String? countryCode; - @override final TranslationBuilder build; + @override final TranslationBuilder build; /// Gets current instance managed by [LocaleSettings]. - _StringsEn get translations => LocaleSettings.instance.translationMap[this]!; + Translations get translations => LocaleSettings.instance.translationMap[this]!; } /// Method A: Simple @@ -48,7 +48,7 @@ enum AppLocale with BaseAppLocale { /// Usage: /// String a = t.someKey.anotherKey; /// String b = t['someKey.anotherKey']; // Only for edge cases! -_StringsEn get t => LocaleSettings.instance.currentTranslations; +Translations get t => LocaleSettings.instance.currentTranslations; /// Method B: Advanced /// @@ -65,17 +65,10 @@ _StringsEn get t => LocaleSettings.instance.currentTranslations; /// final t = Translations.of(context); // Get t variable. /// String a = t.someKey.anotherKey; // Use t variable. /// String b = t['someKey.anotherKey']; // Only for edge cases! -class Translations { - Translations._(); // no constructor - - static _StringsEn of(BuildContext context) => InheritedLocaleData.of(context).translations; -} - -/// The provider for method B -class TranslationProvider extends BaseTranslationProvider { +class TranslationProvider extends BaseTranslationProvider { TranslationProvider({required super.child}) : super(settings: LocaleSettings.instance); - static InheritedLocaleData of(BuildContext context) => InheritedLocaleData.of(context); + static InheritedLocaleData of(BuildContext context) => InheritedLocaleData.of(context); } /// Method B shorthand via [BuildContext] extension method. @@ -84,11 +77,11 @@ class TranslationProvider extends BaseTranslationProvider /// Usage (e.g. in a widget's build method): /// context.t.someKey.anotherKey extension BuildContextTranslationsExtension on BuildContext { - _StringsEn get t => TranslationProvider.of(this).translations; + Translations get t => TranslationProvider.of(this).translations; } /// Manages all translation instances and the current locale -class LocaleSettings extends BaseFlutterLocaleSettings { +class LocaleSettings extends BaseFlutterLocaleSettings { LocaleSettings._() : super(utils: AppLocaleUtils.instance); static final instance = LocaleSettings._(); @@ -110,7 +103,7 @@ class LocaleSettings extends BaseFlutterLocaleSettings { } /// Provides utility functions without any side effects. -class AppLocaleUtils extends BaseAppLocaleUtils { +class AppLocaleUtils extends BaseAppLocaleUtils { AppLocaleUtils._() : super(baseLocale: _baseLocale, locales: AppLocale.values); static final instance = AppLocaleUtils._(); @@ -126,11 +119,16 @@ class AppLocaleUtils extends BaseAppLocaleUtils { // translations // Path: -class _StringsEn implements BaseTranslations { +class Translations implements BaseTranslations { + /// Returns the current translations of the given [context]. + /// + /// Usage: + /// final t = Translations.of(context); + static Translations of(BuildContext context) => InheritedLocaleData.of(context).translations; /// You can call this constructor and build your own translation instance of this locale. /// Constructing via the enum [AppLocale.build] is preferred. - _StringsEn.build({Map? overrides, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver}) + Translations.build({Map? overrides, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver}) : assert(overrides == null, 'Set "translation_overrides: true" in order to enable this feature.'), $meta = TranslationMetadata( locale: AppLocale.en, @@ -142,12 +140,12 @@ class _StringsEn implements BaseTranslations { } /// Metadata for the translations of . - @override final TranslationMetadata $meta; + @override final TranslationMetadata $meta; /// Access flat map dynamic operator[](String key) => $meta.getTranslation(key); - late final _StringsEn _root = this; // ignore: unused_field + late final Translations _root = this; // ignore: unused_field // Translations Map get locales => { @@ -205,6 +203,7 @@ class _StringsEn implements BaseTranslations { String get formula => 'Formula'; String get exactValue => 'Exact value'; String get neverPlayedTL => 'That user never played Tetra League'; + String get botTL => 'Bots are not allowed to play Tetra League'; String get exportDB => 'Export local database'; String get exportDBDescription => 'It contains states and Tetra League records of the tracked players and list of tracked players.'; String get desktopExportAlertTitle => 'Desktop export'; @@ -573,7 +572,7 @@ class _StringsEn implements BaseTranslations { class _StringsNewsPartsEn { _StringsNewsPartsEn._(this._root); - final _StringsEn _root; // ignore: unused_field + final Translations _root; // ignore: unused_field // Translations String get leaderboardStart => 'Got '; @@ -595,7 +594,7 @@ class _StringsNewsPartsEn { class _StringsStatCellNumEn { _StringsStatCellNumEn._(this._root); - final _StringsEn _root; // ignore: unused_field + final Translations _root; // ignore: unused_field // Translations String get xpLevel => 'XP Level'; @@ -657,7 +656,7 @@ class _StringsStatCellNumEn { class _StringsNumOfGameActionsEn { _StringsNumOfGameActionsEn._(this._root); - final _StringsEn _root; // ignore: unused_field + final Translations _root; // ignore: unused_field // Translations String get pc => 'All Clears'; @@ -670,7 +669,7 @@ class _StringsNumOfGameActionsEn { class _StringsPopupActionsEn { _StringsPopupActionsEn._(this._root); - final _StringsEn _root; // ignore: unused_field + final Translations _root; // ignore: unused_field // Translations String get cancel => 'Cancel'; @@ -682,7 +681,7 @@ class _StringsPopupActionsEn { class _StringsErrorsEn { _StringsErrorsEn._(this._root); - final _StringsEn _root; // ignore: unused_field + final Translations _root; // ignore: unused_field // Translations String connection({required Object code, required Object message}) => 'Some issue with connection: ${code} ${message}'; @@ -704,8 +703,7 @@ class _StringsErrorsEn { } // Path: -class _StringsRu implements _StringsEn { - +class _StringsRu implements Translations { /// You can call this constructor and build your own translation instance of this locale. /// Constructing via the enum [AppLocale.build] is preferred. _StringsRu.build({Map? overrides, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver}) @@ -720,7 +718,7 @@ class _StringsRu implements _StringsEn { } /// Metadata for the translations of . - @override final TranslationMetadata $meta; + @override final TranslationMetadata $meta; /// Access flat map @override dynamic operator[](String key) => $meta.getTranslation(key); @@ -783,6 +781,7 @@ class _StringsRu implements _StringsEn { @override String get formula => 'Формула'; @override String get exactValue => 'Точное значение'; @override String get neverPlayedTL => 'Этот игрок никогда не играл в Тетра Лигу'; + @override String get botTL => 'Ботам нельзя играть в Тетра Лигу'; @override String get exportDB => 'Экспортировать локальную базу данных'; @override String get exportDBDescription => 'Она содержит состояния аккаунтов и их матчей в Тетра Лиге для отслеживаемых игроков и список таких игроков.'; @override String get desktopExportAlertTitle => 'Экспорт на десктопе'; @@ -1284,7 +1283,7 @@ class _StringsErrorsRu implements _StringsErrorsEn { /// Flat map(s) containing all translations. /// Only for edge cases! For simple maps, use the map function of this library. -extension on _StringsEn { +extension on Translations { dynamic _flatMapFunction(String path) { switch (path) { case 'locales.en': return 'English'; @@ -1352,6 +1351,7 @@ extension on _StringsEn { case 'formula': return 'Formula'; case 'exactValue': return 'Exact value'; case 'neverPlayedTL': return 'That user never played Tetra League'; + case 'botTL': return 'Bots are not allowed to play Tetra League'; case 'exportDB': return 'Export local database'; case 'exportDBDescription': return 'It contains states and Tetra League records of the tracked players and list of tracked players.'; case 'desktopExportAlertTitle': return 'Desktop export'; @@ -1855,6 +1855,7 @@ extension on _StringsRu { case 'formula': return 'Формула'; case 'exactValue': return 'Точное значение'; case 'neverPlayedTL': return 'Этот игрок никогда не играл в Тетра Лигу'; + case 'botTL': return 'Ботам нельзя играть в Тетра Лигу'; case 'exportDB': return 'Экспортировать локальную базу данных'; case 'exportDBDescription': return 'Она содержит состояния аккаунтов и их матчей в Тетра Лиге для отслеживаемых игроков и список таких игроков.'; case 'desktopExportAlertTitle': return 'Экспорт на десктопе'; diff --git a/lib/views/main_view.dart b/lib/views/main_view.dart index 88e9869..baab8cc 100644 --- a/lib/views/main_view.dart +++ b/lib/views/main_view.dart @@ -1,3 +1,5 @@ +// ignore_for_file: type_literal_in_constant_pattern + import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -51,11 +53,7 @@ Future copyToClipboard(String text) async { } String get40lTime(int microseconds){ - if (microseconds > 60000000) { - return "${(microseconds/1000000/60).floor()}:${(_secs.format(microseconds /1000000 % 60))}"; - } else{ - return _timeInSec.format(microseconds / 1000000); - } + return microseconds > 60000000 ? "${(microseconds/1000000/60).floor()}:${(_secs.format(microseconds /1000000 % 60))}" : _timeInSec.format(microseconds / 1000000); } class _MainState extends State with SingleTickerProviderStateMixin { @@ -345,7 +343,7 @@ class _MainState extends State with SingleTickerProviderStateMixin { body: TabBarView( controller: _tabController, children: [ - TLThingy(tl: snapshot.data![0].tlSeason1, userID: snapshot.data![0].userId, states: snapshot.data![2], topTR: snapshot.data![7]), + TLThingy(tl: snapshot.data![0].tlSeason1, userID: snapshot.data![0].userId, states: snapshot.data![2], topTR: snapshot.data![7], bot: snapshot.data![0].role == "bot"), _TLRecords(userID: snapshot.data![0].userId, data: snapshot.data![3]), _History(states: snapshot.data![2], update: _justUpdate), _RecordThingy(record: (snapshot.data![1]['sprint'].isNotEmpty) ? snapshot.data![1]['sprint'][0] : null), @@ -565,7 +563,7 @@ class _TLRecords extends StatelessWidget { ), );}, )] - : [Center(child: Text(t.noRecords, style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)))], + : [Center(child: Text(t.noRecords, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28)))], ); } } @@ -591,10 +589,10 @@ class _History extends StatelessWidget{ } ), if(chartsData[_chartsIndex].value!.length > 1) _HistoryChartThigy(data: chartsData[_chartsIndex].value!, title: "ss", yAxisTitle: _historyShortTitles[_chartsIndex], bigScreen: bigScreen, leftSpace: bigScreen? 80 : 45, yFormat: bigScreen? _f2 : NumberFormat.compact(),) - else Center(child: Text(t.notEnoughData, style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28))) + else Center(child: Text(t.notEnoughData, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28))) ], ), - ] : [Center(child: Text(t.noHistorySaved, textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)))]); + ] : [Center(child: Text(t.noHistorySaved, textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28)))]); } } @@ -881,7 +879,7 @@ class _RecordThingy extends StatelessWidget { ), ] : [ - Text(t.noRecord, textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)) + Text(t.noRecord, textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28)) ], ); }); @@ -897,8 +895,9 @@ class _OtherThingy extends StatelessWidget { const _OtherThingy({Key? key, required this.zen, required this.bio, required this.distinguishment, this.newsletter}) : super(key: key); - List getDistinguishmentSetOfWidgets(String? text) { - if (text == null) return [TextSpan(text: "Header is missing", style: const TextStyle(fontSize: 28, fontWeight: FontWeight.bold, color: Colors.redAccent))]; + List getDistinguishmentTitle(String? text) { + if (distinguishment?.type == "twc") return [const TextSpan(text: "TETR.IO World Champion", style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold, color: Colors.yellowAccent))]; + if (text == null) return [const TextSpan(text: "Header is missing", style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold, color: Colors.redAccent))]; var exploded = text.split(" "); List result = []; for (String shit in exploded){ @@ -922,6 +921,12 @@ class _OtherThingy extends StatelessWidget { return result; } + String getDistinguishmentSubtitle(String? text){ + if (distinguishment?.type == "twc") return "${distinguishment?.detail} TETR.IO World Championship"; + if (text == null) return "Footer is missing"; + return text; + } + ListTile getNewsTile(News news){ Map gametypes = { "40l": t.sprint, @@ -1082,10 +1087,10 @@ class _OtherThingy extends StatelessWidget { textAlign: TextAlign.center, text: TextSpan( style: DefaultTextStyle.of(context).style, - children: getDistinguishmentSetOfWidgets(distinguishment!.header), + children: getDistinguishmentTitle(distinguishment?.header), ), ), - Text(distinguishment!.footer ?? "Footer is missing" , style: const TextStyle(fontSize: 18), textAlign: TextAlign.center), + Text(getDistinguishmentSubtitle(distinguishment?.footer), style: const TextStyle(fontSize: 18), textAlign: TextAlign.center), ], ), ), diff --git a/lib/widgets/stat_sell_num.dart b/lib/widgets/stat_sell_num.dart index 5efc22e..190f9a1 100644 --- a/lib/widgets/stat_sell_num.dart +++ b/lib/widgets/stat_sell_num.dart @@ -25,15 +25,26 @@ class StatCellNum extends StatelessWidget { @override Widget build(BuildContext context) { - NumberFormat f = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: fractionDigits ?? 0); + NumberFormat comparef = NumberFormat("+#,###.###;-#,###.###")..maximumFractionDigits = fractionDigits ?? 0; + NumberFormat intf = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 0); + NumberFormat fractionf = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: fractionDigits ?? 0)..maximumIntegerDigits = 0; + num fraction = playerStat.isNegative ? 1 - (playerStat - playerStat.floor()) : playerStat - playerStat.floor(); + int integer = playerStat.isNegative ? (playerStat + fraction).toInt() : (playerStat - fraction).toInt(); + // String valueAsString = fractionDigits == null ? f.format(playerStat.floor()) : f.format(playerStat); + // var exploded = valueAsString.split("."); return Column( children: [ - Text( - fractionDigits == null ? f.format(playerStat.floor()) : f.format(playerStat), + RichText( + text: TextSpan(text: intf.format(integer), + children: [ + TextSpan(text: fractionf.format(fraction).substring(1), style: TextStyle(fontSize: 16)) + ], style: TextStyle( fontFamily: "Eurostile Round Extended", + //fontWeight: FontWeight.bold, fontSize: isScreenBig ? 32 : 24, - ), + ) + ) ), if (oldPlayerStat != null) Text(NumberFormat("+#,###.###;-#,###.###").format(playerStat - oldPlayerStat!), style: TextStyle( color: higherIsBetter ? @@ -66,8 +77,9 @@ class StatCellNum extends StatelessWidget { child: Text(okText??"OK"), onPressed: () {Navigator.of(context).pop();} ) - ], - )); + ], + ) + ); }, style: ButtonStyle( padding: MaterialStateProperty.all(EdgeInsets.zero)), diff --git a/lib/widgets/tl_thingy.dart b/lib/widgets/tl_thingy.dart index 5d357aa..71cac7b 100644 --- a/lib/widgets/tl_thingy.dart +++ b/lib/widgets/tl_thingy.dart @@ -20,8 +20,9 @@ class TLThingy extends StatefulWidget { final String userID; final List states; final bool showTitle; + final bool bot; final double? topTR; - const TLThingy({Key? key, required this.tl, required this.userID, required this.states, this.showTitle = true, this.topTR}) : super(key: key); + const TLThingy({Key? key, required this.tl, required this.userID, required this.states, this.showTitle = true, this.bot=false, this.topTR}) : super(key: key); @override State createState() => _TLThingyState(); @@ -408,7 +409,7 @@ class _TLThingyState extends State { if (currentTl.nerdStats != null) Graphs(currentTl.apm!, currentTl.pps!, currentTl.vs!, currentTl.nerdStats!, currentTl.playstyle!) ] : [ - Text(t.neverPlayedTL, style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)), + Text(widget.bot ? t.botTL : t.neverPlayedTL, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28)), ], ); }, diff --git a/res/i18n/strings.i18n.json b/res/i18n/strings.i18n.json index 842915c..31046fa 100644 --- a/res/i18n/strings.i18n.json +++ b/res/i18n/strings.i18n.json @@ -68,6 +68,7 @@ "formula": "Formula", "exactValue": "Exact value", "neverPlayedTL": "That user never played Tetra League", + "botTL": "Bots are not allowed to play Tetra League", "exportDB": "Export local database", "exportDBDescription": "It contains states and Tetra League records of the tracked players and list of tracked players.", "desktopExportAlertTitle": "Desktop export", diff --git a/res/i18n/strings_ru.i18n.json b/res/i18n/strings_ru.i18n.json index 184e4ce..9bfbfc2 100644 --- a/res/i18n/strings_ru.i18n.json +++ b/res/i18n/strings_ru.i18n.json @@ -68,6 +68,7 @@ "formula": "Формула", "exactValue": "Точное значение", "neverPlayedTL": "Этот игрок никогда не играл в Тетра Лигу", + "botTL": "Ботам нельзя играть в Тетра Лигу", "exportDB": "Экспортировать локальную базу данных", "exportDBDescription": "Она содержит состояния аккаунтов и их матчей в Тетра Лиге для отслеживаемых игроков и список таких игроков.", "desktopExportAlertTitle": "Экспорт на десктопе",