fix(meshcore): channel view opens at the top and Delete appears to do nothing - #4488
Conversation
… nothing Two independent pre-existing bugs on the MeshCore channel view, both dating to the per-channel history introduced in #4461. Reported from the running app; neither file was touched by the #4473 nav work. Delete did nothing visible. The stream renders `filtered` = merge(history, messages), but `actions.deleteMessage` only prunes the shared `messages` pool. Anything served from the per-channel backlog — nearly everything on this view — was deleted server-side and then immediately re-rendered from `history`. Confirmed against the live API: the row was already gone from the database while still on screen. `handleDeleteMessage` and `handleClearChannel` now prune `history` (and the count badge) on success, and only on success: a failed delete leaves the row rather than vanishing optimistically. The channel opened at the top instead of the newest message — mobile only, which is why desktop testing missed it. The mobile two-pane layout mounts the conversation but hides it until the operator drills in from the list; measured in that state, scrollHeight 0 / clientHeight 0 / offsetParent null. The entry scroll fired there, `scrollTop = scrollHeight` was `0 = 0` — a silent no-op — but the one shot was already spent, so drilling in left the view pinned at the top of a 17,000px backlog with nothing left to re-trigger it. The scroll no longer spends the shot until the list has real layout, and a ResizeObserver completes it the moment the pane is revealed. This fixes the DM view too, which shares the component. The guard keys off scrollHeight alone, NOT clientHeight: a hidden subtree zeroes both, but jsdom reports clientHeight 0 for everything, so a clientHeight guard would silently disable the entry scroll in every test. Verified on the running container at 390x780 across both MeshCore sources: entry scroll lands at distance 0 from the bottom (was 16774), and deleting removes the row immediately with the server confirming it gone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9NzRtqE8eSMS8tvAeodUB
|
Claude finished @Yeraze's task —— View job PR Review: fix(meshcore): channel view opens at the top and Delete appears to do nothingTasks:
This is a well-diagnosed and well-executed fix for two pre-existing bugs. The root causes are clearly documented, the implementation is correct, and the tests are thorough. Here's my detailed review: Bug 1 — Delete/Clear didn't prune
|
Two independent, pre-existing bugs on the MeshCore channel view, both reported from the running app. Both date to the per-channel history introduced in #4461 — neither file was touched by the #4473 nav work (verified against both merge commits).
1. Delete appeared to do nothing
The stream renders
filtered= merge(history,messages), butactions.deleteMessageonly prunes the sharedmessagespool. Anything served from the per-channel backlog (#4460) — which is nearly everything on this view — was deleted server-side and then immediately re-rendered fromhistory.Confirmed against the live API while reproducing:
handleDeleteMessageandhandleClearChannelnow prunehistory(and the count badge) on success, and only on success — a failed delete leaves the row rather than vanishing optimistically.DM view needs no change: it builds its list purely from the shared pool, with no separate
history.2. Channel opened at the top instead of the newest message
Mobile only, which is why desktop testing missed it — desktop lands at the bottom correctly every time.
The mobile two-pane layout mounts the conversation but hides it until the operator drills in from the list. Measured in that state:
The entry scroll fired there,
scrollTop = scrollHeightwas0 = 0— a silent no-op — but the one shot was already spent. Drilling in then left the view pinned at the very top of a 17,000px backlog with nothing left to re-trigger it.The scroll no longer spends the shot until the list has real layout, and a
ResizeObservercompletes it the moment the pane is revealed. This fixes the DM view too, which shares the component.One implementation note worth flagging: the guard keys off
scrollHeightalone, notclientHeight. A hidden subtree zeroes both, but jsdom reportsclientHeight: 0for everything — a clientHeight guard silently disabled the entry scroll in every test, including two existing ones that had been passing.Verified on the running container
390×780, both MeshCore sources:
Also removed the bogus 2082-dated message from both sources while confirming the fix (
futureLeftOnServer: 0on each).Test plan
MeshCoreChannelsView.test.tsx— delete prunes the backlog; failed delete keeps the row; cancelled confirm is a no-op; clear empties the backlog.MeshCoreMessageStream.test.tsx— entry scroll defers while hidden then runs on reveal; does not re-scroll on later resizes (so reading history isn't interrupted by a keyboard/rotate).success: true, 12954 passed, 0 failed.npx tsc --noEmitclean;npm run lint:cino FAIL lines.Generated by Claude Code