fix/dm-stable-state-on-send #21

Merged
nrupard merged 3 commits from fix/dm-stable-state-on-send into main 2026-04-29 15:46:12 +02:00
Owner
No description provided.
Previously DmViewPage called use_server_future for the room, then early-returned on the loading or error branches before declaring the rest of its hooks (messages signal, WS subscriptions, draft, auto-scroll, etc.). When any parent re-render briefly caused dm_room() to evaluate to None or Err, the hook count dropped, Dioxus tore down the post-suspense state, and on the next render rebuilt it from scratch. To the user this looked like a page refresh: the message list, draft input, and scroll position all flashed.

Split the page into a thin DmViewPage wrapper that resolves the Room and an inner DmRoomView component that owns all the per-room hooks. The wrapper keys the inner component on room.id so navigating between DMs gets a fresh component, and within a single DM the inner component now has a stable hook list that no longer depends on the wrapper's branching. Sending and receiving DMs now updates the local messages signal seamlessly via the existing WebSocket events, matching the room view behavior.
The WebSocket onmessage closure captures a Copy of the latest_event Signal and is leaked via forget(), so it outlives the component scope on hot reload or unmount. Calling Signal::set on a dropped value panicked with `called Result::unwrap() on an Err value: Dropped`, surfaced from src/components/use_websocket.rs:159.

Switch the onmessage write to try_write so a dropped signal is a silent no-op. Apply the same guard to the sender.set calls in connect_ws so the reconnect loop exits cleanly when the owning scope is gone, instead of looping forever and panicking on the next set.
The sidebar refetches DM list, unread counts, and rooms in response to WebSocket events by bumping a version signal that the use_server_future closure reads. The `?` operator on use_server_future returns Err(Suspended) whenever the underlying resource state is Pending, which includes every refetch — not just the initial load. Suspense propagates to the nearest SuspenseBoundary, and Dioxus inserts a default one at the root of the tree, so every DM-driven sidebar refetch unmounted the entire app (sidebar plus the route Outlet) until the new data arrived. To the user that looked like a page refresh on every DM send and receive. Server-channel messages did not bump any sidebar version, so #-room views never tripped the boundary.

Switch the rooms / dms / unread / search_results hooks to use_resource. use_resource exposes the same Option<Result<T>> API, never auto-suspends, and keeps the previous value while refetching so the existing match-on-Option fallbacks already in this file render the cached list during the refetch window. The version-signal subscription pattern is unchanged.
nrupard deleted branch fix/dm-stable-state-on-send 2026-04-29 15:46:12 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!21
No description provided.