This project was started using the Very Good CLI 🤖.
"A companion app for PaaS (Plants as a Service) companies."
- 💅 Design System: Material 3 with a green seed color, incl. dark and light mode
- 🏄♂ ️State Management:
riverpod
: All AsyncStates (loading, error, data) handled by UI - ➡️ Mono-directional Data Flow: Data Service -> Repository -> AsyncNotifierProvider -> UI
- 🪝 Local State Management:
flutter_hooks
- 🐝 Local Data Persistence:
hive
- 🗳️ Caching:
stash
using anisar
implementation - 🧭 Navigation:
auto_route
- 🗣️ Internationalization:
flutter_localizations
- 📄 Declarative Logging:
logger
with listeners on providers (BL), widget states and route changes, connection states and cache changes. - 🤌 Lint Rules:
very_good_analysis
- 🏭 Continuous Integration:
Github Action
with avery good workflow
as the base
Mock backend via local NoSQL database (hive
), initialized with json data & made pseudo async with a short network delay of 300 milliseconds.
Developed using Flutter 3.7.8 and Dart 2.19.5, tested only on Android (API 31, Pixel 4a Emulator).
- Tests
- Change App Logo to Leafy Leasing Logo.
This project contains three flavors:
- development
- staging
- production
To run the desired flavor either use the launch configuration in VSCode/Android Studio or use the following commands:
flutter pub get && flutter pub run build_runner build --delete-conflicting-outputs
# 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
*Leafy Leasing should work on iOS, Android, Web, and Windows.
All those flavors are pointing to the same bootstrap function but have different dotenvs
.
- ICM Big new structure (e.g. new backend integration or project setup) (w/o features)
- FT New Feature
- REF Refactoring
- RM Removal
- ENH Enhancement
- BFX Bugfix
- DAT Data (configs, dummy data)
- LOC Localization / Internationalization
- DEP Deployment (e.g. CI/CD)
- DOC Documentation (e.g. README, docstrings)
To run all unit and widget tests use the following command:
$ 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
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:leafy_leasing/l10n/l10n.dart';
@override
Widget build(BuildContext context) {
return Text(context.lc.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>es</string>
</array>
...
- For each supported locale, add a new ARB file in
lib/l10n/arb
.
├── l10n
│ ├── arb
│ │ ├── app_en.arb
│ │ └── app_de.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_de.arb
{
"@@locale": "de",
"counterAppBarTitle": "Zähler",
"@counterAppBarTitle": {
"description": "Text, der in der AppBar der Zählerseite angezeigt wird"
}
}
The logo is designed with some help from BlueWillow AI (=sth. like Midjourney).
- To initialize a new splash screen, use
flutter pub run flutter_native_splash:create --path=flutter_native_splash.yaml
.
The developer has access to a file lib/shared/secrets.dart
which is not pushed to the repository. It is the place for
API keys and other access tokens. When a Github workflow is triggered, it will create the file on the fly by accessing
the Github Secrets and injecting them into the file. The file is then used by the app to access the secrets.
The single Github Repository Secret is called SECRETS_FILE_CONTENT
and it contains the entire file content of lib/secrets.dart
.
It is saved as base64 and needs to be kept up to date: base64 -i lib/shared/secrets.dart
is pasted into it.