1
0

Fix Display and generator starts

Dieser Commit ist enthalten in:
Chaoscaot 2023-01-28 17:06:35 +01:00
Ursprung 2484560ced
Commit 6b8f631235
8 geänderte Dateien mit 432 neuen und 57 gelöschten Zeilen

Datei anzeigen

@ -21,6 +21,7 @@ import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:steamwar_multitool/src/screens/display/display.dart';
import 'package:steamwar_multitool/src/screens/generator/bracket_generator.dart';
import 'package:steamwar_multitool/src/screens/event/event.dart';
import 'package:steamwar_multitool/src/screens/event/event_fights_graph.dart';
@ -46,14 +47,14 @@ final _routes = GoRouter(
return EditEventScreen(eventId);
}),
GoRoute(
path: "/event/:eventId/graph",
path: "/event/:eventId/generator",
builder: (context, state) {
final eventId = int.tryParse(state.params['eventId']!);
if (eventId == null) {
context.go("/");
return const SizedBox();
}
return EventfightsGraph(eventId);
return BracketGeneratorScreen(eventId);
}),
GoRoute(
path: "/display/:eventId",

Datei anzeigen

@ -78,16 +78,27 @@ class DisplayScreenLoaded extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final fights = useState(
eventData.fights.where((element) => element.group == group).toList());
final nextFight = useMemoized(() {
final fights = eventData.fights;
if (fights.isEmpty) {
Future.delayed(const Duration(seconds: 30), () async {
fights.value = (await (await ref.read(eventRepositoryProvider.future))
.listFights(eventData.event.id))
.where((element) => element.group == group)
.toList();
});
if (fights.value.isEmpty) {
return null;
}
final now = DateTime.now();
final nextFight = fights.firstWhere(
(element) => element.start.isAfter(now) && element.group == group);
return nextFight;
});
try {
final nextFight = fights.value.firstWhere(
(element) => element.start.isAfter(now) && element.group == group);
return nextFight;
} catch (e) {
return null;
}
}, [fights.value]);
return Theme(
data: ThemeData.dark(useMaterial3: true),
@ -95,12 +106,6 @@ class DisplayScreenLoaded extends HookConsumerWidget {
backgroundColor: Colors.blue,
body: Stack(
children: [
Image.asset(
"images/background.png",
fit: BoxFit.cover,
height: double.infinity,
width: double.infinity,
),
Column(
mainAxisSize: MainAxisSize.max,
children: [
@ -108,22 +113,35 @@ class DisplayScreenLoaded extends HookConsumerWidget {
SizedBox(
width: double.infinity,
child: Card(
margin: const EdgeInsets.all(8),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Text(
'SteamWar.de - ${eventData.event.name}',
style: const TextStyle(fontSize: 24))),
margin: const EdgeInsets.all(8),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Flexible(
child: ChipClock(),
flex: 1,
),
Spacer(
flex: 4,
),
Text('SteamWar.de - ${eventData.event.name}',
style: const TextStyle(fontSize: 24)),
Spacer(
flex: 5,
),
],
),
],
)),
),
],
),
),
),
Expanded(
child: FightList(
eventData.fights
fights.value
.where(
(element) => group == null || element.group == group)
.toList(),
@ -154,6 +172,25 @@ class DisplayScreenLoaded extends HookConsumerWidget {
}
}
class ChipClock extends HookConsumerWidget {
const ChipClock({
super.key,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final update = useState(0);
useEffect(() {
Future.delayed(const Duration(seconds: 10), () {
update.value++;
});
}, [update.value]);
return Chip(
label: Text(kTimeFormat.format(DateTime.now())),
);
}
}
final kTimeFormat = DateFormat('HH:mm');
class FightList extends HookConsumerWidget {
@ -171,7 +208,7 @@ class FightList extends HookConsumerWidget {
scrollController.offset) {
npos = 0.0;
} else {
npos = scrollController.offset + 300;
npos = scrollController.offset + 325;
}
await scrollController.animateTo(
npos,

Datei anzeigen

@ -1,30 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
class BracketGeneratorScreen extends HookConsumerWidget {
const BracketGeneratorScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
return const Placeholder();
}
}

Datei anzeigen

@ -20,6 +20,7 @@
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:grouped_list/grouped_list.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
@ -308,11 +309,54 @@ class EventFightList extends HookConsumerWidget {
value: "export",
child: Text("Export Data"),
),
PopupMenuItem(
child: Text("Display Link"),
value: "display",
),
];
},
onSelected: (value) {
if (value == "export") {
openExportedFights(fights.value, event.name);
} else if (value == "display") {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text("Display Link"),
content: Text(
"https://steamwar.de/eventplanner/#/display/${event.id}",
style: const TextStyle(fontFamily: "monospace"),
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text("Close"),
),
ElevatedButton(
onPressed: () async {
Clipboard.setData(ClipboardData(
text:
"https://steamwar.de/eventplanner/#/display/${event.id}?key=${(await ref.read(userDataProvider.future)).key}"));
Navigator.of(context).pop();
},
child: const Text("Copy With Key"),
),
ElevatedButton(
onPressed: () {
Clipboard.setData(ClipboardData(
text:
"https://steamwar.de/eventplanner/#/display/${event.id}"));
Navigator.of(context).pop();
},
child: const Text("Copy"),
),
],
);
},
);
}
},
),

Datei anzeigen

