- Normalize snake_case REST API responses to camelCase in useChat so
messages are correctly attributed after page reload
- Remove max-w-3xl from chat-ui messages and composer for full-width
- Remove discussion header/border so chat fills the tablo section
- Remove plan badge pills from settings page header
- Use org logo in NavigationBar avatar instead of first-letter fallback
- Persist plan announcement in localStorage instead of sessionStorage
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a `chat` i18n namespace (FR/EN) and replace all hardcoded strings
in chat components with useTranslation calls. Introduce a `labels` prop
on ChatProvider so chat-ui renders translated typing indicators,
placeholders, and aria labels. Also filter out typing events from the
current user on the client side.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The chat REST API returns raw DB rows with snake_case fields
(user_id, created_at) while WS messages use camelCase. Handle
both to prevent Invalid Date errors from new Date(undefined).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The @import in main.css failed because ./src/chat-ui.css wasn't
in the exports field. Add explicit export and use correct path.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Import chat-ui.css via CSS @import in main.css (not JS import)
so @layer directives go through Tailwind's compilation
- Add @source directive for packages/chat-ui so Tailwind v4
scans the package for utility classes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace chatscope implementation with ChatProvider, ChatMessageList,
and ChatComposer from @xtablo/chat-ui. Props interface unchanged.
Also fix unused Tag import in chat-ui layouts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace leftover chatcn CSS variables in ticket status/priority
configs and filter tabs with xtablo design tokens.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Spec and plan for integrating chatcn as @xtablo/chat-ui package,
replacing chatscope for the chat UI rendering layer.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add shared ChatMessages component with date separators (Aujourd'hui, Hier, etc.)
- Show sender name and avatar on incoming messages
- Own messages aligned to the right, others to the left
- Show message timestamps on each message
- Typing indicator shows member names
- Optimistic messages shown with reduced opacity
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
DO RPC doesn't support WebSocket upgrade requests. Forward the request
via stub.fetch() and pass userId/channelId via custom headers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove useSignUpToStream from hooks/auth.ts and oauth-signin.tsx
- Fix useRef initial values in useChat.ts
- Remove unused destructured variables in chat.tsx
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Delete ChatProvider, ChannelPreview, CustomChannelHeader, hooks/channel.ts
- Replace TabloDiscussionSection with chatscope-based implementation using useChat
- Update tablo-details.tsx to use useChatUnread instead of useTabloDiscussionUnread
- Remove streamToken field from User type in UserStoreProvider
- Remove useSignUpToStream from shared auth hooks
- Remove stream-chat and stream-chat-react packages
- Remove stream-chat-react CSS import from main.tsx
- Clean up all streamToken references from test mocks and helpers
- Update chat.test.tsx and tablo-details.layout.test.tsx for new implementation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ensures the UpgradeBlockProvider waits for both user and organization
data before computing the block reason, preventing premature paywall
flash. Temporary users are never blocked.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
useUser() throws when the store is null (before user data is fetched).
Switch to useMaybeUser() which safely returns null.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
On mobile, the sidebar was 192px wide (w-48) and could appear collapsed (icons-only)
depending on prior desktop state. This introduces effectivelyCollapsed to always force
expanded mode when the mobile overlay is open, and uses a narrower w-40 (160px) width
to reduce screen coverage on small devices like iPhone SE (375px).
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Add flex-wrap to the member action row (date + remove button) and the
header badge/language selector row so they wrap gracefully on narrow
screens without affecting desktop layout.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Cloudflare serves static assets before the worker runs, so the icon
redirect logic was never reached. Renamed the default icon files to
default-* prefix. The worker now handles all requests for the original
icon paths: redirects to org-specific icons when cookie is set, or to
the renamed defaults otherwise.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
iOS uses the apple-touch-icon link tag for the home screen icon, not
the manifest. The worker now intercepts requests for apple-touch-icon
and favicon PNGs, redirecting to the org-specific version from R2
when the x-org-id cookie is set.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Icons are stored in the web-assets R2 bucket which is already served
via assets.xtablo.com, same as user avatars. No need to proxy through
the API endpoint.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>