Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/const.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ class Const {
static const String frenchBeloteScoreDB = 'belote-score';
static const String tarotScoreDB = 'tarot-score';
static const String purchaseDB = 'iap';
static const String notificationDB = 'notification';
}
48 changes: 22 additions & 26 deletions lib/helpers/correct_instance.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import 'package:carg/models/game/coinche_belote.dart';
import 'package:carg/models/game/contree_belote.dart';
import 'package:carg/models/game/french_belote.dart';
import 'package:carg/models/game/game.dart';
import 'package:carg/models/game/tarot.dart';
import 'package:carg/models/game/game_type.dart';
import 'package:carg/services/impl/game/coinche_belote_game_service.dart';
import 'package:carg/services/impl/game/contree_belote_game_service.dart';
import 'package:carg/services/impl/game/french_belote_game_service.dart';
Expand All @@ -17,51 +13,51 @@ import 'package:carg/services/impl/score/french_belote_score_service.dart';
import 'package:carg/services/impl/score/tarot_score_service.dart';

class CorrectInstance {
static ofGameService(Game game) {
switch (game.runtimeType) {
case FrenchBelote:
static ofGameService(GameType type) {
switch (type) {
case GameType.BELOTE:
return FrenchBeloteGameService();
case CoincheBelote:
case GameType.COINCHE:
return CoincheBeloteGameService();
case ContreeBelote:
case GameType.CONTREE:
return ContreeBeloteGameService();
case Tarot:
case GameType.TAROT:
return TarotGameService();
default:
throw Exception(
'${game.runtimeType.toString()} does not have any registered game service');
'${type.name.toString()} does not have any registered game service');
}
}

static ofRoundService(Game game) {
switch (game.runtimeType) {
case FrenchBelote:
static ofRoundService(GameType type) {
switch (type) {
case GameType.BELOTE:
return FrenchBeloteRoundService();
case CoincheBelote:
case GameType.COINCHE:
return CoincheBeloteRoundService();
case ContreeBelote:
case GameType.CONTREE:
return ContreeBeloteRoundService();
case Tarot:
case GameType.TAROT:
return TarotRoundService();
default:
throw Exception(
'${game.runtimeType.toString()} does not have any registered round service');
'${type.name.toString()} does not have any registered round service');
}
}

static ofScoreService(Game game) {
switch (game.runtimeType) {
case FrenchBelote:
static ofScoreService(GameType type) {
switch (type) {
case GameType.BELOTE:
return FrenchBeloteScoreService();
case CoincheBelote:
case GameType.COINCHE:
return CoincheBeloteScoreService();
case ContreeBelote:
case GameType.CONTREE:
return ContreeBeloteScoreService();
case Tarot:
case GameType.TAROT:
return TarotScoreService();
default:
throw Exception(
'${game.runtimeType.toString()} does not have any registered score service');
'${type.name.toString()} does not have any registered score service');
}
}
}
20 changes: 19 additions & 1 deletion lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"about": "About",
"admin": "Admin",
"and": "and",
"appDescription": "The application to record your games of Belote, Coinche, Contrée and Tarot!",
"attack": "Attack",
"back": "Back",
Expand Down Expand Up @@ -32,7 +33,6 @@
"contractTypeCapot": "Capot",
"contractTypeGenerale": "Générale",
"contractTypeFailedGenerale": "Failed générale",
"contractTypeNormal": "Contract",
"copyId": "Copy the ID",
"country": "{count,plural, =0{Country} =1{1 country} other{{count} countries} }",
"@country": {"placeholders":{"count": {}}},
Expand All @@ -41,6 +41,7 @@
"delete": "Delete",
"deleteAll": "Delete all",
"dixDeDer": "Dix de der",
"doYouWantToContinue": "Do you want to continue?",
"edition": "Edition",
"email": "Email",
"emailSent": "Login email sent",
Expand All @@ -50,6 +51,7 @@
"enterOtp": "Please enter the OTP code sent to",
"error": "Error",
"errorDuringPurchase": "Error during purchase",
"errorGameNotFound": "Game not found",
"errorInvalidPhoneNumber": "The phone number is invalid",
"errorLoadingPage": "Error encountered while loading the page",
"errorPlayerAlreadyLinked": "This player is already linked to another account",
Expand All @@ -59,13 +61,19 @@
"gameAnticlockwiseDirection": "This card game is played in a anticlockwise direction",
"gameClockwiseDirection": "This card game is played in a clockwise direction",
"gameDistribution": "Game distribution",
"gameEnded": "Game ended",
"gameEndedNotificationMessage": "A {game_type} game just ended! Do you want to check the scores?",
"@gameEndedNotificationMessage": {"placeholders":{"game_type": {}}},
"gameEndedNotificationMessageSmall": "A {game_type} game just ended!",
"@gameEndedNotificationMessageSmall": {"placeholders":{"game_type": {}}},
"gameIsStarting": "Game is initializing",
"gameNotes": "Game notes",
"games": "Games",
"gameSelection": "Game selection",
"idCopied": "ID copied to clipboard",
"information": "Information",
"informationAboutTheApp": "Information about the app",
"informationMessage": "Information message",
"inProgress": "In progress",
"leave": "Leave",
"linkPlayer": "Link an existing player to this account",
Expand All @@ -84,18 +92,26 @@
"messagePlayerDistributeCardsFirsPart": "It's",
"messagePlayerDistributeCardsSecondPart": "'s turn to distribute the cards!",
"messageSmsInfo": "An SMS containing an OTP will be sent to you. Standard messaging and data rates apply",
"messageStartGame": "{count,plural, =1{You are about to send a game request notification to this player:} other{You are about to send a game request notification to these players:}",
"@messageStartGame": {"placeholders":{"count": {}}},
"messageStopGame": "You are about to complete this game. The winners as well as the losers (shameful) will be designated",
"messageWelcomeDescription": "The application that allows you to record your games of Belote, Coinche, Contrée and Tarot!",
"myAccount": "My account",
"myPlayers": "My players",
"myProfile": "My profile",
"myTeams": "My teams",
"newGame": "New game",
"newGameInvite": "You have received a new invitation to a {game_type} game from this player:",
"@newGameInvite": {"placeholders":{"game_type": {}}},
"newGameInviteSmall": "You have received a new invitation to a {game_type} game!",
"@newGameInviteSmall": {"placeholders":{"game_type": {}}},
"newGameInviteJoinAsking": "Do you want to join?",
"newEmail": "New email address",
"newPhoneNumber": "New phone number",
"newPhoneNumberValidate": "New phone number validated successfully!",
"newPlayer": "New player",
"newRound": "New round",
"no": "No",
"noEmailProvided": "No email provided",
"noGamesYet": "No games yet",
"noName": "No name",
Expand All @@ -104,6 +120,7 @@
"noProducts": "No products are available for purchase",
"noScoreYet": "No score yet",
"noStatisticYet": "No statistics yet",
"notificationsTitle": "Notifications",
"otp": "One-time password (OTP)",
"otpSend": "OTP code sent successfully",
"or": "or",
Expand Down Expand Up @@ -169,6 +186,7 @@
"them": "Them",
"trickPoints": "Trick points",
"type": "Type",
"yes": "Yes",
"youDontHaveAnyPlayer": "You don't have any players",
"unableAppInfo": "Unable to get application information",
"unableToOpen": "Unable to open the web page",
Expand Down
24 changes: 21 additions & 3 deletions lib/l10n/app_fr.arb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"about": "À propos",
"admin": "Admin",
"and": "et",
"appDescription": "L'application pour enregistrer vos parties de Belote, Coinche, Contrée et Tarot !",
"attack": "Attaque",
"back": "Retour",
Expand Down Expand Up @@ -40,6 +41,7 @@
"delete": "Supprimer",
"deleteAll": "Tout supprimer",
"dixDeDer": "Dix de der",
"doYouWantToContinue": "Voulez-vous continuer ?",
"edition": "Édition",
"email": "Email",
"emailSent": "Email de conexion envoyé",
Expand All @@ -49,6 +51,7 @@
"enterOtp": "Veuillez entrer le code OTP envoyé au",
"error": "Erreur",
"errorDuringPurchase": "Erreur durant l'achat",
"errorGameNotFound": "Partie non trouvée",
"errorInvalidPhoneNumber": "Le numéro de téléphone est invalide",
"errorLoadingPage": "Erreur rencontrée lors du chargement de la page",
"errorPlayerAlreadyLinked": "Ce joueur est déjà associé à un autre compte",
Expand All @@ -58,13 +61,19 @@
"gameAnticlockwiseDirection": "Ce jeu de carte se joue dans le sens antihorraire",
"gameClockwiseDirection": "Ce jeu de carte se joue dans le sens horraire",
"gameDistribution": "Distribution des parties",
"gameEnded": "Partie terminée",
"gameEndedNotificationMessage": "Une partie de {game_type} vient juste de se terminer ! Voulez-vous consulter les scores ?",
"@gameEndedNotificationMessage": {"placeholders":{"game_type": {}}},
"gameEndedNotificationMessageSmall": "Une partie de {game_type} vient juste de se terminer !",
"@gameEndedNotificationMessageSmall": {"placeholders":{"game_type": {}}},
"gameIsStarting": "Partie en cours d'initialisation",
"gameNotes": "Notes de partie",
"games": "Parties",
"gameSelection": "Sélection du jeu",
"idCopied": "ID copié dans le presse papier",
"information": "Informations",
"informationAboutTheApp": "Informations concernant l'application",
"informationMessage": "Message d'information",
"inProgress": "En cours",
"leave": "Quitter",
"linkPlayer": "Lier un joueur existant à ce compte",
Expand All @@ -83,18 +92,26 @@
"messagePlayerDistributeCardsFirsPart": "C'est au tours de",
"messagePlayerDistributeCardsSecondPart": " de distribuer les cartes !",
"messageSmsInfo": "Un SMS contenant un OTP va vous être envoyé. Des frais standards d'envoi de messages et d'échange de données s'appliquent",
"messageStartGame": "{count,plural, =1{Vous êtes sur le point d'envoyer une notification de demande de partie à ce joueur.euse :} other{Vous êtes sur le point d'envoyer une notification de demande de partie à ces joueurs.euses :}",
"@messageStartGame": {"placeholders":{"count": {}}},
"messageStopGame": "Tu es sur le point de terminer cette partie. Les gagnants ainsi que les perdants (honteux) vont être désignés",
"messageWelcomeDescription": "L'application qui vous permet d'enregistrer vos parties de Belote, Coinche, Contrée et Tarot !",
"myAccount": "Mon compte",
"myPlayers": "Mes joueurs",
"myProfile": "Mon profil",
"myTeams": "Mes équipes",
"newGame": "Nouvelle partie",
"newGameInvite": "Vous avez reçu une nouvelle invitation à une partie de {game_type} de la part de ce.tte joueur.euse : ",
"@newGameInvite": {"placeholders":{"game_type": {}}},
"newGameInviteSmall": "Vous avez reçu une nouvelle invitation à une partie de {game_type} !",
"@newGameInviteSmall": {"placeholders":{"game_type": {}}},
"newGameInviteJoinAsking": "Voulez-vous rejoindre cette partie ?",
"newEmail": "Nouvelle adresse email",
"newPhoneNumber": "Nouveau numéro de téléphone",
"newPhoneNumberValidate": "Nouveau numéro de téléphone validé avec succès !",
"newPlayer": "Nouveau/nouvelle joueur/joueuse",
"newPlayer": "Nouveau.elle joueur.euse",
"newRound": "Nouvelle manche",
"no": "Non",
"noEmailProvided": "Pas d'email renseigné",
"noGamesYet": "Pas encore de parties",
"noName": "Sans nom",
Expand All @@ -103,6 +120,7 @@
"noProducts": "Aucun produit n'est diponible à l'achat",
"noScoreYet": "Pas encore de score",
"noStatisticYet": "Pas encore de statistiques",
"notificationsTitle": "Notifications",
"otp": "Mot de passe à usage unique (OTP)",
"otpSend": "Code OTP envoyé avec succès",
"or": "ou",
Expand All @@ -120,8 +138,7 @@
"playerOrder": "Ordre des joueurs",
"playerSelection": "Sélection des joueurs",
"points": "{count,plural, =0{Point} other{{count} points}",
"@points": {"placeholders":{"count": {}}},

"@points": {"placeholders":{"count": {}}},
"privacyPolicy": "Politique de confidentialité",
"profilePicture": "Image de profil (URL)",
"profileTitle": "Profil",
Expand Down Expand Up @@ -169,6 +186,7 @@
"them": "Eux",
"trickPoints": "Point des plis",
"type": "Type",
"yes": "Oui",
"youDontHaveAnyPlayer": "Vous ne disposez pas de joueur",
"unableAppInfo": "mpossible d'obtenir les informations de l'application",
"unableToOpen": "Impossible d'ouvrir la page ",
Expand Down
2 changes: 2 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:carg/app_theme.dart';
import 'package:carg/services/auth/auth_service.dart';
import 'package:carg/views/screens/home_screen.dart';
import 'package:carg/views/screens/notifications_screen.dart';
import 'package:carg/views/screens/register/register_screen.dart';
import 'package:carg/views/screens/splash_screen.dart';
import 'package:carg/views/screens/user_screen.dart';
Expand Down Expand Up @@ -63,6 +64,7 @@ class _CargState extends State<Carg> {
routes: {
UserScreen.routeName: (context) => const UserScreen(),
RegisterScreen.routeName: (context) => RegisterScreen(),
NotificationsScreen.routeName: (context) => NotificationsScreen(),
HomeScreen.routeName: (context) => HomeScreen(
requestedIndex:
ModalRoute.of(context)!.settings.arguments as int? ?? 0)
Expand Down
61 changes: 61 additions & 0 deletions lib/models/notification/abstract_game_notification.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import 'package:carg/helpers/correct_instance.dart';
import 'package:carg/helpers/custom_route.dart';
import 'package:carg/models/game/belote_game.dart';
import 'package:carg/models/game/game_type.dart';
import 'package:carg/models/game/tarot.dart';
import 'package:carg/models/notification/abstract_notification.dart';
import 'package:carg/models/players/belote_players.dart';
import 'package:carg/services/game/abstract_game_service.dart';
import 'package:carg/views/helpers/info_snackbar.dart';
import 'package:carg/views/screens/play/play_belote_screen.dart';
import 'package:carg/views/screens/play/play_tarot_game_screen.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

abstract class AbstractGameNotification extends AbstractNotification {
final String gameId;
final GameType gameType;

AbstractGameNotification(
{super.id,
super.notificationStatus,
super.timeStamp,
required super.kind,
required super.boundTo,
required this.gameId,
required this.gameType});

@override
Map<String, dynamic> toJSON() {
var tmpJSON = super.toJSON();
tmpJSON.addAll({'game_id': gameId, 'game_type': gameType.name});
return tmpJSON;
}

/// Return the correct service to instanciate the associated game
AbstractGameService getGameService() {
return CorrectInstance.ofGameService(gameType);
}

/// Open the game screen
void goToGame(BuildContext context) async {
var gameService = getGameService();
var game = await gameService.get(gameId);

if (game == null) {
InfoSnackBar.showErrorSnackBar(
context, AppLocalizations.of(context)!.errorGameNotFound);
} else {
Navigator.push(
context,
CustomRouteFade(
builder: (context) => gameType == GameType.TAROT
? PlayTarotGameScreen(tarotGame: game as Tarot)
: PlayBeloteScreen(
beloteGame: game as Belote<BelotePlayers>,
),
),
);
}
}
}
Loading