Commit Graph

30 Commits

Author SHA1 Message Date
Nicolas Varrot
916910f5ce fix: resolve all ESLint errors and add lint step to CI
- Extract credential helpers to src/lib/credentials.ts (fixes react-refresh/only-export-components)
- Extract buildImageSrc to src/lib/image.ts (fixes react-refresh/only-export-components)
- Reorder useCallback declarations in useGateway to fix react-hooks/immutability
- Sync refs via useEffect instead of during render (fixes react-hooks/refs)
- Replace useState initializer effect with lazy initializer functions in LoginScreen
- Add comments to empty catch blocks (fixes no-empty)
- Remove unused variable (fixes @typescript-eslint/no-unused-vars)
- Downgrade react-hooks/set-state-in-effect to warning (valid init/status patterns)
- Add lint step to CI workflow (runs before type-check and build)
2026-02-11 23:37:37 +00:00
Nicolas Varrot
f8be728842 fix: use exponential backoff with jitter for WebSocket reconnection
Replace fixed 3s reconnect delay with exponential backoff (1s → 30s cap)
plus 30% jitter to prevent thundering herd. Resets on successful
connection or manual disconnect.
2026-02-11 22:33:02 +00:00
Nicolas Varrot
5b2f3a340d feat: add retry/resend button on user messages
Hover over any user message to reveal a retry button (↻) that resends
the message text. Disabled while a response is generating.
Includes EN/FR i18n strings.
2026-02-11 21:56:48 +00:00
Nicolas Varrot
473d23c140 feat: add browser notifications and tab title badge for unread messages
When the tab is not focused:
- Tab title shows unread count: (3) PinchChat
- Browser notification with message preview (if permitted)
- Notifications collapse into one via tag
- Click notification to focus tab
- All clears when tab regains focus
- Permission requested on first user interaction
2026-02-11 21:45:59 +00:00
Nicolas Varrot
fd66fed96f fix(a11y): add prefers-reduced-motion support for all animations
Disables animations and reduces transition durations to near-zero
when the user has enabled reduced-motion in their OS settings.
Also replaces README screenshot placeholder with link to live demo.
2026-02-11 21:26:08 +00:00
Nicolas Varrot
693229c14e refactor: replace any types with proper TypeScript types across gateway client, hooks, and components
- Add GatewayMessage and JsonPayload interfaces to gateway.ts
- Type WebSocket message parsing with GatewayMessage instead of any
- Use ReturnType<typeof setTimeout> for timer refs
- Type chat event payload destructuring explicitly
- Add ChatPayloadMessage interface for extractText()
- Replace any casts in loadSessions/loadHistory with typed assertions
- Add str() helper in ToolCall.tsx for safe unknown→string extraction
- Use Extract<MessageBlock, ...> type guards instead of `as any` casts
- Type CodeBlock children prop properly
2026-02-11 21:17:44 +00:00
Nicolas Varrot
b61a232948 feat: add ErrorBoundary for graceful crash recovery
- Catches render errors and shows a styled recovery UI instead of blank white screen
- Try Again button re-renders, Reload button refreshes the page
- Error details shown in a collapsible pre block
- Full i18n support (EN/FR)
- Wraps the entire app in main.tsx
2026-02-11 20:53:16 +00:00
Nicolas Varrot
78f82fd551 fix(a11y): add ARIA attributes to interactive elements
- ImageBlock: wrap clickable image in <button> with aria-label, add
  role=dialog and aria-modal to lightbox overlay
- KeyboardShortcuts: add role=dialog and aria-modal to modal overlay
- CodeBlock: add aria-label to copy button
- LanguageSelector: add aria-label with current language
2026-02-11 20:36:35 +00:00
Nicolas Varrot
72f7d76cc4 feat: add emoji icons to tool call badges
Replace Lucide icons with emojis on tool call badges for better visual
identification:  exec, 🔍 web_search, 📖 read, ✏️ write/edit,
🧠 memory,  cron, 🚀 sessions_spawn, and more.

Also reduces bundle by removing unused Lucide icon imports from ToolCall.

