Stories verified, and errors stop blaming Contacts

Stories driven end to end on Android against relay.flamenet.io: Post opens the
scoped photo picker, a selected image is encrypted and uploaded, it appears in
the strip as "You", and opening it decrypts and renders the picture. Together
with groups, that leaves iOS voice notes as the only feature still unverified —
and that one needs a physical device, because a simulator has no audio input.

⚠️ **The screen has ONE error slot and it lived inside BuddyList**, so
everything that failed anywhere reported itself underneath the Contacts
heading. A rate-limited story post read as a contacts problem, which is how
somebody ends up re-adding a contact to fix a story. It now renders at screen
level, under the call banner, where it belongs to the screen rather than to one
section of it.

⚠️ Worth knowing for later runs: the relay enforces per-account rate limits,
and a session that has been driving both apps hard will hit them. "Too many
attempts. Wait a few minutes." is the app reporting a real server response, not
a bug — the story posted on the retry after the window cleared.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Paul Hitt
2026-08-26 08:10:38 -04:00
co-authored by Claude Opus 5
parent 5c8060b690
commit fb099442a0
2 changed files with 13 additions and 4 deletions
@@ -140,10 +140,6 @@ fun ColumnScope.BuddyList(model: MessengerViewModel, phase: MessengerViewModel.P
) { Text("Add contact") }
}
phase.error?.let {
Text(it, color = MaterialTheme.colorScheme.error, modifier = Modifier.testTag("error"))
}
if (phase.buddies.isEmpty()) {
// Says what to do, not merely that there is nothing. An empty state
// that only reports emptiness leaves the person stuck.
@@ -318,6 +318,19 @@ private fun ColumnScope.SignedIn(
// whatever screen somebody is on.
CallBanner(model, phase)
// ⚠️ **Screen level, not inside Contacts.** There is ONE error slot shared
// by everything on this screen, and it used to be rendered inside
// BuddyList — so a story that failed to post, or a group that could not be
// created, appeared underneath the Contacts heading and read as a contacts
// problem. Observed with a rate-limited story post reported under Contacts.
phase.error?.let {
Text(
it,
color = MaterialTheme.colorScheme.error,
modifier = Modifier.testTag("error").padding(top = Space.sm),
)
}
// Each section on its own card. ⚠️ The sections themselves are unchanged —
// same composables, same testTags, same order — because this is a skin over
// screens that work, and moving them would mean re-pointing the UI tests