fix #81 , colors for achievements, achievements for tl and qp and erm...

This commit is contained in:
dan63047 2024-12-22 02:28:51 +03:00
parent c1b9db3b15
commit 16abd4c15c
10 changed files with 209 additions and 57 deletions

View File

@ -45,6 +45,27 @@ const List<String> ranks = [
"x",
"x+"
];
const List<String> ranks2 = [
"top1",
"x+",
"x",
"u",
"ss",
"s+",
"s",
"s-",
"a+",
"a",
"a-",
"b+",
"b",
"b-",
"c+",
"c",
"c-",
"d+",
"d"
];
const Map<String, double> rankCutoffs = {
"x+": 0.002,
"x": 0.01,
@ -178,6 +199,16 @@ const Map<String, Color> rankColors = {
'top1': Colors.yellowAccent
};
const List<Color> achievementColors = [
Colors.grey,
Color(0xFFB38070), // bronze
Color(0xFF7E9EA7), // silver
Color(0xFFE2A042), // gold
Color(0xFF70D0A3), // platinum
Color(0xFFD590FF), // diamond
Colors.white,
];
const Map<String, Duration> sprintAverages = {
// based on https://discord.com/channels/673303546107658242/674421736162197515/1277367281264889908
'x+': Duration(seconds: 18, milliseconds: 867),

View File

@ -4,9 +4,9 @@
/// To regenerate, run: `dart run slang`
///
/// Locales: 2
/// Strings: 1528 (764 per locale)
/// Strings: 1530 (765 per locale)
///
/// Built on 2024-12-12 at 21:30 UTC
/// Built on 2024-12-21 at 17:08 UTC
// coverage:ignore-file
// ignore_for_file: type=lint
@ -187,6 +187,7 @@ class Translations implements BaseTranslations<AppLocale, Translations> {
String get nerdStats => 'Nerd Stats';
String get playstyles => 'Playstyles';
String get horoscopes => 'Horoscopes';
String get relatedAchievements => 'Related Achievements';
String get season => 'Season';
String get smooth => 'Smooth';
String get dateAndTime => 'Date & Time';
@ -890,7 +891,7 @@ class _StringsSettingsDestinationEn {
// Translations
String get title => 'Settings';
String get general => 'General';
String get customization => 'Custonization';
String get customization => 'Customization';
String get database => 'Local database';
String get checking => 'Checking...';
String get enterToSubmit => 'Press Enter to submit';
@ -1726,6 +1727,7 @@ class _StringsRuRu implements Translations {
@override String get nerdStats => 'Для Задротов';
@override String get playstyles => 'Стили игры';
@override String get horoscopes => 'Гороскопы';
@override String get relatedAchievements => 'Достижения режима';
@override String get season => 'Сезон';
@override String get smooth => 'Сглаживание';
@override String get dateAndTime => 'Дата и время';
@ -3248,6 +3250,7 @@ extension on Translations {
case 'nerdStats': return 'Nerd Stats';
case 'playstyles': return 'Playstyles';
case 'horoscopes': return 'Horoscopes';
case 'relatedAchievements': return 'Related Achievements';
case 'season': return 'Season';
case 'smooth': return 'Smooth';
case 'dateAndTime': return 'Date & Time';
@ -3477,7 +3480,7 @@ extension on Translations {
case 'savedDataDestination.TLrecords': return 'TL Records';
case 'settingsDestination.title': return 'Settings';
case 'settingsDestination.general': return 'General';
case 'settingsDestination.customization': return 'Custonization';
case 'settingsDestination.customization': return 'Customization';
case 'settingsDestination.database': return 'Local database';
case 'settingsDestination.checking': return 'Checking...';
case 'settingsDestination.enterToSubmit': return 'Press Enter to submit';
@ -4061,6 +4064,7 @@ extension on _StringsRuRu {
case 'nerdStats': return 'Для Задротов';
case 'playstyles': return 'Стили игры';
case 'horoscopes': return 'Гороскопы';
case 'relatedAchievements': return 'Достижения режима';
case 'season': return 'Сезон';
case 'smooth': return 'Сглаживание';
case 'dateAndTime': return 'Дата и время';

View File

@ -35,7 +35,7 @@ import 'package:tetra_stats/services/sqlite_db_controller.dart';
import 'package:csv/csv.dart';
const String dbName = "TetraStats.db";
const String webVersionDomain = "tsbeta.dan63.by";
const String webVersionDomain = "ts.dan63.by";
const String tetrioUsersTable = "tetrioUsers";
const String tetrioUsersToTrackTable = "tetrioUsersToTrack";
const String tetraLeagueMatchesTable = "tetrioAlphaLeagueMathces";
@ -831,7 +831,12 @@ class TetrioService extends DB {
Uri url;
if (kIsWeb) {
url = Uri.https(webVersionDomain, 'oskware_bridge.php', {"endpoint": "TLLeaderboard"});
url = Uri.https(webVersionDomain, 'oskware_bridge.php', {
"endpoint": "leaderboard",
"lb": lb??"league",
if (prisecter != null) "after": prisecter,
if (country != null) "country": country
});
} else {
url = Uri.https('ch.tetr.io', 'api/users/by/${lb??"league"}', {
"limit": "100",

View File

@ -1,3 +1,5 @@
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_layout_grid/flutter_layout_grid.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
@ -15,6 +17,7 @@ import 'package:tetra_stats/data_objects/summaries.dart';
import 'package:tetra_stats/data_objects/tetra_league.dart';
import 'package:tetra_stats/data_objects/tetrio_constants.dart';
import 'package:tetra_stats/data_objects/tetrio_player.dart';
import 'package:tetra_stats/data_objects/tetrio_player_from_leaderboard.dart';
import 'package:tetra_stats/gen/strings.g.dart';
import 'package:tetra_stats/main.dart';
import 'package:tetra_stats/utils/colors_functions.dart';
@ -120,8 +123,9 @@ class ZenithCard extends StatelessWidget {
final RecordSingle? record;
final bool old;
final double width;
final List<Achievement> achievements;
const ZenithCard(this.record, this.old, {this.width = double.infinity});
const ZenithCard(this.record, this.old, this.achievements, {this.width = double.infinity});
Widget splitsCard(){
return Card(
@ -246,7 +250,23 @@ class ZenithCard extends StatelessWidget {
),
),
if (record != null) NerdStatsThingy(nerdStats: record!.aggregateStats.nerdStats, width: width),
if (record != null) Graphs(record!.aggregateStats.apm, record!.aggregateStats.pps, record!.aggregateStats.vs, record!.aggregateStats.nerdStats, record!.aggregateStats.playstyle)
if (record != null) Graphs(record!.aggregateStats.apm, record!.aggregateStats.pps, record!.aggregateStats.vs, record!.aggregateStats.nerdStats, record!.aggregateStats.playstyle),
if (achievements.isNotEmpty) Card(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Spacer(),
Text(t.relatedAchievements, style: Theme.of(context).textTheme.titleLarge),
const Spacer()
],
),
),
if (achievements.isNotEmpty) Wrap(
direction: Axis.horizontal,
children: [
for (Achievement achievement in achievements) FractionallySizedBox(widthFactor: 1/((width/600).ceil()), child: AchievementSummary(achievement: achievement)),
],
),
],
);
}
@ -573,11 +593,10 @@ class AchievementSummary extends StatelessWidget{
),
child: ClipRect(
child: Align(
alignment: Alignment.topLeft.add(Alignment(0.285 * (((achievement?.k??1) - 1) % 8), 0.285 * (((achievement?.k??0) - 1) / 8).floor())),
//alignment: Alignment.topLeft.add(Alignment(0.285 * 1, 0)),
alignment: Alignment.topLeft.add(Alignment(0.286 * (((achievement?.k??1) - 1) % 8), 0.286 * (((achievement?.k??0) - 1) / 8).floor())),
heightFactor: 0.125,
widthFactor: 0.125,
child: Image.asset("res/icons/achievements.png", width: 2048, height: 2048, scale: 1, color: achievement?.v == null ? Colors.grey : Colors.white),
child: Image.asset("res/icons/achievements.png", width: 2048, height: 2048, scale: 1, color: achievement?.v == null ? Colors.grey : achievementColors[min(achievement!.rank!, 6)]),
),
),
),
@ -718,7 +737,6 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
1 2
3 4
5 6
7 7
''' : '''
t
1
@ -727,10 +745,9 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
4
5
6
7
''',
columnSizes: width > 600 ? [auto, auto] : [auto],
rowSizes: width > 600 ? [auto, auto, auto, auto, auto, auto] : [auto, auto, auto, auto, auto, auto, auto, auto],
rowSizes: width > 600 ? [auto, auto, auto, auto, auto] : [auto, auto, auto, auto, auto, auto, auto],
columnGap: 0,
rowGap: 0,
children: [
@ -869,34 +886,11 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
),
),
).inGridArea('6'),
if (summaries.achievements.isNotEmpty) Card(
child: Padding(
padding: const EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 0.0),
child: Column(
children: [
if (summaries.achievements.firstWhere((e) => e.k == 16).v != null) Row(
children: [
const Text("Total height climbed in QP"),
const Spacer(),
Text("${f2.format(summaries.achievements.firstWhere((e) => e.k == 16).v!)} m"),
],
),
if (summaries.achievements.firstWhere((e) => e.k == 17).v != null) Row(
children: [
const Text("KO's in QP"),
const Spacer(),
Text(intf.format(summaries.achievements.firstWhere((e) => e.k == 17).v!)),
],
)
],
),
),
).inGridArea('7')
],
);
}
Widget getTetraLeagueCard(TetraLeague data, Cutoffs? cutoffs, CutoffTetrio? averages, List<TetraLeague> states, PlayerLeaderboardPosition? lbPos, double width){
Widget getTetraLeagueCard(TetraLeague data, Cutoffs? cutoffs, CutoffTetrio? averages, List<TetraLeague> states, PlayerLeaderboardPosition? lbPos, double width, List<Achievement> achievements){
TetraLeague toSee;
TetraLeague? toCompare;
if (currentRangeValues.start.round() == 0){
@ -963,7 +957,24 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
),
),
if (data.nerdStats != null) NerdStatsThingy(nerdStats: toSee.nerdStats!, oldNerdStats: toCompare?.nerdStats, averages: averages, lbPos: lbPos, width: width),
if (data.nerdStats != null) Graphs(toSee.apm!, toSee.pps!, toSee.vs!, toSee.nerdStats!, toSee.playstyle!)
if (data.nerdStats != null) Graphs(toSee.apm!, toSee.pps!, toSee.vs!, toSee.nerdStats!, toSee.playstyle!),
Card(
//surfaceTintColor: rankColors[data.rank],
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Spacer(),
Text(t.relatedAchievements, style: Theme.of(context).textTheme.titleLarge),
const Spacer()
],
),
),
Wrap(
direction: Axis.horizontal,
children: [
for (Achievement achievement in achievements) FractionallySizedBox(widthFactor: 1/((width/600).ceil()), child: AchievementSummary(achievement: achievement)),
],
),
],
);
}
@ -1164,19 +1175,19 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
super.initState();
}
Widget rigthCard(AsyncSnapshot<FetchResults> snapshot, List<Achievement> sprintAchievements, List<Achievement> blitzAchievements, double width){
Widget rigthCard(AsyncSnapshot<FetchResults> snapshot, List<Achievement> sprintAchievements, List<Achievement> blitzAchievements, List<Achievement> tlAchievements, List<Achievement> qpAchievements, List<Achievement> qpExAchievements, double width){
return switch (rightCard){
Cards.overview => getOverviewCard(snapshot.data!.summaries!, (snapshot.data!.averages != null && snapshot.data!.summaries!.league.rank != "z") ? snapshot.data!.averages!.data[snapshot.data!.summaries!.league.rank] : (snapshot.data!.averages != null && snapshot.data!.summaries!.league.percentileRank != "z") ? snapshot.data!.averages!.data[snapshot.data!.summaries!.league.percentileRank] : null, width),
Cards.tetraLeague => switch (cardMod){
CardMod.info => getTetraLeagueCard(snapshot.data!.summaries!.league, snapshot.data!.cutoffs, (snapshot.data!.averages != null && snapshot.data!.summaries!.league.rank != "z") ? snapshot.data!.averages!.data[snapshot.data!.summaries!.league.rank] : (snapshot.data!.averages != null && snapshot.data!.summaries!.league.percentileRank != "z") ? snapshot.data!.averages!.data[snapshot.data!.summaries!.league.percentileRank] : null, snapshot.data!.states, snapshot.data!.playerPos, width),
CardMod.info => getTetraLeagueCard(snapshot.data!.summaries!.league, snapshot.data!.cutoffs, (snapshot.data!.averages != null && snapshot.data!.summaries!.league.rank != "z") ? snapshot.data!.averages!.data[snapshot.data!.summaries!.league.rank] : (snapshot.data!.averages != null && snapshot.data!.summaries!.league.percentileRank != "z") ? snapshot.data!.averages!.data[snapshot.data!.summaries!.league.percentileRank] : null, snapshot.data!.states, snapshot.data!.playerPos, width, tlAchievements),
CardMod.ex => getPreviousSeasonsList(snapshot.data!.summaries!.pastLeague, width),
CardMod.records => getRecentTLrecords(widget.constraints, snapshot.data!.player!.userId),
_ => const Center(child: Text("huh?"))
},
Cards.quickPlay => switch (cardMod){
CardMod.info => ZenithCard(snapshot.data?.summaries?.zenith != null ? snapshot.data!.summaries!.zenith : snapshot.data!.summaries?.zenithCareerBest, snapshot.data!.summaries?.zenith == null, width: width),
CardMod.info => ZenithCard(snapshot.data?.summaries?.zenith != null ? snapshot.data!.summaries!.zenith : snapshot.data!.summaries?.zenithCareerBest, snapshot.data!.summaries?.zenith == null, qpAchievements, width: width),
CardMod.records => getListOfRecords("zenith/recent", "zenith/top", widget.constraints),
CardMod.ex => ZenithCard(snapshot.data?.summaries?.zenithEx != null ? snapshot.data!.summaries!.zenithEx : snapshot.data!.summaries?.zenithExCareerBest, snapshot.data!.summaries?.zenithEx == null, width: width),
CardMod.ex => ZenithCard(snapshot.data?.summaries?.zenithEx != null ? snapshot.data!.summaries!.zenithEx : snapshot.data!.summaries?.zenithExCareerBest, snapshot.data!.summaries?.zenithEx == null, qpExAchievements, width: width),
CardMod.exRecords => getListOfRecords("zenithex/recent", "zenithex/top", widget.constraints),
},
Cards.sprint => switch (cardMod){
@ -1224,6 +1235,48 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
closestAverageBlitz = blitzAverages.entries.last;
blitzBetterThanClosestAverage = false;
}
List<Achievement> tlAchievements = snapshot.data!.summaries!.achievements.isNotEmpty ? <Achievement>[
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 10),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 12),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 13),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 14),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 15),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 47),
] : [];
List<Achievement> qpAchievements = snapshot.data!.summaries!.achievements.isNotEmpty ? <Achievement>[
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 16),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 17),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 18),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 20),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 21),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 22),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 23),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 24),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 25),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 26),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 27),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 28),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 29),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 30),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 33),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 41),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 43),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 44),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 45),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 46),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 51),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 54),
] : [];
List<Achievement> qpExAchievements = snapshot.data!.summaries!.achievements.isNotEmpty ? <Achievement>[
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 19),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 31),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 32),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 34),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 40),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 49),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 50),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 53),
] : [];
List<Achievement> sprintAchievements = snapshot.data!.summaries!.achievements.isNotEmpty ? <Achievement>[
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 5),
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 7),
@ -1293,7 +1346,7 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
child: SlideTransition(
position: _offsetAnimation,
child: SingleChildScrollView(
child: rigthCard(snapshot, sprintAchievements, blitzAchievements, width - 450),
child: rigthCard(snapshot, sprintAchievements, blitzAchievements, tlAchievements, qpAchievements, qpExAchievements, width - 450),
),
),
),
@ -1351,7 +1404,7 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
if (snapshot.data!.player!.role == "bot") FakeDistinguishmentThingy(bot: true, botMaintainers: snapshot.data!.player!.botmaster),
if (snapshot.data!.player!.role == "banned") FakeDistinguishmentThingy(banned: true)
else if (snapshot.data!.player!.badstanding == true) FakeDistinguishmentThingy(badStanding: true),
rigthCard(snapshot, sprintAchievements, blitzAchievements, width),
rigthCard(snapshot, sprintAchievements, blitzAchievements, tlAchievements, qpAchievements, qpExAchievements, width),
if (rightCard == Cards.overview) Card(
child: Column(
children: [

View File

@ -32,8 +32,8 @@ class SingleplayerRecordView extends StatelessWidget {
maxWidth: 768
),
child: switch (record.gamemode){
"zenith" => ZenithCard(record, false, width: MediaQuery.of(context).size.width),
"zenithex" => ZenithCard(record, false, width: MediaQuery.of(context).size.width),
"zenith" => ZenithCard(record, false, [], width: MediaQuery.of(context).size.width),
"zenithex" => ZenithCard(record, false, [], width: MediaQuery.of(context).size.width),
_ => SingleplayerRecord(record: record, hideTitle: true)
},
),

View File

@ -55,19 +55,19 @@ class TetraLeagueThingy extends StatelessWidget{
@override
Widget build(BuildContext context) {
print(ranks2.indexOf(league.rank != "z" ? league.rank : league.percentileRank)-1);
return Card(
//surfaceTintColor: rankColors[league.rank],
child: Column(
children: [
TLRatingThingy(userID: league.id, tlData: league, oldTl: toCompare, showPositions: true),
if (league.gamesPlayed > 9) TLProgress(
tlData: league,
previousRankTRcutoff: cutoffs != null ? cutoffs!.tr[league.rank != "z" ? league.rank : league.percentileRank] : null,
nextRankTRcutoff: cutoffs != null ? (league.rank != "z" ? league.rank == "x+" : league.percentileRank == "x+") ? 25000 : cutoffs!.tr[ranks.elementAtOrNull(ranks.indexOf(league.rank != "z" ? league.rank : league.percentileRank)+1)] : null,
nextRankTRcutoff: cutoffs != null ? cutoffs!.tr[ranks2[ranks2.indexOf(league.rank != "z" ? league.rank : league.percentileRank)-1]] : null,
previousRankTRcutoffTarget: league.rank != "z" ? rankTargets[league.rank] : null,
nextRankTRcutoffTarget: (league.rank != "z" && league.rank != "x+") ? rankTargets[ranks.elementAtOrNull(ranks.indexOf(league.rank)+1)] : null,
nextRankTRcutoffTarget: (league.rank != "z" && league.rank != "x+") ? rankTargets[ranks2[ranks2.indexOf(league.rank != "z" ? league.rank : league.percentileRank)-1]] : null,
previousGlickoCutoff: cutoffs != null ? cutoffs!.glicko[league.rank != "z" ? league.rank : league.percentileRank] : null,
nextRankGlickoCutoff: cutoffs != null ? (league.rank != "z" ? league.rank == "x+" : league.percentileRank == "x+") ? 25000 : cutoffs!.glicko[ranks.elementAtOrNull(ranks.indexOf(league.rank != "z" ? league.rank : league.percentileRank)+1)] : null,
nextRankGlickoCutoff: cutoffs != null ? cutoffs!.glicko[ranks2[ranks2.indexOf(league.rank != "z" ? league.rank : league.percentileRank)-1]] : null,
),
Row(
crossAxisAlignment: CrossAxisAlignment.center,

View File

@ -1,7 +1,9 @@
import 'dart:math';
import 'dart:ui' as ui;
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart' show Size;
import 'package:intl/intl.dart';
import 'package:syncfusion_flutter_gauges/gauges.dart';
import 'package:tetra_stats/data_objects/tetrio_constants.dart';
@ -16,6 +18,45 @@ import 'package:tetra_stats/views/compare_view_tiles.dart';
import 'package:tetra_stats/widgets/text_timestamp.dart';
import 'package:transparent_image/transparent_image.dart';
Future<ui.Image> osksFuture = loadImage(Uri.https("tetr.io", "/user-content/banners/5e32fc85ab319c2ab1beb07c.jpg", {"rv": "1628366386763"}));
Future<ui.Image> loadImage(Uri url) async {
final response = await teto.client.get(url);
return await decodeImageFromList(response.bodyBytes);
}
Widget createCustomImage(ui.Image image) {
return SizedBox(
width: image.width.toDouble(),
height: image.height.toDouble()/64,
child: CustomPaint(
size: Size(128.0, 128.0),
painter: ImagePainter(image),
),
);
}
class ImagePainter extends CustomPainter {
ImagePainter(ui.Image this.image);
final ui.Image image;
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.red
..strokeWidth = 5
..style = PaintingStyle.stroke;
canvas.translate(-240, 0);
canvas.scale(0.5);
canvas.drawImage(image, Offset.zero, paint);
}
@override
bool shouldRepaint(ImagePainter oldDelegate) =>
image != oldDelegate.image;
}
class UserThingy extends StatefulWidget {
final TetrioPlayer player;
final bool showStateTimestamp;
@ -103,14 +144,30 @@ class _UserThingyState extends State<UserThingy> with SingleTickerProviderStateM
constraints: const BoxConstraints(maxWidth: 960),
height: widget.player.bannerRevision != null ? 218.0 : 138.0,
child: Stack(
//clipBehavior: Clip.none,
children: [
// TODO: osk banner can cause memory leak
if (widget.player.bannerRevision != null) FadeInImage.memoryNetwork(image: kIsWeb ? "https://ts.dan63.by/oskware_bridge.php?endpoint=TetrioBanner&user=${widget.player.userId}&rv=${widget.player.bannerRevision}" : "https://tetr.io/user-content/banners/${widget.player.userId}.jpg?rv=${widget.player.bannerRevision}",
// Very weird solution to draw only the first frame of the gif
if (widget.player.userId == "5e32fc85ab319c2ab1beb07c") FutureBuilder<ui.Image>(
future: osksFuture,
builder: (context, snapshot) {
switch (snapshot.connectionState){
case ConnectionState.none:
case ConnectionState.waiting:
case ConnectionState.active:
return SizedBox(width: 960);
case ConnectionState.done:
return createCustomImage(snapshot.data!);
}
},
) // If not osk, using a normal widget like a normal human being
else if (widget.player.bannerRevision != null) FadeInImage.memoryNetwork(
image: kIsWeb ? "https://ts.dan63.by/oskware_bridge.php?endpoint=TetrioBanner&user=${widget.player.userId}&rv=${widget.player.bannerRevision}" : "https://tetr.io/user-content/banners/${widget.player.userId}.jpg?rv=${widget.player.bannerRevision}",
placeholder: kTransparentImage,
fit: BoxFit.cover,
height: 120,
fadeInCurve: Easing.standard, fadeInDuration: Durations.long4
fadeInCurve: Easing.standard, fadeInDuration: Durations.long4,
imageErrorBuilder: (context, object, trace){
return SizedBox(width: 960);
}
),
Positioned(
top: widget.player.bannerRevision != null ? 90.0 : 10.0,

View File

@ -2,7 +2,7 @@ name: tetra_stats
description: Track your and other player stats in TETR.IO
publish_to: 'none'
version: 2.0.0-beta+339
version: 2.0.0-beta2+40
environment:
sdk: '>=3.0.0'

View File

@ -47,6 +47,7 @@
"nerdStats": "Nerd Stats",
"playstyles": "Playstyles",
"horoscopes": "Horoscopes",
"relatedAchievements": "Related Achievements",
"season": "Season",
"smooth": "Smooth",
"dateAndTime": "Date & Time",
@ -286,7 +287,7 @@
"settingsDestination": {
"title": "Settings",
"general": "General",
"customization": "Custonization",
"customization": "Customization",
"database": "Local database",
"checking": "Checking...",
"enterToSubmit": "Press Enter to submit",

View File

@ -47,6 +47,7 @@
"nerdStats": "Для Задротов",
"playstyles": "Стили игры",
"horoscopes": "Гороскопы",
"relatedAchievements": "Достижения режима",
"season": "Сезон",
"smooth": "Сглаживание",
"dateAndTime": "Дата и время",