diff --git a/lib/main.dart b/lib/main.dart index a5458b6..4a02ac5 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,13 +1,18 @@ import 'dart:async'; import 'dart:io'; +import 'dart:isolate'; import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'dart:developer' as developer; import 'package:package_info_plus/package_info_plus.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:tetra_stats/services/tetrio_crud.dart'; import 'package:tetra_stats/views/customization_view.dart'; +import 'package:tetra_stats/views/ranks_averages_view.dart'; +import 'package:tetra_stats/views/sprint_and_blitz_averages.dart'; +import 'package:tetra_stats/views/tl_leaderboard_view.dart'; import 'package:window_manager/window_manager.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart'; @@ -24,6 +29,38 @@ late SharedPreferences prefs; late TetrioService teto; ColorScheme sheme = const ColorScheme.dark(primary: Colors.cyanAccent, secondary: Colors.white); +Future computeIsolate(Future Function() function) async { + final receivePort = ReceivePort(); + var rootToken = RootIsolateToken.instance!; + await Isolate.spawn<_IsolateData>( + _isolateEntry, + _IsolateData( + token: rootToken, + function: function, + answerPort: receivePort.sendPort, + ), + ); + return await receivePort.first; +} + +void _isolateEntry(_IsolateData isolateData) async { + BackgroundIsolateBinaryMessenger.ensureInitialized(isolateData.token); + final answer = await isolateData.function(); + isolateData.answerPort.send(answer); +} + +class _IsolateData { + final RootIsolateToken token; + final Function function; + final SendPort answerPort; + + _IsolateData({ + required this.token, + required this.function, + required this.answerPort, + }); +} + void setAccentColor(Color color){ // does this thing work??? yes??? no??? sheme = ColorScheme.dark(primary: color, secondary: Colors.white); } @@ -38,6 +75,26 @@ final router = GoRouter( GoRoute( path: 'settings', builder: (_, __) => const SettingsView(), + routes: [ + GoRoute( + path: 'customization', + builder: (_, __) => const CustomizationView(), + ), + ] + ), + GoRoute( + path: "leaderboard", + builder: (_, __) => const TLLeaderboardView(), + routes: [ + GoRoute( + path: "LBvalues", + builder: (_, __) => const RankAveragesView(), + ), + ] + ), + GoRoute( + path: "LBvalues", + builder: (_, __) => const RankAveragesView(), ), GoRoute( path: 'states', @@ -48,9 +105,9 @@ final router = GoRouter( builder: (_, __) => const CalcView(), ), GoRoute( - path: 'customization', - builder: (_, __) => const CustomizationView(), - ), + path: 'sprintAndBlitzAverages', + builder: (_, __) => const SprintAndBlitzView(), + ) ] ), GoRoute( // that one intended for Android users, that can open https://ch.tetr.io/u/ links @@ -92,10 +149,10 @@ void main() async { } // I dont want to store old cache - Timer.periodic(Duration(minutes: 5), (Timer timer) async { + Timer.periodic(Duration(minutes: 5), (Timer timer) { teto.cacheRoutine(); developer.log("Cache routine complete, next one in ${DateTime.now().add(Duration(minutes: 5))}", name: "main"); - if (prefs.getBool("updateInBG") == true) await teto.fetchTracked(); + // if (prefs.getBool("updateInBG") == true) teto.fetchTracked(); // TODO: Somehow avoid doing that in main isolate }); runApp(TranslationProvider( diff --git a/lib/utils/numers_formats.dart b/lib/utils/numers_formats.dart index bd6c119..7a22180 100644 --- a/lib/utils/numers_formats.dart +++ b/lib/utils/numers_formats.dart @@ -8,5 +8,6 @@ final NumberFormat f4 = NumberFormat.decimalPatternDigits(locale: LocaleSettings final NumberFormat f3 = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 3); final NumberFormat f2 = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 2); final NumberFormat f2l = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 2)..minimumFractionDigits = 0; +final NumberFormat f1 = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 1); final NumberFormat f0 = NumberFormat.decimalPattern(LocaleSettings.currentLocale.languageCode); final NumberFormat percentage = NumberFormat.percentPattern(LocaleSettings.currentLocale.languageCode)..maximumFractionDigits = 2; \ No newline at end of file diff --git a/lib/utils/relative_timestamps.dart b/lib/utils/relative_timestamps.dart new file mode 100644 index 0000000..5e5645f --- /dev/null +++ b/lib/utils/relative_timestamps.dart @@ -0,0 +1,59 @@ +import 'package:tetra_stats/utils/numers_formats.dart'; + +/// Returns string, that represents time difference between [dateTime] and now +String relativeDateTime(DateTime dateTime){ + Duration difference = dateTime.difference(DateTime.now()); + bool inPast = difference.isNegative; + Duration absDifference = difference.abs(); + double timeInterval; + + // years + timeInterval = absDifference.inSeconds / 31536000; + if (timeInterval >= 100.0) { + return inPast ? "${timeInterval.truncate()} years ago" : "in ${timeInterval.truncate()} years"; + } else if (timeInterval >= 10.0) { + return inPast ? "${f1.format(timeInterval)} years ago" : "in ${f1.format(timeInterval)} years"; + } else if (timeInterval >= 1.0) { + return inPast ? "${f2.format(timeInterval)} years ago" : "in ${f2.format(timeInterval)} years"; + } + + // months + timeInterval = absDifference.inSeconds / 2592000; + if (timeInterval >= 10.0) { + return inPast ? "${timeInterval.truncate()} months ago" : "in ${timeInterval.truncate()} months"; + } else if (timeInterval >= 1.0) { + return inPast ? "${f1.format(timeInterval)} months ago" : "in ${f1.format(timeInterval)} months"; + } + + // days + timeInterval = absDifference.inSeconds / 86400; + if (timeInterval >= 10.0) { + return inPast ? "${timeInterval.truncate()} days ago" : "in ${timeInterval.truncate()} days"; + } else if (timeInterval >= 1.0) { + return inPast ? "${f1.format(timeInterval)} days ago" : "in ${f1.format(timeInterval)} days"; + } + + // hours + timeInterval = absDifference.inSeconds / 3600; + if (timeInterval >= 10.0) { + return inPast ? "${timeInterval.truncate()} hours ago" : "in ${timeInterval.truncate()} hours"; + } else if (timeInterval >= 1.0) { + return inPast ? "${f1.format(timeInterval)} hours ago" : "in ${f1.format(timeInterval)} hours"; + } + + // minutes + timeInterval = absDifference.inSeconds / 60; + if (timeInterval >= 10.0) { + return inPast ? "${timeInterval.truncate()} minutes ago" : "in ${timeInterval.truncate()} minutes"; + } else if (timeInterval >= 1.0) { + return inPast ? "${f1.format(timeInterval)} minutes ago" : "in ${f1.format(timeInterval)} minutes"; + } + + // seconds + timeInterval = absDifference.inMilliseconds / 1000; + if (timeInterval >= 10.0) { + return inPast ? "${timeInterval.truncate()} seconds ago" : "in ${timeInterval.truncate()} seconds"; + } else { + return inPast ? "${f1.format(timeInterval)} seconds ago" : "in ${f1.format(timeInterval)} seconds"; + } +} \ No newline at end of file diff --git a/lib/views/customization_view.dart b/lib/views/customization_view.dart index 533b128..7bb27d0 100644 --- a/lib/views/customization_view.dart +++ b/lib/views/customization_view.dart @@ -22,6 +22,7 @@ class CustomizationState extends State { late bool oskKagariGimmick; late bool sheetbotRadarGraphs; late int ratingMode; + late int timestampMode; void changeColor(Color color) { setState(() => pickerColor = color); @@ -60,6 +61,11 @@ class CustomizationState extends State { } else { ratingMode = 0; } + if (prefs.getInt("timestampMode") != null) { + timestampMode = prefs.getInt("ratingMode")!; + } else { + timestampMode = 0; + } } ThemeData getTheme(BuildContext context, Color color){ @@ -125,6 +131,23 @@ class CustomizationState extends State { oskKagariGimmick = value; }); }),), + ListTile(title: Text("Timestamps"), + subtitle: Text(t.oskKagariDescription, style: subtitleStyle), + trailing: DropdownButton( + value: timestampMode, + items: [ + DropdownMenuItem(value: 0, child: Text("Absolute (GMT)")), + DropdownMenuItem(value: 1, child: Text("Absolute (Local Time)")), + DropdownMenuItem(value: 2, child: Text("Relative")) + ], + onChanged: (dynamic value){ + prefs.setInt("timestampMode", value); + setState(() { + timestampMode = value; + }); + }, + ), + ), ListTile(title: Text("Main representation of rating"), subtitle: Text(t.oskKagariDescription, style: subtitleStyle), trailing: DropdownButton( @@ -141,13 +164,6 @@ class CustomizationState extends State { }); }, ), - // trailing: Switch(value: sheetbotRadarGraphs, onChanged: (bool value){ - // prefs.setBool("sheetbotRadarGraphs", value); - // setState(() { - // sheetbotRadarGraphs = value; - // }); - // } - // ), ), ListTile(title: Text("Sheetbot-like behavior for radar graphs"), subtitle: Text(t.oskKagariDescription, style: subtitleStyle), diff --git a/lib/views/main_view.dart b/lib/views/main_view.dart index 0e52c2d..8f8695d 100644 --- a/lib/views/main_view.dart +++ b/lib/views/main_view.dart @@ -18,15 +18,13 @@ import 'package:tetra_stats/main.dart' show prefs, teto; import 'package:tetra_stats/services/crud_exceptions.dart'; import 'package:tetra_stats/utils/numers_formats.dart'; import 'package:tetra_stats/utils/text_shadow.dart'; -import 'package:tetra_stats/views/ranks_averages_view.dart' show RankAveragesView; -import 'package:tetra_stats/views/sprint_and_blitz_averages.dart'; -import 'package:tetra_stats/views/tl_leaderboard_view.dart' show TLLeaderboardView; import 'package:tetra_stats/views/tl_match_view.dart' show TlMatchResultView; import 'package:tetra_stats/widgets/finesse_thingy.dart'; import 'package:tetra_stats/widgets/lineclears_thingy.dart'; import 'package:tetra_stats/widgets/list_tile_trailing_stats.dart'; import 'package:tetra_stats/widgets/search_box.dart'; import 'package:tetra_stats/widgets/stat_sell_num.dart'; +import 'package:tetra_stats/widgets/text_timestamp.dart'; import 'package:tetra_stats/widgets/tl_thingy.dart'; import 'package:tetra_stats/widgets/user_thingy.dart'; import 'package:window_manager/window_manager.dart'; @@ -41,7 +39,6 @@ List _historyShortTitles = ["TR", "Glicko", "RD", "APM", "PPS", "VS", "APP", "DS late ScrollController _scrollController; final NumberFormat _timeInSec = NumberFormat("#,###.###s.", LocaleSettings.currentLocale.languageCode); final NumberFormat secs = NumberFormat("00.###", LocaleSettings.currentLocale.languageCode); -final DateFormat _dateFormat = DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms(); class MainView extends StatefulWidget { @@ -98,7 +95,6 @@ class _MainState extends State with TickerProviderStateMixin { bool _TLHistoryWasFetched = false; late TabController _tabController; late TabController _wideScreenTabController; - late bool fixedScroll; String get title => "Tetra Stats: $_titleNickname"; @@ -652,12 +648,7 @@ class _NavDrawerState extends State { leading: const Icon(Icons.leaderboard), title: Text(t.tlLeaderboard), onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const TLLeaderboardView(), - ), - ); + context.go("/leaderboard"); }, ), ), @@ -666,12 +657,7 @@ class _NavDrawerState extends State { leading: const Icon(Icons.compress), title: Text(t.rankAveragesViewTitle), onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const RankAveragesView(), - ), - ); + context.go("/LBvalues"); }, ), ), @@ -680,12 +666,7 @@ class _NavDrawerState extends State { leading: const Icon(Icons.bar_chart), title: Text(t.sprintAndBlitsViewTitle), onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const SprintAndBlitzView(), - ), - ); + context.go("/sprintAndBlitzAverages"); }, ), ), @@ -767,7 +748,7 @@ class _TLRecords extends StatelessWidget { leading: Text("${data[index].endContext.firstWhere((element) => element.userId == userID).points} : ${data[index].endContext.firstWhere((element) => element.userId != userID).points}", style: bigScreen ? const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28, shadows: textShadow) : const TextStyle(fontSize: 28, shadows: textShadow)), title: Text("vs. ${data[index].endContext.firstWhere((element) => element.userId != userID).username}"), - subtitle: Text(_dateFormat.format(data[index].timestamp)), + subtitle: Text(timestamp(data[index].timestamp)), trailing: TrailingStats( data[index].endContext.firstWhere((element) => element.userId == userID).secondary, data[index].endContext.firstWhere((element) => element.userId == userID).tertiary, @@ -930,7 +911,7 @@ class _HistoryChartThigyState extends State<_HistoryChartThigy> { style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 20), ), ), - Text(_gamesPlayedInsteadOfDateAndTime ? t.gamesPlayed(games: t.games(n: data.gamesPlayed)) : _dateFormat.format(data.timestamp)) + Text(_gamesPlayedInsteadOfDateAndTime ? t.gamesPlayed(games: t.games(n: data.gamesPlayed)) : timestamp(data.timestamp)) ], ), ); @@ -1086,7 +1067,7 @@ class _TwoRecordsThingy extends StatelessWidget { )), if (sprint!.rank != null) TextSpan(text: "№${sprint!.rank}", style: TextStyle(color: getColorOfRank(sprint!.rank!))), if (sprint!.rank != null) const TextSpan(text: " • "), - TextSpan(text: _dateFormat.format(sprint!.timestamp!)), + TextSpan(text: timestamp(sprint!.timestamp!)), ] ), ), @@ -1142,7 +1123,7 @@ class _TwoRecordsThingy extends StatelessWidget { else TextSpan(text: "${t.verdictGeneral(n: readableIntDifference(blitz!.endContext!.score, closestAverageBlitz.value), verdict: blitzBetterThanClosestAverage ? t.verdictBetter : t.verdictWorse, rank: closestAverageBlitz.key.toUpperCase())}\n", style: TextStyle( color: blitzBetterThanClosestAverage ? Colors.greenAccent : Colors.redAccent )), - TextSpan(text: _dateFormat.format(blitz!.timestamp!)), + TextSpan(text: timestamp(blitz!.timestamp!)), if (blitz!.rank != null) const TextSpan(text: " • "), if (blitz!.rank != null) TextSpan(text: "№${blitz!.rank}", style: TextStyle(color: getColorOfRank(blitz!.rank!))), ] @@ -1254,7 +1235,7 @@ class _RecordThingy extends StatelessWidget { )), if (record!.rank != null) TextSpan(text: "№${record!.rank}", style: TextStyle(color: getColorOfRank(record!.rank!))), if (record!.rank != null) const TextSpan(text: " • "), - TextSpan(text: _dateFormat.format(record!.timestamp!)), + TextSpan(text: timestamp(record!.timestamp!)), ] ), ) @@ -1368,7 +1349,7 @@ class _OtherThingy extends StatelessWidget { ] ) ), - subtitle: Text(_dateFormat.format(news.timestamp)), + subtitle: Text(timestamp(news.timestamp)), ); case "personalbest": return ListTile( @@ -1383,7 +1364,7 @@ class _OtherThingy extends StatelessWidget { ] ) ), - subtitle: Text(_dateFormat.format(news.timestamp)), + subtitle: Text(timestamp(news.timestamp)), leading: Image.asset( "res/icons/improvement-local.png", height: 48, @@ -1405,7 +1386,7 @@ class _OtherThingy extends StatelessWidget { ] ) ), - subtitle: Text(_dateFormat.format(news.timestamp)), + subtitle: Text(timestamp(news.timestamp)), leading: Image.asset( "res/tetrio_badges/${news.data["type"]}.png", height: 48, @@ -1427,7 +1408,7 @@ class _OtherThingy extends StatelessWidget { ] ) ), - subtitle: Text(_dateFormat.format(news.timestamp)), + subtitle: Text(timestamp(news.timestamp)), leading: Image.asset( "res/tetrio_tl_alpha_ranks/${news.data["rank"]}.png", height: 48, @@ -1448,7 +1429,7 @@ class _OtherThingy extends StatelessWidget { ] ) ), - subtitle: Text(_dateFormat.format(news.timestamp)), + subtitle: Text(timestamp(news.timestamp)), leading: Image.asset( "res/icons/supporter-tag.png", height: 48, @@ -1469,7 +1450,7 @@ class _OtherThingy extends StatelessWidget { ] ) ), - subtitle: Text(_dateFormat.format(news.timestamp)), + subtitle: Text(timestamp(news.timestamp)), leading: Image.asset( "res/icons/supporter-tag.png", height: 48, @@ -1482,7 +1463,7 @@ class _OtherThingy extends StatelessWidget { default: // if type is unknown return ListTile( title: Text(t.newsParts.unknownNews(type: news.type)), - subtitle: Text(_dateFormat.format(news.timestamp)), + subtitle: Text(timestamp(news.timestamp)), ); } } diff --git a/lib/views/settings_view.dart b/lib/views/settings_view.dart index bad170c..30394c1 100644 --- a/lib/views/settings_view.dart +++ b/lib/views/settings_view.dart @@ -264,7 +264,7 @@ class SettingsState extends State { subtitle: Text(t.customizationDescription, style: const TextStyle(fontFamily: "Eurostile Round Condensed", color: Colors.grey)), trailing: const Icon(Icons.arrow_right), onTap: () { - context.go("/customization"); + context.go("/settings/customization"); },), ListTile(title: Text("Update stats in the background"), subtitle: Text("While tetra stats is running, it can update stats of the current player when cache expires, as well, as tetra league stats of tracked players", style: const TextStyle(fontFamily: "Eurostile Round Condensed", color: Colors.grey)), diff --git a/lib/views/states_view.dart b/lib/views/states_view.dart index 2ceaec9..4263129 100644 --- a/lib/views/states_view.dart +++ b/lib/views/states_view.dart @@ -7,6 +7,7 @@ import 'package:tetra_stats/gen/strings.g.dart'; import 'package:tetra_stats/main.dart' show teto; import 'package:tetra_stats/views/mathes_view.dart'; import 'package:tetra_stats/views/state_view.dart'; +import 'package:tetra_stats/widgets/text_timestamp.dart'; import 'package:window_manager/window_manager.dart'; class StatesView extends StatefulWidget { @@ -38,7 +39,6 @@ class StatesState extends State { @override Widget build(BuildContext context) { final t = Translations.of(context); - final DateFormat dateFormat = DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms(); return Scaffold( appBar: AppBar( title: Text(t.statesViewTitle(number: widget.states.length, nickname: widget.states.last.username.toUpperCase())), @@ -60,14 +60,14 @@ class StatesState extends State { itemCount: widget.states.length, itemBuilder: (context, index) { return ListTile( - title: Text(dateFormat.format(widget.states[index].state)), + title: Text(timestamp(widget.states[index].state)), subtitle: Text(t.statesViewEntry(level: widget.states[index].level.toStringAsFixed(2), gameTime: widget.states[index].gameTime, friends: widget.states[index].friendCount, rd: NumberFormat.compact().format(widget.states[index].tlSeason1.rd))), trailing: IconButton( icon: const Icon(Icons.delete_forever), onPressed: () { DateTime nn = widget.states[index].state; teto.deleteState(widget.states[index]).then((value) => setState(() { - ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.stateRemoved(date: dateFormat.format(nn))))); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.stateRemoved(date: timestamp(nn))))); })); }, ), diff --git a/lib/views/tracked_players_view.dart b/lib/views/tracked_players_view.dart index 8738be5..905e3f4 100644 --- a/lib/views/tracked_players_view.dart +++ b/lib/views/tracked_players_view.dart @@ -7,6 +7,7 @@ import 'package:tetra_stats/gen/strings.g.dart'; import 'package:tetra_stats/main.dart' show teto; import 'package:tetra_stats/utils/filesizes_converter.dart'; import 'package:tetra_stats/views/states_view.dart'; +import 'package:tetra_stats/widgets/text_timestamp.dart'; import 'package:window_manager/window_manager.dart'; late String oldWindowTitle; @@ -37,7 +38,6 @@ class TrackedPlayersState extends State { @override Widget build(BuildContext context) { final t = Translations.of(context); - final DateFormat dateFormat = DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms(); return Scaffold( appBar: AppBar( title: Text(t.trackedPlayersViewTitle), @@ -109,7 +109,7 @@ class TrackedPlayersState extends State { itemBuilder: (context, index) { return ListTile( title: Text(t.trackedPlayersEntry(nickname: allPlayers[keys[index]]!.last.username, numberOfStates: allPlayers[keys[index]]!.length)), - subtitle: Text(t.trackedPlayersDescription(firstStateDate: dateFormat.format(allPlayers[keys[index]]!.first.state), lastStateDate: dateFormat.format(allPlayers[keys[index]]!.last.state))), + subtitle: Text(t.trackedPlayersDescription(firstStateDate: timestamp(allPlayers[keys[index]]!.first.state), lastStateDate: timestamp(allPlayers[keys[index]]!.last.state))), trailing: IconButton( icon: const Icon(Icons.delete_forever), onPressed: () { diff --git a/lib/widgets/text_timestamp.dart b/lib/widgets/text_timestamp.dart new file mode 100644 index 0000000..d17bbd3 --- /dev/null +++ b/lib/widgets/text_timestamp.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:tetra_stats/gen/strings.g.dart'; +import 'package:tetra_stats/main.dart'; +import 'package:tetra_stats/utils/relative_timestamps.dart'; + +final DateFormat dateFormat = DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms(); + +String timestamp(DateTime dateTime){ + int timestampMode = prefs.getInt("timestampMode")??0; + return timestampMode == 2 ? relativeDateTime(dateTime) : dateFormat.format(timestampMode == 1 ? dateTime.toLocal() : dateTime); +} + +// class TextTimestamp extends StatelessWidget{ +// @override +// Widget build(BuildContext context) { +// // TODO: implement build +// return; +// } + +// } \ No newline at end of file diff --git a/lib/widgets/tl_thingy.dart b/lib/widgets/tl_thingy.dart index 9571cf6..08a9ab5 100644 --- a/lib/widgets/tl_thingy.dart +++ b/lib/widgets/tl_thingy.dart @@ -3,18 +3,17 @@ import 'package:intl/intl.dart'; import 'package:tetra_stats/data_objects/tetrio.dart'; import 'package:syncfusion_flutter_gauges/gauges.dart'; import 'package:tetra_stats/gen/strings.g.dart'; - import 'package:tetra_stats/utils/colors_functions.dart'; import 'package:tetra_stats/utils/numers_formats.dart'; import 'package:tetra_stats/widgets/gauget_num.dart'; import 'package:tetra_stats/widgets/graphs.dart'; import 'package:tetra_stats/widgets/stat_sell_num.dart'; +import 'package:tetra_stats/widgets/text_timestamp.dart'; import 'package:tetra_stats/widgets/tl_progress_bar.dart'; import 'package:tetra_stats/widgets/tl_rating_thingy.dart'; var intFDiff = NumberFormat("+#,###;-#,###"); -final DateFormat dateFormat = DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms(); class TLThingy extends StatefulWidget { final TetraLeagueAlpha tl; @@ -69,7 +68,7 @@ class _TLThingyState extends State { return Column( children: [ if (widget.showTitle) Text(t.tetraLeague, style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)), - if (oldTl != null) Text(t.comparingWith(newDate: dateFormat.format(currentTl.timestamp), oldDate: dateFormat.format(oldTl!.timestamp)), + if (oldTl != null) Text(t.comparingWith(newDate: timestamp(currentTl.timestamp), oldDate: timestamp(oldTl!.timestamp)), textAlign: TextAlign.center,), if (oldTl != null) RangeSlider(values: _currentRangeValues, max: widget.states.length.toDouble(), labels: RangeLabels( diff --git a/lib/widgets/user_thingy.dart b/lib/widgets/user_thingy.dart index 2bb572e..7d9a77d 100644 --- a/lib/widgets/user_thingy.dart +++ b/lib/widgets/user_thingy.dart @@ -10,6 +10,7 @@ import 'package:intl/intl.dart'; import 'package:tetra_stats/utils/text_shadow.dart'; import 'dart:developer' as developer; import 'package:tetra_stats/widgets/stat_sell_num.dart'; +import 'package:tetra_stats/widgets/text_timestamp.dart'; const Map xpTableScuffed = { // level: xp required 05000: 67009018.4885772, @@ -126,7 +127,7 @@ class UserThingy extends StatelessWidget { ], ), showStateTimestamp - ? Text(t.fetchDate(date: dateFormat.format(player.state))) + ? Text(t.fetchDate(date: timestamp(player.state))) : Wrap(direction: Axis.horizontal, alignment: WrapAlignment.center, spacing: 25, crossAxisAlignment: WrapCrossAlignment.start, children: [ FutureBuilder( future: teto.isPlayerTracking(player.userId), @@ -340,7 +341,7 @@ class UserThingy extends StatelessWidget { ), children: [ if (player.country != null) TextSpan(text: "${t.countries[player.country]} • "), - TextSpan(text: "${t.playerRole[player.role]}${t.playerRoleAccount}${player.registrationTime == null ? t.wasFromBeginning : '${t.created} ${dateFormat.format(player.registrationTime!)}'}"), + TextSpan(text: "${t.playerRole[player.role]}${t.playerRoleAccount}${player.registrationTime == null ? t.wasFromBeginning : '${t.created} ${timestamp(player.registrationTime!)}'}"), if (player.supporterTier > 0) const TextSpan(text: " • "), if (player.supporterTier > 0) WidgetSpan(child: Icon(player.supporterTier > 1 ? Icons.star : Icons.star_border, color: player.supporterTier > 1 ? Colors.yellowAccent : Colors.white), alignment: PlaceholderAlignment.middle, baseline: TextBaseline.alphabetic), if (player.supporterTier > 0) TextSpan(text: player.supporterTier.toString(), style: TextStyle(color: player.supporterTier > 1 ? Colors.yellowAccent : Colors.white))