Experimental changes for tl_match_view
This commit is contained in:
parent
0d2d83a98a
commit
49c5dfdf5a
|
@ -68,6 +68,9 @@ class CalcState extends State<CalcView> {
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
|
child: Center(
|
||||||
|
child: Container(
|
||||||
|
constraints: BoxConstraints(maxWidth: 768),
|
||||||
child: NestedScrollView(
|
child: NestedScrollView(
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
headerSliverBuilder: (context, value) {
|
headerSliverBuilder: (context, value) {
|
||||||
|
@ -135,6 +138,8 @@ class CalcState extends State<CalcView> {
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,6 +256,9 @@ class CompareState extends State<CompareView> {
|
||||||
appBar: AppBar(title: Text("$titleGreenSide ${t.vs} $titleRedSide")),
|
appBar: AppBar(title: Text("$titleGreenSide ${t.vs} $titleRedSide")),
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
|
child: Center(
|
||||||
|
child: Container(
|
||||||
|
constraints: BoxConstraints(maxWidth: 768),
|
||||||
child: NestedScrollView(
|
child: NestedScrollView(
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
headerSliverBuilder: (context, value) {
|
headerSliverBuilder: (context, value) {
|
||||||
|
@ -322,7 +325,10 @@ class CompareState extends State<CompareView> {
|
||||||
)
|
)
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
body: ListView(
|
body: Center(
|
||||||
|
child: Container(
|
||||||
|
constraints: BoxConstraints(maxWidth: 768),
|
||||||
|
child: ListView(
|
||||||
children: !listEquals(theGreenSide, [null, null, null]) && !listEquals(theRedSide, [null, null, null])? [
|
children: !listEquals(theGreenSide, [null, null, null]) && !listEquals(theRedSide, [null, null, null])? [
|
||||||
if (theGreenSide[0] != null &&
|
if (theGreenSide[0] != null &&
|
||||||
theRedSide[0] != null &&
|
theRedSide[0] != null &&
|
||||||
|
@ -692,9 +698,13 @@ class CompareState extends State<CompareView> {
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Text(t.compareViewNoValues(avgR: "\$avgR"), textAlign: TextAlign.center),
|
child: Text(t.compareViewNoValues(avgR: "\$avgR"), textAlign: TextAlign.center),
|
||||||
)], // This is so fucked up holy shit
|
)], // This is so fucked up holy shit
|
||||||
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -786,6 +796,8 @@ class PlayerSelector extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TextStyle verdictStyle = TextStyle(fontSize: 14, fontFamily: "Eurostile Round Condensed", color: Colors.grey, height: 1.1);
|
||||||
|
|
||||||
class CompareThingy extends StatelessWidget {
|
class CompareThingy extends StatelessWidget {
|
||||||
final num greenSide;
|
final num greenSide;
|
||||||
final num redSide;
|
final num redSide;
|
||||||
|
@ -868,7 +880,7 @@ class CompareThingy extends StatelessWidget {
|
||||||
Text(
|
Text(
|
||||||
verdict(greenSide, redSide,
|
verdict(greenSide, redSide,
|
||||||
fractionDigits != null ? fractionDigits! + 2 : 0),
|
fractionDigits != null ? fractionDigits! + 2 : 0),
|
||||||
style: const TextStyle(fontSize: 16),
|
style: verdictStyle,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
@ -981,11 +993,7 @@ class CompareBoolThingy extends StatelessWidget {
|
||||||
style: const TextStyle(fontSize: 22),
|
style: const TextStyle(fontSize: 22),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
const Text(
|
const Text("---", style: verdictStyle, textAlign: TextAlign.center)
|
||||||
"---",
|
|
||||||
style: TextStyle(fontSize: 16),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
|
@ -1085,10 +1093,7 @@ class CompareDurationThingy extends StatelessWidget {
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
verdict(greenSide, redSide).toString(),
|
verdict(greenSide, redSide).toString(), style: verdictStyle, textAlign: TextAlign.center)
|
||||||
style: const TextStyle(fontSize: 16),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
|
@ -1176,11 +1181,7 @@ class CompareRegTimeThingy extends StatelessWidget {
|
||||||
style: const TextStyle(fontSize: 22),
|
style: const TextStyle(fontSize: 22),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
Text(
|
Text(verdict(greenSide, redSide), style: verdictStyle, textAlign: TextAlign.center)
|
||||||
verdict(greenSide, redSide),
|
|
||||||
style: const TextStyle(fontSize: 16),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
|
|
|
@ -20,6 +20,7 @@ import 'package:tetra_stats/utils/text_shadow.dart';
|
||||||
import 'package:tetra_stats/views/ranks_averages_view.dart' show RankAveragesView;
|
import 'package:tetra_stats/views/ranks_averages_view.dart' show RankAveragesView;
|
||||||
import 'package:tetra_stats/views/tl_leaderboard_view.dart' show TLLeaderboardView;
|
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/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/tl_thingy.dart';
|
import 'package:tetra_stats/widgets/tl_thingy.dart';
|
||||||
|
@ -582,18 +583,14 @@ class _TLRecords extends StatelessWidget {
|
||||||
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(_dateFormat.format(data[index].timestamp)),
|
||||||
trailing: Table(defaultColumnWidth: const IntrinsicColumnWidth(),
|
trailing: TrailingStats(
|
||||||
defaultVerticalAlignment: TableCellVerticalAlignment.baseline,
|
data[index].endContext.firstWhere((element) => element.userId == userID).secondary,
|
||||||
textBaseline: TextBaseline.alphabetic,
|
data[index].endContext.firstWhere((element) => element.userId == userID).tertiary,
|
||||||
columnWidths: const {
|
data[index].endContext.firstWhere((element) => element.userId == userID).extra,
|
||||||
0: FixedColumnWidth(50),
|
data[index].endContext.firstWhere((element) => element.userId != userID).secondary,
|
||||||
2: FixedColumnWidth(50),
|
data[index].endContext.firstWhere((element) => element.userId != userID).tertiary,
|
||||||
},
|
data[index].endContext.firstWhere((element) => element.userId != userID).extra
|
||||||
children: [
|
),
|
||||||
TableRow(children: [Text(_f2.format(data[index].endContext.firstWhere((element) => element.userId == userID).secondary), textAlign: TextAlign.right, style: const TextStyle(height: 1.1)), const Text(" :", style: TextStyle(height: 1.1)), Text(_f2.format(data[index].endContext.firstWhere((element) => element.userId != userID).secondary), textAlign: TextAlign.right, style: const TextStyle(height: 1.1)), const Text(" APM", textAlign: TextAlign.right, style: TextStyle(height: 1.1))]),
|
|
||||||
TableRow(children: [Text(_f2.format(data[index].endContext.firstWhere((element) => element.userId == userID).tertiary), textAlign: TextAlign.right, style: const TextStyle(height: 1.1)), const Text(" :", style: TextStyle(height: 1.1)), Text(_f2.format(data[index].endContext.firstWhere((element) => element.userId != userID).tertiary), textAlign: TextAlign.right, style: const TextStyle(height: 1.1)), const Text(" PPS", textAlign: TextAlign.right, style: TextStyle(height: 1.1))]),
|
|
||||||
TableRow(children: [Text(_f2.format(data[index].endContext.firstWhere((element) => element.userId == userID).extra), textAlign: TextAlign.right, style: const TextStyle(height: 1.1)), const Text(" :", style: TextStyle(height: 1.1)), Text(_f2.format(data[index].endContext.firstWhere((element) => element.userId != userID).extra), textAlign: TextAlign.right, style: const TextStyle(height: 1.1)), const Text(" VS", textAlign: TextAlign.right, style: TextStyle(height: 1.1))]),
|
|
||||||
],),
|
|
||||||
onTap: () => Navigator.push(context, MaterialPageRoute(builder: (context) => TlMatchResultView(record: data[index], initPlayerId: userID))),
|
onTap: () => Navigator.push(context, MaterialPageRoute(builder: (context) => TlMatchResultView(record: data[index], initPlayerId: userID))),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'dart:math';
|
||||||
import 'package:tetra_stats/data_objects/tetrio_multiplayer_replay.dart';
|
import 'package:tetra_stats/data_objects/tetrio_multiplayer_replay.dart';
|
||||||
import 'package:tetra_stats/services/crud_exceptions.dart';
|
import 'package:tetra_stats/services/crud_exceptions.dart';
|
||||||
import 'package:tetra_stats/views/compare_view.dart' show CompareThingy, CompareBoolThingy;
|
import 'package:tetra_stats/views/compare_view.dart' show CompareThingy, CompareBoolThingy;
|
||||||
|
import 'package:tetra_stats/widgets/list_tile_trailing_stats.dart';
|
||||||
import 'package:tetra_stats/widgets/vs_graphs.dart';
|
import 'package:tetra_stats/widgets/vs_graphs.dart';
|
||||||
import 'main_view.dart' show teto, secs;
|
import 'main_view.dart' show teto, secs;
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
@ -36,12 +38,10 @@ class TlMatchResultView extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class TlMatchResultState extends State<TlMatchResultView> {
|
class TlMatchResultState extends State<TlMatchResultView> {
|
||||||
late ScrollController _scrollController;
|
|
||||||
late Future<ReplayData?> replayData;
|
late Future<ReplayData?> replayData;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState(){
|
void initState(){
|
||||||
_scrollController = ScrollController();
|
|
||||||
rounds = [DropdownMenuItem(value: -1, child: Text(t.match))];
|
rounds = [DropdownMenuItem(value: -1, child: Text(t.match))];
|
||||||
rounds.addAll([for (int i = 0; i < widget.record.endContext.first.secondaryTracking.length; i++) DropdownMenuItem(value: i, child: Text(t.roundNumber(n: i+1)))]);
|
rounds.addAll([for (int i = 0; i < widget.record.endContext.first.secondaryTracking.length; i++) DropdownMenuItem(value: i, child: Text(t.roundNumber(n: i+1)))]);
|
||||||
replayData = teto.analyzeReplay(widget.record.replayId, widget.record.replayAvalable);
|
replayData = teto.analyzeReplay(widget.record.replayId, widget.record.replayAvalable);
|
||||||
|
@ -59,64 +59,8 @@ class TlMatchResultState extends State<TlMatchResultView> {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
Widget buildComparison(bool bigScreen, bool showMobileSelector){
|
||||||
Widget build(BuildContext context) {
|
return NestedScrollView(
|
||||||
final t = Translations.of(context);
|
|
||||||
bool bigScreen = MediaQuery.of(context).size.width > 768;
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text("${widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).username.toUpperCase()} ${t.vs} ${widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).username.toUpperCase()} ${t.inTLmatch} ${dateFormat.format(widget.record.timestamp)}"),
|
|
||||||
actions: [
|
|
||||||
PopupMenuButton(
|
|
||||||
enabled: widget.record.replayAvalable,
|
|
||||||
itemBuilder: (BuildContext context) => <PopupMenuEntry>[
|
|
||||||
PopupMenuItem(
|
|
||||||
value: 1,
|
|
||||||
child: Text(t.downloadReplay),
|
|
||||||
),
|
|
||||||
PopupMenuItem(
|
|
||||||
value: 2,
|
|
||||||
child: Text(t.openReplay),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
onSelected: (value) async {
|
|
||||||
switch (value) {
|
|
||||||
case 1:
|
|
||||||
if (kIsWeb){
|
|
||||||
// final _base64 = base64Encode([1,2,3,4,5]);
|
|
||||||
// final anchor = AnchorElement(href: 'data:application/octet-stream;base64,$_base64')..target = 'blank';
|
|
||||||
//final anchor = AnchorElement(href: 'https://inoue.szy.lol/api/replay/${widget.record.replayId}')..target = 'blank';
|
|
||||||
//anchor.download = "${widget.record.replayId}.ttrm";
|
|
||||||
//document.body!.append(anchor);
|
|
||||||
//anchor.click();
|
|
||||||
//anchor.remove();
|
|
||||||
} else{
|
|
||||||
try{
|
|
||||||
String path = await teto.saveReplay(widget.record.replayId);
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.replaySaved(path: path))));
|
|
||||||
} on TetrioReplayAlreadyExist{
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.errors.replayAlreadySaved)));
|
|
||||||
} on SzyNotFound {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.errors.replayExpired)));
|
|
||||||
} on SzyForbidden {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.errors.replayRejected)));
|
|
||||||
} on SzyTooManyRequests {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.errors.tooManyRequests)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
await launchInBrowser(Uri.parse("https://tetr.io/#r:${widget.record.replayId}"));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
})
|
|
||||||
]
|
|
||||||
),
|
|
||||||
backgroundColor: Colors.black,
|
|
||||||
body: SafeArea(
|
|
||||||
child: NestedScrollView(
|
|
||||||
controller: _scrollController,
|
|
||||||
headerSliverBuilder: (context, value) {
|
headerSliverBuilder: (context, value) {
|
||||||
return [
|
return [
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
|
@ -178,7 +122,7 @@ class TlMatchResultState extends State<TlMatchResultView> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
if (showMobileSelector) SliverToBoxAdapter(
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
@ -195,10 +139,10 @@ class TlMatchResultState extends State<TlMatchResultView> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (widget.record.ownId == widget.record.replayId) SliverToBoxAdapter(
|
if (widget.record.ownId == widget.record.replayId && showMobileSelector) SliverToBoxAdapter(
|
||||||
child: Center(child: Text(t.p1nkl0bst3rAlert, textAlign: TextAlign.center)),
|
child: Center(child: Text(t.p1nkl0bst3rAlert, textAlign: TextAlign.center)),
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(child: FutureBuilder(future: replayData, builder: (context, snapshot) {
|
if (showMobileSelector) SliverToBoxAdapter(child: FutureBuilder(future: replayData, builder: (context, snapshot) {
|
||||||
switch(snapshot.connectionState){
|
switch(snapshot.connectionState){
|
||||||
case ConnectionState.none:
|
case ConnectionState.none:
|
||||||
case ConnectionState.waiting:
|
case ConnectionState.waiting:
|
||||||
|
@ -507,8 +451,288 @@ class TlMatchResultState extends State<TlMatchResultView> {
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildRoundSelector(double width){
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.all(8.0000000),
|
||||||
|
child: SizedBox(
|
||||||
|
width: width,
|
||||||
|
child: NestedScrollView(
|
||||||
|
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
|
||||||
|
return [
|
||||||
|
SliverToBoxAdapter(child:
|
||||||
|
Wrap(
|
||||||
|
alignment: WrapAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
FutureBuilder(future: replayData, builder: (context, snapshot) {
|
||||||
|
switch(snapshot.connectionState){
|
||||||
|
case ConnectionState.none:
|
||||||
|
case ConnectionState.waiting:
|
||||||
|
case ConnectionState.active:
|
||||||
|
return const CircularProgressIndicator();
|
||||||
|
case ConnectionState.done:
|
||||||
|
if (!snapshot.hasError){
|
||||||
|
var time = framesToTime(snapshot.data!.totalLength);
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(t.matchLength),
|
||||||
|
RichText(
|
||||||
|
text: TextSpan(
|
||||||
|
text: "${time.inMinutes}:${NumberFormat("00", LocaleSettings.currentLocale.languageCode).format(time.inSeconds%60)}",
|
||||||
|
style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28, fontWeight: FontWeight.w500),
|
||||||
|
children: [TextSpan(text: ".${NumberFormat("000", LocaleSettings.currentLocale.languageCode).format(time.inMilliseconds%1000)}", style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100))]
|
||||||
),
|
),
|
||||||
|
)
|
||||||
|
],);
|
||||||
|
}else{
|
||||||
|
String reason;
|
||||||
|
switch (snapshot.error.runtimeType){
|
||||||
|
case ReplayNotAvalable:
|
||||||
|
reason = t.matchIsTooOld;
|
||||||
|
break;
|
||||||
|
case SzyNotFound:
|
||||||
|
reason = t.matchIsTooOld;
|
||||||
|
break;
|
||||||
|
case SzyForbidden:
|
||||||
|
reason = t.errors.replayRejected;
|
||||||
|
break;
|
||||||
|
case SzyTooManyRequests:
|
||||||
|
reason = t.errors.tooManyRequests;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
reason = snapshot.error.toString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
if (widget.record.ownId != widget.record.replayId) Text("${t.replayIssue}: $reason"),
|
||||||
|
if (widget.record.ownId == widget.record.replayId) Center(child: Text(t.p1nkl0bst3rAlert, textAlign: TextAlign.center)),
|
||||||
|
if (widget.record.ownId != widget.record.replayId) RichText(
|
||||||
|
text: TextSpan(
|
||||||
|
text: "-:--",
|
||||||
|
style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.grey),
|
||||||
|
children: [TextSpan(text: ".---", style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100))]
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
},),
|
||||||
|
if (widget.record.ownId != widget.record.replayId) Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Text("Number of rounds"),
|
||||||
|
RichText(
|
||||||
|
text: TextSpan(
|
||||||
|
text: widget.record.endContext.first.secondaryTracking.length > 0 ? widget.record.endContext.first.secondaryTracking.length.toString() : "---",
|
||||||
|
style: TextStyle(
|
||||||
|
fontFamily: "Eurostile Round Extended",
|
||||||
|
fontSize: 28,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: widget.record.endContext.first.secondaryTracking.length == 0 ? Colors.grey : null
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],),
|
||||||
|
Column(children: [
|
||||||
|
OverflowBar(
|
||||||
|
alignment: MainAxisAlignment.spaceEvenly,
|
||||||
|
children: <Widget>[
|
||||||
|
TextButton( child: const Text('Match stats'),
|
||||||
|
style: roundSelector == -1 ? ButtonStyle(backgroundColor: MaterialStatePropertyAll(Colors.grey.shade900)) : null,
|
||||||
|
onPressed: () {
|
||||||
|
roundSelector = -1;
|
||||||
|
setState(() {});
|
||||||
|
}),
|
||||||
|
TextButton( child: const Text('Time-weighted match stats'), onPressed: () {
|
||||||
|
roundSelector = -1;
|
||||||
|
setState(() {});
|
||||||
|
}),
|
||||||
|
//TextButton( child: const Text('Button 3'), onPressed: () {}),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
// Column(
|
||||||
|
// children: [
|
||||||
|
// ListTile(
|
||||||
|
// leading: Text("Round time"),
|
||||||
|
// title: Text("Winner", textAlign: TextAlign.center,),
|
||||||
|
// trailing: Text("Round stats"),
|
||||||
|
// )
|
||||||
|
// ],
|
||||||
|
// )
|
||||||
|
],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
];
|
||||||
|
},
|
||||||
|
body: ListView.builder(itemCount: widget.record.endContext.first.secondaryTracking.length,
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
return FutureBuilder(future: replayData, builder: (context, snapshot) {
|
||||||
|
switch(snapshot.connectionState){
|
||||||
|
case ConnectionState.none:
|
||||||
|
case ConnectionState.waiting:
|
||||||
|
case ConnectionState.active:
|
||||||
|
return const LinearProgressIndicator();
|
||||||
|
case ConnectionState.done:
|
||||||
|
if (!snapshot.hasError){
|
||||||
|
var time = framesToTime(snapshot.data!.roundLengths[index]);
|
||||||
|
var accentColor = snapshot.data!.roundWinners[index][0] == widget.initPlayerId ? Colors.green : Colors.red;
|
||||||
|
var bgColor = roundSelector == index ? Colors.grey.shade900 : Colors.transparent;
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
stops: const [0, 0.05],
|
||||||
|
colors: [accentColor, bgColor]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
child: ListTile(
|
||||||
|
leading:RichText(
|
||||||
|
text: TextSpan(
|
||||||
|
text: "${time.inMinutes}:${NumberFormat("00", LocaleSettings.currentLocale.languageCode).format(time.inSeconds%60)}",
|
||||||
|
style: TextStyle(fontFamily: "Eurostile Round", fontSize: 22, fontWeight: FontWeight.w500),
|
||||||
|
children: [TextSpan(text: ".${NumberFormat("000", LocaleSettings.currentLocale.languageCode).format(time.inMilliseconds%1000)}", style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100))]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
title: Text(snapshot.data!.roundWinners[index][1], textAlign: TextAlign.center),
|
||||||
|
trailing: TrailingStats(
|
||||||
|
widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).secondaryTracking[index],
|
||||||
|
widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).tertiaryTracking[index],
|
||||||
|
widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).extraTracking[index],
|
||||||
|
widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).secondaryTracking[index],
|
||||||
|
widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).tertiaryTracking[index],
|
||||||
|
widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).extraTracking[index]
|
||||||
|
),
|
||||||
|
onTap:(){
|
||||||
|
roundSelector = index;
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}else{
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: roundSelector == index ? Colors.grey.shade900 : Colors.transparent
|
||||||
|
),
|
||||||
|
child: ListTile(
|
||||||
|
leading: RichText(
|
||||||
|
text: TextSpan(
|
||||||
|
text: "-:--",
|
||||||
|
style: TextStyle(fontFamily: "Eurostile Round", fontSize: 22, fontWeight: FontWeight.w500, color: Colors.grey),
|
||||||
|
children: [TextSpan(text: ".---", style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100))]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
title: Text("---", style: TextStyle(color: Colors.grey), textAlign: TextAlign.center),
|
||||||
|
trailing: TrailingStats(
|
||||||
|
widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).secondaryTracking[index],
|
||||||
|
widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).tertiaryTracking[index],
|
||||||
|
widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).extraTracking[index],
|
||||||
|
widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).secondaryTracking[index],
|
||||||
|
widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).tertiaryTracking[index],
|
||||||
|
widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).extraTracking[index]
|
||||||
|
),
|
||||||
|
onTap:(){
|
||||||
|
roundSelector = index;
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
})
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget getMainWidget(double viewportWidth) {
|
||||||
|
if (viewportWidth <= 1024) {
|
||||||
|
return Center(
|
||||||
|
child: Container(
|
||||||
|
constraints: BoxConstraints(maxWidth: 768),
|
||||||
|
child: buildComparison(viewportWidth > 768, true)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
//mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 768,
|
||||||
|
child: buildComparison(true, false)
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
constraints: BoxConstraints(maxWidth: 768),
|
||||||
|
child: buildRoundSelector(max(viewportWidth-768-16, 200)),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final t = Translations.of(context);
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text("${widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).username.toUpperCase()} ${t.vs} ${widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).username.toUpperCase()} ${t.inTLmatch} ${dateFormat.format(widget.record.timestamp)}"),
|
||||||
|
actions: [
|
||||||
|
PopupMenuButton(
|
||||||
|
enabled: widget.record.replayAvalable,
|
||||||
|
itemBuilder: (BuildContext context) => <PopupMenuEntry>[
|
||||||
|
PopupMenuItem(
|
||||||
|
value: 1,
|
||||||
|
child: Text(t.downloadReplay),
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
value: 2,
|
||||||
|
child: Text(t.openReplay),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
onSelected: (value) async {
|
||||||
|
switch (value) {
|
||||||
|
case 1:
|
||||||
|
if (kIsWeb){
|
||||||
|
// final _base64 = base64Encode([1,2,3,4,5]);
|
||||||
|
// final anchor = AnchorElement(href: 'data:application/octet-stream;base64,$_base64')..target = 'blank';
|
||||||
|
//final anchor = AnchorElement(href: 'https://inoue.szy.lol/api/replay/${widget.record.replayId}')..target = 'blank';
|
||||||
|
//anchor.download = "${widget.record.replayId}.ttrm";
|
||||||
|
//document.body!.append(anchor);
|
||||||
|
//anchor.click();
|
||||||
|
//anchor.remove();
|
||||||
|
} else{
|
||||||
|
try{
|
||||||
|
String path = await teto.saveReplay(widget.record.replayId);
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.replaySaved(path: path))));
|
||||||
|
} on TetrioReplayAlreadyExist{
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.errors.replayAlreadySaved)));
|
||||||
|
} on SzyNotFound {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.errors.replayExpired)));
|
||||||
|
} on SzyForbidden {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.errors.replayRejected)));
|
||||||
|
} on SzyTooManyRequests {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.errors.tooManyRequests)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
await launchInBrowser(Uri.parse("https://tetr.io/#r:${widget.record.replayId}"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.black,
|
||||||
|
body: getMainWidget(MediaQuery.of(context).size.width),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
|
|
||||||
|
class TrailingStats extends StatelessWidget{
|
||||||
|
final double yourAPM;
|
||||||
|
final double yourPPS;
|
||||||
|
final double yourVS;
|
||||||
|
final double notyourAPM;
|
||||||
|
final double notyourPPS;
|
||||||
|
final double notyourVS;
|
||||||
|
|
||||||
|
const TrailingStats(this.yourAPM, this.yourPPS, this.yourVS, this.notyourAPM, this.notyourPPS, this.notyourVS, {super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final NumberFormat f2 = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 2);
|
||||||
|
return Table(
|
||||||
|
defaultColumnWidth: const IntrinsicColumnWidth(),
|
||||||
|
defaultVerticalAlignment: TableCellVerticalAlignment.baseline,
|
||||||
|
textBaseline: TextBaseline.alphabetic,
|
||||||
|
columnWidths: const {
|
||||||
|
0: FixedColumnWidth(42),
|
||||||
|
2: FixedColumnWidth(42),
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
TableRow(children: [Text(f2.format(yourAPM), textAlign: TextAlign.right, style: const TextStyle(height: 1.1)), const Text(" :", style: TextStyle(height: 1.1)), Text(f2.format(notyourAPM), textAlign: TextAlign.right, style: const TextStyle(height: 1.1)), const Text(" APM", textAlign: TextAlign.right, style: TextStyle(height: 1.1))]),
|
||||||
|
TableRow(children: [Text(f2.format(yourPPS), textAlign: TextAlign.right, style: const TextStyle(height: 1.1)), const Text(" :", style: TextStyle(height: 1.1)), Text(f2.format(notyourPPS), textAlign: TextAlign.right, style: const TextStyle(height: 1.1)), const Text(" PPS", textAlign: TextAlign.right, style: TextStyle(height: 1.1))]),
|
||||||
|
TableRow(children: [Text(f2.format(yourVS), textAlign: TextAlign.right, style: const TextStyle(height: 1.1)), const Text(" :", style: TextStyle(height: 1.1)), Text(f2.format(notyourVS), textAlign: TextAlign.right, style: const TextStyle(height: 1.1)), const Text(" VS", textAlign: TextAlign.right, style: TextStyle(height: 1.1))]),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue