Using this template is easy.
- Choose template from branch.
- Press use this template button.
- Create your repository.
- Clone your repository.
- Rename package name from
dev.csejrup.template
to your liking. - Rename the project name from
template
to your need.
Freezed Code generator.
This template optimizes freezed generator only to certain suffixes to improve build time. The available suffixes are:
*.codegen.dart
*.model.dart
*.entity.dart
For blocs, it automaticly read inside blocs
directory.
Snackbar Flash
You can use snackbar easily with FlashCubit
. You can call context.displayFlash(message)
to show a snackbar.
Before running the project, make sure to generate the necessary code for dependency injection. Run this command:
flutter packages pub run build_runner build
This command generates code for injectable
modules and factories which are part of this project's dependency injection system.
This project contains 3 flavors:
- development
- staging
- production
To run the desired flavor either use the launch configuration in VSCode/Android Studio or use the following commands:
# Development
$ flutter run --flavor development --target lib/main_development.dart
# Staging
$ flutter run --flavor staging --target lib/main_staging.dart
# Production
$ flutter run --flavor production --target lib/main_production.dart
Our application makes use of the Freezed package, a code generator for unions/pattern-matching/copy. This package helps us in creating immutable and copyable classes easily. This simplifies the process of managing states in our Flutter application.
- Immutability: Freezed generates immutable classes, this means once an object is created, it cannot be changed. This can be especially useful in reducing bugs related to state management.
- Union Types/Sealed Classes: This provides us a way to define a type which could be one of a variety of types, but each with a known and finite list of possibilities.
- Simplicity: Freezed allows you to generate code that is clean and easy to use. For example, it eliminates the need to manually implement copyWith methods for our classes.
- Integration with other packages: Freezed integrates well with other packages such as
json_serializable
for JSON serialization.
@freezed
abstract class Union with _$Union {
const factory Union(int value) = Data;
const factory Union.loading() = Loading;
const factory Union.error([String message]) = ErrorDetails;
}
---
## Running Tests 🧪
To run all unit and widget tests use the following command:
```sh
# Run test with coverage
$ flutter test --coverage --test-randomize-ordering-seed random
To view the generated coverage report you can use lcov.
# Generate Coverage Report
$ genhtml coverage/lcov.info -o coverage/
# Open Coverage Report
$ open coverage/index.html
The project is already included some library to speed up the development process.
All the libraries above are compatible with Flutter 3.
Notes: *need to install flutter_gen
The project is structured following the principles of Clean Architecture and a modular approach for improved scalability, maintainability, and readability.
...
assets
├── fonts # Non-Google fonts
├── google_fonts # Google fonts offline
├── icons # App icons
├── images # App images
lib
├── app
| ├── router
| | ├── app_router.dart # Application Router
| ├── view
| | ├── app.dart # MainApp File
| ├── app.dart
├── core
| ├── di # Dependency Injection Module
| ├── domain # Base Classes for domain layer
| ├── utils # utilities, constants, and extensions
├── shared # Shared Entity, Models, Widget, Service, Utils
├── features
| ├── counter # Feature Counter
| | ├── data
| | | ├── datasources # Data source (network, local)
| | | ├── models # DTO / Payload Model
| | | ├── repositories # Implementation of domain Repository
| | ├── domain
| | | ├── entities # Business Domain Entity
| | | ├── repositories # Interface Repository
| | | ├── usecases # Business Use Cases
| | ├── presentation
| | | ├── blocs # Application Logic & State management
| | | ├── pages # Application pages
| | | ├── widgets # Common Widgets in Feature
├── l10n
│ ├── arb
│ │ ├── app_en.arb # English Translation
│ │ └── app_da.arb # Danish Translation
├── bootstrap.dart # Common Main Bootstrap Script
├── main_development.dart # Env Development main method
├── main_production.dart # Env Production main method
├── main_staging.dart # Env Staging main method
test
├── app # App Test
├── features
| ├── counter # Feature Counter Test
| | ├── data
| | | ├── datasources # Data source (network, local) test
| | | ├── models # DTO / Payload Model test
| | | ├── repositories # Implementation repository test
| | ├── domain
| | | ├── entities # Business Domain Entity test
| | | ├── repositories # Interface Repository test
| | | ├── usecases # Business Use Cases test
| | ├── presentation
| | | ├── blocs # Bloc Test
| | | ├── pages # Application pages test
| | | ├── widgets # Common Widgets in Feature test
├── helpers # Common Test Helpers
...
This project relies on flutter_localizations and follows the official internationalization guide for Flutter.
- To add a new localizable string, open the
app_en.arb
file atlib/l10n/arb/app_en.arb
.
{
"@@locale": "en",
"counterAppBarTitle": "Counter",
"@counterAppBarTitle": {
"description": "Text shown in the AppBar of the Counter Page"
}
}
- Then add a new key/value and description
{
"@@locale": "en",
"counterAppBarTitle": "Counter",
"@counterAppBarTitle": {
"description": "Text shown in the AppBar of the Counter Page"
},
"helloWorld": "Hello World",
"@helloWorld": {
"description": "Hello World Text"
}
}
- Use the new string
import 'package:template/l10n/l10n.dart';
@override
Widget build(BuildContext context) {
final l10n = context.l10n;
return Text(l10n.helloWorld);
}
Update the CFBundleLocalizations
array in the Info.plist
at ios/Runner/Info.plist
to include the new locale.
...
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>da</string>
</array>
...
- For each supported locale, add a new ARB file in
lib/l10n/arb
.
├── l10n
│ ├── arb
│ │ ├── app_en.arb
│ │ └── app_da.arb
- Add the translated strings to each
.arb
file:
app_en.arb
{
"@@locale": "en",
"counterAppBarTitle": "Counter",
"@counterAppBarTitle": {
"description": "Text shown in the AppBar of the Counter Page"
}
}
app_da.arb
{
"@@locale": "da",
"counterAppBarTitle": "Tæller",
"@counterAppBarTitle": {
"description": "Tekst vist i AppBar på Tæller-siden"
}
}