4 Commits
Author SHA1 Message Date
Bendik Aagaard LynghaugandClaude Opus 4.8 8ab1b50310 chore: Release cnats version 0.3.2
Release / build (x86_64, ubuntu-latest, /sccache) (push) Successful in 1m30s
Release / docker (push) Successful in 13s
Release / build (aarch64, aarch64, /var/lib/gitea-runner/sccache) (push) Successful in 12m52s
Release / update-aur (push) Successful in 28s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-03 10:17:22 +02:00
Bendik Aagaard LynghaugandClaude Opus 4.8 ede1b8497f fix(call): mirror SSR node structure so the lobby call button hydrates
CallPanel's hydrate body wraps the join button in a dynamic child
(`{move || if in_call {..} else {button}}`), which serializes hydration
marker comments; the SSR body rendered a *static* button (plus a
`disabled=true` the hydrate button lacks). That structural mismatch meant
`on:click` never attached on the first lobby load — the call button was dead
until a client-side nav re-rendered the subtree. Mirror the dynamic-child
wrapper and the button's serialized attributes in the SSR branch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-03 10:16:50 +02:00
Bendik Aagaard Lynghaug cc88f3c325 chore: Release cnats version 0.3.1
Release / build (aarch64, aarch64, /var/lib/gitea-runner/sccache) (push) Failing after 1s
Release / build (x86_64, ubuntu-latest, /sccache) (push) Successful in 1m32s
Release / update-aur (push) Skipped
Release / docker (push) Successful in 2m11s
2026-10-02 18:33:24 +02:00
Bendik Aagaard LynghaugandClaude Fable 5.1 e4c0094f34 Fix release build: box the call tiles, icons and in-call subtree
`cargo leptos build --release` died with "queries overflow the depth
limit": every tile's Show/icon views inlined into one enormous
hydrate_async type for the whole call subtree. VideoTile, CallIcon and
CallActive now return AnyView, the same cut CallPanel got in 0.2.1. The
dev profile never tripped it, which is why 0.3.0 shipped broken.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L3sD29ozDvqA7jozeZXZoB
2026-10-02 18:33:23 +02:00
4 changed files with 30 additions and 12 deletions
Generated
+1 -1
View File
@@ -345,7 +345,7 @@ dependencies = [
[[package]]
name = "cnats"
version = "0.3.0"
version = "0.3.2"
dependencies = [
"anyhow",
"async-nats",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "cnats"
version = "0.3.0"
version = "0.3.2"
edition = "2021"
[lib]
+1 -1
View File
@@ -1,6 +1,6 @@
# Maintainer: Bendik Aagaard Lynghaug <bendik.lynghaug@gmail.com>
pkgname=cnats
pkgver=0.3.0
pkgver=0.3.1
pkgrel=1
pkgdesc="Web chat over NATS subjects with Kanidm SSO (Leptos SSR)"
arch=('x86_64' 'aarch64')
+25 -7
View File
@@ -472,19 +472,30 @@ fn CallPanel(room: Memo<String>, me: String) -> impl IntoView {
}
.into_any()
}
// Must mirror the hydrate branch's default (not-in-call) markup exactly -
// hydration reconciles this SSR output against what the hydrate branch
// above expects to find, and an empty div here (vs. the button hydrate
// wants) is a hydration mismatch that panics and traps the whole wasm
// instance, killing all reactivity on the page.
// Must mirror the hydrate branch's default (not-in-call) markup AND its
// node structure exactly. The hydrate branch puts the button inside a
// dynamic child (`{move || ...}`), which serializes hydration-marker
// comments around it; if SSR emits a plain static button instead, the
// hydrate walk can't find the dynamic node, so it never attaches
// `on:click` - the call button is dead on the first lobby load until a
// client-side nav re-renders the subtree. So: same `{move || ...}` wrapper,
// and only the attributes the hydrate button actually serializes to
// (class/title/aria-label; `on:click` is a JS listener, not HTML). No
// `disabled` here - the hydrate button has none and hydration won't clear
// a stray SSR-only attribute.
#[cfg(not(feature = "hydrate"))]
{
let _ = (room, me);
view! {
<div class="call-panel">
<button class="call-join" title="join call" aria-label="join call" disabled=true>
{move || {
view! {
<button class="call-join" title="join call" aria-label="join call">
"☎"
</button>
}
.into_any()
}}
</div>
}
.into_any()
@@ -660,6 +671,7 @@ fn CallActive(call_state: crate::webrtc::CallState) -> impl IntoView {
</div>
</div>
}
.into_any()
}
#[cfg(feature = "hydrate")]
@@ -729,10 +741,15 @@ fn CallIcon(kind: CallIconKind, off: Signal<bool>) -> impl IntoView {
</Show>
</svg>
}
.into_any()
}
/// One participant's tile: the `<video>` plus a name label and mic/cam/
/// screen badges. Click pins it as the stage; double-click goes
/// screen badges. Returns `AnyView` (as do `CallIcon` and `CallActive`):
/// left generic, every tile's `Show`s and icons inline into one enormous
/// `hydrate_async` type for the whole call subtree, and the release build
/// dies with "queries overflow the depth limit" - the same wall
/// `CallPanel` hit in 0.2.1. Click pins it as the stage; double-click goes
/// fullscreen (handy for reading a shared screen). A child component so
/// each tile owns its `NodeRef`/effect pair instead of the parent juggling
/// a `Vec` of node refs by hand.
@@ -825,6 +842,7 @@ fn VideoTile(
</span>
</div>
}
.into_any()
}
/// Bridges `/call-sse/{room}` into `CallState::handle_signal`. A separate