Skip to content

Commit f8d2cbd

Browse files
committed
fix(messenger): head a solo group with its invite card, messages or not
The invite card only replaced the group's info card while the transcript was empty, so a group whose only member had posted anything fell back to the old header. iOS decides on who is in the chat instead: the card heads the transcript while the viewer is a member and nobody else has joined (ConversationScreen.showsGroupInvite). State.showsGroupInviteCard now carries that rule and MessageList reads it. Once someone joins, the header goes back to the info card and the invite stays on the group's profile.
1 parent 87e6de5 commit f8d2cbd

3 files changed

Lines changed: 32 additions & 6 deletions

File tree

‎apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/ChatViewModel.kt‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,16 @@ internal class ChatViewModel @Inject constructor(
467467
get() = (subject as? ChatSubject.Group)
468468
?.takeIf { it.isMember == true }
469469
?.let { Linkify.groupChatInvite(it.chatId) }
470+
471+
/**
472+
* Whether the group's invite card heads the transcript in place of its info card: a group
473+
* the viewer has joined that nobody else has (node 10330:19164). Decided by who is in the
474+
* chat, not by whether it has messages, so posting into a solo group keeps the card. Once
475+
* someone joins, the invite moves to the group's profile, as on iOS.
476+
*/
477+
val showsGroupInviteCard: Boolean
478+
get() = groupInviteUrl != null &&
479+
(subject as? ChatSubject.Group)?.memberCount?.let { it <= 1 } == true
470480
}
471481

472482
/**

‎apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/screens/components/MessageList.kt‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -421,13 +421,13 @@ internal fun MessageList(
421421
}
422422
}
423423

424-
// Chat start shows contact info container. An empty group the viewer can invite to
425-
// shows its invite card there instead (node 10330:19164): inviting someone is the
426-
// only thing to do with an empty group, and it is the same card a DM transcript
424+
// Chat start shows contact info container. A group nobody else has joined shows its
425+
// invite card there instead (node 10330:19164), whether or not it has messages:
426+
// inviting someone is the thing left to do, and it is the same card a DM transcript
427427
// renders for the link, with a different CTA and destination.
428428
val inviteUrl = state.groupInviteUrl
429429
val inviteGroup = state.subject as? ChatSubject.Group
430-
if (messages.itemCount == 0 && inviteUrl != null && inviteGroup != null) {
430+
if (state.showsGroupInviteCard && inviteUrl != null && inviteGroup != null) {
431431
item(key = "group-invite-card") {
432432
val card = remember(inviteGroup, inviteUrl, state.ruleCurrency) {
433433
inviteGroup.toGroupInviteCard(

‎apps/flipcash/features/messenger/src/test/kotlin/com/flipcash/app/messenger/internal/ChatViewModelStateTest.kt‎

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,15 @@ class ChatViewModelStateTest {
4343

4444
private val gatedRules = ChatRules(listener = listOf(unmet), speaker = emptyList())
4545

46-
private fun group(isMember: Boolean?, rules: ChatRules? = gatedRules) = ChatSubject.Group(
46+
private fun group(
47+
isMember: Boolean?,
48+
rules: ChatRules? = gatedRules,
49+
memberCount: Long = 1L,
50+
) = ChatSubject.Group(
4751
chatId = groupChatId,
4852
groupTitle = "Ballers",
4953
picture = null,
50-
memberCount = 1L,
54+
memberCount = memberCount,
5155
rules = rules,
5256
isMember = isMember,
5357
)
@@ -239,6 +243,18 @@ class ChatViewModelStateTest {
239243
assertNull(ChatViewModel.State().groupInviteUrl)
240244
}
241245

246+
@Test
247+
fun `the invite card heads a group only while the viewer is its only member`() {
248+
// Messages have no say: a solo group the viewer has posted in still has nobody to talk to.
249+
assertTrue(ChatViewModel.State(subject = group(isMember = true)).showsGroupInviteCard)
250+
assertFalse(
251+
ChatViewModel.State(subject = group(isMember = true, memberCount = 2L)).showsGroupInviteCard,
252+
)
253+
assertFalse(ChatViewModel.State(subject = group(isMember = false)).showsGroupInviteCard)
254+
assertFalse(ChatViewModel.State(subject = group(isMember = null)).showsGroupInviteCard)
255+
assertFalse(ChatViewModel.State(subject = dm).showsGroupInviteCard)
256+
}
257+
242258
@Test
243259
fun `a chat id with no uuid form yields no link rather than a malformed one`() {
244260
// A DM's id is a 32-byte hash. Reaching this through a Group subject is unreachable in the

0 commit comments

Comments
 (0)