Skip to content

feat: the app has a concept of money - #46

Merged
GeiserX merged 1 commit into
mainfrom
feat/show-earnings
Aug 5, 2026
Merged

feat: the app has a concept of money#46
GeiserX merged 1 commit into
mainfrom
feat/show-earnings

Conversation

@GeiserX

@GeiserX GeiserX commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Client half of CashPilot-android-35t (P1). The server half is CashPilot#242, already merged.

The gap

grep -riE "earning|balance|payout" across this source returned nothing. The app is named CashPilot and showed no money at all — it pushed a heartbeat and never read anything back.

It couldn't just call an earnings endpoint: every one on the server goes through _require_auth_api, which needs a user session. A per-worker key reads none of them, and giving a phone an owner-level credential to render a number is a bad trade. So the server now returns the figures on the heartbeat — the one call this client is already authenticated for.

What this adds

The model, a StateFlow beside the existing lastHeartbeat state, and the display rules.

The rules are the point. Each is something the server took care to express, and that a client can throw away without noticing:

server says client must show
usd: null — nothing ever read (em-dash), never $0.00
usd: 0.0 — a real measurement $0.00
total_usd: null — no platform read no total line at all
shared_with_other_workers: true must not imply this device earned it

That first row is the one that matters. A confident $0.00 beside a service the user is actively running is a lie, and it's the exact defect class the server side of this project has spent dozens of fixes removing. Getting it wrong here would reintroduce it on mobile.

Attribution stays honest. Providers report one balance per account, so when the same app runs on two machines nothing can split it. The payload carries that fact and the client keeps it, rather than presenting an account figure as a device figure.

Offline is the normal case on a phone. The last figures are kept rather than blanked on every connectivity blip — but timestamped, so the UI can say they're stale instead of passing them off as current. earningsToKeep and earningsAreStale are both pure and unit-tested.

Tests

14, covering every rule above plus the wire format — including a case that parses the exact JSON the server emits and asserts an unread platform stays null rather than becoming 0.0, and one proving an older server that sends no earnings key reads as unknown rather than as an empty set of figures.

Verification

No JDK on either machine here, so I have not run the suite locally and am not claiming I did — same as the two Android PRs before this, both of which CI validated cleanly. CI is the gate.

Not in this PR

Rendering it on the dashboard. This lands the model, the state, and the rules with tests; wiring it into AppCard and the summary header is a UI change that belongs with the UI-renewal bead, where screenshot tests will exist to prove it. Splitting it keeps this diff reviewable and keeps the honesty rules under test independently of layout.

grep for earning|balance|payout across this source returned nothing. The app is
named CashPilot and showed no money at all -- it pushed a heartbeat and never
read anything back.

The server now returns per-platform earnings on the heartbeat, which is the one
call this client is already authenticated for, so no second credential is
needed. This adds the model, keeps the last known figures in a StateFlow beside
the existing lastHeartbeat state, and adds the display rules.

The rules are the point, and each is a thing the server took care to express
that a client can easily throw away:
  - null usd means NOTHING WAS EVER READ -> em-dash, never "$0.00"
  - a genuine 0.0 is a measurement -> "$0.00"
  - no total when no platform has been read -> no line at all, not "$0.00"
  - a platform also running on another machine cannot be attributed to this
    device, and the payload says so
  - a phone is offline often, so the last figures are KEPT rather than blanked
    on every blip -- but timestamped, so the UI can say they are stale instead
    of passing them off as current
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@GeiserX, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 11 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a8909074-5e45-49ac-b5bb-5456bb86d0ed

📥 Commits

Reviewing files that changed from the base of the PR and between f7332c6 and 2f7d542.

📒 Files selected for processing (4)
  • app/src/main/java/com/cashpilot/android/model/Heartbeat.kt
  • app/src/main/java/com/cashpilot/android/service/HeartbeatService.kt
  • app/src/main/java/com/cashpilot/android/util/FormatUtils.kt
  • app/src/test/java/com/cashpilot/android/EarningsDisplayTest.kt

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@GeiserX
GeiserX merged commit 05a587b into main Aug 5, 2026
3 checks passed
@GeiserX
GeiserX deleted the feat/show-earnings branch August 5, 2026 14:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant