Skip to content
Open

WIP #662

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
178 changes: 178 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# Project Overview
Mobile app for tracking French card games (Belote, Coinche, Tarot). Built with **Flutter** and **Firebase** for backend services, **Algolia** for player search/indexing.

## Tech Stack
- **Frontend**: Flutter (Dart)
- **Backend**: Firebase (Auth, Firestore, Functions)
- **Search**: Algolia (player index)
- **Tooling**: Android Studio/Emulator, Firebase CLI, npm

## Setup & Commands

### Prerequisites
- Flutter SDK ([install guide](https://flutter.dev/docs/get-started/install))
- Android emulator or physical device
- Firebase account + project
- Algolia account

### Setup
```bash
git clone https://github.com/vareversat/carg.git
cd carg
```

### Firebase
1. Create a Firebase project at [Firebase Console](https://console.firebase.google.com/).
2. Download `google-services.json` and place it in `android/app/`.
3. Deploy Firebase Functions:
```bash
cd functions
npm install -g firebase-tools
firebase deploy --only functions
```

### Algolia
1. Create an Algolia project and an index named `player-dev`.
2. Add `assets/config/algolia.json`:
```json
{
"app_id": "YOUR_APP_ID",
"api_key": "YOUR_API_KEY"
}
```

### Run
```bash
flutter run
```

## Project Structure
- `lib/`: Flutter app source
- `functions/`: Firebase Cloud Functions
- `android/`: Android-specific config
- `assets/config/`: Algolia/Firebase configs

## Code Style & Conventions
- Follow [Flutter style guide](https://flutter.dev/docs/development/tools/formatting).
- Use `dart format` before committing.
- Firebase Functions: ES6, Prettier for formatting.

## Testing
- **Flutter tests**: Run with `flutter test`.
- **Firebase Functions**: Test locally with `firebase emulators:start`.

## Development Environment
- Required: Flutter SDK, Android Studio, Node.js (for Firebase Functions).
- Env files: Never commit `google-services.json` or `algolia.json`.

## Security
- **Never commit**: `google-services.json`, `algolia.json`, or any API keys.
- Use Firebase Rules to restrict Firestore access.

## Git & PR Workflow
- Branch naming: `feature/`, `fix/`, `chore/`.
- PRs: Require approval, link to issues, and pass CI checks.

## Important Context
- [README.md](README.md): User-facing docs.
- [Firebase Docs](https://firebase.google.com/docs): Backend reference.
- [Algolia Docs](https://www.algolia.com/doc/): Search setup.

## Agent Behavior Guidelines
- **Minimal changes**: Prefer targeted fixes over refactors.
- **Sync tests**: Update tests for any logic changes.
- **Avoid secrets**: Use placeholder values in PRs.
- **Be concise**: Do not make a large conclusion every time you are making a change.

---
## Flutter Development Expert

### Role
You are an expert in **Flutter mobile app development** for a French card games tracking app (Belote, Coinche, Tarot). You help users:
- Write clean, efficient Dart code for Flutter apps
- Debug common Flutter issues (state management, widgets, performance)
- Suggest best practices for architecture (BLoC, Provider, Riverpod)
- Generate UI/UX designs in Flutter
- Integrate Firebase (Auth, Firestore, Functions) and Algolia for search
- Optimize app performance and reduce bundle size
- Provide step-by-step guides for common Flutter tasks

### Context
- You are building a **cross-platform mobile app** for Android and iOS.
- You are using **Flutter 3.19+** and **Dart 3.3+**.
- You want to follow modern Flutter best practices (null safety, responsive design, clean architecture).
- You are open to using popular packages like `flutter_bloc`, `go_router`, `shared_preferences`, `firebase_auth`, `cloud_firestore`, `algolia`.
- The app should be **performant, maintainable, and scalable**.
- Firebase is used for backend services (Auth, Firestore, Functions).
- Algolia is used for player search/indexing.

### Constraints
- Avoid using deprecated packages or APIs.
- Always suggest alternatives if a package is outdated or no longer maintained.
- Provide code examples in Dart, with comments explaining key parts.
- If the user asks for a complex feature, break it down into smaller, manageable steps.
- Always ask clarifying questions if the request is ambiguous (e.g., "Is this for the Belote or Tarot game mode?").
- **Never commit secrets** (e.g., API keys, `google-services.json`, `algolia.json`).
- Use Firebase Rules to restrict Firestore access.

### Examples

#### Example 1: Writing a Widget
**User:** "How do I create a dynamic list of card games in Flutter?"
**You:**
```dart
// Use a ListView.builder for lazy loading
ListView.builder(
itemCount: games.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
title: Text(games[index].name),
subtitle: Text(games[index].description),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => GameDetailScreen(game: games[index]),
),
),
),
);
},
)
```
- Explain why `ListView.builder` is better than `ListView` for large datasets.
- Mention how to manage the `games` list (e.g., using a BLoC or Firestore stream).

---
#### Example 2: Debugging a Common Error
**User:** "Why is my Flutter app crashing with 'Null is not a subtype of String' in the Algolia search?"
**You:**
1. Ask for the stack trace or relevant code snippet.
2. Explain that this error usually occurs when a variable expected to be non-null is null.
3. Suggest using null checks (`??`, `?.`, or `!`) or error handling in the code.
4. Recommend using Algolia’s Flutter package with proper null safety.

---
### Resources
- [Flutter Docs](https://docs.flutter.dev/)
- [Dart API Reference](https://api.flutter.dev/)
- [Pub.dev](https://pub.dev/) (for package suggestions)
- [Firebase Docs](https://firebase.google.com/docs)
- [Algolia Flutter Docs](https://www.algolia.com/doc/guides/building-search-ui/getting-started/flutter/)
- [Flutter YouTube Channel](https://www.youtube.com/c/flutterdev)

### Response Style
- Be **concise but thorough**.
- Use bullet points for lists or step-by-step instructions.
- Highlight key code snippets with ```dart ```.
- If the user asks for a feature, always ask clarifying questions (e.g., "Is this for the Belote or Tarot game mode?").
- If the user provides code, review it and suggest improvements.
- **Never expose secrets** (e.g., API keys, `google-services.json`, `algolia.json`).
- **Be direct**: Only use verbs and actions. No explanations, no fluff.
- **Examples**:
- Instead of: *"Use a ListView.builder for lazy loading"*
→ Write: *"Use ListView.builder. Lazy load."*
- Instead of: *"Explain why ListView.builder is better than ListView for large datasets"*
→ Write: *"ListView.builder better than ListView for large datasets. Explain why."*
- **Never**: Start with "Let me help you" or "Here’s how you do it."
- **Always**: Start with a verb (e.g., "Write", "Debug", "Use", "Check").
5 changes: 5 additions & 0 deletions devtools_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
description: This file stores settings for Dart & Flutter DevTools.
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
extensions:
- provider: true
- shared_preferences: true
1 change: 1 addition & 0 deletions lib/const.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,5 @@ class Const {
/// Local storage
static const String storageThemeKey = 'THEME';
static const String storageContrastKey = 'CONTRAST';
static const String storageDynamicColorsKey = 'DYNAMIC_COLORS';
}
35 changes: 31 additions & 4 deletions lib/gen/assets.gen.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion lib/gen/fonts.gen.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,10 @@
"unableAppInfo": "Unable to get application information",
"unableToOpen": "Unable to open the web page",
"us": "Us",
"useDynamicColors": "Use device colors",
"dynamicColorsEnabled": "Dynamic colors enabled - using system theme",
"dynamicColorsDisabled": "Dynamic colors disabled - using app theme",
"dynamicColorsNote": "Note: Colors are extracted from your device's wallpaper and system settings",
"useMyGravatar": "Use my Gravatar",
"username": "Username",
"confirm": "Confirm",
Expand Down
4 changes: 4 additions & 0 deletions lib/l10n/app_fr.arb
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,10 @@
"unableAppInfo": "mpossible d'obtenir les informations de l'application",
"unableToOpen": "Impossible d'ouvrir la page ",
"us": "Nous",
"useDynamicColors": "Utiliser les couleurs du système",
"dynamicColorsEnabled": "Couleurs dynamiques activées - utilisation du thème système",
"dynamicColorsDisabled": "Couleurs dynamiques désactivées - utilisation du thème de l'application",
"dynamicColorsNote": "Note : Les couleurs sont extraites de votre fond d'écran et des paramètres système",
"useMyGravatar": "Utiliser mon Gravatar",
"username": "Nom d'utilisateur",
"confirm": "Confirmer",
Expand Down
24 changes: 24 additions & 0 deletions lib/l10n/app_localizations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1118,6 +1118,30 @@ abstract class AppLocalizations {
/// **'Us'**
String get us;

/// No description provided for @useDynamicColors.
///
/// In en, this message translates to:
/// **'Use device colors'**
String get useDynamicColors;

/// No description provided for @dynamicColorsEnabled.
///
/// In en, this message translates to:
/// **'Dynamic colors enabled - using system theme'**
String get dynamicColorsEnabled;

/// No description provided for @dynamicColorsDisabled.
///
/// In en, this message translates to:
/// **'Dynamic colors disabled - using app theme'**
String get dynamicColorsDisabled;

/// No description provided for @dynamicColorsNote.
///
/// In en, this message translates to:
/// **'Note: Colors are extracted from your device\'s wallpaper and system settings'**
String get dynamicColorsNote;

/// No description provided for @useMyGravatar.
///
/// In en, this message translates to:
Expand Down
16 changes: 16 additions & 0 deletions lib/l10n/app_localizations_en.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// ignore: unused_import
import 'package:intl/intl.dart' as intl;

import 'app_localizations.dart';

// ignore_for_file: type=lint
Expand Down Expand Up @@ -585,6 +586,21 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get us => 'Us';

@override
String get useDynamicColors => 'Use device colors';

@override
String get dynamicColorsEnabled =>
'Dynamic colors enabled - using system theme';

@override
String get dynamicColorsDisabled =>
'Dynamic colors disabled - using app theme';

@override
String get dynamicColorsNote =>
'Note: Colors are extracted from your device\'s wallpaper and system settings';

@override
String get useMyGravatar => 'Use my Gravatar';

Expand Down
16 changes: 16 additions & 0 deletions lib/l10n/app_localizations_fr.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// ignore: unused_import
import 'package:intl/intl.dart' as intl;

import 'app_localizations.dart';

// ignore_for_file: type=lint
Expand Down Expand Up @@ -589,6 +590,21 @@ class AppLocalizationsFr extends AppLocalizations {
@override
String get us => 'Nous';

@override
String get useDynamicColors => 'Utiliser les couleurs du système';

@override
String get dynamicColorsEnabled =>
'Couleurs dynamiques activées - utilisation du thème système';

@override
String get dynamicColorsDisabled =>
'Couleurs dynamiques désactivées - utilisation du thème de l\'application';

@override
String get dynamicColorsNote =>
'Note : Les couleurs sont extraites de votre fond d\'écran et des paramètres système';

@override
String get useMyGravatar => 'Utiliser mon Gravatar';

Expand Down
1 change: 0 additions & 1 deletion lib/models/game/game_type.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// ignore_for_file: constant_identifier_names
import 'package:carg/l10n/app_localizations.dart';

import 'package:flutter/material.dart';

enum GameType { COINCHE, BELOTE, TAROT, CONTREE, UNDEFINE }
Expand Down
2 changes: 1 addition & 1 deletion lib/models/iap/purchase/purchase.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'package:carg/models/carg_object.dart';
import 'package:carg/models/iap/product/product_type_enum.dart';
import 'package:carg/models/iap/iap_source_enum.dart';
import 'package:carg/models/iap/product/product_type_enum.dart';

abstract class Purchase extends CargObject {
final IAPSourceEnum iapSource;
Expand Down
Loading
Loading