Lazy loading for a leaderboards in redesign was implemented
This commit is contained in:
parent
a2a85ce151
commit
c3214f5ba9
|
@ -150,7 +150,11 @@ class TetraLeague {
|
|||
apm ?? 0,
|
||||
pps ?? 0,
|
||||
vs ?? 0,
|
||||
decaying);
|
||||
decaying,
|
||||
-1,
|
||||
-1,
|
||||
Duration(seconds: -1),
|
||||
-1);
|
||||
|
||||
num? getStatByEnum(Stats stat){
|
||||
switch (stat) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// ignore_for_file: hash_and_equals
|
||||
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:tetra_stats/data_objects/est_tr.dart';
|
||||
import 'package:tetra_stats/data_objects/nerd_stats.dart';
|
||||
import 'package:tetra_stats/data_objects/playstyle.dart';
|
||||
|
@ -27,6 +29,10 @@ class TetrioPlayerFromLeaderboard {
|
|||
late NerdStats nerdStats;
|
||||
late EstTr estTr;
|
||||
late Playstyle playstyle;
|
||||
late int gamesPlayedTotal;
|
||||
late int gamesWonTotal;
|
||||
late Duration playtime;
|
||||
late int ar;
|
||||
|
||||
TetrioPlayerFromLeaderboard(
|
||||
this.userId,
|
||||
|
@ -46,13 +52,19 @@ class TetrioPlayerFromLeaderboard {
|
|||
this.apm,
|
||||
this.pps,
|
||||
this.vs,
|
||||
this.decaying){
|
||||
this.decaying,
|
||||
this.gamesPlayedTotal,
|
||||
this.gamesWonTotal,
|
||||
this.playtime,
|
||||
this.ar){
|
||||
nerdStats = NerdStats(apm, pps, vs);
|
||||
estTr = EstTr(apm, pps, vs, nerdStats.app, nerdStats.dss, nerdStats.dsp, nerdStats.gbe);
|
||||
playstyle = Playstyle(apm, pps, nerdStats.app, nerdStats.vsapm, nerdStats.dsp, nerdStats.gbe, estTr.srarea, estTr.statrank);
|
||||
}
|
||||
|
||||
double get winrate => gamesWon / gamesPlayed;
|
||||
double get winrateTotal => gamesWonTotal / gamesWonTotal;
|
||||
double get level => pow((xp / 500), 0.6) + (xp / (5000 + (max(0, xp - 4 * pow(10, 6)) / 5000))) + 1;
|
||||
double get esttracc => estTr.esttr - tr;
|
||||
double get s1tr => gxe * 250;
|
||||
|
||||
|
@ -66,7 +78,7 @@ class TetrioPlayerFromLeaderboard {
|
|||
gamesPlayed = json['league']['gamesplayed'] as int;
|
||||
gamesWon = json['league']['gameswon'] as int;
|
||||
tr = json['league']['tr'] != null ? json['league']['tr'].toDouble() : 0;
|
||||
gxe = json['league']['gxe']??-1;
|
||||
gxe = json['league']['gxe']?.toDouble();
|
||||
glicko = json['league']['glicko']?.toDouble();
|
||||
rd = json['league']['rd']?.toDouble();
|
||||
rank = json['league']['rank'];
|
||||
|
@ -75,6 +87,10 @@ class TetrioPlayerFromLeaderboard {
|
|||
pps = json['league']['pps'] != null ? json['league']['pps'].toDouble() : 0.00;
|
||||
vs = json['league']['vs'] != null ? json['league']['vs'].toDouble(): 0.00;
|
||||
decaying = json['league']['decaying'];
|
||||
gamesPlayedTotal = json['gamesplayed'] as int;
|
||||
gamesWonTotal = json['gameswon'] as int;
|
||||
playtime = Duration(microseconds: (json['gametime'].toDouble() * 1000000).floor());
|
||||
ar = json['ar'];
|
||||
nerdStats = NerdStats(apm, pps, vs);
|
||||
estTr = EstTr(apm, pps, vs, nerdStats.app, nerdStats.dss, nerdStats.dsp, nerdStats.gbe);
|
||||
playstyle = Playstyle(apm, pps, nerdStats.app, nerdStats.vsapm, nerdStats.dsp, nerdStats.gbe, estTr.srarea, estTr.statrank);
|
||||
|
|
|
@ -798,34 +798,60 @@ class TetrioService extends DB {
|
|||
}
|
||||
}
|
||||
|
||||
// Stream<TetrioPlayersLeaderboard> fetchFullLeaderboard() async* {
|
||||
// late double after;
|
||||
// int lbLength = 100;
|
||||
// TetrioPlayersLeaderboard leaderboard = await fetchTLLeaderboard();
|
||||
// after = leaderboard.leaderboard.last.tr;
|
||||
// while (lbLength == 100){
|
||||
// TetrioPlayersLeaderboard pseudoLb = await fetchTLLeaderboard(after: after);
|
||||
// leaderboard.addPlayers(pseudoLb.leaderboard);
|
||||
// lbLength = pseudoLb.leaderboard.length;
|
||||
// after = pseudoLb.leaderboard.last.tr;
|
||||
// yield leaderboard;
|
||||
// }
|
||||
// }
|
||||
|
||||
// i want to know progress, so i trying to figure out this thing:
|
||||
// Stream<TetrioPlayersLeaderboard> fetchTLLeaderboardAsStream() async {
|
||||
// TetrioPlayersLeaderboard? cached = _cache.get("league", TetrioPlayersLeaderboard);
|
||||
// if (cached != null) return cached;
|
||||
Future<List<TetrioPlayerFromLeaderboard>> fetchTetrioLeaderboard({double? after, String? lb}) async {
|
||||
const int lbLength = 100;
|
||||
// TetrioPlayersLeaderboard? cached = _cache.get("league", TetrioPlayersLeaderboard);
|
||||
// if (cached != null) return cached;
|
||||
|
||||
// Uri url;
|
||||
// if (kIsWeb) {
|
||||
// url = Uri.https('ts.dan63.by', 'oskware_bridge.php', {"endpoint": "TLLeaderboard"});
|
||||
// } else {
|
||||
// url = Uri.https('ch.tetr.io', 'api/users/lists/league/all');
|
||||
// }
|
||||
Uri url;
|
||||
if (kIsWeb) {
|
||||
url = Uri.https('ts.dan63.by', 'oskware_bridge.php', {"endpoint": "TLLeaderboard"});
|
||||
} else {
|
||||
url = Uri.https('ch.tetr.io', 'api/users/by/${lb??"league"}', {
|
||||
"limit": "100",
|
||||
if (after != null && after != -1) "after": "$after:0:0"
|
||||
});
|
||||
}
|
||||
try{
|
||||
final response = await client.get(url);
|
||||
|
||||
// Stream<TetrioPlayersLeaderboard> stream = http.StreamedRequest("GET", url);
|
||||
// }
|
||||
switch (response.statusCode) {
|
||||
case 200:
|
||||
_lbPositions.clear();
|
||||
var rawJson = jsonDecode(response.body);
|
||||
if (rawJson['success']) { // if api confirmed that everything ok
|
||||
List<TetrioPlayerFromLeaderboard> leaderboard = [];
|
||||
for (Map<String, dynamic> entry in rawJson['data']['entries']) {
|
||||
leaderboard.add(TetrioPlayerFromLeaderboard.fromJson(entry, DateTime.fromMillisecondsSinceEpoch(rawJson['cache']['cached_at'])));
|
||||
}
|
||||
developer.log("fetchTLLeaderboard: Leaderboard retrieved and cached", name: "services/tetrio_crud");
|
||||
//_leaderboardsCache[rawJson['cache']['cached_until'].toString()] = leaderboard;
|
||||
//_cache.store(leaderboard, rawJson['cache']['cached_until']);
|
||||
return leaderboard;
|
||||
} else { // idk how to hit that one
|
||||
developer.log("fetchTLLeaderboard: Bruh", name: "services/tetrio_crud", error: rawJson);
|
||||
throw Exception("Failed to get leaderboard (problems on the tetr.io side)"); // will it be on tetr.io side?
|
||||
}
|
||||
case 403:
|
||||
throw TetrioForbidden();
|
||||
case 429:
|
||||
throw TetrioTooManyRequests();
|
||||
case 418:
|
||||
throw TetrioOskwareBridgeProblem();
|
||||
case 500:
|
||||
case 502:
|
||||
case 503:
|
||||
case 504:
|
||||
throw TetrioInternalProblem();
|
||||
default:
|
||||
developer.log("fetchTLLeaderboard: Failed to fetch leaderboard", name: "services/tetrio_crud", error: response.statusCode);
|
||||
throw ConnectionIssue(response.statusCode, response.reasonPhrase??"No reason");
|
||||
}
|
||||
} on http.ClientException catch (e, s) {
|
||||
developer.log("$e, $s");
|
||||
throw http.ClientException(e.message, e.uri);
|
||||
}
|
||||
}
|
||||
|
||||
TetrioPlayersLeaderboard? getCachedLeaderboard(){
|
||||
return _cache.get("league", TetrioPlayersLeaderboard);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart' hide Badge;
|
||||
|
@ -207,6 +209,23 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
|||
}
|
||||
}
|
||||
|
||||
class DestinationCutoffs extends StatefulWidget{
|
||||
final BoxConstraints constraints;
|
||||
|
||||
const DestinationCutoffs({super.key, required this.constraints});
|
||||
|
||||
@override
|
||||
State<DestinationLeaderboards> createState() => _DestinationCutoffsState();
|
||||
}
|
||||
|
||||
class _DestinationCutoffsState extends State<DestinationLeaderboards> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// TODO: implement build
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
class DestinationLeaderboards extends StatefulWidget{
|
||||
final BoxConstraints constraints;
|
||||
|
||||
|
@ -216,10 +235,72 @@ class DestinationLeaderboards extends StatefulWidget{
|
|||
State<DestinationLeaderboards> createState() => _DestinationLeaderboardsState();
|
||||
}
|
||||
|
||||
enum Leaderboards{
|
||||
tl,
|
||||
xp,
|
||||
ar
|
||||
}
|
||||
|
||||
class _DestinationLeaderboardsState extends State<DestinationLeaderboards> {
|
||||
Cards rightCard = Cards.tetraLeague;
|
||||
//Duration postSeasonLeft = seasonStart.difference(DateTime.now());
|
||||
final List<String> leaderboards = ["Tetra League", "Quick Play", "Quick Play Expert"];
|
||||
final Map<Leaderboards, String> leaderboards = {Leaderboards.tl: "Tetra League", Leaderboards.xp: "XP", Leaderboards.ar: "Acievement Points"};
|
||||
Leaderboards _currentLb = Leaderboards.tl;
|
||||
final StreamController<List<TetrioPlayerFromLeaderboard>> _dataStreamController = StreamController<List<TetrioPlayerFromLeaderboard>>();
|
||||
late final ScrollController _scrollController;
|
||||
Stream<List<TetrioPlayerFromLeaderboard>> get dataStream => _dataStreamController.stream;
|
||||
List<TetrioPlayerFromLeaderboard> list = [];
|
||||
bool _isFetchingData = false;
|
||||
double after = 25000.00;
|
||||
|
||||
Future<void> _fetchData() async {
|
||||
if (_isFetchingData) {
|
||||
// Avoid fetching new data while already fetching
|
||||
return;
|
||||
}
|
||||
try {
|
||||
_isFetchingData = true;
|
||||
setState(() {});
|
||||
|
||||
final items = switch(_currentLb){
|
||||
Leaderboards.tl => await teto.fetchTetrioLeaderboard(after: after),
|
||||
Leaderboards.xp => await teto.fetchTetrioLeaderboard(after: after, lb: "xp"),
|
||||
Leaderboards.ar => await teto.fetchTetrioLeaderboard(after: after, lb: "ar"),
|
||||
};
|
||||
|
||||
list.addAll(items);
|
||||
|
||||
_dataStreamController.add(list);
|
||||
after = switch (_currentLb){
|
||||
Leaderboards.tl => list.last.tr,
|
||||
Leaderboards.xp => list.last.xp,
|
||||
Leaderboards.ar => list.last.ar.toDouble(),
|
||||
};
|
||||
} catch (e) {
|
||||
_dataStreamController.addError(e);
|
||||
} finally {
|
||||
// Set to false when data fetching is complete
|
||||
_isFetchingData = false;
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_scrollController = ScrollController();
|
||||
_fetchData();
|
||||
_scrollController.addListener(() {
|
||||
_scrollController.addListener(() {
|
||||
final maxScroll = _scrollController.position.maxScrollExtent;
|
||||
final currentScroll = _scrollController.position.pixels;
|
||||
|
||||
if (currentScroll == maxScroll) {
|
||||
// When the last item is fully visible, load the next page.
|
||||
_fetchData();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -247,7 +328,17 @@ class _DestinationLeaderboardsState extends State<DestinationLeaderboards> {
|
|||
return Card(
|
||||
surfaceTintColor: theme.colorScheme.primary,
|
||||
child: ListTile(
|
||||
title: Text(leaderboards[index]),
|
||||
title: Text(leaderboards.values.elementAt(index)),
|
||||
onTap: () {
|
||||
_currentLb = leaderboards.keys.elementAt(index);
|
||||
list.clear();
|
||||
after = switch (_currentLb){
|
||||
Leaderboards.tl => 25000.00,
|
||||
Leaderboards.xp => -1.00,
|
||||
Leaderboards.ar => -1.00,
|
||||
};
|
||||
_fetchData();
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -258,11 +349,45 @@ class _DestinationLeaderboardsState extends State<DestinationLeaderboards> {
|
|||
),
|
||||
SizedBox(
|
||||
width: widget.constraints.maxWidth - 350 - 88,
|
||||
child: const Card(
|
||||
child: Column(
|
||||
children: [
|
||||
|
||||
],
|
||||
child: Card(
|
||||
child: StreamBuilder<List<TetrioPlayerFromLeaderboard>>(
|
||||
stream: dataStream,
|
||||
builder:(context, snapshot) {
|
||||
switch (snapshot.connectionState){
|
||||
case ConnectionState.none:
|
||||
case ConnectionState.waiting:
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
case ConnectionState.active:
|
||||
case ConnectionState.done:
|
||||
if (snapshot.hasData){
|
||||
return Column(
|
||||
children: [
|
||||
Text(leaderboards[_currentLb]!, style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28, height: 0.9)),
|
||||
const Divider(color: Color.fromARGB(50, 158, 158, 158)),
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
itemCount: list.length,
|
||||
itemBuilder: (BuildContext context, int index){
|
||||
return ListTile(
|
||||
leading: Text(intf.format(index+1)),
|
||||
title: Text(snapshot.data![index].username),
|
||||
trailing: Text(switch (_currentLb){
|
||||
Leaderboards.tl => f2.format(snapshot.data![index].tr),
|
||||
Leaderboards.xp => f2.format(snapshot.data![index].level),
|
||||
Leaderboards.ar => intf.format(snapshot.data![index].ar),
|
||||
}),
|
||||
);
|
||||
}
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
if (snapshot.hasError){ return FutureError(snapshot); }
|
||||
}
|
||||
return Text("huh?");
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -297,13 +422,11 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
late TooltipBehavior _leagueTooltipBehavior;
|
||||
String yAxisTitle = "";
|
||||
bool _smooth = false;
|
||||
//final List _historyShortTitles = ["TR", "Glicko", "RD", "APM", "PPS", "VS", "APP", "DS/S", "DS/P", "APP + DS/P", "VS/APM", "Cheese", "GbE", "wAPP", "Area", "eTR", "±eTR", "Opener", "Plonk", "Inf. DS", "Stride"];
|
||||
final List<DropdownMenuItem<Stats>> _yAxis = [for (MapEntry e in chartsShortTitles.entries) DropdownMenuItem(value: e.key, child: Text(e.value))];
|
||||
Graph _graph = Graph.history;
|
||||
Stats _Ychart = Stats.tr;
|
||||
Stats _Xchart = Stats.tr;
|
||||
int _season = currentSeason-1;
|
||||
//late List<List<DropdownMenuItem<List<_HistoryChartSpot>>>> historyData;
|
||||
//Duration postSeasonLeft = seasonStart.difference(DateTime.now());
|
||||
|
||||
@override
|
||||
|
@ -365,7 +488,6 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
animationDuration: 0,
|
||||
builder: (dynamic data, dynamic point, dynamic series,
|
||||
int pointIndex, int seriesIndex) {
|
||||
print(point);
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
|
@ -454,7 +576,7 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
case ConnectionState.active:
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
case ConnectionState.done:
|
||||
if (snapshot.hasData && snapshot.data!.isNotEmpty){
|
||||
if (snapshot.hasData){
|
||||
List<_HistoryChartSpot> selectedGraph = snapshot.data![_season][_Ychart]!;
|
||||
yAxisTitle = chartsShortTitles[_Ychart]!;
|
||||
return SfCartesianChart(
|
||||
|
@ -500,20 +622,7 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
),
|
||||
],
|
||||
);
|
||||
}else{
|
||||
return Center(child:
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(snapshot.error.toString(), style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 42, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(snapshot.stackTrace.toString(), textAlign: TextAlign.center),
|
||||
),
|
||||
],
|
||||
)
|
||||
);
|
||||
}
|
||||
}else{ return FutureError(snapshot); }
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -546,20 +655,7 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
)
|
||||
],
|
||||
);
|
||||
}else{
|
||||
return Center(child:
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(snapshot.error.toString(), style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 42, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(snapshot.stackTrace.toString(), textAlign: TextAlign.center),
|
||||
),
|
||||
],
|
||||
)
|
||||
);
|
||||
}
|
||||
}else{ return FutureError(snapshot); }
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -580,9 +676,14 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
return SfCartesianChart(
|
||||
tooltipBehavior: _leagueTooltipBehavior,
|
||||
zoomPanBehavior: _zoomPanBehavior,
|
||||
primaryXAxis: _gamesPlayedInsteadOfDateAndTime ? const NumericAxis() : const DateTimeAxis(),
|
||||
primaryYAxis: const NumericAxis(
|
||||
rangePadding: ChartRangePadding.additional,
|
||||
primaryXAxis: const DateTimeAxis(),
|
||||
primaryYAxis: NumericAxis(
|
||||
// isInversed: true,
|
||||
maximum: switch (_Ychart){
|
||||
Stats.tr => 25000.0,
|
||||
Stats.gxe => 100.00,
|
||||
_ => null
|
||||
},
|
||||
),
|
||||
margin: const EdgeInsets.all(0),
|
||||
series: <CartesianSeries>[
|
||||
|
@ -590,34 +691,18 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
enableTooltip: true,
|
||||
dataSource: snapshot.data,
|
||||
animationDuration: 0,
|
||||
//opacity: _smooth ? 0 : 1,
|
||||
//opacity: 0.5,
|
||||
xValueMapper: (Cutoffs data, _) => data.ts,
|
||||
yValueMapper: (Cutoffs data, _) => data.tr[rank],
|
||||
color: rankColors[rank],
|
||||
// trendlines:<Trendline>[
|
||||
// Trendline(
|
||||
// isVisible: _smooth,
|
||||
// period: (selectedGraph.length/175).floor(),
|
||||
// type: TrendlineType.movingAverage,
|
||||
// color: Theme.of(context).colorScheme.primary)
|
||||
// ],
|
||||
yValueMapper: (Cutoffs data, _) => switch (_Ychart){
|
||||
Stats.glicko => data.glicko[rank],
|
||||
Stats.gxe => data.gxe[rank],
|
||||
_ => data.tr[rank]
|
||||
},
|
||||
color: rankColors[rank]!
|
||||
)
|
||||
],
|
||||
);
|
||||
}else{
|
||||
return Center(child:
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(snapshot.error.toString(), style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 42, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(snapshot.stackTrace.toString(), textAlign: TextAlign.center),
|
||||
),
|
||||
],
|
||||
)
|
||||
);
|
||||
}
|
||||
}else{ return FutureError(snapshot); }
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -679,7 +764,7 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
children: [
|
||||
const Padding(padding: EdgeInsets.all(8.0), child: Text("Y:", style: TextStyle(fontSize: 22))),
|
||||
DropdownButton<Stats>(
|
||||
items: _yAxis,
|
||||
items: _graph == Graph.leagueCutoffs ? [DropdownMenuItem(value: Stats.tr, child: Text(chartsShortTitles[Stats.tr]!)), DropdownMenuItem(value: Stats.glicko, child: Text(chartsShortTitles[Stats.glicko]!)), DropdownMenuItem(value: Stats.gxe, child: Text(chartsShortTitles[Stats.gxe]!))] : _yAxis,
|
||||
value: _Ychart,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
|
@ -1254,20 +1339,7 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
|||
],
|
||||
);
|
||||
}
|
||||
if (snapshot.hasError){
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(t.errors.noSuchUser, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 42, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(t.errors.noSuchUserSub, textAlign: TextAlign.center),
|
||||
),
|
||||
],
|
||||
)
|
||||
);
|
||||
}
|
||||
if (snapshot.hasError){ return FutureError(snapshot); }
|
||||
}
|
||||
return const Text("what?");
|
||||
},
|
||||
|
@ -1306,20 +1378,7 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
|||
],
|
||||
);
|
||||
}
|
||||
if (snapshot.hasError){
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(t.errors.noSuchUser, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 42, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(t.errors.noSuchUserSub, textAlign: TextAlign.center),
|
||||
),
|
||||
],
|
||||
)
|
||||
);
|
||||
}
|
||||
if (snapshot.hasError){ return FutureError(snapshot); }
|
||||
}
|
||||
return const Text("what?");
|
||||
},
|
||||
|
@ -1366,20 +1425,7 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
|||
if (snapshot.hasData){
|
||||
return SizedBox(height: constraints.maxHeight - 145, child: _TLRecords(userID: widget.searchFor, changePlayer: (){}, data: snapshot.data!.records, wasActiveInTL: snapshot.data!.records.isNotEmpty, oldMathcesHere: false));
|
||||
}
|
||||
if (snapshot.hasError){
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(t.errors.noSuchUser, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 42, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(t.errors.noSuchUserSub, textAlign: TextAlign.center),
|
||||
),
|
||||
],
|
||||
)
|
||||
);
|
||||
}
|
||||
if (snapshot.hasError){ return FutureError(snapshot); }
|
||||
}
|
||||
return const Text("what?");
|
||||
},
|
||||
|
@ -1760,20 +1806,7 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
|||
case ConnectionState.active:
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
case ConnectionState.done:
|
||||
if (snapshot.hasError){
|
||||
return Center(child:
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(snapshot.error.toString(), style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 42, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(snapshot.stackTrace.toString(), textAlign: TextAlign.center),
|
||||
),
|
||||
],
|
||||
)
|
||||
);
|
||||
}
|
||||
if (snapshot.hasError){ return FutureError(snapshot); }
|
||||
if (snapshot.hasData){
|
||||
blitzBetterThanRankAverage = (snapshot.data!.summaries!.league.rank != "z" && snapshot.data!.summaries!.blitz != null && snapshot.data!.summaries!.league.rank != "x+") ? snapshot.data!.summaries!.blitz!.stats.score > blitzAverages[snapshot.data!.summaries!.league.rank]! : null;
|
||||
sprintBetterThanRankAverage = (snapshot.data!.summaries!.league.rank != "z" && snapshot.data!.summaries!.sprint != null && snapshot.data!.summaries!.league.rank != "x+") ? snapshot.data!.summaries!.sprint!.stats.finalTime < sprintAverages[snapshot.data!.summaries!.league.rank]! : null;
|
||||
|
@ -1837,13 +1870,7 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
|||
case ConnectionState.done:
|
||||
if (snapshot.hasData){
|
||||
return NewsThingy(snapshot.data!);
|
||||
}else if (snapshot.hasError){
|
||||
return Card(child: Column(children: [
|
||||
Text(snapshot.error.toString(), style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 42, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
|
||||
Text(snapshot.stackTrace.toString())
|
||||
]
|
||||
));
|
||||
}
|
||||
}else if (snapshot.hasError){ return FutureError(snapshot); }
|
||||
}
|
||||
return const Text("what?");
|
||||
}
|
||||
|
@ -3318,4 +3345,26 @@ class TLRatingThingy extends StatelessWidget{
|
|||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FutureError extends StatelessWidget{
|
||||
final AsyncSnapshot snapshot;
|
||||
|
||||
FutureError(this.snapshot);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(child:
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(snapshot.error.toString(), style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 42, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(snapshot.stackTrace.toString(), textAlign: TextAlign.center),
|
||||
),
|
||||
],
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue