diff --git a/tarok/lib/constants.dart b/tarok/lib/constants.dart index 2d824ae..3ea1cb9 100644 --- a/tarok/lib/constants.dart +++ b/tarok/lib/constants.dart @@ -37,7 +37,7 @@ const WS_URL = kReleaseMode ? "wss://palcka.si/api/ws" : "ws://localhost:8080/ws"; const LOBBY_WS_URL = kReleaseMode ? "wss://palcka.si/api/lobby" : "ws://localhost:8080/lobby"; -const RELEASE = "0.1.0"; +const RELEASE = "0.1.1"; bool OMOGOCI_STOCKSKIS_PREDLOGE = true; bool SLEPI_TAROK = false; bool AVTOPOTRDI_ZALOZITEV = false; diff --git a/tarok/lib/game/game_controller.dart b/tarok/lib/game/game_controller.dart index 877a61f..601a848 100644 --- a/tarok/lib/game/game_controller.dart +++ b/tarok/lib/game/game_controller.dart @@ -163,6 +163,11 @@ class GameController extends GetxController { @override void onClose() { + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown, + ]); + controller.value.dispose(); if (!kIsWeb && (Platform.isLinux || Platform.isWindows)) { diff --git a/tarok/lib/lobby/friends.dart b/tarok/lib/lobby/friends.dart index f537bf1..d520d02 100644 --- a/tarok/lib/lobby/friends.dart +++ b/tarok/lib/lobby/friends.dart @@ -54,7 +54,7 @@ class Friends extends StatelessWidget { child: Row( children: [ const SizedBox( - width: 100, + width: 10, ), Initicon( text: e.name, @@ -95,7 +95,7 @@ class Friends extends StatelessWidget { }, ), const SizedBox( - width: 100, + width: 10, ), ], ), @@ -113,7 +113,7 @@ class Friends extends StatelessWidget { child: Row( children: [ const SizedBox( - width: 100, + width: 10, ), Initicon( text: e.name, @@ -147,7 +147,7 @@ class Friends extends StatelessWidget { }, ), const SizedBox( - width: 100, + width: 10, ), ], ), @@ -165,7 +165,7 @@ class Friends extends StatelessWidget { child: Row( children: [ const SizedBox( - width: 100, + width: 10, ), SizedBox( height: 70, @@ -244,7 +244,7 @@ class Friends extends StatelessWidget { if (gameId != "" && invited.contains(e.id)) const Icon(Icons.check), const SizedBox( - width: 100, + width: 10, ), ], ), diff --git a/tarok/lib/lobby/lobby.dart b/tarok/lib/lobby/lobby.dart index 12d1a3f..ca07581 100644 --- a/tarok/lib/lobby/lobby.dart +++ b/tarok/lib/lobby/lobby.dart @@ -14,14 +14,11 @@ // along with this program. If not, see . import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart' hide FormData; import 'package:stockskis/stockskis.dart' hide Card, debugPrint; -import 'package:tarok/constants.dart'; import 'package:tarok/lobby/lobby_controller.dart'; -import 'package:tarok/replay.dart'; +import 'package:tarok/lobby/lobby_ui.dart'; import 'package:tarok/ui/main_page.dart'; -import 'package:url_launcher/url_launcher.dart'; Future preloadCards(BuildContext context) async { for (int i = 0; i < CARDS.length; i++) { @@ -46,633 +43,10 @@ class Lobby extends StatelessWidget { tooltip: "new_game".tr, child: const Icon(Icons.add), ), - child: Obx( - () => Row( - children: [ - Expanded( - child: Center( - child: ListView( - shrinkWrap: true, - children: [ - Center( - child: Text( - "welcome_message".tr, - style: const TextStyle(fontSize: 40), - ), - ), - if (controller.guest.value) - Center( - child: Text( - "using_guest_access".tr, - style: const TextStyle(fontSize: 20), - ), - ), - Center( - child: Text( - "games_available".tr, - style: const TextStyle(fontSize: 30), - ), - ), - if (!controller.guest.value) - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("with_players".tr), - const SizedBox( - width: 10, - ), - ElevatedButton.icon( - onPressed: () => - controller.quickGameFind(3, "normal"), - label: Text( - "in_three".tr, - style: const TextStyle( - fontSize: 20, - ), - ), - icon: const Icon(Icons.face), - ), - ElevatedButton.icon( - onPressed: () => - controller.quickGameFind(4, "normal"), - label: Text( - "in_four".tr, - style: const TextStyle( - fontSize: 20, - ), - ), - icon: const Icon(Icons.face), - ), - ]), - if (!controller.guest.value) - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("chatroom".tr), - const SizedBox( - width: 10, - ), - ElevatedButton.icon( - onPressed: () => - controller.quickGameFind(3, "klepetalnica"), - label: Text( - "in_three".tr, - style: const TextStyle( - fontSize: 20, - ), - ), - icon: const Icon(Icons.face), - ), - ElevatedButton.icon( - onPressed: () => - controller.quickGameFind(4, "klepetalnica"), - label: Text( - "in_four".tr, - style: const TextStyle( - fontSize: 20, - ), - ), - icon: const Icon(Icons.face), - ), - ]), - Row(mainAxisAlignment: MainAxisAlignment.center, children: [ - Text("with_bots".tr), - const SizedBox( - width: 10, - ), - ElevatedButton.icon( - onPressed: () => controller.botGame(3), - label: Text( - "in_three".tr, - style: const TextStyle( - fontSize: 20, - ), - ), - icon: const Icon(Icons.smart_toy), - ), - ElevatedButton.icon( - onPressed: () => controller.botGame(4), - label: Text( - "in_four".tr, - style: const TextStyle( - fontSize: 20, - ), - ), - icon: const Icon(Icons.smart_toy), - ), - ]), - if (!controller.guest.value) - const SizedBox( - height: 10, - ), - if (!controller.guest.value) - Center( - child: ElevatedButton( - onPressed: () => Get.defaultDialog( - title: "replay".tr, - content: SingleChildScrollView( - child: Obx( - () => Column(children: [ - Text("replay_desc".tr), - const SizedBox( - height: 10, - ), - Row(children: [ - Expanded( - child: TextField( - controller: - controller.replayController.value, - decoration: InputDecoration( - border: const UnderlineInputBorder(), - labelText: "replay_link".tr, - ), - ), - ), - ]), - ]), - ), - ), - actions: [ - TextButton( - onPressed: () { - Get.back(); - }, - child: Text("cancel".tr), - ), - TextButton( - onPressed: () { - joinReplay( - controller.replayController.value.text); - }, - child: Text("ok".tr), - ), - ], - ), - child: Text("replay".tr), - ), - ), - const SizedBox( - height: 10, - ), - Center( - child: ElevatedButton( - onPressed: () => showDialog( - context: context, - builder: (context) { - return StatefulBuilder( - builder: (context, setState) { - return AlertDialog( - title: Text("modify_bots".tr), - content: SingleChildScrollView( - child: Obx( - () => Column(children: [ - Text("modify_bots_desc".tr), - const SizedBox( - height: 10, - ), - FutureBuilder( - future: controller.getBots(), - builder: (BuildContext context, - AsyncSnapshot snapshot) { - if (controller - .botNames.isNotEmpty) { - return DataTable( - columns: [ - DataColumn( - label: Expanded( - child: Text( - "bot".tr, - style: const TextStyle( - fontStyle: FontStyle - .italic), - ), - ), - ), - DataColumn( - label: Expanded( - child: Text( - "name".tr, - style: const TextStyle( - fontStyle: FontStyle - .italic), - ), - ), - ), - DataColumn( - label: Expanded( - child: Text( - "remove".tr, - style: const TextStyle( - fontStyle: FontStyle - .italic), - ), - ), - ), - ], - rows: [ - ...controller.botNames.map( - (e) => DataRow( - cells: [ - DataCell( - Text(e["type"])), - DataCell( - Text(e["name"])), - DataCell( - IconButton( - icon: const Icon( - Icons.delete), - onPressed: - () async { - await controller - .deleteBot( - e["name"], - e["type"], - ); - await controller - .getBots(); - setState(() {}); - }, - ), - ), - ], - ), - ), - ], - ); - } - return const SizedBox(); - }, - ), - Row(children: [ - Expanded( - child: TextField( - controller: controller - .playerNameController.value, - decoration: InputDecoration( - border: - const UnderlineInputBorder(), - labelText: "bot_name".tr, - ), - ), - ), - IconButton( - icon: const Icon( - Icons.replay_outlined), - onPressed: () async { - String botName = - controller.randomBotName(); - controller.playerNameController - .value.text = botName; - setState(() {}); - }, - ), - ]), - const SizedBox( - height: 10, - ), - Center( - child: SegmentedButton( - segments: >[ - ...BOTS.map( - (e) => ButtonSegment( - value: e, - label: Text( - e["name"].toString()), - ), - ) - ], - selected: { - controller.dropdownValue - }, - onSelectionChanged: - (Set newSelection) { - controller.dropdownValue = - newSelection.first; - setState(() {}); - }, - ), - ), - const SizedBox( - height: 10, - ), - ElevatedButton.icon( - onPressed: () async { - await controller.newBot( - controller.playerNameController - .value.text, - controller.dropdownValue["type"] - as String, - ); - setState(() {}); - }, - label: Text( - "add_bot".tr, - style: const TextStyle( - fontSize: 20, - ), - ), - icon: const Icon(Icons.add), - ), - ]), - ), - ), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text("finish_list_editing".tr), - ), - ], - ); - }); - }), - child: Text("customize_bots".tr), - ), - ), - - const SizedBox( - height: 10, - ), - Align( - alignment: Alignment.center, - child: IntrinsicWidth( - child: Card( - child: ListTile( - leading: const FaIcon(FontAwesomeIcons.discord), - title: Text("discord".tr), - subtitle: Text("discord_desc".tr), - onTap: () async { - await launchUrl( - Uri.parse("https://discord.gg/fzeN4Cnbr3")); - }, - ), - ), - ), - ), - - const SizedBox( - height: 10, - ), - - // PRIORITY QUEUE - GridView.count( - childAspectRatio: 0.75, - crossAxisCount: 4, - physics: - const NeverScrollableScrollPhysics(), // to disable GridView's scrolling - shrinkWrap: true, - children: [ - ...controller.priorityQueue.map( - (e) => GestureDetector( - onTap: () async { - debugPrint("Priority"); - await Get.toNamed("/game", parameters: { - "playing": e.requiredPlayers.toString(), - "gameId": e.id, - "bots": "false", - }); - }, - child: Card( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Center( - child: Text( - "game".trParams({ - "type": e.type == "klepetalnica" - ? "(klepetalnica)" - : "" - }), - ), - ), - if (e.mondfangRadelci) - Center( - child: Text("mondfang_radelci".tr), - ), - if (e.skisfang) - Center( - child: Text("skisfang".tr), - ), - if (e.napovedanMondfang) - Center( - child: Text("predicted_mondfang".tr), - ), - const SizedBox( - height: 10, - ), - ...e.user.map( - (k) => SizedBox( - height: 40, - child: Text( - k.name, - style: const TextStyle( - fontSize: 25, - ), - ), - ), - ), - ListView.builder( - shrinkWrap: true, - itemCount: - e.requiredPlayers - e.user.length, - itemBuilder: - (BuildContext context, int index) { - return Center( - child: SizedBox( - height: 40, - child: Text( - "join_game".tr, - style: const TextStyle( - fontSize: 25, - ), - ), - ), - ); - }, - ), - ], - ), - ), - ), - ), - ], - ), - - // QUEUE - GridView.count( - crossAxisCount: 4, - physics: - const NeverScrollableScrollPhysics(), // to disable GridView's scrolling - shrinkWrap: true, - children: [ - ...controller.queue.map( - (e) => GestureDetector( - onTap: () async { - await Get.toNamed("/game", parameters: { - "playing": e.requiredPlayers.toString(), - "gameId": e.id, - "bots": "false", - }); - }, - child: Card( - child: Column( - children: [ - Center( - child: Text( - "game".trParams({ - "type": e.type == "klepetalnica" - ? "(klepetalnica)" - : "" - }), - ), - ), - if (e.mondfangRadelci) - Center( - child: Text("mondfang_radelci".tr), - ), - if (e.skisfang) - Center( - child: Text("skisfang".tr), - ), - if (e.napovedanMondfang) - Center( - child: Text("predicted_mondfang".tr), - ), - const SizedBox( - height: 10, - ), - ...e.user.map( - (k) => SizedBox( - height: 40, - child: Text( - k.name, - style: const TextStyle( - fontSize: 25, - ), - ), - ), - ), - ListView.builder( - shrinkWrap: true, - itemCount: - e.requiredPlayers - e.user.length, - itemBuilder: - (BuildContext context, int index) { - return Center( - child: SizedBox( - height: 40, - child: Text( - "join_game".tr, - style: const TextStyle( - fontSize: 25, - ), - ), - ), - ); - }, - ), - ], - ), - ), - ), - ), - ], - ), - ], - ), - ), - ), - if (controller.tournaments.isNotEmpty) - Expanded( - child: Center( - child: ListView( - children: [ - ...controller.tournaments.map((e) => Card( - child: Container( - padding: const EdgeInsets.all(10), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Flexible( - child: Text(e["created_by"].length == - 1 - ? "invite_tournament_singular${e['private'] ? '_private' : ''}" - .trParams({ - "who": - (e["created_by"] as List) - .join(", "), - }) - : e["created_by"].length == 2 - ? "invite_tournament_dual${e['private'] ? '_private' : ''}" - .trParams({ - "who": (e["created_by"] - as List) - .join(", "), - }) - : "invite_tournament_plural${e['private'] ? '_private' : ''}" - .trParams({ - "who": (e["created_by"] - as List) - .join(", "), - })), - ), - ], - ), - Text( - "${e["name"]} (Div.${e["division"]})", - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 18, - ), - ), - Text("tournament_rated".trParams({ - "israted": - e["rated"] ? "" : "not_space".tr, - })), - Row( - children: [ - // grozote - Text( - "${DateTime.fromMillisecondsSinceEpoch(e["start_time"]).day}. ${DateTime.fromMillisecondsSinceEpoch(e["start_time"]).month}. ${DateTime.fromMillisecondsSinceEpoch(e["start_time"]).year} — ${DateTime.fromMillisecondsSinceEpoch(e["start_time"]).hour}.${DateTime.fromMillisecondsSinceEpoch(e["start_time"]).minute < 10 ? "0${DateTime.fromMillisecondsSinceEpoch(e["start_time"]).minute}" : DateTime.fromMillisecondsSinceEpoch(e["start_time"]).minute}", - ), - - const Spacer(), - IconButton( - onPressed: () async { - if (e["registered"]) { - await controller - .unregisterContest(e["id"]); - return; - } - await controller - .registerContest(e["id"]); - }, - icon: e["registered"] - ? const Icon(Icons.check) - : const Icon(Icons.cancel), - ), - ], - ), - if (e["private"]) - TextButton( - onPressed: () { - controller.tournamentTestingDialog( - e["id"], e["division"]); - }, - child: - Text("start_tournament_testing".tr), - ), - ]), - ), - )), - ], - ), - ), - ), - ], - ), + child: const Column( + children: [ + LobbyUI(), + ], ), ); } diff --git a/tarok/lib/lobby/lobby_controller.dart b/tarok/lib/lobby/lobby_controller.dart index 2b5e220..fa8e3da 100644 --- a/tarok/lib/lobby/lobby_controller.dart +++ b/tarok/lib/lobby/lobby_controller.dart @@ -302,6 +302,7 @@ class LobbyController extends GetxController { ), ); tournaments.value = jsonDecode(response.data); + print(tournaments); } Future newGame(int players) async { @@ -499,10 +500,14 @@ class LobbyController extends GetxController { // eh, nič zato, smo čist v redu } + print("fetching tournaments"); + try { await fetchTournaments(); } catch (e) {} + print("done fetching tournaments"); + super.onInit(); } diff --git a/tarok/lib/lobby/lobby_ui.dart b/tarok/lib/lobby/lobby_ui.dart new file mode 100644 index 0000000..96db0b0 --- /dev/null +++ b/tarok/lib/lobby/lobby_ui.dart @@ -0,0 +1,549 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:get/get.dart'; +import 'package:tarok/constants.dart'; +import 'package:tarok/lobby/lobby_controller.dart'; +import 'package:tarok/lobby/tournament_invite.dart'; +import 'package:tarok/replay.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class LobbyUI extends StatelessWidget { + const LobbyUI({super.key}); + + @override + Widget build(BuildContext context) { + LobbyController controller = Get.put(LobbyController()); + + return Expanded( + child: Obx( + () => ListView( + children: [ + const TournamentInvite(), + Center( + child: Column( + children: [ + Center( + child: Text( + "welcome_message".tr, + style: const TextStyle(fontSize: 40), + ), + ), + if (controller.guest.value) + Center( + child: Text( + "using_guest_access".tr, + style: const TextStyle(fontSize: 20), + ), + ), + Center( + child: Text( + "games_available".tr, + style: const TextStyle(fontSize: 30), + ), + ), + if (!controller.guest.value) + Center( + child: Text("with_players".tr), + ), + if (!controller.guest.value) + Row(mainAxisAlignment: MainAxisAlignment.center, children: [ + ElevatedButton.icon( + onPressed: () => controller.quickGameFind(3, "normal"), + label: Text( + "in_three".tr, + style: const TextStyle( + fontSize: 20, + ), + ), + icon: const Icon(Icons.face), + ), + ElevatedButton.icon( + onPressed: () => controller.quickGameFind(4, "normal"), + label: Text( + "in_four".tr, + style: const TextStyle( + fontSize: 20, + ), + ), + icon: const Icon(Icons.face), + ), + ]), + if (!controller.guest.value) + Center( + child: Text("chatroom".tr), + ), + if (!controller.guest.value) + Row(mainAxisAlignment: MainAxisAlignment.center, children: [ + ElevatedButton.icon( + onPressed: () => + controller.quickGameFind(3, "klepetalnica"), + label: Text( + "in_three".tr, + style: const TextStyle( + fontSize: 20, + ), + ), + icon: const Icon(Icons.face), + ), + ElevatedButton.icon( + onPressed: () => + controller.quickGameFind(4, "klepetalnica"), + label: Text( + "in_four".tr, + style: const TextStyle( + fontSize: 20, + ), + ), + icon: const Icon(Icons.face), + ), + ]), + Center( + child: Text("with_bots".tr), + ), + Row(mainAxisAlignment: MainAxisAlignment.center, children: [ + ElevatedButton.icon( + onPressed: () => controller.botGame(3), + label: Text( + "in_three".tr, + style: const TextStyle( + fontSize: 20, + ), + ), + icon: const Icon(Icons.smart_toy), + ), + ElevatedButton.icon( + onPressed: () => controller.botGame(4), + label: Text( + "in_four".tr, + style: const TextStyle( + fontSize: 20, + ), + ), + icon: const Icon(Icons.smart_toy), + ), + ]), + if (!controller.guest.value) + const SizedBox( + height: 10, + ), + if (!controller.guest.value) + Center( + child: ElevatedButton( + onPressed: () => Get.defaultDialog( + title: "replay".tr, + content: SingleChildScrollView( + child: Obx( + () => Column(children: [ + Text("replay_desc".tr), + const SizedBox( + height: 10, + ), + Row(children: [ + Expanded( + child: TextField( + controller: + controller.replayController.value, + decoration: InputDecoration( + border: const UnderlineInputBorder(), + labelText: "replay_link".tr, + ), + ), + ), + ]), + ]), + ), + ), + actions: [ + TextButton( + onPressed: () { + Get.back(); + }, + child: Text("cancel".tr), + ), + TextButton( + onPressed: () { + joinReplay( + controller.replayController.value.text); + }, + child: Text("ok".tr), + ), + ], + ), + child: Text("replay".tr), + ), + ), + const SizedBox( + height: 10, + ), + Center( + child: ElevatedButton( + onPressed: () => showDialog( + context: context, + builder: (context) { + return StatefulBuilder( + builder: (context, setState) { + return AlertDialog( + title: Text("modify_bots".tr), + content: SingleChildScrollView( + child: Obx( + () => Column(children: [ + Text("modify_bots_desc".tr), + const SizedBox( + height: 10, + ), + FutureBuilder( + future: controller.getBots(), + builder: (BuildContext context, + AsyncSnapshot snapshot) { + if (controller.botNames.isNotEmpty) { + return DataTable( + columns: [ + DataColumn( + label: Expanded( + child: Text( + "bot".tr, + style: const TextStyle( + fontStyle: + FontStyle.italic), + ), + ), + ), + DataColumn( + label: Expanded( + child: Text( + "name".tr, + style: const TextStyle( + fontStyle: + FontStyle.italic), + ), + ), + ), + DataColumn( + label: Expanded( + child: Text( + "remove".tr, + style: const TextStyle( + fontStyle: + FontStyle.italic), + ), + ), + ), + ], + rows: [ + ...controller.botNames.map( + (e) => DataRow( + cells: [ + DataCell(Text(e["type"])), + DataCell(Text(e["name"])), + DataCell( + IconButton( + icon: const Icon( + Icons.delete), + onPressed: () async { + await controller + .deleteBot( + e["name"], + e["type"], + ); + await controller + .getBots(); + setState(() {}); + }, + ), + ), + ], + ), + ), + ], + ); + } + return const SizedBox(); + }, + ), + Row(children: [ + Expanded( + child: TextField( + controller: controller + .playerNameController.value, + decoration: InputDecoration( + border: + const UnderlineInputBorder(), + labelText: "bot_name".tr, + ), + ), + ), + IconButton( + icon: + const Icon(Icons.replay_outlined), + onPressed: () async { + String botName = + controller.randomBotName(); + controller.playerNameController + .value.text = botName; + setState(() {}); + }, + ), + ]), + const SizedBox( + height: 10, + ), + Center( + child: SegmentedButton( + segments: >[ + ...BOTS.map( + (e) => ButtonSegment( + value: e, + label: + Text(e["name"].toString()), + ), + ) + ], + selected: { + controller.dropdownValue + }, + onSelectionChanged: + (Set newSelection) { + controller.dropdownValue = + newSelection.first; + setState(() {}); + }, + ), + ), + const SizedBox( + height: 10, + ), + ElevatedButton.icon( + onPressed: () async { + await controller.newBot( + controller.playerNameController + .value.text, + controller.dropdownValue["type"] + as String, + ); + setState(() {}); + }, + label: Text( + "add_bot".tr, + style: const TextStyle( + fontSize: 20, + ), + ), + icon: const Icon(Icons.add), + ), + ]), + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text("finish_list_editing".tr), + ), + ], + ); + }); + }), + child: Text("customize_bots".tr), + ), + ), + + const SizedBox( + height: 10, + ), + Align( + alignment: Alignment.center, + child: IntrinsicWidth( + child: Card( + child: ListTile( + leading: const FaIcon(FontAwesomeIcons.discord), + title: Text("discord".tr), + subtitle: Text("discord_desc".tr), + onTap: () async { + await launchUrl( + Uri.parse("https://discord.gg/fzeN4Cnbr3")); + }, + ), + ), + ), + ), + + const SizedBox( + height: 10, + ), + + // PRIORITY QUEUE + GridView.count( + childAspectRatio: 0.75, + crossAxisCount: MediaQuery.of(context).size.width < + MediaQuery.of(context).size.height + ? 1 + : 4, + physics: + const NeverScrollableScrollPhysics(), // to disable GridView's scrolling + shrinkWrap: true, + children: [ + ...controller.priorityQueue.map( + (e) => GestureDetector( + onTap: () async { + debugPrint("Priority"); + await Get.toNamed("/game", parameters: { + "playing": e.requiredPlayers.toString(), + "gameId": e.id, + "bots": "false", + }); + }, + child: Card( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Center( + child: Text( + "game".trParams({ + "type": e.type == "klepetalnica" + ? "(klepetalnica)" + : "" + }), + ), + ), + if (e.mondfangRadelci) + Center( + child: Text("mondfang_radelci".tr), + ), + if (e.skisfang) + Center( + child: Text("skisfang".tr), + ), + if (e.napovedanMondfang) + Center( + child: Text("predicted_mondfang".tr), + ), + const SizedBox( + height: 10, + ), + ...e.user.map( + (k) => SizedBox( + height: 40, + child: Text( + k.name, + style: const TextStyle( + fontSize: 25, + ), + ), + ), + ), + ListView.builder( + shrinkWrap: true, + itemCount: e.requiredPlayers - e.user.length, + itemBuilder: + (BuildContext context, int index) { + return Center( + child: SizedBox( + height: 40, + child: Text( + "join_game".tr, + style: const TextStyle( + fontSize: 25, + ), + ), + ), + ); + }, + ), + ], + ), + ), + ), + ), + ], + ), + + // QUEUE + GridView.count( + crossAxisCount: MediaQuery.of(context).size.width < + MediaQuery.of(context).size.height + ? 1 + : 4, + physics: + const NeverScrollableScrollPhysics(), // to disable GridView's scrolling + shrinkWrap: true, + children: [ + ...controller.queue.map( + (e) => GestureDetector( + onTap: () async { + await Get.toNamed("/game", parameters: { + "playing": e.requiredPlayers.toString(), + "gameId": e.id, + "bots": "false", + }); + }, + child: Card( + child: Column( + children: [ + Center( + child: Text( + "game".trParams({ + "type": e.type == "klepetalnica" + ? "(klepetalnica)" + : "" + }), + ), + ), + if (e.mondfangRadelci) + Center( + child: Text("mondfang_radelci".tr), + ), + if (e.skisfang) + Center( + child: Text("skisfang".tr), + ), + if (e.napovedanMondfang) + Center( + child: Text("predicted_mondfang".tr), + ), + const SizedBox( + height: 10, + ), + ...e.user.map( + (k) => SizedBox( + height: 40, + child: Text( + k.name, + style: const TextStyle( + fontSize: 25, + ), + ), + ), + ), + ListView.builder( + shrinkWrap: true, + itemCount: e.requiredPlayers - e.user.length, + itemBuilder: + (BuildContext context, int index) { + return Center( + child: SizedBox( + height: 40, + child: Text( + "join_game".tr, + style: const TextStyle( + fontSize: 25, + ), + ), + ), + ); + }, + ), + ], + ), + ), + ), + ), + ], + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/tarok/lib/lobby/replays.dart b/tarok/lib/lobby/replays.dart index 2737aa8..1e47344 100644 --- a/tarok/lib/lobby/replays.dart +++ b/tarok/lib/lobby/replays.dart @@ -41,9 +41,10 @@ class Replays extends StatelessWidget { ...controller.replays.map( (e) => Row( children: [ - Text(e.gameId), - const Spacer(), - Text(e.createdAt), + //Text(e.gameId), + //const Spacer(), + Text( + "${DateTime.parse(e.createdAt).day}. ${DateTime.parse(e.createdAt).month}. ${DateTime.parse(e.createdAt).year}, ${DateTime.parse(e.createdAt).hour}.${DateTime.parse(e.createdAt).minute}"), const Spacer(), ElevatedButton( onPressed: () async { diff --git a/tarok/lib/lobby/tournament_invite.dart b/tarok/lib/lobby/tournament_invite.dart new file mode 100644 index 0000000..26ab4cd --- /dev/null +++ b/tarok/lib/lobby/tournament_invite.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:tarok/lobby/lobby_controller.dart'; + +class TournamentInvite extends StatelessWidget { + const TournamentInvite({super.key}); + + @override + Widget build(BuildContext context) { + LobbyController controller = Get.put(LobbyController()); + + return Obx( + () => Column( + children: [ + ...controller.tournaments.map((e) => Card( + child: Container( + padding: const EdgeInsets.all(10), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Flexible( + child: Text(e["created_by"].length == 1 + ? "invite_tournament_singular${e['private'] ? '_private' : ''}" + .trParams({ + "who": + (e["created_by"] as List).join(", "), + }) + : e["created_by"].length == 2 + ? "invite_tournament_dual${e['private'] ? '_private' : ''}" + .trParams({ + "who": (e["created_by"] as List) + .join(", "), + }) + : "invite_tournament_plural${e['private'] ? '_private' : ''}" + .trParams({ + "who": (e["created_by"] as List) + .join(", "), + })), + ), + ], + ), + Text( + "${e["name"]} (Div.${e["division"]})", + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18, + ), + ), + Text("tournament_rated".trParams({ + "israted": e["rated"] ? "" : "not_space".tr, + })), + Row( + children: [ + // grozote + Text( + "${DateTime.fromMillisecondsSinceEpoch(e["start_time"]).day}. ${DateTime.fromMillisecondsSinceEpoch(e["start_time"]).month}. ${DateTime.fromMillisecondsSinceEpoch(e["start_time"]).year} — ${DateTime.fromMillisecondsSinceEpoch(e["start_time"]).hour}.${DateTime.fromMillisecondsSinceEpoch(e["start_time"]).minute < 10 ? "0${DateTime.fromMillisecondsSinceEpoch(e["start_time"]).minute}" : DateTime.fromMillisecondsSinceEpoch(e["start_time"]).minute}", + ), + + const Spacer(), + IconButton( + onPressed: () async { + if (e["registered"]) { + await controller.unregisterContest(e["id"]); + return; + } + await controller.registerContest(e["id"]); + }, + icon: e["registered"] + ? const Icon(Icons.check) + : const Icon(Icons.cancel), + ), + ], + ), + if (e["private"]) + TextButton( + onPressed: () { + controller.tournamentTestingDialog( + e["id"], e["division"]); + }, + child: Text("start_tournament_testing".tr), + ), + ]), + ), + )), + ], + ), + ); + } +} diff --git a/tarok/lib/login/login.dart b/tarok/lib/login/login.dart index 522f65e..2c8cf51 100644 --- a/tarok/lib/login/login.dart +++ b/tarok/lib/login/login.dart @@ -180,7 +180,10 @@ class Login extends StatelessWidget { icon: const FaIcon(FontAwesomeIcons.android), ), ElevatedButton.icon( - onPressed: () {}, + onPressed: () async { + await launchUrl(Uri.parse( + "https://f-droid.org/en/packages/si.palcka.tarok/")); + }, label: const Text( "Android (F-Droid)", style: TextStyle( diff --git a/tarok/lib/tms/tms_controller.dart b/tarok/lib/tms/tms_controller.dart index 4a31b64..b894307 100644 --- a/tarok/lib/tms/tms_controller.dart +++ b/tarok/lib/tms/tms_controller.dart @@ -17,6 +17,7 @@ import 'dart:convert'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:get/get.dart' hide FormData; import 'package:omni_datetime_picker/omni_datetime_picker.dart'; import 'package:tarok/constants.dart'; @@ -30,6 +31,25 @@ class TMSController extends GetxController { var testers = [].obs; var testerHandle = TextEditingController().obs; + @override + void onInit() async { + SystemChrome.setPreferredOrientations([ + DeviceOrientation.landscapeLeft, + DeviceOrientation.landscapeRight, + ]); + await fetchTournaments(); + super.onInit(); + } + + @override + void onClose() { + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown, + ]); + super.onClose(); + } + void newTournamentDialog( {String editId = "", bool private = true, @@ -265,10 +285,4 @@ class TMSController extends GetxController { ); await fetchTournaments(); } - - @override - Future onInit() async { - await fetchTournaments(); - super.onInit(); - } } diff --git a/tarok/lib/tms/tournaments.dart b/tarok/lib/tms/tournaments.dart index 2ab3009..9ae69d6 100644 --- a/tarok/lib/tms/tournaments.dart +++ b/tarok/lib/tms/tournaments.dart @@ -31,6 +31,7 @@ class Tournaments extends StatelessWidget { tooltip: "new_tournament".tr, child: const Icon(Icons.add), ), + automaticallyImplyLeading: true, child: Obx( () => Container( padding: const EdgeInsets.all(15.0), diff --git a/tarok/lib/user/user.dart b/tarok/lib/user/user.dart index d2c6d73..15716d9 100644 --- a/tarok/lib/user/user.dart +++ b/tarok/lib/user/user.dart @@ -29,6 +29,7 @@ class Profile extends StatelessWidget { UserSettingsController controller = Get.put(UserSettingsController()); return PalckaHome( + automaticallyImplyLeading: true, child: Obx( () => ListView( padding: const EdgeInsets.all(30), diff --git a/tarok/lib/user/user_controller.dart b/tarok/lib/user/user_controller.dart index 465ba95..d3764ed 100644 --- a/tarok/lib/user/user_controller.dart +++ b/tarok/lib/user/user_controller.dart @@ -20,6 +20,7 @@ import 'dart:convert'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:get/get.dart' hide FormData; import 'package:tarok/constants.dart'; @@ -65,6 +66,25 @@ class UserSettingsController extends GetxController { var nameController = TextEditingController().obs; var handleController = TextEditingController().obs; + @override + void onInit() async { + SystemChrome.setPreferredOrientations([ + DeviceOrientation.landscapeLeft, + DeviceOrientation.landscapeRight, + ]); + await getUser(); + super.onInit(); + } + + @override + void onClose() { + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown, + ]); + super.onClose(); + } + Future getUser() async { final response = await dio.get( '$BACKEND_URL/account', @@ -130,10 +150,4 @@ class UserSettingsController extends GetxController { ); logout(); } - - @override - void onInit() async { - getUser(); - super.onInit(); - } } diff --git a/tarok/pubspec.yaml b/tarok/pubspec.yaml index c504df6..b845342 100644 --- a/tarok/pubspec.yaml +++ b/tarok/pubspec.yaml @@ -2,7 +2,7 @@ name: tarok description: Tarok program Palčka publish_to: "none" -version: 0.1.0+10 +version: 0.1.1+11 environment: sdk: ">=3.1.4 <4.0.0"