Skip to content

Conversation

@gpunto
Copy link
Contributor

@gpunto gpunto commented Jan 9, 2026

Goal

AND-931: Simplify PollData.upsertVote

The logic to update poll votes had some fairly complex logic, but that's unneeded because we know that the only things that we need to compute locally are "own" properties and we can take the other ones (e.g. counts) from the WS event, like we do in similar cases

Implementation

The implementation mirrors what we are already doing in cases like ActivityData.upsertBookmark. So we take the updated poll data and we only compute the own votes.

Testing

Cast/change votes in a poll and verify that it updates correctly.

Checklist

  • Issue linked (if any)
  • Tests/docs updated
  • I have signed the Stream CLA (required for external contributors)

Summary by CodeRabbit

  • Refactor
    • Restructured internal poll voting system architecture to improve code organization and consistency
    • Consolidated poll state management logic and unified vote operation handling for enhanced reliability
    • Streamlined how poll data flows through vote operations to reduce complexity and potential inconsistencies

✏️ Tip: You can customize this high-level summary in your review settings.

@gpunto gpunto added the pr:internal Internal changes / housekeeping label Jan 9, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Jan 9, 2026

PR checklist ✅

All required conditions are satisfied:

  • Title length is OK (or ignored by label).
  • At least one pr: label exists.
  • Sections ### Goal, ### Implementation, and ### Testing are filled.

🎉 Great job! This PR is ready for review.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Jan 9, 2026

Quality Gate Failed Quality Gate failed

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

See analysis details on SonarQube Cloud

@github-actions
Copy link
Contributor

github-actions bot commented Jan 9, 2026

SDK Size Comparison 📏

SDK Before After Difference Status
stream-feeds-android-client 2.43 MB 2.43 MB 0.00 MB 🟢

@gpunto gpunto marked this pull request as ready for review January 9, 2026 10:11
@coderabbitai
Copy link

coderabbitai bot commented Jan 9, 2026

Walkthrough

This PR refactors poll voting operations to simplify local state computation by accepting updated PollData from WebSocket events and propagating it throughout the state management layer, replacing poll ID strings with full PollData objects.

Changes

Cohort / File(s) Summary
Core Poll Vote Logic
stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/model/PollOperations.kt
Simplified upsertVote and removeVote to accept updated: PollData parameter; introduced unified changeVotes mechanism; removed local vote count/option tracking logic; delegated ownVotes updates to provided lambda hook.
Repository Layer
stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepository.kt, PollsRepositoryImpl.kt
Updated castPollVote and deletePollVote return types from Result<PollVoteData?> to Result<Pair<PollVoteData?, PollData?>> to include updated poll data alongside vote.
State Management - Activity
stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityImpl.kt, ActivityStateImpl.kt, ActivityEventHandler.kt
Updated onPollVoteUpserted and onPollVoteRemoved signatures from (vote, pollId) to (poll, vote) with poll-first parameter order; refactored event handling to emit StateUpdateEvent with updated poll objects.
State Management - Activity List
stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityListStateImpl.kt, ActivityListEventHandler.kt
Changed poll vote handlers from (pollId: String) to (poll: PollData) parameters; updated internal vote operation calls to pass PollData objects.
State Management - Feed
stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImpl.kt, FeedEventHandler.kt
Transitioned poll vote handlers from (vote, pollId) to (poll, vote) with PollData objects; updated call sites and public interface signatures.
State Management - Poll List
stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/PollListStateImpl.kt, PollListEventHandler.kt
Refactored onPollVoteUpserted and onPollVoteRemoved to accept poll: PollData instead of pollId: String; updated internal vote operation invocations.
State Events & Handlers
stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/StateUpdateEvent.kt, PollVoteListEventHandler.kt
Changed PollVoteCasted, PollVoteRemoved, PollVoteChanged data classes from pollId: String to poll: PollData; updated event handler conditionals.
Network Models
stream-feeds-android-network/src/main/kotlin/io/getstream/feeds/android/network/models/PollVoteResponse.kt
Added optional poll: PollResponseData? field to PollVoteResponse.
Tests
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepositoryImplTest.kt, internal/state/ActivityImplTest.kt, ActivityListStateImplTest.kt, ActivityStateImplTest.kt, FeedStateImplTest.kt, PollListStateImplTest.kt, event/handler/*Test.kt
Updated test expectations and assertions to reflect new return types (Pair<PollVoteData?, PollData?>), PollData parameters, and ownVotes behavior; added new test cases for current-user vs. different-user vote scenarios.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • aleksandar-apostolov
  • VelikovPetar

Poem

🐰 A poll vote once tangled with complex math,
Now flows with events on a cleaner path,
PollData leads where pollId did roam,
State updates dance in a unified home,
Simpler logic, less computation to weigh—
The rabbit hops faster this voting day! 🗳️✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'Simplify logic to update poll votes' clearly and concisely summarizes the main change—refactoring complex poll vote update logic into a simpler approach.
Description check ✅ Passed The PR description includes all required sections from the template: Goal (linked to AND-931), Implementation (mirrors ActivityData.upsertBookmark pattern), Testing (manual verification instructions), and completed Checklist items.
Linked Issues check ✅ Passed The PR successfully implements AND-931's objectives: simplifies PollData.upsertVote by removing complex local computation logic, relies on WS events for external data like vote counts, and computes only 'own' properties locally following the ActivityData.upsertBookmark pattern.
Out of Scope Changes check ✅ Passed All code changes are directly aligned with AND-931's scope: refactoring poll vote update logic, updating related method signatures to pass PollData objects, and corresponding test updates. No unrelated changes are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityStateImplTest.kt (1)

390-400: LGTM!

Good coverage for the non-matching poll scenario on vote removal.

Minor naming observation: The new test method names (e.g., onPollVoteUpserted...) omit the on prefix pattern used elsewhere in this file (e.g., on onPollUpdated, then...). This is a minor inconsistency that doesn't affect functionality.

stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImplTest.kt (1)

902-910: Consider removing unused helper function.

The pollWithVote helper function appears to be unused in the current test file. If it's no longer needed after the refactoring, consider removing it to reduce dead code.

♻️ Suggested removal
-    private fun pollWithVote(pollId: String, vote: PollVoteData): PollData =
-        pollData(
-            pollId,
-            "Test Poll",
-            voteCount = 1,
-            ownVotes = listOf(vote),
-            latestVotesByOption = mapOf(vote.optionId to listOf(vote)),
-            voteCountsByOption = mapOf(vote.optionId to 1),
-        )
stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/PollListStateImpl.kt (1)

131-145: Consider enriching KDoc parameter descriptions.

The parameter descriptions @param poll The poll. are minimal. Consider adding context about the poll's role.

📝 Suggested documentation improvement
     /**
      * Called when a poll vote is added or updated.
      *
-     * @param poll The poll.
+     * @param poll The updated poll data from the WebSocket event.
      * @param vote The vote that was added or updated.
      */
     fun onPollVoteUpserted(poll: PollData, vote: PollVoteData)

     /**
      * Called when a poll vote is removed.
      *
-     * @param poll The poll.
+     * @param poll The updated poll data from the WebSocket event.
      * @param vote The vote that was removed.
      */
     fun onPollVoteRemoved(poll: PollData, vote: PollVoteData)
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 48fba31 and ef90003.

📒 Files selected for processing (26)
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/model/PollOperations.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepository.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepositoryImpl.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityImpl.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityListStateImpl.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityStateImpl.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImpl.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/PollListStateImpl.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/StateUpdateEvent.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityEventHandler.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityListEventHandler.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandler.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollListEventHandler.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollVoteListEventHandler.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepositoryImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityListStateImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityStateImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/PollListStateImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityListEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollListEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollVoteListEventHandlerTest.kt
  • stream-feeds-android-network/src/main/kotlin/io/getstream/feeds/android/network/models/PollVoteResponse.kt
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{kt,kts}

📄 CodeRabbit inference engine (AGENTS.md)

Kotlin code targeting JVM 11, using Gradle Kotlin DSL with shared logic in buildSrc/

Files:

  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityImplTest.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityEventHandler.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityListStateImpl.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/StateUpdateEvent.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollVoteListEventHandler.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityStateImplTest.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollListEventHandler.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepository.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityListEventHandler.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityStateImpl.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImpl.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollVoteListEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImplTest.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/model/PollOperations.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/PollListStateImpl.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityListStateImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollListEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepositoryImplTest.kt
  • stream-feeds-android-network/src/main/kotlin/io/getstream/feeds/android/network/models/PollVoteResponse.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandler.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/PollListStateImplTest.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepositoryImpl.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityImpl.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityListEventHandlerTest.kt
**/*.kt

📄 CodeRabbit inference engine (AGENTS.md)

**/*.kt: Run Spotless (ktfmt) to enforce Kotlin style with 4 spaces and no wildcard imports
Run Detekt static analysis before committing and fix all findings
Use PascalCase for type names, camelCase for members

Files:

  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityImplTest.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityEventHandler.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityListStateImpl.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/StateUpdateEvent.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollVoteListEventHandler.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityStateImplTest.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollListEventHandler.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepository.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityListEventHandler.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityStateImpl.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImpl.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollVoteListEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImplTest.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/model/PollOperations.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/PollListStateImpl.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityListStateImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollListEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepositoryImplTest.kt
  • stream-feeds-android-network/src/main/kotlin/io/getstream/feeds/android/network/models/PollVoteResponse.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandler.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/PollListStateImplTest.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepositoryImpl.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityImpl.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityListEventHandlerTest.kt
stream-feeds-android-client/**/*.kt

📄 CodeRabbit inference engine (AGENTS.md)

stream-feeds-android-client/**/*.kt: Enforce explicit API visibility for public APIs
Provide KDoc documentation for all public APIs
Log via StreamLogger with actionable context and no secrets

Files:

  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityImplTest.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityEventHandler.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityListStateImpl.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/StateUpdateEvent.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollVoteListEventHandler.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityStateImplTest.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollListEventHandler.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepository.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityListEventHandler.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityStateImpl.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImpl.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollVoteListEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImplTest.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/model/PollOperations.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/PollListStateImpl.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityListStateImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollListEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepositoryImplTest.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandler.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/PollListStateImplTest.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepositoryImpl.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityImpl.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityListEventHandlerTest.kt
**/*.{kt,properties,gradle}

📄 CodeRabbit inference engine (AGENTS.md)

Scrub sensitive data from logs and configs

Files:

  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityImplTest.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityEventHandler.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityListStateImpl.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/StateUpdateEvent.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollVoteListEventHandler.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityStateImplTest.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollListEventHandler.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepository.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityListEventHandler.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityStateImpl.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImpl.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollVoteListEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImplTest.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/model/PollOperations.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/PollListStateImpl.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityListStateImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollListEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepositoryImplTest.kt
  • stream-feeds-android-network/src/main/kotlin/io/getstream/feeds/android/network/models/PollVoteResponse.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandler.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/PollListStateImplTest.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepositoryImpl.kt
  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityImpl.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityListEventHandlerTest.kt
**/src/test/kotlin/**/*.kt

📄 CodeRabbit inference engine (AGENTS.md)

**/src/test/kotlin/**/*.kt: Place tests under each module's src/test/kotlin, mirroring package names
Cover success, retry, and failure paths for feed mutations, token refresh, and connectivity loss in tests
Use MockWebServer, fakes, Turbine, and coroutines-test for deterministic test assertions
Use backticked test names when helpful for readability

Files:

  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityStateImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollVoteListEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityListStateImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollListEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepositoryImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/PollListStateImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityListEventHandlerTest.kt
stream-feeds-android-network/**/*.kt

📄 CodeRabbit inference engine (AGENTS.md)

stream-feeds-android-network/**/*.kt: Use Retrofit, OkHttp, and Moshi (KSP) for networking and serialization
Keep coroutines structured and thread safe around token refresh, pagination, and realtime updates
Reuse shared retry/backoff helpers instead of implementing bespoke networking logic

Files:

  • stream-feeds-android-network/src/main/kotlin/io/getstream/feeds/android/network/models/PollVoteResponse.kt
🧠 Learnings (4)
📚 Learning: 2025-12-18T09:06:42.772Z
Learnt from: CR
Repo: GetStream/stream-feeds-android PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T09:06:42.772Z
Learning: Applies to **/src/test/kotlin/**/*.kt : Cover success, retry, and failure paths for feed mutations, token refresh, and connectivity loss in tests

Applied to files:

  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityStateImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollVoteListEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityListStateImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollListEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepositoryImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/PollListStateImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityListEventHandlerTest.kt
📚 Learning: 2025-12-18T09:06:42.772Z
Learnt from: CR
Repo: GetStream/stream-feeds-android PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T09:06:42.772Z
Learning: Applies to **/src/test/kotlin/**/*.kt : Use MockWebServer, fakes, Turbine, and coroutines-test for deterministic test assertions

Applied to files:

  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollVoteListEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollListEventHandlerTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepositoryImplTest.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityListEventHandlerTest.kt
📚 Learning: 2025-12-18T09:06:42.772Z
Learnt from: CR
Repo: GetStream/stream-feeds-android PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T09:06:42.772Z
Learning: Applies to stream-feeds-android-client/**/*.kt : Enforce explicit API visibility for public APIs

Applied to files:

  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityListStateImpl.kt
  • stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityListEventHandlerTest.kt
📚 Learning: 2025-12-18T09:06:42.772Z
Learnt from: CR
Repo: GetStream/stream-feeds-android PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T09:06:42.772Z
Learning: Applies to stream-feeds-android-network/**/*.kt : Keep coroutines structured and thread safe around token refresh, pagination, and realtime updates

Applied to files:

  • stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImpl.kt
🧬 Code graph analysis (15)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityImplTest.kt (2)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/test/TestData.kt (2)
  • pollVoteData (516-533)
  • pollData (535-571)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImplTest.kt (1)
  • setupActivityWithPoll (891-895)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityStateImplTest.kt (1)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/test/TestData.kt (2)
  • pollData (535-571)
  • pollVoteData (516-533)
stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityStateImpl.kt (2)
stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityImpl.kt (1)
  • updatePoll (261-265)
stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/model/PollOperations.kt (2)
  • removeVote (133-134)
  • upsertVote (119-126)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollVoteListEventHandlerTest.kt (2)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/test/TestData.kt (2)
  • pollData (535-571)
  • pollVoteData (516-533)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/BaseEventHandlerTest.kt (1)
  • testParams (44-48)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImplTest.kt (2)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/test/TestData.kt (4)
  • pollData (535-571)
  • activityData (206-261)
  • activityPin (385-392)
  • pollVoteData (516-533)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/FeedImplTest.kt (1)
  • setupInitialState (817-830)
stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/model/PollOperations.kt (1)
stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/utils/List.kt (1)
  • upsert (53-66)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandlerTest.kt (1)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/BaseEventHandlerTest.kt (1)
  • testParams (44-48)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityListStateImplTest.kt (1)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/test/TestData.kt (3)
  • pollData (535-571)
  • activityData (206-261)
  • pollVoteData (516-533)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollListEventHandlerTest.kt (1)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/BaseEventHandlerTest.kt (1)
  • testParams (44-48)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityEventHandlerTest.kt (2)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/test/TestData.kt (2)
  • pollData (535-571)
  • pollVoteData (516-533)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/BaseEventHandlerTest.kt (1)
  • testParams (44-48)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepositoryImplTest.kt (2)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/test/TestData.kt (2)
  • pollResponseData (573-596)
  • pollVoteResponseData (831-839)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/repository/RepositoryTestUtils.kt (2)
  • testDelegation (25-29)
  • testDelegation (31-40)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/PollListStateImplTest.kt (2)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/PollListImplTest.kt (1)
  • setupInitialState (105-115)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/test/TestData.kt (2)
  • pollData (535-571)
  • pollVoteData (516-533)
stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepositoryImpl.kt (1)
stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/core/result/ResultUtils.kt (1)
  • runSafely (31-39)
stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityImpl.kt (1)
stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/StateUpdateEvent.kt (4)
  • poll (183-183)
  • poll (185-185)
  • poll (187-187)
  • poll (189-189)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityListEventHandlerTest.kt (2)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/test/TestData.kt (2)
  • pollData (535-571)
  • pollVoteData (516-533)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/BaseEventHandlerTest.kt (1)
  • testParams (44-48)
🔇 Additional comments (40)
stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollVoteListEventHandlerTest.kt (2)

25-25: LGTM: Import addition supports test refactoring.

The import of pollData factory function is necessary for constructing PollData objects in the updated event creation, consistent with the existing pollVoteData import.


61-89: LGTM: Event construction correctly updated to use PollData.

The refactoring properly updates all poll vote event constructors to accept PollData objects instead of plain poll ID strings, aligning with the PR's objective to pass full poll data from WebSocket events. Test coverage is maintained across matching and non-matching poll scenarios for all vote event types.

The unchanged verification blocks correctly reflect that the underlying state methods still expect the same parameters, confirming the refactoring doesn't alter the handler's behavior—just its input signature.

stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityStateImplTest.kt (5)

325-334: LGTM!

The test correctly validates the new signature and behavior: the updated poll from the WebSocket event is used as the base, and ownVotes is computed locally to include the current user's vote. This aligns with the PR objective of simplifying the logic.


336-348: LGTM!

Good coverage for the case where another user votes—verifies that the current user's ownVotes are preserved while accepting the updated poll data from the WebSocket event.


350-360: LGTM!

Correctly tests the guard condition: when the update targets a different poll than the one in state, the existing poll remains unchanged.


362-374: LGTM!

Properly validates vote removal: the poll is updated from the WebSocket event and ownVotes is locally computed to exclude the removed vote.


376-388: LGTM!

Correctly verifies that when another user's vote is removed, the current user's ownVotes are preserved.

stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/model/PollOperations.kt (1)

115-162: Excellent refactoring that achieves the PR objectives.

The new changeVotes abstraction successfully simplifies vote handling by:

  • Centralizing the merge logic between upsertVote and removeVote
  • Computing only ownVotes locally when the vote belongs to the current user (line 155)
  • Taking all other poll data from the updated parameter (WebSocket event data)
  • Using the inline keyword appropriately for the lambda parameter

The ownership check with vote.user?.id == currentUserId correctly handles null users by preserving existing ownVotes unchanged. The enforceUniqueVote handling at line 121 properly replaces all votes when unique voting is enforced.

stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollVoteListEventHandler.kt (1)

41-54: Consistent update to poll-first data model.

The changes correctly reference event.poll.id instead of event.pollId across all three poll vote event handlers (PollVoteCasted, PollVoteChanged, PollVoteRemoved), aligning with the broader refactor to propagate full PollData objects through the event system.

stream-feeds-android-network/src/main/kotlin/io/getstream/feeds/android/network/models/PollVoteResponse.kt (1)

28-29: Backward-compatible API extension.

Adding the nullable poll field with a default value of null safely extends the PollVoteResponse data class to include poll data alongside vote data. The explicit nullability makes it clear to consumers that poll data may not always be present.

stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityEventHandlerTest.kt (1)

193-206: Test updates correctly reflect the new poll-first semantics.

The three poll vote test cases (PollVoteCasted, PollVoteChanged, PollVoteRemoved) are properly updated to:

  • Construct events using pollData() objects instead of poll ID strings
  • Verify that state update methods receive both the PollData and PollVoteData instances

The use of the pollData() factory method works correctly with MockK verification since data classes use structural equality.

stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepositoryImpl.kt (1)

113-125: Richer response payload enables simplified state management.

Both castPollVote and deletePollVote now return Pair<PollVoteData?, PollData?>, providing:

  • The vote data from the operation
  • The updated poll state from the server response

The explicit nullable types in the return signature make it clear that callers must handle cases where either value may be absent. The use of Kotlin's to operator for Pair construction is idiomatic and readable.

Also applies to: 142-156

stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollListEventHandlerTest.kt (1)

70-71: LGTM! Consistent migration to poll-first semantics.

The test cases correctly reflect the updated event constructors that now accept PollData objects instead of poll IDs, and the verification blocks properly validate the new onPollVoteUpserted(poll, vote) and onPollVoteRemoved(poll, vote) signatures.

Also applies to: 75-76, 80-81

stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityImpl.kt (2)

326-344: Consistent implementation for vote removal.

The deletePollVote method follows the same pattern as castPollVote, ensuring consistency across vote operations.


311-324: Null checks are necessary and properly justified.

The repository returns Result<Pair<PollVoteData?, PollData?>> where both elements are nullable, but StateUpdateEvent.PollVoteCasted requires non-nullable constructor parameters. The checks on lines 316-320 defensively ensure both values are present before event emission, preventing NPE. The implementation correctly handles this type contract mismatch and safely returns only the vote data to maintain the method's signature.

stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandler.kt (1)

215-220: LGTM! Event handlers correctly updated to poll-first semantics.

All three poll vote event handlers now correctly pass (poll, vote) to the state update methods, consistent with the refactor across the codebase.

stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandlerTest.kt (1)

440-441: LGTM! Tests correctly validate poll-first semantics.

The parameterized tests properly construct events with poll objects and verify that state methods are called with (poll, pollVote) in the correct order.

Also applies to: 445-446, 450-451

stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityImplTest.kt (2)

365-381: Test correctly validates poll vote deletion.

The test follows the same pattern as castPollVote, ensuring consistency. The assertion on Line 379 expects ownVotes = emptyList() after vote deletion, which is the correct behavior.


346-362: Test correctly validates poll vote casting with proper state computation.

The test properly verifies that:

  • The method returns only the vote (not the poll)
  • The state is updated via event handling to include the new vote in ownVotes
  • The emitted event contains the updated poll from the repository

The architecture is correct: the repository returns the poll without ownVotes computed, and the state layer computes ownVotes locally by checking if vote.user?.id == currentUserId in the changeVotes operation. The test assertion correctly verifies this computed state.

stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityEventHandler.kt (1)

119-123: LGTM!

The event handler correctly passes the full PollData object from WebSocket events to the state update methods. This aligns with the PR objective to simplify vote handling by leveraging poll data from WS events rather than recomputing it locally.

stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/PollListEventHandler.kt (1)

50-60: LGTM!

The poll vote event handling is correctly updated to pass the full PollData object. The lack of filter checks here is appropriate since vote events modify existing polls that have already passed the filter.

stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepositoryImplTest.kt (2)

218-229: LGTM!

The test correctly verifies that castPollVote now returns a Pair<PollVoteData?, PollData?> containing both the vote and updated poll data from the API response. The use of to for Pair creation is idiomatic Kotlin.


260-272: LGTM!

The deletePollVote test is correctly updated to verify the new return type. Both cast and delete vote operations now consistently return poll data alongside vote data.

Based on learnings, consider adding failure path tests for these repository methods to ensure robust error handling coverage.

stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityListEventHandler.kt (1)

84-86: LGTM!

The changes are consistent with the other event handlers, correctly passing PollData and PollVoteData to the state update methods.

stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/repository/PollsRepository.kt (2)

141-145: LGTM!

The return type change to Pair<PollVoteData?, PollData?> appropriately captures both the vote and updated poll data from the API response. Since this is an internal interface, using Pair is acceptable and aligns with the PR objective.


162-167: LGTM!

Consistent return type change for deletePollVote, matching castPollVote. This ensures callers receive the updated poll state after vote deletion.

stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/ActivityListEventHandlerTest.kt (1)

224-238: LGTM!

The parameterized test cases are correctly updated to construct poll vote events with PollData objects and verify the corresponding state update method calls. The test structure maintains consistency with other event handler tests.

stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityStateImpl.kt (2)

154-160: LGTM!

The implementation correctly leverages the updated PollData from WebSocket events. By passing the poll parameter to removeVote/upsertVote, the state update can take external data (like vote counts) from the WS event while computing only the ownVotes locally—exactly matching the PR objective and the pattern used in ActivityData.upsertBookmark.


302-316: LGTM!

The interface changes are well-documented with updated KDoc. The new signatures with poll: PollData as the first parameter provide the necessary context for downstream state updates to merge WS event data with locally-computed own votes.

stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/ActivityListStateImplTest.kt (1)

338-400: LGTM! Comprehensive test coverage for the new poll-vote API.

The tests properly verify the new poll-first semantics:

  • Current user votes are correctly added/removed from ownVotes
  • Different user votes preserve existing ownVotes
  • updatedPoll from WS event is used as the base, with only ownVotes computed locally

This aligns well with the PR objective to rely on WS events for external data while computing only "own" properties locally.

stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/ActivityListStateImpl.kt (2)

197-211: LGTM! Clean implementation of the simplified poll-vote API.

The implementation correctly:

  • Accepts PollData from WS events and uses poll.id for matching
  • Delegates to removeVote/upsertVote with the full PollData object
  • Allows the model layer to take external data (counts, etc.) from the poll while computing ownVotes locally

348-362: KDoc accurately reflects the new API.

The parameter documentation is updated correctly from pollId to poll with appropriate descriptions.

stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/StateUpdateEvent.kt (2)

185-189: LGTM! Event payloads now carry full PollData.

The updated data classes properly carry poll: PollData instead of pollId: String, enabling downstream state handlers to access all poll properties from the WS event. This is the foundation for the simplified vote logic.


328-335: LGTM! WS event mapping correctly constructs new event payloads.

The toModel() extension properly converts WS events to the new StateUpdateEvent types using poll.toModel() for the poll parameter.

stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImpl.kt (2)

353-363: LGTM! Consistent implementation with ActivityListStateImpl.

The implementation correctly:

  • Uses poll.id for matching activities
  • Delegates to removeVote/upsertVote with the full PollData
  • Applies updates to both regular and pinned activities via updateActivitiesWhere

556-560: Interface signatures correctly updated.

The FeedStateUpdates interface now accepts (poll: PollData, vote: PollVoteData) for both vote methods, consistent with the other state interfaces.

stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImplTest.kt (1)

514-597: LGTM! Thorough test coverage for FeedStateImpl poll voting.

The tests comprehensively verify:

  • Current user vote upsert/removal updates ownVotes correctly
  • Different user votes preserve existing ownVotes
  • Both activities and pinnedActivities are updated
  • Non-matching poll IDs leave existing polls unchanged

This provides good confidence in the refactored implementation.

stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/PollListStateImpl.kt (1)

85-95: LGTM! Implementation consistent with other state classes.

The PollListStateImpl correctly implements the new poll-vote API, using poll.id for matching and delegating to the model layer for vote updates.

stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/PollListStateImplTest.kt (2)

95-168: LGTM! Complete test coverage for PollListStateImpl vote operations.

The tests thoroughly cover:

  • Current user vote upsert/removal affecting ownVotes
  • Different user votes preserving existing ownVotes
  • Non-matching poll IDs leaving the list unchanged

Test naming follows clear conventions (backticked names for readability), consistent with coding guidelines.


66-91: Good test naming update.

Renaming from "non-existent poll" to "non-matching poll" better reflects the test semantics—the poll exists but has a different ID than the one in the state.

@VelikovPetar VelikovPetar merged commit a784283 into develop Jan 9, 2026
9 of 12 checks passed
@VelikovPetar VelikovPetar deleted the and-931/simplify-upsert-vote branch January 9, 2026 13:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:internal Internal changes / housekeeping

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants