Skip to content

Conversation

VelikovPetar
Copy link
Contributor

🎯 Goal

Fixes the case where polls are not updated live when they are the root message of a thread.
AddsHasPoll event handling to the ThreadLogic.

🛠 Implementation details

  1. Add the messageId property on the HasPoll events - used to identify the thread in which the poll lives
  2. Add handling for each HasPoll event in the ThreadLogic - updating the thread parent message state

🎨 UI Changes

Before After
thread.polls.before.mov
thread.polls.after.mov

🧪 Testing

  1. Create a poll
  2. Thread reply to the poll
  3. Open the thread
  4. Interact with the poll
  5. The poll should update live

Copy link
Contributor

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 3.22 MB 3.22 MB 0.00 MB 🟢
stream-chat-android-offline 3.45 MB 3.45 MB 0.00 MB 🟢
stream-chat-android-ui-components 10.54 MB 10.54 MB 0.00 MB 🟢
stream-chat-android-compose 12.76 MB 12.76 MB 0.00 MB 🟢

@VelikovPetar VelikovPetar requested a review from Copilot October 15, 2025 12:59
@VelikovPetar VelikovPetar marked this pull request as ready for review October 15, 2025 12:59
@VelikovPetar VelikovPetar requested a review from a team as a code owner October 15, 2025 12:59
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
70.1% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Adds messageId to poll-related events and wires poll event handling into thread logic so polls update live when the poll is on the thread parent message.

  • Introduce messageId on HasPoll events and propagate through DTOs, mappings, and public API.
  • Add ThreadMutableState helpers and ThreadLogic.handlePollEvents to update the parent message’s poll.
  • Route HasPoll events to the appropriate active thread via EventHandlerSequential.

Reviewed Changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
stream-chat-android-state/src/test/java/io/getstream/chat/android/state/plugin/logic/channel/thread/internal/ThreadLogicTest.kt Adds comprehensive tests covering poll event handling in threads.
stream-chat-android-state/src/main/java/io/getstream/chat/android/state/plugin/state/channel/thread/internal/ThreadMutableState.kt Adds parentMessage getter and updateParentMessagePoll(poll) to modify the thread parent’s poll.
stream-chat-android-state/src/main/java/io/getstream/chat/android/state/plugin/logic/channel/thread/internal/ThreadLogic.kt Implements handlePollEvents to process HasPoll events and update parent poll.
stream-chat-android-state/src/main/java/io/getstream/chat/android/state/event/handler/internal/EventHandlerSequential.kt Groups HasPoll events by messageId and dispatches to active thread logic.
stream-chat-android-client/src/test/java/io/getstream/chat/android/client/extensions/internal/PollExtensionsTests.kt Updates tests to include messageId in poll events.
stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/EventMappingTestArguments.kt Extends mapping test args with messageId for poll events.
stream-chat-android-client/src/main/java/io/getstream/chat/android/client/events/ChatEvent.kt Adds messageId to HasPoll and poll event data classes.
stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/EventDtos.kt Adds message_id to poll-related DTOs.
stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/EventMapping.kt Maps message_id from DTOs to messageId in domain events.
stream-chat-android-client/api/stream-chat-android-client.api Updates public API signatures to include messageId.
stream-chat-android-client-test/src/main/java/io/getstream/chat/android/client/test/Mother.kt Adds test helpers to generate poll events with messageId.
CHANGELOG.md Notes the bug fix for polls in thread parent messages.

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +141 to +160
internal fun handlePollEvents(currentUserId: String?, events: List<HasPoll>) {
// Don't handle poll events if there is no poll in the parent message (should never happen)
val parentMessage = mutableState.parentMessage ?: return
val poll = parentMessage.poll ?: return
// Don't handle poll events if the poll in the parent message is different (should never happen)
events
.filter { it.poll.id == poll.id }
.forEach { event ->
val processedPoll = when (event) {
is AnswerCastedEvent -> event.processPoll { poll }
is PollClosedEvent -> event.processPoll { poll }
is PollUpdatedEvent -> event.processPoll { poll }
is VoteRemovedEvent -> event.processPoll { poll }
is VoteCastedEvent -> event.processPoll(currentUserId) { poll }
is VoteChangedEvent -> event.processPoll(currentUserId) { poll }
is PollDeletedEvent -> null // poll is deleted, remove from state
}
mutableState.updateParentMessagePoll(processedPoll)
}
}
Copy link

Copilot AI Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Events in a batch are processed against a stale poll snapshot captured before the loop. If multiple events for the same poll arrive in order (e.g., vote casted then vote changed), the second event won't apply on top of the updated state. Read the latest parentMessage.poll for each event (or update the local base after each iteration) to ensure sequential updates are applied cumulatively.

Copilot uses AI. Check for mistakes.

Comment on lines +499 to +501
messageId?.let {
logicRegistry.thread(it).handlePollEvents(currentUserId, events)
}
Copy link

Copilot AI Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Minor: messageId is already filtered to non-null keys, but still treated as nullable in the forEach. You can avoid the double null-check by unwrapping once (e.g., requireNotNull or a non-null filter) and pass it directly for clearer intent.

Suggested change
messageId?.let {
logicRegistry.thread(it).handlePollEvents(currentUserId, events)
}
logicRegistry.thread(messageId).handlePollEvents(currentUserId, events)

Copilot uses AI. Check for mistakes.

@aleksandar-apostolov aleksandar-apostolov changed the title Fix polls not updating when it is a thread root Fixed an issue where a poll would not update if its a thread root Oct 17, 2025
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