Previous approach had two separate composable entries for setup and
setup-with-clone-params, which Jetpack Navigation couldn't distinguish.
Now uses one route with nullable query param arguments and defaultValue
null, so navigating to "setup" opens fresh and "setup?cloneInstanceId=
...&cloneSiteId=..." opens pre-filled.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Clone button on site list now navigates to setup screen pre-filled
with the source instance's URL, API key, and site ID. User can edit
all fields and save as a new instance. API key is resolved from
encrypted storage via the ViewModel, never passed through nav args.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copies the site ID into the add field so users can duplicate an
existing site and just change the ID. Useful when autodiscovery is
unavailable and multiple sites share the same instance credentials.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use flow.first() instead of collectAsState(initial = null) to
determine start destination. The previous approach fired immediately
with the initial null value before DataStore loaded from disk, always
routing to Setup. Now the loading screen suspends until preferences
are actually read.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 4 new dimension queries (concurrent with existing 4, total 8) to
the dashboard: countries, devices, browsers, and operating systems.
All reuse the existing DimensionSection component with proportional
progress bars.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix Plausible API v2 compatibility: move `limit` into `pagination`
object, add `expectSuccess = true` to Ktor client so API errors are
surfaced instead of "Illegal input" serialization errors, configure
`explicitNulls = false` to avoid sending null fields
- Add smart start destination: app checks DataStore on launch and
navigates directly to dashboard if an instance/site was previously
selected, skipping the setup screen
- Add settings and sites icons to dashboard top bar for navigating
back to instance management and site list
- Add site editing (inline rename) to site list screen
- Fix DateRangeSelector crash caused by sealed class data object
initialization issue in Compose lambda captures
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Working Android dashboard app for self-hosted Plausible Analytics CE.
Connects to Plausible API v2 (POST /api/v2/query), displays top stats,
visitor chart, top sources, and top pages with date range selection.
Architecture: Kotlin + Jetpack Compose + Material 3 + Hilt + Ktor +
SQLDelight + EncryptedSharedPreferences. Single :app module, four-layer
unidirectional data flow (UI → ViewModel → Repository → Data).
Includes: instance management, site list, caching with TTL per date
range, encrypted API key storage, custom Canvas visitor chart,
pull-to-refresh, and unit tests for API, cache, repository, and
domain model layers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>