v0.3.0
Highlights
Voters can now retract their vote on an ACTIVE question ("Change my answer") and recast it before the presenter closes the slide. The whole flow is status-gated end-to-end — the backend refuses retract once the question is CLOSED, and the voter UI hides the retract affordance the moment a close event lands.
Features
- Retract vote endpoint:
DELETE /api/polls/{slug}/votes— status-gated, deletes the caller's vote on the active question and rebroadcasts the tally via SSE (VoteRetractedEvent). - Voter UI: "Change my answer" button on the voted state — clears the per-(slug, questionId) localStorage flag and returns the picker.
- Shared client:
ApiClient.retractVote(slug)in@slidev-polls/shared.
Fixes
- Vote disappears on slide back (this release's voter bug): PollView no longer blanket-clears the per-question
already-votedlocalStorage flags onquestion-closedor on the no-active-question branch of initial load. After the presenter navigated off a poll slide and back, the voter UI flipped from "Answer recorded" to the Submit form even though the server still held the vote — that's gone. - Retract race: backend re-checks
QuestionStatusafter the gatedDELETEso a presenter closing the question while a retract is in flight no longer produces a falseQUESTION_NOT_ACTIVE. - Integration test constraint:
VoteRepositoryImplDeleteByVoterIT.throws_question_not_active_when_question_closednow NULLsactivated_atalongside the CLOSED status flip, matching thepoll_questions_active_timestamp_ckconstraint and the production close path.
Chores
- Bumped
com.diffplug.spotless:spotless-maven-pluginto 3.5.1.
Artifacts
- Backend image:
ghcr.io/asm0dey/slidev-polls:v0.3.0(multi-arch —linux/amd64,linux/arm64). - npm:
@slidev-polls/shared@0.3.0,@slidev-polls/component@0.3.0.