Closes feedback item #15.
2026-02-11 20:25:31 +00:00
Nicolas Varrot
59104b4217 feat: support line breaks in messages (remark-breaks plugin) 2026-02-11 20:22:17 +00:00
Nicolas Varrot
84c8e24457 style: unify token progress bars with subtle cyan opacity ramp
Replace the disparate gradient/orange/red color scheme with a single
soft sky-blue (rgb 56,189,248) that subtly intensifies as usage grows.
Opacity ramps from 0.35 at low usage to 1.0 at full context.
Applies to both sidebar session bars and header token bar.
2026-02-11 20:15:31 +00:00
Nicolas Varrot
ae83545377 feat: add keyboard shortcuts help modal (press ? to open) 2026-02-11 19:56:18 +00:00
Nicolas Varrot
177970988a feat(sidebar): add session search filter with Ctrl+K shortcut
- Search input appears when 4+ sessions exist
- Filters sessions by label/key in real-time
- Ctrl+K / Cmd+K keyboard shortcut to focus search
- Clear button and 'no results' state
- i18n support (EN + FR)
2026-02-11 19:46:28 +00:00
Nicolas Varrot
dd5b56e02c feat: add copy-to-clipboard button on assistant messages
Appears on hover over assistant message bubbles. Shows a check icon
with 'Copied!' feedback for 2s after clicking. i18n support (EN/FR).
Does not show on streaming messages or empty messages.
2026-02-11 19:26:06 +00:00
Nicolas Varrot
195ad621f7 fix(i18n): use i18n key for 'Parameters' label in tool call expansion
The 'Paramètres' label in ToolCall.tsx was hardcoded in French instead of
using the i18n system. Added tool.parameters key to both EN and FR locales.
2026-02-11 18:56:11 +00:00
Nicolas Varrot
91c22a10af fix: close sidebar overlay on Escape key + aria-hidden for screen readers 2026-02-11 18:46:01 +00:00
Nicolas Varrot
32a2166fd3 feat: connection lost/reconnected banner with i18n
Adds a slim animated banner below the header that:
- Shows 'Connection lost — reconnecting…' with spinner when WS drops
- Flashes 'Reconnected!' with auto-dismiss after 3s on recovery
- Only appears after initial connection (not on first load)
- Supports EN/FR via i18n system
- Uses aria role=alert for accessibility
2026-02-11 18:36:51 +00:00
Nicolas Varrot
b56c80a454 feat: add scroll-to-bottom button when scrolled up in chat
Floating button appears when user scrolls away from the bottom of the
conversation, making it easy to jump back to the latest messages.
Includes i18n labels (EN/FR) and smooth scroll animation.
2026-02-11 17:56:09 +00:00
Nicolas Varrot
762a5f2026 feat: inline image display with lightbox
- Add image block type for base64 and URL images
- Parse image/image_url blocks from gateway history
- Render images inline in chat messages (rounded, dark-themed)
- Click-to-zoom lightbox with Escape to close
- Markdown images also use the lightbox component
- Detect base64 images in tool results (e.g. Read tool on image files)
- Support png, jpg, gif, webp formats
2026-02-11 17:18:10 +00:00
Nicolas Varrot
97c16be399 feat: integrate PinchChat logo throughout the app
- Use logo.png as favicon (replaces emoji SVG)
- Show logo in header next to title
- Show larger logo on login screen
- Add OG image meta tag
- Add centered logo in README
- Closes feedback item #8
2026-02-11 16:47:02 +00:00
Nicolas Varrot
9b3aed4adc feat: add runtime language selector in header (EN/FR toggle)
- Add LanguageSelector component with globe icon + cycle button
- Refactor i18n to support reactive locale switching via useSyncExternalStore
- Locale priority: localStorage > VITE_LOCALE > navigator.language > 'en'
- All components now use useT() hook for reactive re-rendering on locale change
- Persists choice to localStorage (key: pinchchat-locale)
- No page reload needed — instant switch
2026-02-11 16:18:22 +00:00
Nicolas Varrot
b6a989bb51 feat: add copy button on code blocks
Hover over any fenced code block to reveal a floating copy-to-clipboard
button (top-right corner). Provides visual feedback (checkmark) on success.
Uses a custom ReactMarkdown <pre> component wrapper.
2026-02-11 15:46:49 +00:00
Nicolas Varrot
3e7a5969e0 fix: smart auto-scroll — only scroll to bottom when user is near bottom
Previously, every message update forced a scroll to bottom, which was
disruptive when reading older messages in the history. Now the chat only
auto-scrolls if the user is within 150px of the bottom, or if they just
sent a message. This preserves scroll position when browsing history
while still following new streaming content.
2026-02-11 14:47:11 +00:00
Nicolas Varrot
88c393ed50 fix: use i18n locale for timestamp formatting instead of hardcoded fr-FR 2026-02-11 14:31:32 +00:00
Nicolas Varrot
99b7db9793 feat: add i18n support with VITE_LOCALE env var (en/fr)
- Lightweight i18n system in src/lib/i18n.ts (no external deps)
- All UI strings extracted to translation keys
- English (default) and French locales included
- Set VITE_LOCALE=fr in .env for French UI
- Fallback to English for unknown locales
2026-02-11 13:19:20 +00:00
Nicolas Varrot
36f948027b feat: runtime login screen — remove token from build
- Add LoginScreen component with Gateway URL + Token fields
- Store credentials in localStorage (not in bundle)
- Auto-reconnect with stored credentials on reload
- Add logout button (LogOut icon) in Header
- Remove VITE_GATEWAY_TOKEN from .env.example
- VITE_GATEWAY_WS_URL now only pre-fills the URL field
- Dark neon theme consistent with rest of app

Closes feedback item #4
2026-02-11 12:48:58 +00:00
Nicolas Varrot
8834b2ac36 fix: filter out NO_REPLY messages from chat display
NO_REPLY is an internal agent response that should not be visible
to users. Messages with content exactly matching 'NO_REPLY' are
now hidden from the chat view.
2026-02-11 12:31:07 +00:00
Nicolas Varrot
3370916931 fix: localize UI to English and add ARIA accessibility attributes
- Replace all French UI strings with English (Connected, Thinking, Result, Send, etc.)
- Add role="log" + aria-live="polite" to chat message area
- Add role="form" + aria-label to message input area
- Add aria-label to sidebar toggle, attach file, send, and textarea
- Add role="banner" to header, role="navigation" to sidebar
- Add role="application" to app root
2026-02-11 12:17:54 +00:00
Nicolas Varrot
d58c34fbd7 feat: rename ClawChat → PinchChat across entire project
- Update package.json name and repo URL
- Update README.md, CONTRIBUTING.md branding and links
- Update UI components (Header, Chat) display names
- Update gateway user-agent string
- Rename GitHub repo via API
- Mark FEEDBACK.md item #1 as done
2026-02-11 11:16:19 +00:00
Nicolas Varrot
1f8ff9ae0a Initial commit — ClawChat v1.0.0 2026-02-11 00:48:43 +00:00