Skip to content

Latest commit

 

History

History
126 lines (93 loc) · 4.53 KB

File metadata and controls

126 lines (93 loc) · 4.53 KB

Contributing to Streak

Bug fixes, features or a well-written issue — all of it helps.

Note

Only here to translate? You don't need any of this. Head to TRANSLATING.md — no code required.


Ground rules

Small fix Just open a pull request.
Feature or behavior change Open an issue first, so we agree on the direction before you spend an evening on it.
Bug The issue templates ask for your app version and device — those two answers save all the guessing.

Streak is deliberately small, offline and free of trackers. Analytics, ads, accounts and network backends are out of scope.


Getting set up

git clone https://github.com/InlitX/streak.git
cd streak
flutter pub get     # also generates the localization code
flutter run

You'll need the Flutter SDK (stable), the Android SDK and JDK 17. Streak targets Android 9 (API 28) and up.

Before opening a pull request, keep both of these green:

flutter analyze     # no issues
flutter test        # all passing

If you touch completions, streaks, scheduling or the importers, add a test — that's where a quiet regression corrupts someone's real history.


Good to know

Five traps that have already bitten this codebase, none of which fail loudly.

  • Date walks need a floor. Avoidance habits are clean by default, so a loop walking backwards day by day must stop at the habit's createdAt. Unbounded, it freezes the app.
  • Never dispose a TextEditingController right after await showDialog. The future completes when the dialog starts closing, while the field is still mounted and rebuilding. Own it in a State instead.
  • Never let R8 rename the notification plugin. flutter_local_notifications stores its scheduled alarms as JSON written by Gson, which uses the field names. Release builds obfuscate, so a build that renames those fields cannot read what the previous one wrote: the whole store fails with Expected BEGIN_ARRAY but was BOOLEAN, the boot receiver restores nothing and no reminder ever fires again. android/app/proguard-rules.pro keeps com.dexterous.**; do not remove it, and check reminders after touching anything under android/app/build.gradle.kts.
  • Schedule reminders before syncing the widgets. Saving a habit used to sync the home-screen widgets first and reschedule last; closing the app right after saving killed the reminder. Anything that must survive the user leaving goes first, and the form awaits the save before popping.
  • Glance draws only the first 10 children of a Row or Column — no error, just half a widget. Chunk anything longer, and run flutter clean after Kotlin changes or you'll keep testing the old one.

The code

Flutter + Dart, state in provider, storage in hive_ce, charts from fl_chart, home widgets in Kotlin with Jetpack Glance.

Features are self-contained — each owns its models, controllers, pages and widgets. Anything that changes a habit's completions belongs in CompletionOps, which both the UI and the widgets call.

Directory layout
lib/
├── main.dart       App entry point and home-widget callback
├── app/            App shell, navigation host, theming
├── core/           Storage, date helpers, icons, routing, shared widgets
├── l10n/           Translation files (source of truth)
├── features/       habits · statistics · focus · settings · onboarding
└── services/       Notifications, widgets, backup, import, launcher icon

android/            Android host project and the Glance widgets
fastlane/           Store listing and changelogs — F-Droid reads these
screenshots/        Screenshots used by the READMEs and app stores
test/               Unit tests

Style: match the code around you. Comments are rare on purpose — prefer a name that explains itself. Every user-visible string goes in lib/l10n/app_en.arb and is used via context.l10n.your_key; leave the other languages to Weblate, and never rename an existing key or its translations are lost everywhere.

Note

Versions, tags, signing and publishing are handled by the maintainer — never bump a version or push a tag in a pull request. CI builds every PR as a check.


By contributing you agree that your work ships under the project's GNU GPLv3.