Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ class RosterStateHolder @Inject constructor(

when {
incoming <= stored -> continue
// The summary is all a membership change carries and all it needs: it edits no
// member, so a skipped version here is not a hole in the cached list to repair.
change is RosterChange.MembershipChanged -> applyChange(chatId, change)
incoming > stored + 1 -> refetch(chatId, stored, incoming)
else -> applyChange(chatId, change)
}
Expand All @@ -59,6 +62,8 @@ class RosterStateHolder @Inject constructor(
when (change) {
is RosterChange.MemberJoined -> memberDataSource.upsert(chatId, listOf(change.member))
is RosterChange.MemberLeft -> memberDataSource.deleteMember(chatId, change.userId)
// Summary only; the cached member list stays as it is.
is RosterChange.MembershipChanged -> Unit
}
metadataDataSource.updateRoster(
chatId = chatId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,10 @@ class EventStreamDelegate @Inject constructor(
// Same best-effort contract as TitleChanged above.
metadataDataSource.updatePicture(chatId, metaUpdate.newPicture)
}
is MetadataUpdate.CoverPictureChanged -> {
// Same best-effort contract as TitleChanged above. Replaces the cached cover.
metadataDataSource.updateCoverPicture(chatId, metaUpdate.newCoverPicture)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,10 @@ class GroupFeedDelegate @Inject constructor(
// of the chat, whether you left from this device or another one.
metadataDataSource.clearViewerState(chatId)
}

// No list-level meaning: it edits neither your membership nor the member list.
// The summary is applied by RosterStateHolder below.
is RosterChange.MembershipChanged -> Unit
}
}
rosterStateHolder.apply(chatId, changes)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,45 @@ class RosterStateHolderTest {
coEvery { metadataDataSource.getRosterVersion(chatId) } returns version
}

@Test
fun `a membership change applies the summary and leaves the member list alone`() = runTest {
storedVersion(4)

subject.apply(
chatId,
listOf(RosterChange.MembershipChanged(RosterSummary(memberCount = 12, version = 5))),
)

coVerify { metadataDataSource.updateRoster(chatId, memberCount = 12, rosterVersion = 5) }
coVerify(exactly = 0) { memberDataSource.upsert(any(), any()) }
coVerify(exactly = 0) { memberDataSource.deleteMember(any(), any()) }
}

@Test
fun `a membership change that skips versions is applied without a refetch`() = runTest {
storedVersion(4)

subject.apply(
chatId,
listOf(RosterChange.MembershipChanged(RosterSummary(memberCount = 12, version = 9))),
)

coVerify(exactly = 0) { controller.getChat(any(), any()) }
coVerify { metadataDataSource.updateRoster(chatId, memberCount = 12, rosterVersion = 9) }
}

@Test
fun `a membership change at or below the stored version is dropped`() = runTest {
storedVersion(5)

subject.apply(
chatId,
listOf(RosterChange.MembershipChanged(RosterSummary(memberCount = 12, version = 5))),
)

coVerify(exactly = 0) { metadataDataSource.updateRoster(any(), any(), any()) }
}

@Test
fun `a join one version ahead is applied`() = runTest {
storedVersion(4)
Expand Down
Loading
Loading