Skip to content

Design-fidelity pass: markdown render fix, notification preview, per-chat mute#77

Merged
EyalDelarea merged 11 commits into
mainfrom
claude/strange-bassi-4c4ee2
Jun 12, 2026
Merged

Design-fidelity pass: markdown render fix, notification preview, per-chat mute#77
EyalDelarea merged 11 commits into
mainfrom
claude/strange-bassi-4c4ee2

Conversation

@EyalDelarea

@EyalDelarea EyalDelarea commented Jun 12, 2026

Copy link
Copy Markdown
Owner

What & why

Audited the CatchApp web UI against the Claude Design hi-fi handoff (source of truth: Hi-Fi.html + hf_*.jsx + the design_handoff_catchapp_ui/ spec) and drove every screen against the real backend (single-user local: Postgres + RabbitMQ + Ollama, real WhatsApp data) in a browser. A 7-agent design-fidelity audit produced a precise 49-item delta list; this PR closes the notable visual + behavioral gaps to reach 1:1 across every screen the app actually shows.

Changes

Quality fixes (first pass)

  • fix(ui): render markdown in summary bullets + the Today info card; strip ^[#n] citation noise (renderInline).
  • feat(ui): Settings morning-notification lock-screen preview (§8).
  • feat(multi-tenant) + feat(ui): per-chat mute — the §7 third scope state (migration + listSuggestibleGroupIds + suggest-handler filter + /api/scopes + Sources moon toggle).

1:1 parity pass (this round)

  • Today (היום): desktop now renders the web-native digest board (.dg-board: greeting head + inline subline + note pill + flat wide in-place cards) per hf_v2.jsx — the v1 phone Stories stack is kept only for mobile (<780px); a matchMedia listener swaps on resize.
  • Summarizing loader: the retired Glacier "phase tube" is replaced everywhere by the designed .sumload scene (bobbing brand glyph, pulsing ring, orbiting dots, rising bubbles, sparkles, indeterminate bar — all CSS, reduced-motion-safe).
  • Updates (עדכונים): interactive category filter chips, a distinct filtered-empty state, and a real "N חדשות" badge (listGroups now computes messages-since-last-summary).
  • Sources (צ׳אטים): avatar + status-line rows inside one surface card with hairline dividers, dimmed excluded rows, the designed flex callout with an "N/M פעילים" accent pill, larger spec switch, bottom legend.
  • Settings (הגדרות): reordered to the §8 spine (engine panel first), added the "איפוס למידה" row (→ POST /api/suggestions/reset-learning), amber .beta badge, and a real delete-everything confirm dialog (honest "not available yet" — no server wipe endpoint).
  • Ask (שאל): the designed .ask-state searching row (spark + title + sub + dot ripple), white-space:nowrap citation chips, LTR-wrapped [n], design suggestion starters.
  • People (אנשים): flat hover rows (framed accent only when selected), design font sizes, source-icon chips, removed the invented count badge.
  • Shell: stale banner uses --warn tokens (was hard-coded amber); meetings/todos nav-rail count badges populate.

Verification (browser, real backend)

Each screen re-checked at desktop + mobile, light מרווה + dark לילה: Today board fills the width (no more "phone in a window") and collapses to the Stories stack + bottom nav on mobile; Updates chips filter and the badge wiring is confirmed (Bar Hevr=42 new); Sources mute persists to the DB; Settings reorder + amber beta + reset/confirm wired; Ask searching state + citations; markdown renders cleanly with chat-tag chips.

CI gate green locally: biome ✅ · tsc --noEmit ✅ · build ✅ · 1329 tests pass (147 files, 0 failures).

Remaining (documented follow-up)

  • Onboarding 5-step flow (§1) — still unwired and gated behind multi-tenant auth, so single-user-local (the default) never runs it; the user is already linked and won't see it. Building it cleanly needs gate-decoupling + a preview route and is routed through spec-kit. A follow-up task is queued.
  • A few P2/P3 nits intentionally left: Sources ⋯ overflow menu (kept functional inline controls), Ask no-results ErrorSurface (needs a backend empty SSE signal), Settings single-time chip (kept the more-functional multi-time picker).

🤖 Generated with Claude Code

EyalDelarea and others added 11 commits June 12, 2026 15:30
…on noise

Structured-summary topic/decision bullets (renderSumBullets) and the Today
info card body escaped raw model text, so **bold** labels and ## headings
rendered literally and inline ^[#n] source-citation markers leaked through.

Add renderInline() (escape + citation strip + bold/chat-tags) for single-line
contexts, route summary bullets through it, render the info-card body via
renderMarkdown, and strip ^[#n] noise in renderMarkdown itself (the .src /
.sum-jump affordance already carries the real messageId). Matches the design's
clean structured summary card.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Settings' "התראת בוקר" row gains a "תצוגה מקדימה" button that overlays the
designed lock-screen push mock (.notif-preview/.notif-card, CSS already ported):
brand glyph + "הסיכום של היום מוכן ✦ · 5 דברים מחכים לך · קריאה של דקה".
Dismiss via backdrop, the סגירה button, or Esc. Closes the one §8 gap.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A muted chat stays included (still in Updates/catch-up, still summarized) but
the suggestion engine skips it: no proactive suggestions or notifications.

- migration: add `muted boolean not null default false` to chat_scopes (RLS
  inherited from the table policy).
- chat-scopes repo: thread `muted` through ScopeRow/ScopeUpdate/listScopes/
  upsertScope; add listSuggestibleGroupIds (included AND NOT muted) — a strict
  subset of listIncludedGroupIds (summaries still cover muted chats).
- suggest.generate handler: scope-filter on the suggestible set, not the
  included set (dep renamed loadIncludedGroupIds → loadSuggestibleGroupIds).
- /api/scopes: accept + return `muted`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Each included chat row gains a moon (quiet) button that toggles its muted
scope optimistically via PUT /api/scopes. Muted = accent-filled; excluded
chats show no mute control (mute only applies to included chats). A muted
chat stays in Updates/catch-up but stops producing proactive suggestions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Desktop Today (≥780px) now renders the web-native digest board (.dg-board:
dg-head greeting + inline subline + note pill, dg-grid of wide in-place cards)
per hf_v2.jsx CommandCenter — the v1 phone Stories stack is kept only for the
mobile column (it read as 'a phone in a window' on desktop). Board + stack share
the deck and onTodayAct; a matchMedia listener re-paints on breakpoint cross.

Also replaces the retired Glacier 'phase tube' with the designed .sumload scene
(bobbing brand glyph, pulsing ring, orbiting dots, rising bubbles, sparkles,
indeterminate bar — all CSS, reduced-motion-safe) everywhere summaries load,
fixes the stale banner to use --warn tokens (was hard-coded amber), and fills
the meetings/todos nav-rail count badges.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…'N חדשות' badge

- category filter chips (הכול + each category with included chats) that filter
  the list client-side; loadGroupsIntoList now carries each chat's categoryId.
- filtered-empty state ('אין עדכונים בקטגוריה זו') distinct from the
  no-included-chats empty state.
- listGroups computes a real newCount (messages since the chat's last summary;
  un-summarized chats count all) → the card's 'N חדשות' accent badge.
- card meta trimmed to a single muted descriptor; 'קבץ לפי' label sized to spec.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…xcluded, callout pill

- each category is one .surface card with hairline .divide between rows (was
  per-row bordered cards); rows gain an avatar + a status line (מוזן/מוחרג/מושתק
  + category) instead of a bare message count.
- excluded rows dim via .src-row--off; the include switch moves to the row end
  and matches the design size (42×25, knob 19, soft shadow).
- intro callout becomes the designed flex banner: filter icon + bold title +
  sub-line + an accent N/M פעילים pill. Adds the bottom helper legend.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ta, wipe confirm

- reorder to the §8 spine: privacy callout → מנוע ההצעות (ניסיוני) → פרטיות
  ונתונים → הסיכום היומי, with תצוגה kept as a trailing additive card.
- add the 'איפוס למידה / אפס' engine row, wired to POST
  /api/suggestions/reset-learning (resetSuggestionLearning in lib/api.js).
- .beta badge switches to the amber --warn ramp (was green, bordered).
- enable the 'מחיקה' button → a designed .confirm-card dialog; since no
  server-side wipe endpoint exists yet, the confirm is honest (a visible
  'not available — disconnect manually' toast, not a fake success).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…TR [n]

- pre-answer loading uses the designed .ask-state row (spark + title + sub +
  three-dot ripple) instead of an in-bubble writing caret.
- .src citation chip gets white-space:nowrap so a long chat name + date stays on
  one line; the [n] index is wrapped dir=ltr so it doesn't reorder in RTL.
- suggestion starters match the design set (סכם את כל הקבוצות מהשבוע / למי עדיין
  לא חזרתי?).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- list rows go flat (hover-only) with the framed accent state reserved for the
  selected row; name/note/meta sized to spec (15.5/13.5/12), note wraps.
- drop the invented warmWaiting/total count badge (the title lives in the appbar).
- 'הצעד הבא' kicker is muted/non-uppercase with no icon, per .kicker.
- .src/.srcchip chips use the design's source (reply) glyph instead of arrowL
  (shared with Today + Agenda source chips).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@EyalDelarea EyalDelarea merged commit fc7e882 into main Jun 12, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant