Fix Display and generator starts
Dieser Commit ist enthalten in:
Ursprung
2484560ced
Commit
6b8f631235
@ -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",
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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"),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
|
62
lib/src/screens/generator/bracket_generator.dart
Normale Datei
62
lib/src/screens/generator/bracket_generator.dart
Normale Datei
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
199
lib/src/screens/generator/generators/group_generator.dart
Normale Datei
199
lib/src/screens/generator/generators/group_generator.dart
Normale Datei
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
61
lib/src/screens/generator/loaded_generator.dart
Normale Datei
61
lib/src/screens/generator/loaded_generator.dart
Normale Datei
@ -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))),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -60,6 +60,7 @@ class HomeScreen extends HookConsumerWidget {
|
||||
return;
|
||||
}
|
||||
navRailIndex.value = index;
|
||||
Navigator.pop(context);
|
||||
},
|
||||
children: [
|
||||
Padding(
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren