fix(polls): you can vote on a poll you just created (#284) #383

Merged
jared merged 1 commits from fix/poll-vote-local-echo into lotus 2026-10-17 23:26:31 -04:00
Owner

Fixes #284.

PollContent read mEvent.getId() once, during render. For a poll you've just created, that is the local-echo id (~!room:txn). Nothing re-rendered it when the SDK swapped in the real $id, which caused two failures:

  • The vote's m.relates_to pointed at the local id.
  • The SDK then threw synchronously (Cannot call getPendingEvents with pendingEventOrdering == chronological), so no vote was sent until a reload.

Change

  • The id is now state, updated on MatrixEventEvent.LocalEventIdReplaced and Status, so the vote, end-poll and tally all use the real id.
  • Voting and ending are disabled while the id is still local.
  • Synchronous throws from the send are caught.

Verified

  • New Playwright test in e2e/local-homeserver.spec.ts: create a poll in the UI, vote without reloading, and assert an m.poll.response relating to the real $ id. It fails on lotus and passes here.
  • Manual run: before, a page error and no vote reached the server. After, the vote arrived and there were no page errors.

Note: the timeline row's data-message-id still shows the local id until a reload. That is cosmetic and separate, so I left it alone.

tsc clean · unit tests pass · ESLint clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5

Fixes #284. `PollContent` read `mEvent.getId()` once, during render. For a poll you've just created, that is the local-echo id (`~!room:txn`). Nothing re-rendered it when the SDK swapped in the real `$id`, which caused two failures: - The vote's `m.relates_to` pointed at the local id. - The SDK then threw synchronously (`Cannot call getPendingEvents with pendingEventOrdering == chronological`), so no vote was sent until a reload. **Change** - The id is now state, updated on `MatrixEventEvent.LocalEventIdReplaced` and `Status`, so the vote, end-poll and tally all use the real id. - Voting and ending are disabled while the id is still local. - Synchronous throws from the send are caught. **Verified** - New Playwright test in `e2e/local-homeserver.spec.ts`: create a poll in the UI, vote without reloading, and assert an `m.poll.response` relating to the real `$` id. It **fails on `lotus`** and **passes here**. - Manual run: before, a page error and no vote reached the server. After, the vote arrived and there were no page errors. Note: the timeline row's `data-message-id` still shows the local id until a reload. That is cosmetic and separate, so I left it alone. `tsc` clean · unit tests pass · ESLint clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
jared added 1 commit 2026-10-17 19:54:05 -04:00
fix(polls): you can vote on a poll you just created (#284)
CI / Build & Quality Checks (pull_request) Successful in 2m53s
CI / Trigger Desktop Build (pull_request) Skipped
CI / Docker image build & smoke test (pull_request) Skipped
CI / Secret scan (gitleaks) (pull_request) Successful in 8s
CI / Playwright smoke (e2e) (pull_request) Successful in 14m12s
f9172cc339
PollContent read mEvent.getId() once at render. For your own new poll
that is the local echo id (~!room:txn), and nothing re-rendered it when
the SDK swapped in the real $id, so the vote related to the local id
and the SDK threw synchronously (getPendingEvents under chronological
ordering): no vote was ever sent. Track the id via LocalEventIdReplaced
and Status, block voting while it is still local, and catch synchronous
throws. Adds the Playwright regression the issue asks for.

Fixes #284

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
jared merged commit 4ab5a8fd06 into lotus 2026-10-17 23:26:31 -04:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/cinny#383