feat(sync): surface per-peer hostnames in sync report UI - #303
TimeToBuildBob wants to merge 2 commits into
Conversation
The Rust JNI `to_jni_json()` already emits a `peers` array with per-device `hostname` and `outcome.kind` fields; only aggregate counts were parsed on the Kotlin side. - Add `SyncPeer(hostname, outcome)` data class - Extend `SyncStatus` with `peers: List<SyncPeer>` (empty-default for backward compatibility with older native libs) - Parse the `peers` JSON array in `fromJniResponse()` - Update `formatSyncDetail()` to append `(desktop, laptop, !server)` after the aggregate peer line when per-peer data is available; `!` prefix marks failed peers for instant visual distinction without extra prose - 4 new unit tests covering parsing, rendering, and the no-peers fallback Closes ActivityWatch#285 Git-Session-Id: e1f4
|
| // Per-peer breakdown from the "peers" array in the JNI response. Empty for | ||
| // older native libs that pre-date the SyncReport JNI output. | ||
| val peers: List<SyncPeer> = emptyList(), |
There was a problem hiding this comment.
peers is added to SyncStatus, but the SharedPreferences adapter neither writes nor restores it. The settings UI always reloads the status through prefs.getLastSyncStatus(), so this field defaults to an empty list even after the completion broadcast. As a result, the new hostname rendering never appears in the actual UI; persist and restore the peer summaries alongside the aggregate fields.
There was a problem hiding this comment.
Fixed in 8752040. AWPreferences now persists peers as JSON (lastSyncPeers) next to the aggregate counts, and getLastSyncStatus() restores them. Decode never throws. Added encode/decode round-trip tests so formatSyncDetail still shows hostnames after the prefs reload the UI actually uses.
The settings UI reloads via getLastSyncStatus(), which dropped the new peers list so hostname rendering never appeared. Store peers as JSON next to the aggregate counts; decode never throws. Git-Session-Id: 7229f9f5-7b91-55aa-b26d-81c6a42708c7
|
@greptileai review |
|
CI-green and mergeable (Greptile 5/5) — waiting only on a maintainer click. This PR is ready to merge, but the bot has pull-only access to this repo and can't self-merge — surfacing it here so it isn't lost. The monitoring loop will stop re-flagging it now that this note is posted. |
Summary
The Rust JNI
to_jni_json()already emits a fullpeersarray with per-devicehostnameandoutcome.kind; only the aggregate counts (peers_imported,peers_skipped,peers_failed) were parsed on the Kotlin side.This PR wires the per-peer data through:
SyncPeer(hostname, outcome)data class toSyncInterface.ktSyncStatuswithpeers: List<SyncPeer>(empty-default — fully backward-compatible with older native libs that don't emit thepeerskey)peersJSON array infromJniResponse()formatSyncDetail()to append hostnames in parens after the aggregate peer line, e.g.:!prefix marks failed peers for quick visual distinction without extra proseCloses #285
Test plan
./gradlew :mobile:testStandardDebugUnitTest --tests "net.activitywatch.android.SyncSettingsActivityTest"Co-Authored-By: Bob timetobuildbob@gmail.com