Fix verified web audit batch (WEB-D/WEB-E/DRY): 409 banner, diff clamp, outside-click, ChannelModal isPrivate, sidebar lock, emoji filter, shared resize helper - #55
Merged
Conversation
…u outside-click, ChannelModal isPrivate, sidebar lock, emoji filter; DRY resize helper WEB-D: - api.js apiPost now attaches the parsed JSON error body (err.body) on non-2xx so ArtifactPanel's 409 banner shows the real latest_author / latest_version instead of "Someone" / v0 (+ test for the 409 path). - ArtifactPanel: derive the diff "compare" version as the nearest EXISTING older version (never data.version-1 -> v0), null when none; the Content/Diff toggle refuses diff when no older version exists. - ArtifactPanel: add panel-level outside-click close for the primary version dropdown (the header comment claimed this but no listener existed). The compare dropdown's open-state lives in ArtifactDetailHeader (out of file set) and needs a one-line follow-up there. WEB-E: - ChannelModal emits the Private toggle as a 3rd onCreate arg (backward compatible; App.svelte -> store.createChannel wiring is a follow-up). - ChannelContextMenu outside-click guard now treats the portaled Mute submenu as "inside" so a real mousedown->click reaches the action (+ test simulating mousedown then click). - SidebarChannelRow lock glyph keyed off visibility==='private' || mode==='invite' (was mode==='private', which never matched), consistent with ChannelAdminPanel; exposes data-glyph for testing. - EmojiPicker category tabs + search now actually filter the grid (per-category datasets + cross-category search + empty state) (+ tests). DRY: - Extract the ~130-line drag-resize logic duplicated between ArtifactPanel and ThreadPanel into lib/resizable-panel.svelte.js (createResizablePanel); both panels consume it. mqtt-store's separate safeStorage copy is left as a noted follow-up (different owner).
Aztec03hub
added a commit
that referenced
this pull request
Jun 26, 2026
…tion (#55 follow-up) (#56) The DRY extraction in #55 moved the keyboard nudge step into the shared createResizablePanel default and dropped the local `const KEY_STEP = 16`, which broke the source-level pin in e2e/scenarios/10-thread-panel.spec.ts ("ThreadPanel pins KEY_STEP = 16") and turned post-merge CI red on the E2E job (web unit tests + build + lint stayed green). Re-declare KEY_STEP=16 alongside its MIN/MAX/DEFAULT/STORAGE_KEY siblings and pass it explicitly into the helper so it is wired, not dead. No behaviour change (the helper already defaulted keyStep to 16).
Aztec03hub
added a commit
that referenced
this pull request
Jun 26, 2026
…low-up) (#57) PRIMARY: @mentions inside inline emphasis lost their mention styling. MessageBubble.parseBody emitted bold/italic/strike tokens whose inner `value` was raw text never run through the mention/link splitter, so an @mention in **bold** or *italic* rendered with emphasis styling but no mention pill/color. Extract the mention+link classification into a shared `splitTextToSegments` helper, run it over emphasis inner values, and render the resulting children INSIDE the emphasis wrapper via a recursive `renderSeg` snippet — mentions/links now inherit emphasis styling AND get their own chip/link styling. Code spans stay literal (never linkified). `hasSelfMention` now recurses into emphasis children for the border accent. SECONDARY (audit follow-ups): - ChannelModal isPrivate wired end-to-end: App -> store.createChannel(id, topic, isPrivate). The create API takes no visibility arg, so createChannel sets the local row + retained meta to private AND persists via the admin path (setVisibility -> comms_conversation_update), mirroring ChannelAdminPanel. #handleMeta now reads visibility from the broadcast. - ArtifactDetailHeader Compare dropdown closes on outside mousedown via a <svelte:window> guard, mirroring ArtifactPanel's primary-dropdown pattern. - safeStorage DRY: extracted the byte-identical copies from mqtt-store and resizable-panel into a shared web/src/lib/safe-storage.js. Tests: +11 (bold/italic/strike/plain mention chips + code-not-linkified; createChannel private/public/queued; compare-dropdown outside-click). 1314 -> 1325 tests, all green; build green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes a batch of verified web-only audit findings (WEB-D, WEB-E, DRY). Web files only; all tests green, build green, Svelte autofixer clean on every edited
.svelte/.svelte.js.WEB-D
apiPost(lib/api.js) discarded the parsed error response body, so ArtifactPanel's 409 handler readundefinedauthor/version. NowapiPostattacheserr.body(parsed JSON,nullon non-JSON) on non-2xx; ArtifactPanel already readsbody.latest_author/body.latest_version. New test covers the previously-untested 409 path.compareVersion = data.version - 1with no clamp. Now it derives the nearest existing older version (null when none), and the Content/Diff toggle refuses diff when no older version exists.mousedownoutside-click that closes the primary version dropdown (the open-state ArtifactPanel owns), matching the pattern other menus use. Follow-up: the Compare dropdown's open-state lives inArtifactDetailHeader.svelte(outside this change's file set) and needs a one-line outside-click addition there.WEB-E
isPrivate.handleCreatenow emits it as a third positional arg,onCreate(name, description, isPrivate)— backward compatible (arity-2 callers ignore it). Follow-up: wireApp.svelte→store.createChannelto honor it.menuEl.contains, but the submenu is portaled to<body>, so a realmousedownclosed the menu before the click fired. The guard now also treats the portaled submenu as "inside". New test simulatesmousedownthenclick.mode === 'private'never matched (modeholdsopen/invite; privacy lives invisibility). Nowvisibility === 'private' || mode === 'invite', consistent withChannelAdminPanel. Exposesdata-glyphfor testing.DRY
web/src/lib/resizable-panel.svelte.js(createResizablePanel), consumed by both panels. Follow-up:mqtt-store.svelte.jskeeps its ownsafeStoragecopy (different owner) — left as a noted remaining duplication.Verification
pnpm --dir web test: 1306 passed / 97 files, 0 skipped, 0 failures, no stderr/unhandled (stable across 3 runs).pnpm --dir web build: green.issues: []on all six edited components + the new module.🤖 Generated with Claude Code