d3b708636f
Switches the ConversationPage chat list from a full O(N) render to windowed rendering via react-virtuoso. On long histories only the visible rows (plus a 400px overscan buffer) live in the DOM, ending the scroll jank and layout thrashing that hit conversations with >500 messages. Preserved behaviors: - Newest message visible on open via initialTopMostItemIndex. - Auto-scroll on send via a pending-count-based effect (the old setStickToBottom + useLayoutEffect pattern doesn't apply now that Virtuoso owns the scroll element). - Realtime auto-follow only when scrolled to bottom (followOutput). - 'New messages while away' counter + 'jump to newest' pill via atBottomStateChange. - Pinned-message / reply / search jumps via virtuosoRef.scrollToIndex; expands displayCount on the fly if the target is outside the rendered slice. Flash highlight unchanged. - Load-older infinite scroll via Virtuoso startReached (replaces the IntersectionObserver-on-sentinel pattern). - Per-conversation position memory now keys on row index instead of pixel scrollTop (the latter isn't meaningful under virtualization). Also wires the PinnedMessagesPanel onJump callback (previously a TODO that just closed the panel) into jumpToMessage, since virtualization made the smooth-scroll-from-pinned UX easy to deliver as a side benefit.
@chat-app/desktop
Tauri v2 + React + Vite + Tailwind desktop client (macOS / Windows / Linux).
Prerequisites
- Node 22+, pnpm 9+
- Rust + Cargo (install via https://rustup.rs)
- Platform build deps:
- macOS: Xcode Command Line Tools
- Linux:
libwebkit2gtk-4.1-dev,build-essential,libssl-dev(Debian/Ubuntu) - Windows: Microsoft C++ Build Tools + WebView2
Dev
# from repo root
pnpm install
pnpm desktop:dev # tauri dev — launches Vite + native window
pnpm desktop:build # production bundle per platform
Layout
src/— React app (Vite bundles intodist/).src-tauri/— Rust backend.main.rswires Tauri plugins.vite.config.ts— port1420, HMR on1421, aliases to shared packages.
Secure Storage
Session tokens + user private keys live in Stronghold (tauri-plugin-stronghold).
Local message history lives in SQLite (tauri-plugin-sql), DB file encrypted at rest.