Pull to refresh + now we have only one chart

But it's possible to change sets of data for chart
Also changed fetch function in main view
This commit is contained in:
dan63047 2023-06-26 20:13:53 +03:00
parent 8770d5dca8
commit 041b70a86c
6 changed files with 139 additions and 141 deletions

View File

@ -344,7 +344,7 @@ class EndContextSingle {
late int piecesPlaced; late int piecesPlaced;
late int lines; late int lines;
late int score; late int score;
late int seed; late double seed;
late Duration finalTime; late Duration finalTime;
late int tSpins; late int tSpins;
late Clears clears; late Clears clears;
@ -373,7 +373,7 @@ class EndContextSingle {
required this.finesse}); required this.finesse});
EndContextSingle.fromJson(Map<String, dynamic> json) { EndContextSingle.fromJson(Map<String, dynamic> json) {
seed = json['seed']; seed = json['seed'].toDouble();
lines = json['lines']; lines = json['lines'];
inputs = json['inputs']; inputs = json['inputs'];
holds = json['holds'] ?? 0; holds = json['holds'] ?? 0;

View File

@ -34,13 +34,14 @@ const String createTetrioUsersToTrack = '''
'''; ''';
const String createTetrioTLRecordsTable = ''' const String createTetrioTLRecordsTable = '''
CREATE TABLE IF NOT EXISTS "tetrioAlphaLeagueMathces" ( CREATE TABLE IF NOT EXISTS "tetrioAlphaLeagueMathces" (
"id" TEXT, "id" TEXT NOT NULL UNIQUE,
"replayId" TEXT, "replayId" TEXT,
"player1id" TEXT, "player1id" TEXT,
"player2id" TEXT, "player2id" TEXT,
"timestamp" TEXT, "timestamp" TEXT,
"endContext1" TEXT, "endContext1" TEXT,
"endContext2" TEXT "endContext2" TEXT,
PRIMARY KEY("id")
) )
'''; ''';
@ -70,7 +71,6 @@ class TetrioService extends DB {
final allPlayers = await getAllPlayers(); final allPlayers = await getAllPlayers();
_players = allPlayers.toList().first; // ??? _players = allPlayers.toList().first; // ???
_tetrioStreamController.add(_players); _tetrioStreamController.add(_players);
developer.log("_loadPlayers: $_players", name: "services/tetrio_crud");
} }
Future<void> deletePlayer(String id) async { Future<void> deletePlayer(String id) async {

View File

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'dart:math'; import 'dart:math';
@ -17,6 +19,9 @@ String _searchFor = "dan63047";
String _titleNickname = "dan63047"; String _titleNickname = "dan63047";
final TetrioService teto = TetrioService(); final TetrioService teto = TetrioService();
late SharedPreferences prefs; late SharedPreferences prefs;
var chartsData = <DropdownMenuItem<List<FlSpot>>>[];
List chartsShortTitles = ["TR", "Glicko", "RD", "APM", "PPS", "VS", "APP", "DS/S", "DS/P", "APP + DS/P", "VS/APM", "Cheese", "GbE", "wAPP", "Area", "eTR", "±eTR"];
int chartsIndex = 0;
const allowedHeightForPlayerIdInPixels = 40.0; const allowedHeightForPlayerIdInPixels = 40.0;
const allowedHeightForPlayerBioInPixels = 30.0; const allowedHeightForPlayerBioInPixels = 30.0;
const givenTextHeightByScreenPercentage = 0.3; const givenTextHeightByScreenPercentage = 0.3;
@ -43,7 +48,7 @@ class _MainState extends State<MainView> with SingleTickerProviderStateMixin {
final List<Widget> myTabs = [ final List<Widget> myTabs = [
const Tab(text: "Tetra League"), const Tab(text: "Tetra League"),
const Tab(text: "TL Records"), const Tab(text: "TL Records"),
const Tab(text: "TL History"), const Tab(text: "History"),
const Tab(text: "40 Lines"), const Tab(text: "40 Lines"),
const Tab(text: "Blitz"), const Tab(text: "Blitz"),
const Tab(text: "Other"), const Tab(text: "Other"),
@ -110,33 +115,48 @@ class _MainState extends State<MainView> with SingleTickerProviderStateMixin {
Future<List> fetch(String nickOrID) async { Future<List> fetch(String nickOrID) async {
TetrioPlayer me = await teto.fetchPlayer(nickOrID); TetrioPlayer me = await teto.fetchPlayer(nickOrID);
setState((){_titleNickname = me.username;}); setState((){_titleNickname = me.username;});
var tlStream = await teto.getTLStream(me.userId);
List<TetraLeagueAlphaRecord> tlMatches = [];
bool isTracking = await teto.isPlayerTracking(me.userId); bool isTracking = await teto.isPlayerTracking(me.userId);
List<TetrioPlayer> states = []; List<TetrioPlayer> states = [];
if (isTracking){ if (isTracking){
teto.storeState(me); teto.storeState(me);
teto.saveTLMatchesFromStream(await teto.getTLStream(me.userId)); teto.saveTLMatchesFromStream(await teto.getTLStream(me.userId));
states.addAll(await teto.getPlayer(me.userId)); states.addAll(await teto.getPlayer(me.userId));
chartsData = <DropdownMenuItem<List<FlSpot>>>[
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.gamesPlayed > 9) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.rating)], child: const Text("Tetra Rating")),
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.gamesPlayed > 9) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.glicko!)], child: const Text("Glicko")),
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.gamesPlayed > 9) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.rd!)], child: const Text("Rating Deviation")),
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.apm != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.apm!)], child: const Text("Attack Per Minute")),
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.pps != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.pps!)], child: const Text("Pieces Per Second")),
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.vs != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.vs!)], child: const Text("Versus Score")),
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.app)], child: const Text("Attack Per Piece")),
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.dss)], child: const Text("Downstack Per Second")),
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.dsp)], child: const Text("Downstack Per Piece")),
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.appdsp)], child: const Text("APP + DS/P")),
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.vsapm)], child: const Text("VS/APM")),
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.cheese)], child: const Text("Cheese Index")),
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.gbe)], child: const Text("Garbage Efficiency")),
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.nyaapp)], child: const Text("Weighted APP")),
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.area)], child: const Text("Area")),
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.estTr != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.estTr!.esttr)], child: const Text("Est. of TR")),
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.esttracc != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.esttracc!)], child: const Text("Accuracy of Est.")),
];
tlMatches.addAll(await teto.getTLMatchesbyPlayerID(me.userId));
for (var match in tlStream.records) {
if (!tlMatches.contains(match)) tlMatches.add(match);
} }
Map<String, dynamic> records = await teto.fetchRecords(me.userId); tlMatches.sort((a, b) {
return [me, records, states, isTracking];
}
Future<List<TetraLeagueAlphaRecord>> getTLMatches(String userID) async {
var fetched = await teto.getTLStream(userID);
bool isTracked = await teto.isPlayerTracking(userID);
if (!isTracked) return fetched.records;
teto.saveTLMatchesFromStream(fetched);
var fromdb = await teto.getTLMatchesbyPlayerID(userID);
for (var match in fetched.records) {
if (!fromdb.contains(match)) fromdb.add(match);
}
fromdb.sort((a, b) {
if(a.timestamp.isBefore(b.timestamp)) return 1; if(a.timestamp.isBefore(b.timestamp)) return 1;
if(a.timestamp.isAtSameMomentAs(b.timestamp)) return 0; if(a.timestamp.isAtSameMomentAs(b.timestamp)) return 0;
if(a.timestamp.isAfter(b.timestamp)) return -1; if(a.timestamp.isAfter(b.timestamp)) return -1;
return 0; return 0;
}); });
return fromdb; } else{
tlMatches = tlStream.records;
}
Map<String, dynamic> records = await teto.fetchRecords(me.userId);
return [me, records, states, tlMatches, isTracking];
} }
void _justUpdate() { void _justUpdate() {
@ -234,8 +254,20 @@ class _MainState extends State<MainView> with SingleTickerProviderStateMixin {
case ConnectionState.done: case ConnectionState.done:
//bool bigScreen = MediaQuery.of(context).size.width > 1024; //bool bigScreen = MediaQuery.of(context).size.width > 1024;
if (snapshot.hasData) { if (snapshot.hasData) {
return NestedScrollView( return RefreshIndicator(
onRefresh: () {
return Future(() => changePlayer(snapshot.data![0].userId));
},
notificationPredicate: (notification) {
// with NestedScrollView local(depth == 2) OverscrollNotification are not sent
if (notification is OverscrollNotification || Platform.isIOS) {
return notification.depth == 2;
}
return notification.depth == 0;
},
child: NestedScrollView(
controller: _scrollController, controller: _scrollController,
physics: const AlwaysScrollableScrollPhysics(),
headerSliverBuilder: (context, value) { headerSliverBuilder: (context, value) {
return [ return [
SliverToBoxAdapter( SliverToBoxAdapter(
@ -259,8 +291,8 @@ class _MainState extends State<MainView> with SingleTickerProviderStateMixin {
TLThingy( TLThingy(
tl: snapshot.data![0].tlSeason1, tl: snapshot.data![0].tlSeason1,
userID: snapshot.data![0].userId), userID: snapshot.data![0].userId),
_TLRecords(userID: snapshot.data![0].userId, get: getTLMatches,), _TLRecords(userID: snapshot.data![0].userId, data: snapshot.data![3]),
_TLHistory(states: snapshot.data![2]), _History(states: snapshot.data![2], update: _justUpdate),
_RecordThingy( _RecordThingy(
record: (snapshot.data![1]['sprint'].isNotEmpty) record: (snapshot.data![1]['sprint'].isNotEmpty)
? snapshot.data![1]['sprint'][0] ? snapshot.data![1]['sprint'][0]
@ -273,6 +305,7 @@ class _MainState extends State<MainView> with SingleTickerProviderStateMixin {
zen: snapshot.data![1]['zen'], bio: snapshot.data![0].bio) zen: snapshot.data![1]['zen'], bio: snapshot.data![0].bio)
], ],
), ),
),
); );
} else if (snapshot.hasError) { } else if (snapshot.hasError) {
return Center( return Center(
@ -401,29 +434,16 @@ class _NavDrawerState extends State<NavDrawer> {
class _TLRecords extends StatelessWidget { class _TLRecords extends StatelessWidget {
final String userID; final String userID;
final Future<List<TetraLeagueAlphaRecord>> Function(String user) get; final List<TetraLeagueAlphaRecord> data;
const _TLRecords({required this.userID, required this.get}); const _TLRecords({required this.userID, required this.data});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FutureBuilder( return ListView( // TODO: Redo using ListView.builder()
future: get(userID), physics: const AlwaysScrollableScrollPhysics(),
builder: (context, snapshot) { children: (data.isNotEmpty)
switch (snapshot.connectionState) { ? [for (var value in data) ListTile(
case ConnectionState.none:
case ConnectionState.waiting:
case ConnectionState.active:
return const Center(
child: CircularProgressIndicator(color: Colors.white));
case ConnectionState.done:
if (snapshot.hasError) {
return Text(snapshot.error.toString(), style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28));
} else {
return ListView(
physics: const ClampingScrollPhysics(),
children: (snapshot.data!.isNotEmpty)
? [for (var value in snapshot.data!) ListTile(
leading: Text("${value.endContext.firstWhere((element) => element.userId == userID).points} : ${value.endContext.firstWhere((element) => element.userId != userID).points}", leading: Text("${value.endContext.firstWhere((element) => element.userId == userID).points} : ${value.endContext.firstWhere((element) => element.userId != userID).points}",
style: const TextStyle( style: const TextStyle(
fontFamily: "Eurostile Round Extended", fontFamily: "Eurostile Round Extended",
@ -446,54 +466,30 @@ class _TLRecords extends StatelessWidget {
: [const Center(child: Text("No records", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)))], : [const Center(child: Text("No records", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)))],
); );
} }
}
});
}
} }
class _TLHistory extends StatelessWidget{ class _History extends StatelessWidget{
final List<TetrioPlayer> states; final List<TetrioPlayer> states;
const _TLHistory({required this.states}); final Function update;
const _History({required this.states, required this.update});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
bool bigScreen = MediaQuery.of(context).size.width > 768; bool bigScreen = MediaQuery.of(context).size.width > 768;
List<FlSpot> trData = [for (var state in states) if (state.tlSeason1.gamesPlayed > 9) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.rating)];
List<FlSpot> apmData = [for (var state in states) if (state.tlSeason1.apm != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.apm!)];
List<FlSpot> ppsData = [for (var state in states) if (state.tlSeason1.pps != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.pps!)];
List<FlSpot> vsData = [for (var state in states) if (state.tlSeason1.vs != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.vs!)];
List<FlSpot> appData = [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.app)];
List<FlSpot> dssData = [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.dss)];
List<FlSpot> dspData = [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.dsp)];
List<FlSpot> appdspData = [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.appdsp)];
List<FlSpot> vsapmData = [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.vsapm)];
List<FlSpot> cheeseData = [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.cheese)];
List<FlSpot> gbeData = [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.gbe)];
List<FlSpot> nyaappData = [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.nyaapp)];
List<FlSpot> areaData = [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.area)];
List<FlSpot> estTrData = [for (var state in states) if (state.tlSeason1.estTr != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.estTr!.esttr)];
List<FlSpot> estaccData = [for (var state in states) if (state.tlSeason1.esttracc != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.esttracc!)];
return ListView(physics: const ClampingScrollPhysics(), return ListView(physics: const ClampingScrollPhysics(),
children: states.isNotEmpty ? [ children: states.isNotEmpty ? [
Column( Column(
children: [ children: [
if(trData.length > 1) _HistoryChartThigy(data: trData, title: "Tetra Rating", yAxisTitle: "TR", bigScreen: bigScreen, leftSpace: bigScreen? 80 : 45, yFormat: bigScreen? f2 : NumberFormat.compact(),), DropdownButton(
if(apmData.length > 1) _HistoryChartThigy(data: apmData, title: "Attack Per Minute", yAxisTitle: "APM", bigScreen: bigScreen, leftSpace: 40, yFormat: NumberFormat.compact(),), items: chartsData,
if(ppsData.length > 1) _HistoryChartThigy(data: ppsData, title: "Pieces Per Second", yAxisTitle: "PPS", bigScreen: bigScreen, leftSpace: 40, yFormat: NumberFormat.compact(),), value: chartsData[chartsIndex].value,
if(vsData.length > 1) _HistoryChartThigy(data: vsData, title: "Versus Score", yAxisTitle: "VS", bigScreen: bigScreen, leftSpace: 40, yFormat: NumberFormat.compact(),), onChanged: (value) {
if(appData.length > 1) _HistoryChartThigy(data: appData, title: "Attack Per Piece", yAxisTitle: "APP", bigScreen: bigScreen, leftSpace: 48, yFormat: NumberFormat.compact(),), chartsIndex = chartsData.indexWhere((element) => element.value == value);
if(dssData.length > 1) _HistoryChartThigy(data: dssData, title: bigScreen ? "Downstack Per Second" : "Downstack\nPer Second", yAxisTitle: "DS/S", bigScreen: bigScreen, leftSpace: 48, yFormat: NumberFormat.compact(),), update();
if(dspData.length > 1) _HistoryChartThigy(data: dspData, title: bigScreen ? "Downstack Per Piece" : "Downstack\nPer Piece", yAxisTitle: "DS/P", bigScreen: bigScreen, leftSpace: 48, yFormat: NumberFormat.compact(),), }
if(appdspData.length > 1) _HistoryChartThigy(data: appdspData, title: "APP + DS/P", yAxisTitle: "APP + DS/P", bigScreen: bigScreen, leftSpace: 48, yFormat: NumberFormat.compact(),), ),
if(vsapmData.length > 1) _HistoryChartThigy(data: vsapmData, title: "VS/APM", yAxisTitle: "VS/APM", bigScreen: bigScreen, leftSpace: 48, yFormat: NumberFormat.compact(),), if(chartsData[chartsIndex].value!.length > 1) _HistoryChartThigy(data: chartsData[chartsIndex].value!, title: "ss", yAxisTitle: chartsShortTitles[chartsIndex], bigScreen: bigScreen, leftSpace: bigScreen? 80 : 45, yFormat: bigScreen? f2 : NumberFormat.compact(),)
if(cheeseData.length > 1) _HistoryChartThigy(data: cheeseData, title: "Cheese Index", yAxisTitle: "Cheese", bigScreen: bigScreen, leftSpace: 40, yFormat: NumberFormat.compact(),), else const Center(child: Text("Not enough data", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)))
if(gbeData.length > 1) _HistoryChartThigy(data: gbeData, title: "Garbage Efficiency", yAxisTitle: "GbE", bigScreen: bigScreen, leftSpace: 48, yFormat: NumberFormat.compact(),),
if(nyaappData.length > 1) _HistoryChartThigy(data: nyaappData, title: "Weighted APP", yAxisTitle: "wAPP", bigScreen: bigScreen, leftSpace: 48, yFormat: NumberFormat.compact(),),
if(areaData.length > 1) _HistoryChartThigy(data: areaData, title: "Area", yAxisTitle: "Area", bigScreen: bigScreen, leftSpace: 40, yFormat: NumberFormat.compact(),),
if(estTrData.length > 1) _HistoryChartThigy(data: estTrData, title: "Est. of TR", yAxisTitle: "eTR", bigScreen: bigScreen, leftSpace: bigScreen? 80 : 45, yFormat: bigScreen? f2 : NumberFormat.compact(),),
if(estaccData.length > 1) _HistoryChartThigy(data: estaccData, title: "Accuracy of Est.", yAxisTitle: "±eTR", bigScreen: bigScreen, leftSpace: 60, yFormat: NumberFormat.compact(explicitSign: true),),
if(trData.length <= 1 || apmData.length <= 1 || ppsData.length <= 1 || vsData.length <= 1 || appData.length <= 1 || dssData.length <= 1 || dspData.length <= 1 || appdspData.length <= 1 || vsapmData.length <= 1 || cheeseData.length <= 1 || gbeData.length <= 1 || nyaappData.length <= 1 || areaData.length <= 1 || estTrData.length <= 1 || estaccData.length <= 1) const Center(child: Text("Some charts aren't shown due to lack of data...", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)))
// Why it's look like a garbage solution???
], ],
), ),
] : [const Center(child: Text("No history saved", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)))]); ] : [const Center(child: Text("No history saved", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)))]);
@ -512,12 +508,12 @@ class _HistoryChartThigy extends StatelessWidget{
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
double xInterval = bigScreen ? max(1, (data.last.x - data.first.x) / 6) : max(1, (data.last.x - data.first.x) / 3); double xInterval = bigScreen ? max(1, (data.last.x - data.first.x) / 6) : max(1, (data.last.x - data.first.x) / 3);
return AspectRatio( return SizedBox(
aspectRatio: bigScreen ? 1.9 : 1.1, width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height - 100,
child: Stack( child: Stack(
children: [ children: [
Row(mainAxisAlignment: MainAxisAlignment.center, children: [Text(title, style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28))]), Padding( padding: bigScreen ? const EdgeInsets.fromLTRB(40, 40, 40, 48) : const EdgeInsets.fromLTRB(0, 40, 0, 48) ,
Padding( padding: bigScreen ? const EdgeInsets.fromLTRB(40, 75, 40, 48) : const EdgeInsets.fromLTRB(0, 80, 0, 48) ,
child: LineChart( child: LineChart(
LineChartData( LineChartData(
lineBarsData: [LineChartBarData(spots: data)], lineBarsData: [LineChartBarData(spots: data)],
@ -558,7 +554,7 @@ class _RecordThingy extends StatelessWidget {
return LayoutBuilder(builder: (context, constraints) { return LayoutBuilder(builder: (context, constraints) {
bool bigScreen = constraints.maxWidth > 768; bool bigScreen = constraints.maxWidth > 768;
return ListView.builder( return ListView.builder(
physics: const ClampingScrollPhysics(), physics: const AlwaysScrollableScrollPhysics(),
itemCount: 1, itemCount: 1,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
return Column( return Column(
@ -881,7 +877,7 @@ class _OtherThingy extends StatelessWidget {
return LayoutBuilder(builder: (context, constraints) { return LayoutBuilder(builder: (context, constraints) {
bool bigScreen = constraints.maxWidth > 768; bool bigScreen = constraints.maxWidth > 768;
return ListView.builder( return ListView.builder(
physics: const ClampingScrollPhysics(), physics: const AlwaysScrollableScrollPhysics(),
itemCount: 1, itemCount: 1,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
return Column( return Column(

View File

@ -85,6 +85,8 @@ flutter:
- res/tetrio_badges/early-supporter.png - res/tetrio_badges/early-supporter.png
- res/tetrio_badges/founder.png - res/tetrio_badges/founder.png
- res/tetrio_badges/galactic2x2_1.png - res/tetrio_badges/galactic2x2_1.png
- res/tetrio_badges/galactic2x2_2.png
- res/tetrio_badges/galactic2x2_3.png
- res/tetrio_badges/ggc_1.png - res/tetrio_badges/ggc_1.png
- res/tetrio_badges/ggc_2.png - res/tetrio_badges/ggc_2.png
- res/tetrio_badges/ggc_3.png - res/tetrio_badges/ggc_3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB