Skip to content

fix(chat): stop deactivating tip DMs that have no name or phone - #1336

Merged
bmc08gt merged 1 commit into
code/cashfrom
fix/tip-dm-read-only
Aug 26, 2026
Merged

fix(chat): stop deactivating tip DMs that have no name or phone#1336
bmc08gt merged 1 commit into
code/cashfrom
fix/tip-dm-read-only

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

A tipper who has never set a display name shows up in the tips list, and then opens read-only — DeactivatedChatBottomBar, no composer, no way to reply.

The gate that decides whether a DM stays usable was written out twice, and the copies disagreed:

  • FeedSyncDelegate.feed applies it only to CONTACT_DM.
  • The deactivation collector in ChatViewModel applied it to every chat, so Event.ChatDeactivated(isReadOnly = true) fired for a tip DM whose counterparty had no name and no verified phone.

The gate is right for a contact DM: that chat is reached through the phone number and named from the device contact, so losing both leaves nothing to address. A tip DM is reached by user id, has no phone by design, and is named by the counterparty's @handle — there is nothing there for the gate to protect.

What changed

isDmAddressable(chatType, counterparty) moves into services/flipcash as the single rule, and both call sites route through it.

The conversation's collector now combines the members flow with state.chatType, so the gate is type-aware. An unresolved type is left open — a chat reports UNKNOWN until its kind settles, and gating on that would flash the deactivated composer before the type arrives.

Tests

DmAddressabilityTest covers both directions of each branch, including the two cases that were the bug (a tip DM with only a handle, and one with nothing at all) and the UNKNOWN case. shared:chat's existing FeedSyncCombinedFeedTest covers the feed side unchanged.

The identity gate that decides whether a DM stays usable was written out twice,
and the copies disagreed. `FeedSyncDelegate.feed` applies it only to
`CONTACT_DM`; the deactivation collector in `ChatViewModel` applied it to every
chat. A tipper who has never set a display name therefore appeared in the tips
list and then opened read-only, on `DeactivatedChatBottomBar` with no composer.

A tip DM is addressed by user id. The counterparty has no phone by design, and a
claimed `@handle` names them, so the gate has nothing to protect there.

Extract `isDmAddressable(chatType, counterparty)` into `services/flipcash` and
route both call sites through it. The conversation now combines the members flow
with its chat type, and an unresolved type — `UNKNOWN`, which is what a chat
reports until its kind settles — is left open, so the composer can't flash
deactivated before the type arrives.
@bmc08gt bmc08gt self-assigned this Aug 26, 2026
@github-actions github-actions Bot added type: fix Bug fix area: network gRPC, connectivity, API, exchange rates labels Aug 26, 2026
@bmc08gt
bmc08gt merged commit 55976ae into code/cash Aug 26, 2026
3 checks passed
@bmc08gt
bmc08gt deleted the fix/tip-dm-read-only branch August 27, 2026 15:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: network gRPC, connectivity, API, exchange rates type: fix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant