Repository navigation
Conversation
Flutter app (Android + iOS) for field surveys of reptiles and amphibians: record a transect on a Google Map, drop a point per finding, and attach one observation record per animal — species, locality, development stage, sex, counts, habitat and more. Surveys export as CSV or KML; the whole database backs up to JSON. The record fields and the 50-species catalog follow the survey data dictionary in "Vrste za aplikaciju.xlsx". The app started as a copy of Bird Tracker (rs.antonijevic.bird_tracker) and ships as a separate app; that history stays in the bird_tracker repository. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… UI form labels and tests
…e image picking support.
feat: add backup/restore functionality with media assets and integrat…
…tion, Maps NaN camera)
Herp Tracker was forked from Bird Tracker with this code intact, so both
production crashes reported on the Play Console for bird_tracker#8 are
reachable here too — the fixes are ported as-is, with the herp-specific
export code (altitude/accuracy columns, the KML balloon rows) left alone.
Location: every path that starts updates now goes through
ensureLocationPermission() — the location plugin's changeSettings started
native updates without checking, and without ACCESS_FINE_LOCATION Android
answered with a SecurityException in a GMS callback that nothing in Dart could
catch. The gate is re-run every time (an "Only this time" grant expires), the
startup permission flow and the "unfinished transect" dialog are sequenced, and
a double tap on Start no longer opens two transect rows or leaks a subscription.
Upgraded `location` 8.0.1 -> 10.0.2, which also turns that SecurityException
into a PERMISSION_DENIED error. Android 12+ "Approximate location" is refused
with a FINE-only request over the MainActivity channel, which is the only
request that shows the upgrade-to-precise dialog.
Map: the camera follows the user only while the app is resumed; updates kept
arriving from the foreground service with the screen off and animating the
paused MapView every second fed the renderer NaN targets. The
_HomePageState.controller field was never assigned, so following did not work
at all before. Coordinates are validated on every way in (double.parse('NaN')
succeeds), KML routes split on any whitespace.
Background mode is now tied to recording — enabled in _startListener, disabled
in _stopListener — instead of on every launch and my-location tap, which left
the Android foreground service tracking with no transect in progress.
Also: iOS deployment target 15.0, openSettings works on iOS, stale Isar
proguard rule removed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YH1jd4b3FFvSrntnsXfjCo
…e again easy_localization walks a key as a path through the JSON, splitting on '.', so 'species.Pelophylax kl. esculentus' was looked up as species -> "Pelophylax kl" -> " esculentus", found nothing, fell back to a flat top-level key that does not exist either, and came back as the raw key. The edible frog therefore showed up as "species.Pelophylax kl. esculentus" in the autocomplete list — the only one of the 50 catalog names carrying an abbreviation. The translation key loses the dots; kSpecies keeps the real Latin name, which is what lands in the database, the CSV and the KML payload, so nothing already recorded or exported changes. Both call sites go through speciesLabel() rather than interpolating the name into the key by hand, and a test asserts every catalog entry resolves, so the next name that needs the same treatment fails loudly instead of silently rendering as a key. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YH1jd4b3FFvSrntnsXfjCo
Port the Bird Tracker crash fixes, and fix the one species name with a dot in it
First step of the monorepo: the app becomes one workspace member so a shared tracker_core package can sit next to it. No code changes — every tracked file is a rename, and the root gains only the workspace pubspec, a generic .gitignore and a README. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- apps/herp_tracker joins the pub workspace (resolution: workspace); the per-app lock files give way to one root pubspec.lock - tool/check_all.sh runs analyze + test for every package and app; CI runs the same script on every PR - the two `(_, __)` lint infos that already failed `flutter analyze` in both apps use Dart's wildcard `_` instead Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Everything the tracker apps share moves into packages/tracker_core: the
map screen, GPS transect recording, photos, sembast storage, zip backup,
CSV/KML/KMZ export and import, the drawer and the record form shell. An
app supplies a TrackerConfig — branding plus its record type, species
catalog, export columns and form fields — and calls runTrackerApp.
- TrackerRecord is what the core knows about a record: species, photos,
toJson, a summary and a list subtitle. Placemark holds List<TrackerRecord>
under the same 'species' JSON key every stored transect and KML uses.
- The record form is split: RecordFormShell owns the species field, the
photo strip with its file-deletion rules and the buttons; the app's
RecordFieldsState owns its own fields and builds the record on save.
- Herp Tracker's export improvements come along for every app: altitude
and accuracy on the point, RFC 4180 CSV cells, the record columns
driving both the CSV and one <Data> row per field in the KML balloon.
- The KML payload is read by local name whatever namespace wrote it, so a
survey exported by one tracker imports into another; the legacy
description fallback is an app hook (bird has one, herp never needed it).
- Translations merge: core UI strings first, the app's file on top;
strings naming the app take it as {app}.
- Bird's CSV keeps its columns and English headers, gains the transect,
point and photo columns and RFC 4180 quoting; its test pins that.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The duplicated infrastructure goes; what stays is the herp domain — HerpRecord, the field options and catalog, HerpFormFields, and a TrackerConfig with the export columns of "Vrste za aplikaciju.xlsx". The translation files keep only the domain blocks and the strings worded for reptiles and amphibians; everything else comes from the core. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The atlas-code button and the −/+ count field were written out in full in each app's form; both now come from the core, along with the DMS helper the CSV exports use. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The white stork nest census from the old `rode` branch, rewritten as a third tracker app: one species (no species field), one nest per point, the surveyor's details in every export row. Only the domain is written — NestRecord, the nest position/state options, the form fields and the census sheet's columns; map, recording, photos, backup, KML/KMZ and the crash fixes come from the core. The android/ and ios/ shells are Bird Tracker's with the package, bundle id, name, permission prose and icons changed. Also: build_release.sh names the bundle after the app in all three apps, the root CLAUDE.md carries the shared knowledge and each app's only its domain. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…rmission plugin The ~100 lines of MainActivity.kt that request ACCESS_BACKGROUND_LOCATION and ACCESS_FINE_LOCATION one at a time were copied into every app. They are now one Android plugin package in the workspace (FlutterPlugin + ActivityAware + RequestPermissionsResultListener), with the Dart wrapper moved out of tracker_core; every app's MainActivity is the plain FlutterActivity and the channel name no longer depends on the package. Android only — the Dart side already short-circuits to success on iOS. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…rget to 15.0 feat: add devtools_options.yaml for Dart & Flutter DevTools settings refactor: enhance SembastService to ensure database readiness before operations test: add home_page_test to validate UI behavior without active transects
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.