Commit Graph

67 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
85c23b4e2d chore: release v1.1.0 — bump version and finalize changelog 2026-02-11 22:15:35 +00:00
Nicolas Varrot
88b6494523 feat: add OG card image + Twitter/OG meta tags for social sharing 2026-02-11 22:13:54 +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
d02009475b docs: add PR template and security policy
- Add .github/PULL_REQUEST_TEMPLATE.md with checklist for contributors
- Add SECURITY.md with vulnerability reporting instructions
2026-02-11 21:35:29 +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
d724a8ca0b docs: update CHANGELOG with recent additions (ErrorBoundary, a11y, shortcuts, search, emoji badges) 2026-02-11 20:55:39 +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
c3824dd29f docs: mark feedback item #15 as done 2026-02-11 20:25:39 +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
02e4bcf554 fix(landing): left-align demo chat messages (inherited text-align:center from hero) 2026-02-11 20:18:46 +00:00
Nicolas Varrot
538fb3a7bd docs: mark feedback item #14 as done 2026-02-11 20:15:41 +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
38d7aab6da docs: mark feedback item #13 as done 2026-02-11 20:07:23 +00:00
Nicolas Varrot
d11849817a style(landing): move demo to hero, replace grid with alternating feature sections
- Demo animation is now the first thing visitors see (in the hero)
- Features use alternating left/right layout with visual panels
- Each feature has a mini illustration (tool badges, session list, etc.)
- Scroll-reveal animation on feature rows
- Removed the old grid layout
- Responsive: stacks vertically on mobile

Closes feedback #13
2026-02-11 20:07:02 +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
50cd18867c docs: update CHANGELOG with all recent additions and fixes 2026-02-11 19:35: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
cbee0efcee docs: mark feedback item #12 as done 2026-02-11 19:17:03 +00:00
Nicolas Varrot
d26c4988f2 feat(landing): add animated fake UI demo with tool call visualization
Replaces the screenshot placeholder with a live animated demo showing:
- Sidebar with fake sessions and token usage bars
- User typing animation with cursor
- Thinking indicator with animated dots
- Colored tool call badges (web_search, exec)
- Expandable tool results with parameters
- Formatted assistant response with markdown
- Auto-looping animation

All pure CSS/JS, no dependencies. Matches the app's dark theme and color scheme.

Closes feedback item #12
2026-02-11 19:16:52 +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
569dbc6d4d docs: mark feedback item #11 as done 2026-02-11 18:25:42 +00:00
Nicolas Varrot
f556c8db8e docs: rewrite features for README and landing page
Reorder and rewrite feature descriptions to highlight what actually
differentiates PinchChat: tool call visualization, GPT-like interface,
multi-session navigation. Remove generic features (markdown, file upload,
dark theme) that don't sell the product. Pragmatic tone, no fluff.
2026-02-11 18:25:32 +00:00
Nicolas Varrot
71c6491f69 docs: add CHANGELOG.md and link from README 2026-02-11 18:15:57 +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
04e1f3b778 docs: mark Mermaid diagram feedback item #10 as done 2026-02-11 17:45:26 +00:00
Nicolas Varrot
02d2ab3bf7 docs: replace ASCII architecture diagram with Mermaid 2026-02-11 17:45:15 +00:00
Nicolas Varrot
09ae82df6c docs: mark GitHub Pages feedback item #9 as done 2026-02-11 17:36:30 +00:00
Nicolas Varrot
4f47732fa0 docs: add GitHub Pages landing page with features showcase 2026-02-11 17:36:04 +00:00
Nicolas Varrot
ee5d870f06 docs: mark image display feedback item #7 as done 2026-02-11 17:18:19 +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
375302a27b docs: mark logo feedback item #8 as done 2026-02-11 16:47:09 +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
af7d9280fb docs: add new feedback items #7-#9 and logo asset 2026-02-11 16:45:51 +00:00
Nicolas Varrot
e2c46cfd41 docs: mark Docker feedback as done 2026-02-11 16:31:43 +00:00
Nicolas Varrot
5fd73001f7 feat: add Docker support with Dockerfile, compose, CI, and oneliner install
- Multi-stage Dockerfile (node build + nginx:alpine serve)
- nginx.conf with SPA fallback, gzip, asset caching
- docker-compose.yml for easy deployment
- GitHub Actions workflow to build & push to ghcr.io on every push
- .dockerignore to keep image lean
- Updated README with Docker-first quick start and badge
2026-02-11 16:31:33 +00:00
Nicolas Varrot
42857da83d docs: mark language selector feedback as done 2026-02-11 16:18:37 +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
8af812807a docs: add architecture diagram and component overview to README 2026-02-11 15:17:10 +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