ustomization -> Relative timestamps
This commit is contained in:
parent
cedb304c1a
commit
751e7a7071
|
@ -1,13 +1,18 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'dart:isolate';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'dart:developer' as developer;
|
import 'dart:developer' as developer;
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:tetra_stats/services/tetrio_crud.dart';
|
import 'package:tetra_stats/services/tetrio_crud.dart';
|
||||||
import 'package:tetra_stats/views/customization_view.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:window_manager/window_manager.dart';
|
||||||
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
||||||
import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';
|
import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';
|
||||||
|
@ -24,6 +29,38 @@ late SharedPreferences prefs;
|
||||||
late TetrioService teto;
|
late TetrioService teto;
|
||||||
ColorScheme sheme = const ColorScheme.dark(primary: Colors.cyanAccent, secondary: Colors.white);
|
ColorScheme sheme = const ColorScheme.dark(primary: Colors.cyanAccent, secondary: Colors.white);
|
||||||
|
|
||||||
|
Future<dynamic> 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???
|
void setAccentColor(Color color){ // does this thing work??? yes??? no???
|
||||||
sheme = ColorScheme.dark(primary: color, secondary: Colors.white);
|
sheme = ColorScheme.dark(primary: color, secondary: Colors.white);
|
||||||
}
|
}
|
||||||
|
@ -38,6 +75,26 @@ final router = GoRouter(
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: 'settings',
|
path: 'settings',
|
||||||
builder: (_, __) => const SettingsView(),
|
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(
|
GoRoute(
|
||||||
path: 'states',
|
path: 'states',
|
||||||
|
@ -48,9 +105,9 @@ final router = GoRouter(
|
||||||
builder: (_, __) => const CalcView(),
|
builder: (_, __) => const CalcView(),
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: 'customization',
|
path: 'sprintAndBlitzAverages',
|
||||||
builder: (_, __) => const CustomizationView(),
|
builder: (_, __) => const SprintAndBlitzView(),
|
||||||
),
|
)
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
GoRoute( // that one intended for Android users, that can open https://ch.tetr.io/u/ links
|
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
|
// I dont want to store old cache
|
||||||
Timer.periodic(Duration(minutes: 5), (Timer timer) async {
|
Timer.periodic(Duration(minutes: 5), (Timer timer) {
|
||||||
teto.cacheRoutine();
|
teto.cacheRoutine();
|
||||||
developer.log("Cache routine complete, next one in ${DateTime.now().add(Duration(minutes: 5))}", name: "main");
|
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(
|
runApp(TranslationProvider(
|
||||||
|
|
|
@ -8,5 +8,6 @@ final NumberFormat f4 = NumberFormat.decimalPatternDigits(locale: LocaleSettings
|
||||||
final NumberFormat f3 = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 3);
|
final NumberFormat f3 = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 3);
|
||||||
final NumberFormat f2 = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 2);
|
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 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 f0 = NumberFormat.decimalPattern(LocaleSettings.currentLocale.languageCode);
|
||||||
final NumberFormat percentage = NumberFormat.percentPattern(LocaleSettings.currentLocale.languageCode)..maximumFractionDigits = 2;
|
final NumberFormat percentage = NumberFormat.percentPattern(LocaleSettings.currentLocale.languageCode)..maximumFractionDigits = 2;
|
|
@ -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";
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ class CustomizationState extends State<CustomizationView> {
|
||||||
late bool oskKagariGimmick;
|
late bool oskKagariGimmick;
|
||||||
late bool sheetbotRadarGraphs;
|
late bool sheetbotRadarGraphs;
|
||||||
late int ratingMode;
|
late int ratingMode;
|
||||||
|
late int timestampMode;
|
||||||
|
|
||||||
void changeColor(Color color) {
|
void changeColor(Color color) {
|
||||||
setState(() => pickerColor = color);
|
setState(() => pickerColor = color);
|
||||||
|
@ -60,6 +61,11 @@ class CustomizationState extends State<CustomizationView> {
|
||||||
} else {
|
} else {
|
||||||
ratingMode = 0;
|
ratingMode = 0;
|
||||||
}
|
}
|
||||||
|
if (prefs.getInt("timestampMode") != null) {
|
||||||
|
timestampMode = prefs.getInt("ratingMode")!;
|
||||||
|
} else {
|
||||||
|
timestampMode = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThemeData getTheme(BuildContext context, Color color){
|
ThemeData getTheme(BuildContext context, Color color){
|
||||||
|
@ -125,6 +131,23 @@ class CustomizationState extends State<CustomizationView> {
|
||||||
oskKagariGimmick = value;
|
oskKagariGimmick = value;
|
||||||
});
|
});
|
||||||
}),),
|
}),),
|
||||||
|
ListTile(title: Text("Timestamps"),
|
||||||
|
subtitle: Text(t.oskKagariDescription, style: subtitleStyle),
|
||||||
|
trailing: DropdownButton(
|
||||||
|
value: timestampMode,
|
||||||
|
items: <DropdownMenuItem>[
|
||||||
|
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"),
|
ListTile(title: Text("Main representation of rating"),
|
||||||
subtitle: Text(t.oskKagariDescription, style: subtitleStyle),
|
subtitle: Text(t.oskKagariDescription, style: subtitleStyle),
|
||||||
trailing: DropdownButton(
|
trailing: DropdownButton(
|
||||||
|
@ -141,13 +164,6 @@ class CustomizationState extends State<CustomizationView> {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
// trailing: Switch(value: sheetbotRadarGraphs, onChanged: (bool value){
|
|
||||||
// prefs.setBool("sheetbotRadarGraphs", value);
|
|
||||||
// setState(() {
|
|
||||||
// sheetbotRadarGraphs = value;
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// ),
|
|
||||||
),
|
),
|
||||||
ListTile(title: Text("Sheetbot-like behavior for radar graphs"),
|
ListTile(title: Text("Sheetbot-like behavior for radar graphs"),
|
||||||
subtitle: Text(t.oskKagariDescription, style: subtitleStyle),
|
subtitle: Text(t.oskKagariDescription, style: subtitleStyle),
|
||||||
|
|
|
@ -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/services/crud_exceptions.dart';
|
||||||
import 'package:tetra_stats/utils/numers_formats.dart';
|
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||||
import 'package:tetra_stats/utils/text_shadow.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/views/tl_match_view.dart' show TlMatchResultView;
|
||||||
import 'package:tetra_stats/widgets/finesse_thingy.dart';
|
import 'package:tetra_stats/widgets/finesse_thingy.dart';
|
||||||
import 'package:tetra_stats/widgets/lineclears_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/list_tile_trailing_stats.dart';
|
||||||
import 'package:tetra_stats/widgets/search_box.dart';
|
import 'package:tetra_stats/widgets/search_box.dart';
|
||||||
import 'package:tetra_stats/widgets/stat_sell_num.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/tl_thingy.dart';
|
||||||
import 'package:tetra_stats/widgets/user_thingy.dart';
|
import 'package:tetra_stats/widgets/user_thingy.dart';
|
||||||
import 'package:window_manager/window_manager.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;
|
late ScrollController _scrollController;
|
||||||
final NumberFormat _timeInSec = NumberFormat("#,###.###s.", LocaleSettings.currentLocale.languageCode);
|
final NumberFormat _timeInSec = NumberFormat("#,###.###s.", LocaleSettings.currentLocale.languageCode);
|
||||||
final NumberFormat secs = NumberFormat("00.###", 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 {
|
class MainView extends StatefulWidget {
|
||||||
|
@ -98,7 +95,6 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
||||||
bool _TLHistoryWasFetched = false;
|
bool _TLHistoryWasFetched = false;
|
||||||
late TabController _tabController;
|
late TabController _tabController;
|
||||||
late TabController _wideScreenTabController;
|
late TabController _wideScreenTabController;
|
||||||
late bool fixedScroll;
|
|
||||||
|
|
||||||
String get title => "Tetra Stats: $_titleNickname";
|
String get title => "Tetra Stats: $_titleNickname";
|
||||||
|
|
||||||
|
@ -652,12 +648,7 @@ class _NavDrawerState extends State<NavDrawer> {
|
||||||
leading: const Icon(Icons.leaderboard),
|
leading: const Icon(Icons.leaderboard),
|
||||||
title: Text(t.tlLeaderboard),
|
title: Text(t.tlLeaderboard),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
context.go("/leaderboard");
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const TLLeaderboardView(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -666,12 +657,7 @@ class _NavDrawerState extends State<NavDrawer> {
|
||||||
leading: const Icon(Icons.compress),
|
leading: const Icon(Icons.compress),
|
||||||
title: Text(t.rankAveragesViewTitle),
|
title: Text(t.rankAveragesViewTitle),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
context.go("/LBvalues");
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const RankAveragesView(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -680,12 +666,7 @@ class _NavDrawerState extends State<NavDrawer> {
|
||||||
leading: const Icon(Icons.bar_chart),
|
leading: const Icon(Icons.bar_chart),
|
||||||
title: Text(t.sprintAndBlitsViewTitle),
|
title: Text(t.sprintAndBlitsViewTitle),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
context.go("/sprintAndBlitzAverages");
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const SprintAndBlitzView(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -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}",
|
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)),
|
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}"),
|
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(
|
trailing: TrailingStats(
|
||||||
data[index].endContext.firstWhere((element) => element.userId == userID).secondary,
|
data[index].endContext.firstWhere((element) => element.userId == userID).secondary,
|
||||||
data[index].endContext.firstWhere((element) => element.userId == userID).tertiary,
|
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),
|
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) TextSpan(text: "№${sprint!.rank}", style: TextStyle(color: getColorOfRank(sprint!.rank!))),
|
||||||
if (sprint!.rank != null) const TextSpan(text: " • "),
|
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(
|
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
|
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) const TextSpan(text: " • "),
|
||||||
if (blitz!.rank != null) TextSpan(text: "№${blitz!.rank}", style: TextStyle(color: getColorOfRank(blitz!.rank!))),
|
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) TextSpan(text: "№${record!.rank}", style: TextStyle(color: getColorOfRank(record!.rank!))),
|
||||||
if (record!.rank != null) const TextSpan(text: " • "),
|
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":
|
case "personalbest":
|
||||||
return ListTile(
|
return ListTile(
|
||||||
|
@ -1383,7 +1364,7 @@ class _OtherThingy extends StatelessWidget {
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
subtitle: Text(_dateFormat.format(news.timestamp)),
|
subtitle: Text(timestamp(news.timestamp)),
|
||||||
leading: Image.asset(
|
leading: Image.asset(
|
||||||
"res/icons/improvement-local.png",
|
"res/icons/improvement-local.png",
|
||||||
height: 48,
|
height: 48,
|
||||||
|
@ -1405,7 +1386,7 @@ class _OtherThingy extends StatelessWidget {
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
subtitle: Text(_dateFormat.format(news.timestamp)),
|
subtitle: Text(timestamp(news.timestamp)),
|
||||||
leading: Image.asset(
|
leading: Image.asset(
|
||||||
"res/tetrio_badges/${news.data["type"]}.png",
|
"res/tetrio_badges/${news.data["type"]}.png",
|
||||||
height: 48,
|
height: 48,
|
||||||
|
@ -1427,7 +1408,7 @@ class _OtherThingy extends StatelessWidget {
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
subtitle: Text(_dateFormat.format(news.timestamp)),
|
subtitle: Text(timestamp(news.timestamp)),
|
||||||
leading: Image.asset(
|
leading: Image.asset(
|
||||||
"res/tetrio_tl_alpha_ranks/${news.data["rank"]}.png",
|
"res/tetrio_tl_alpha_ranks/${news.data["rank"]}.png",
|
||||||
height: 48,
|
height: 48,
|
||||||
|
@ -1448,7 +1429,7 @@ class _OtherThingy extends StatelessWidget {
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
subtitle: Text(_dateFormat.format(news.timestamp)),
|
subtitle: Text(timestamp(news.timestamp)),
|
||||||
leading: Image.asset(
|
leading: Image.asset(
|
||||||
"res/icons/supporter-tag.png",
|
"res/icons/supporter-tag.png",
|
||||||
height: 48,
|
height: 48,
|
||||||
|
@ -1469,7 +1450,7 @@ class _OtherThingy extends StatelessWidget {
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
subtitle: Text(_dateFormat.format(news.timestamp)),
|
subtitle: Text(timestamp(news.timestamp)),
|
||||||
leading: Image.asset(
|
leading: Image.asset(
|
||||||
"res/icons/supporter-tag.png",
|
"res/icons/supporter-tag.png",
|
||||||
height: 48,
|
height: 48,
|
||||||
|
@ -1482,7 +1463,7 @@ class _OtherThingy extends StatelessWidget {
|
||||||
default: // if type is unknown
|
default: // if type is unknown
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(t.newsParts.unknownNews(type: news.type)),
|
title: Text(t.newsParts.unknownNews(type: news.type)),
|
||||||
subtitle: Text(_dateFormat.format(news.timestamp)),
|
subtitle: Text(timestamp(news.timestamp)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -264,7 +264,7 @@ class SettingsState extends State<SettingsView> {
|
||||||
subtitle: Text(t.customizationDescription, style: const TextStyle(fontFamily: "Eurostile Round Condensed", color: Colors.grey)),
|
subtitle: Text(t.customizationDescription, style: const TextStyle(fontFamily: "Eurostile Round Condensed", color: Colors.grey)),
|
||||||
trailing: const Icon(Icons.arrow_right),
|
trailing: const Icon(Icons.arrow_right),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.go("/customization");
|
context.go("/settings/customization");
|
||||||
},),
|
},),
|
||||||
ListTile(title: Text("Update stats in the background"),
|
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)),
|
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)),
|
||||||
|
|
|
@ -7,6 +7,7 @@ import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/main.dart' show teto;
|
import 'package:tetra_stats/main.dart' show teto;
|
||||||
import 'package:tetra_stats/views/mathes_view.dart';
|
import 'package:tetra_stats/views/mathes_view.dart';
|
||||||
import 'package:tetra_stats/views/state_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';
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
class StatesView extends StatefulWidget {
|
class StatesView extends StatefulWidget {
|
||||||
|
@ -38,7 +39,6 @@ class StatesState extends State<StatesView> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final t = Translations.of(context);
|
final t = Translations.of(context);
|
||||||
final DateFormat dateFormat = DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms();
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(t.statesViewTitle(number: widget.states.length, nickname: widget.states.last.username.toUpperCase())),
|
title: Text(t.statesViewTitle(number: widget.states.length, nickname: widget.states.last.username.toUpperCase())),
|
||||||
|
@ -60,14 +60,14 @@ class StatesState extends State<StatesView> {
|
||||||
itemCount: widget.states.length,
|
itemCount: widget.states.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return ListTile(
|
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))),
|
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(
|
trailing: IconButton(
|
||||||
icon: const Icon(Icons.delete_forever),
|
icon: const Icon(Icons.delete_forever),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
DateTime nn = widget.states[index].state;
|
DateTime nn = widget.states[index].state;
|
||||||
teto.deleteState(widget.states[index]).then((value) => setState(() {
|
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)))));
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -7,6 +7,7 @@ import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/main.dart' show teto;
|
import 'package:tetra_stats/main.dart' show teto;
|
||||||
import 'package:tetra_stats/utils/filesizes_converter.dart';
|
import 'package:tetra_stats/utils/filesizes_converter.dart';
|
||||||
import 'package:tetra_stats/views/states_view.dart';
|
import 'package:tetra_stats/views/states_view.dart';
|
||||||
|
import 'package:tetra_stats/widgets/text_timestamp.dart';
|
||||||
import 'package:window_manager/window_manager.dart';
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
late String oldWindowTitle;
|
late String oldWindowTitle;
|
||||||
|
@ -37,7 +38,6 @@ class TrackedPlayersState extends State<TrackedPlayersView> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final t = Translations.of(context);
|
final t = Translations.of(context);
|
||||||
final DateFormat dateFormat = DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms();
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(t.trackedPlayersViewTitle),
|
title: Text(t.trackedPlayersViewTitle),
|
||||||
|
@ -109,7 +109,7 @@ class TrackedPlayersState extends State<TrackedPlayersView> {
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(t.trackedPlayersEntry(nickname: allPlayers[keys[index]]!.last.username, numberOfStates: allPlayers[keys[index]]!.length)),
|
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(
|
trailing: IconButton(
|
||||||
icon: const Icon(Icons.delete_forever),
|
icon: const Icon(Icons.delete_forever),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
|
|
@ -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;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
|
@ -3,18 +3,17 @@ import 'package:intl/intl.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
import 'package:tetra_stats/data_objects/tetrio.dart';
|
||||||
import 'package:syncfusion_flutter_gauges/gauges.dart';
|
import 'package:syncfusion_flutter_gauges/gauges.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
|
|
||||||
import 'package:tetra_stats/utils/colors_functions.dart';
|
import 'package:tetra_stats/utils/colors_functions.dart';
|
||||||
import 'package:tetra_stats/utils/numers_formats.dart';
|
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||||
import 'package:tetra_stats/widgets/gauget_num.dart';
|
import 'package:tetra_stats/widgets/gauget_num.dart';
|
||||||
import 'package:tetra_stats/widgets/graphs.dart';
|
import 'package:tetra_stats/widgets/graphs.dart';
|
||||||
import 'package:tetra_stats/widgets/stat_sell_num.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_progress_bar.dart';
|
||||||
import 'package:tetra_stats/widgets/tl_rating_thingy.dart';
|
import 'package:tetra_stats/widgets/tl_rating_thingy.dart';
|
||||||
|
|
||||||
|
|
||||||
var intFDiff = NumberFormat("+#,###;-#,###");
|
var intFDiff = NumberFormat("+#,###;-#,###");
|
||||||
final DateFormat dateFormat = DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms();
|
|
||||||
|
|
||||||
class TLThingy extends StatefulWidget {
|
class TLThingy extends StatefulWidget {
|
||||||
final TetraLeagueAlpha tl;
|
final TetraLeagueAlpha tl;
|
||||||
|
@ -69,7 +68,7 @@ class _TLThingyState extends State<TLThingy> {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
if (widget.showTitle) Text(t.tetraLeague, style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
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,),
|
textAlign: TextAlign.center,),
|
||||||
if (oldTl != null) RangeSlider(values: _currentRangeValues, max: widget.states.length.toDouble(),
|
if (oldTl != null) RangeSlider(values: _currentRangeValues, max: widget.states.length.toDouble(),
|
||||||
labels: RangeLabels(
|
labels: RangeLabels(
|
||||||
|
|
|
@ -10,6 +10,7 @@ import 'package:intl/intl.dart';
|
||||||
import 'package:tetra_stats/utils/text_shadow.dart';
|
import 'package:tetra_stats/utils/text_shadow.dart';
|
||||||
import 'dart:developer' as developer;
|
import 'dart:developer' as developer;
|
||||||
import 'package:tetra_stats/widgets/stat_sell_num.dart';
|
import 'package:tetra_stats/widgets/stat_sell_num.dart';
|
||||||
|
import 'package:tetra_stats/widgets/text_timestamp.dart';
|
||||||
|
|
||||||
const Map<int, double> xpTableScuffed = { // level: xp required
|
const Map<int, double> xpTableScuffed = { // level: xp required
|
||||||
05000: 67009018.4885772,
|
05000: 67009018.4885772,
|
||||||
|
@ -126,7 +127,7 @@ class UserThingy extends StatelessWidget {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
showStateTimestamp
|
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: [
|
: Wrap(direction: Axis.horizontal, alignment: WrapAlignment.center, spacing: 25, crossAxisAlignment: WrapCrossAlignment.start, children: [
|
||||||
FutureBuilder(
|
FutureBuilder(
|
||||||
future: teto.isPlayerTracking(player.userId),
|
future: teto.isPlayerTracking(player.userId),
|
||||||
|
@ -340,7 +341,7 @@ class UserThingy extends StatelessWidget {
|
||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
if (player.country != null) TextSpan(text: "${t.countries[player.country]} • "),
|
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) 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) 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))
|
if (player.supporterTier > 0) TextSpan(text: player.supporterTier.toString(), style: TextStyle(color: player.supporterTier > 1 ? Colors.yellowAccent : Colors.white))
|
||||||
|
|
Loading…
Reference in New Issue