commit a2b1c2eb8ad11a752fea1fa75f5b233ec2043d61
parent d824539220c6ce5105a4937b7b4c3c0c04ce423c
Author: Silas Brack <silasbrack@gmail.com>
Date: Thu, 11 Jun 2026 12:31:36 +0200
fix: use proper SSE format and outer morph for vote responses
Vote handler now returns text/event-stream with
datastar-patch-elements events instead of text/html with
non-standard custom headers. Vote button template includes
wrapper span with ID for proper outer morph matching.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Diffstat:
2 files changed, 8 insertions(+), 14 deletions(-)
diff --git a/src/handlers/vote.rs b/src/handlers/vote.rs
@@ -1,14 +1,13 @@
use askama::Template;
use axum::{
- body::Body,
extract::{Path, State},
- http::{StatusCode, header},
response::Response,
};
use axum_extra::extract::cookie::CookieJar;
use crate::error::AppError;
use crate::handlers::auth::get_tokens_from_cookies;
+use crate::sse;
use crate::state::AppState;
use crate::templates::VoteButtonTemplate;
use crate::trailbase::{self, TARGET_TYPE_COMMENT, TARGET_TYPE_STORY};
@@ -44,14 +43,7 @@ fn render_vote_button(
};
let html = template.render()?;
- let selector = format!("#vote-{}-{}", target_type, target_id);
- Ok(Response::builder()
- .status(StatusCode::OK)
- .header(header::CONTENT_TYPE, "text/html")
- .header("datastar-selector", &selector)
- .header("datastar-mode", "inner")
- .body(Body::from(html))
- .unwrap())
+ Ok(sse::patch_elements(&html))
}
/// Vote on a story (Datastar endpoint)
diff --git a/templates/vote_button.html b/templates/vote_button.html
@@ -1,4 +1,6 @@
-<button
- class="vote-btn{% if voted %} voted{% endif %}"
- data-on:click="@post('/vote/{{ target_type }}/{{ target_id }}')"
->▲</button>
+<span id="vote-{{ target_type }}-{{ target_id }}">
+ <button
+ class="vote-btn{% if voted %} voted{% endif %}"
+ data-on:click="@post('/vote/{{ target_type }}/{{ target_id }}')"
+ >▲</button>
+</span>