@ -0,0 +1,62 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:steamwar_multitool/src/components/components.dart';
import 'package:steamwar_multitool/src/provider/events.dart';
import 'package:steamwar_multitool/src/screens/generator/loaded_generator.dart';
import 'package:steamwar_multitool/src/types/types.dart';
class BracketGeneratorScreen extends HookConsumerWidget {
final int eventId;
const BracketGeneratorScreen(this.eventId, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final event = useMemoized(() => ref
.watch(eventRepositoryProvider.future)
.then((value) => value.getEvent(eventId)));
return FutureBuilder(
builder: (context, data) {
if (data.hasError) {
return Scaffold(
appBar: AppBar(
title: const Text('Error'),
),
body: ErrorComponent(data.error!, data.stackTrace));
}
if (!data.hasData) {
return Scaffold(
appBar: AppBar(
title: const Text('Loading'),
),
body: const LinearProgressIndicator());
}
final event = data.data as EventExtended;
return LoadedBracketGenerator(event);
},
future: event,
);
}
}

Datei anzeigen

@ -0,0 +1,199 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:steamwar_multitool/src/types/types.dart';
class GroupBracketGenerator extends HookConsumerWidget {
final EventExtended event;
const GroupBracketGenerator(this.event, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final groups = useState<List<List<int>>>([]);
final notInGroupTeams = useMemoized(
() => event.teams
.where((element) =>
!groups.value.any((element2) => element2.contains(element.id)))
.toList(),
[groups.value]);
useMemoized(() {
for (final group in groups.value) {
if (group.isEmpty) {
groups.value =
groups.value.where((element) => element != group).toList();
}
}
}, [groups.value]);
final canProceed = useMemoized(
() =>
groups.value.every((element) => element.length >= 2) &&
groups.value.reduce((value, element) => value + element).length ==
event.teams.length,
[groups.value, notInGroupTeams]);
return Scaffold(
appBar: AppBar(
title: Text('Group Bracket Generator'),
),
floatingActionButton: FloatingActionButton(
onPressed: !canProceed
? null
: () {
groups.value.add([]);
},
child: Icon(Icons.navigate_next),
),
body: Column(
mainAxisSize: MainAxisSize.max,
children: [
Wrap(
crossAxisAlignment: WrapCrossAlignment.start,
alignment: WrapAlignment.start,
children: [
for (final team in notInGroupTeams)
Padding(
padding: const EdgeInsets.all(8.0),
child: Draggable<Team>(
data: team,
feedback: Material(
color: Colors.transparent, child: _TeamChip(team)),
child: _TeamChip(team),
),
),
],
),
Wrap(
crossAxisAlignment: WrapCrossAlignment.start,
alignment: WrapAlignment.start,
children: [
for (final group in groups.value)
Padding(
padding: const EdgeInsets.all(8.0),
child: DragTarget<Team>(
builder: (context, candidateData, rejectedData) {
return SizedBox(
width: 200,
height: 200,
child: Card(
child: Column(
children: [
Text('Group ${groups.value.indexOf(group) + 1}'),
Wrap(
children: [
for (final teamId in group)
Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
child: _TeamChip(
event.teams.firstWhere((element) =>
element.id == teamId),
),
onTap: () {
groups.value = [
for (final addGroup in groups.value)
if (addGroup.contains(teamId))
addGroup
.where((element) =>
element != teamId)
.toList()
else
addGroup
];
},
),
),
],
),
],
),
),
);
},
onWillAccept: (data) => true,
onAccept: (data) {
groups.value = [
for (final addGroup in groups.value)
if (addGroup.contains(data.id))
addGroup
.where((element) => element != data.id)
.toList()
else if (addGroup == group)
[...addGroup, data.id]
else
addGroup
];
},
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: DragTarget<Team>(
builder: (context, candidateData, rejectedData) {
return SizedBox(
width: 200,
height: 200,
child: Card(
child: Column(
children: const [
Text('New Group'),
],
),
),
);
},
onWillAccept: (data) => true,
onAccept: (data) {
groups.value = [
...groups.value,
[data.id],
];
},
),
),
],
),
],
),
);
}
}
class _TeamChip extends StatelessWidget {
final Team team;
const _TeamChip(this.team, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Chip(
label: Text(team.name,
style: TextStyle(
color: team.color.computeLuminance() > 0.5
? Colors.black
: Colors.white)),
backgroundColor: team.color,
);
}
}

Datei anzeigen

@ -0,0 +1,61 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:steamwar_multitool/src/screens/generator/generators/group_generator.dart';
import 'package:steamwar_multitool/src/types/event.dart';
class BracketGenerators {
String name;
Widget Function(EventExtended event) builder;
BracketGenerators(this.name, this.builder);
}
final List<BracketGenerators> bracketGenerators = [
BracketGenerators('Group Bracket', (event) => GroupBracketGenerator(event)),
];
class LoadedBracketGenerator extends HookConsumerWidget {
final EventExtended event;
const LoadedBracketGenerator(this.event, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(
title: Text('Bracket Generator'),
leading:
BackButton(onPressed: () => context.go('/event/${event.event.id}')),
),
body: ListView(
children: [
for (final generator in bracketGenerators)
ListTile(
title: Text(generator.name),
onTap: () => Navigator.of(context).push(
MaterialPageRoute(builder: (_) => generator.builder(event))),
),
],
),
);
}
}

Datei anzeigen

@ -60,6 +60,7 @@ class HomeScreen extends HookConsumerWidget {
return;
}
navRailIndex.value = index;
Navigator.pop(context);
},
children: [
Padding(