Passive Aggressive Generator
A playful Flutter app that serves up passive‑aggressive quotes on demand.
PAGen is a small cross‑platform Flutter application that generates passive‑aggressive quotes ("notes") you can throw at the world. You pick how aggressive you feel with a slider, optionally choose a frustration theme (Kitchen, Laundry, Public…), and tap the troll face to get a fresh note. You can also rate notes (👍 / 👎) and add your own.
Quotes are stored locally in an on‑device SQLite database that is seeded from a bundled asset on first launch. The UI is localized (English, French, Swedish).
- 🎚️ Passive ↔ Aggressive slider to tune the tone of generated notes.
- 🗂️ Themes to target a specific frustration source.
- ✍️ Add your own quotes, persisted locally.
- 👍 Rate quotes up or down.
- 🌍 Localized in English, French and Swedish.
- 📱 Runs everywhere Flutter does — Android, iOS, web, macOS, Linux and Windows.
| Concern | Choice |
|---|---|
| Framework | Flutter (stable, Dart 3, null‑safe) |
| Local storage | sqflite |
| Localization | flutter_i18n |
| Preferences | shared_preferences |
| Logging | logger |
| Onboarding | introduction_screen |
lib/
├── main.dart # App entry point, theme and localization setup
├── states.dart # Shared app state (InheritedWidget) + quote selection
├── db_helper.dart # SQLite access layer
├── models/
│ └── quote.dart # QuoteModel data class
├── screens/ # Full‑page screens (splash, onboarding, home, add quote)
├── widgets/ # Reusable UI pieces (app bar, drawer, slider, settings…)
└── utils/
└── app_logger.dart # Central app logger
assets/
├── init_quotes.db # Seed database bundled with the app
├── images/ # Logo and onboarding images
└── locales/ # i18n translation files (en, fr, sv)
- Install the Flutter SDK (stable channel, Dart 3) — see the official guide.
- Verify your toolchain:
flutter doctor -v# Fetch dependencies
flutter pub get
# (Optional) list available devices / emulators
flutter devices
# Run in debug mode on the connected device
flutter runRun the full CI pipeline locally (format check, analyze, tests, dependency audit):
./tool/ci.shIndividual steps:
flutter pub get
dart format --output=none --set-exit-if-changed lib test
dart analyze --fatal-infos
flutter testBump the version (version: x.y.z+build) in pubspec.yaml before each release.
# Android
flutter build appbundle --release # Play Store bundle
flutter build apk --release # standalone APK
# iOS (signing handled by Xcode / CI)
flutter build ios --release --no-codesign
# Web
flutter build web --releaseThe launcher icon is generated from assets/images/trollface.png via
flutter_launcher_icons.
After changing image_path under flutter_launcher_icons in pubspec.yaml, run:
dart run flutter_launcher_iconsCI runs on GitHub Actions.
Workflow: .github/workflows/ci.yml
- Dependency install, format check, static analysis, and tests
- Same steps as
tool/ci.sh— run that script locally before pushing
Workflow: .github/workflows/release-android.yml
Triggered manually from the GitHub Actions tab (Run workflow). Choose none to build only and download APK/AAB artifacts from the run; pick a Play Store track to deploy after the build.
Configure these repository secrets:
| Secret | Purpose |
|---|---|
ANDROID_KEYSTORE_BASE64 |
Release keystore file, base64-encoded |
ANDROID_KEY_STORE_PASSWORD |
Keystore password |
ANDROID_KEY_PASSWORD |
Key password |
ANDROID_KEY_ALIAS |
Key alias |
PLAY_STORE_JSON_KEY |
Google Play service account JSON (for deploy only) |
Build and upload use Fastlane lanes in android/fastlane (build_android,
deploy_android).
This project is licensed under the GNU General Public License v3.0. See the LICENSE file for the full text.
