From 505caa9aff8d2911dd67232fc1b7a48f9f8a20c6 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 31 Oct 2024 21:02:05 +0530 Subject: [PATCH] Persist input text in local storage (#472) --- app/(chat)/layout.tsx | 2 + components/custom/multimodal-input.tsx | 25 +++++++- next.config.ts | 3 + package.json | 2 +- pnpm-lock.yaml | 86 +++++++++++++------------- 5 files changed, 73 insertions(+), 45 deletions(-) diff --git a/app/(chat)/layout.tsx b/app/(chat)/layout.tsx index eb6f8f9..46ff8aa 100644 --- a/app/(chat)/layout.tsx +++ b/app/(chat)/layout.tsx @@ -5,6 +5,8 @@ import { SidebarInset, SidebarProvider } from '@/components/ui/sidebar'; import { auth } from '../(auth)/auth'; +export const experimental_ppr = true; + export default async function Layout({ children, }: { diff --git a/components/custom/multimodal-input.tsx b/components/custom/multimodal-input.tsx index 1615ef8..5dc3481 100644 --- a/components/custom/multimodal-input.tsx +++ b/components/custom/multimodal-input.tsx @@ -13,6 +13,7 @@ import React, { ChangeEvent, } from 'react'; import { toast } from 'sonner'; +import { useLocalStorage } from 'usehooks-ts'; import { sanitizeUIMessages } from '@/lib/utils'; @@ -84,6 +85,27 @@ export function MultimodalInput({ } }; + const [localStorageInput, setLocalStorageInput] = useLocalStorage( + 'input', + '' + ); + + useEffect(() => { + if (textareaRef.current) { + const domValue = textareaRef.current.value; + // Prefer DOM value over localStorage to handle hydration + const finalValue = domValue || localStorageInput || ''; + setInput(finalValue); + adjustHeight(); + } + // Only run once after hydration + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useEffect(() => { + setLocalStorageInput(input); + }, [input, setLocalStorageInput]); + const handleInput = (event: React.ChangeEvent) => { setInput(event.target.value); adjustHeight(); @@ -98,11 +120,12 @@ export function MultimodalInput({ }); setAttachments([]); + setLocalStorageInput(''); if (width && width > 768) { textareaRef.current?.focus(); } - }, [attachments, handleSubmit, setAttachments, width]); + }, [attachments, handleSubmit, setAttachments, setLocalStorageInput, width]); const uploadFile = async (file: File) => { const formData = new FormData(); diff --git a/next.config.ts b/next.config.ts index 5bc3af2..b875b00 100644 --- a/next.config.ts +++ b/next.config.ts @@ -2,6 +2,9 @@ import type { NextConfig } from 'next'; const nextConfig: NextConfig = { /* config options here */ + experimental: { + ppr: true, + }, images: { remotePatterns: [ { diff --git a/package.json b/package.json index d40a009..9835e0d 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "framer-motion": "^11.3.19", "geist": "^1.3.1", "lucide-react": "^0.446.0", - "next": "15.0.1", + "next": "15.0.3-canary.2", "next-auth": "5.0.0-beta.25", "next-themes": "^0.3.0", "orderedmap": "^2.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 34dea21..415dd1f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,7 +40,7 @@ dependencies: version: 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@19.0.0-rc-45804af1-20241021)(react@19.0.0-rc-45804af1-20241021) '@vercel/analytics': specifier: ^1.3.1 - version: 1.3.2(next@15.0.1)(react@19.0.0-rc-45804af1-20241021) + version: 1.3.2(next@15.0.3-canary.2)(react@19.0.0-rc-45804af1-20241021) '@vercel/blob': specifier: ^0.24.1 version: 0.24.1 @@ -79,16 +79,16 @@ dependencies: version: 11.11.10(react-dom@19.0.0-rc-45804af1-20241021)(react@19.0.0-rc-45804af1-20241021) geist: specifier: ^1.3.1 - version: 1.3.1(next@15.0.1) + version: 1.3.1(next@15.0.3-canary.2) lucide-react: specifier: ^0.446.0 version: 0.446.0(react@19.0.0-rc-45804af1-20241021) next: - specifier: 15.0.1 - version: 15.0.1(react-dom@19.0.0-rc-45804af1-20241021)(react@19.0.0-rc-45804af1-20241021) + specifier: 15.0.3-canary.2 + version: 15.0.3-canary.2(react-dom@19.0.0-rc-45804af1-20241021)(react@19.0.0-rc-45804af1-20241021) next-auth: specifier: 5.0.0-beta.25 - version: 5.0.0-beta.25(next@15.0.1)(react@19.0.0-rc-45804af1-20241021) + version: 5.0.0-beta.25(next@15.0.3-canary.2)(react@19.0.0-rc-45804af1-20241021) next-themes: specifier: ^0.3.0 version: 0.3.0(react-dom@19.0.0-rc-45804af1-20241021)(react@19.0.0-rc-45804af1-20241021) @@ -1380,8 +1380,8 @@ packages: '@types/pg': 8.11.6 dev: false - /@next/env@15.0.1: - resolution: {integrity: sha512-lc4HeDUKO9gxxlM5G2knTRifqhsY6yYpwuHspBZdboZe0Gp+rZHBNNSIjmQKDJIdRXiXGyVnSD6gafrbQPvILQ==} + /@next/env@15.0.3-canary.2: + resolution: {integrity: sha512-+1Gbej9xUFJuXl8R0hQh7yGsfOOhf/U7CPpu9o980G5upph6iCPIVcn6GE4pnF7gK4mPn+paBMMtqjIl3XOdpA==} dev: false /@next/eslint-plugin-next@14.2.5: @@ -1390,8 +1390,8 @@ packages: glob: 10.3.10 dev: true - /@next/swc-darwin-arm64@15.0.1: - resolution: {integrity: sha512-C9k/Xv4sxkQRTA37Z6MzNq3Yb1BJMmSqjmwowoWEpbXTkAdfOwnoKOpAb71ItSzoA26yUTIo6ZhN8rKGu4ExQw==} + /@next/swc-darwin-arm64@15.0.3-canary.2: + resolution: {integrity: sha512-gB0z5Src6KZ6/JqWM/CL/6kJUD8SKanrBlrsNUfOj3ZzQlP7aov6K63P7zUIKXuB7QK0rwfgLuncUHKm+PWsuA==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -1399,8 +1399,8 @@ packages: dev: false optional: true - /@next/swc-darwin-x64@15.0.1: - resolution: {integrity: sha512-uHl13HXOuq1G7ovWFxCACDJHTSDVbn/sbLv8V1p+7KIvTrYQ5HNoSmKBdYeEKRRCbEmd+OohOgg9YOp8Ux3MBg==} + /@next/swc-darwin-x64@15.0.3-canary.2: + resolution: {integrity: sha512-R6xFPG7au0tMoXfCgxHTUAhKFAtbT3om2WaXA9QVDe9b2EkxPngPinmTTdEgMuv7R1AwitcpNhhOrn9U1vqTVQ==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -1408,8 +1408,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-gnu@15.0.1: - resolution: {integrity: sha512-LvyhvxHOihFTEIbb35KxOc3q8w8G4xAAAH/AQnsYDEnOvwawjL2eawsB59AX02ki6LJdgDaHoTEnC54Gw+82xw==} + /@next/swc-linux-arm64-gnu@15.0.3-canary.2: + resolution: {integrity: sha512-5fYl9TBVbUj/wXNiqjkz/WVmgVDYSi5L6KHQWRvK9UGlRAcbDLwKwBtBAm4PB4GgzPJ/aVHUdbXnEAQIP7g51A==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -1417,8 +1417,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-musl@15.0.1: - resolution: {integrity: sha512-vFmCGUFNyk/A5/BYcQNhAQqPIw01RJaK6dRO+ZEhz0DncoW+hJW1kZ8aH2UvTX27zPq3m85zN5waMSbZEmANcQ==} + /@next/swc-linux-arm64-musl@15.0.3-canary.2: + resolution: {integrity: sha512-n+gMZ6dtj0BD2y6dPzzy+8r5TIQPsYNzODfAw7nwor0kGp5Y6HJwrKmnDj3wDTEEh2107gq27T7g8BlcNXl0Nw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -1426,8 +1426,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-gnu@15.0.1: - resolution: {integrity: sha512-5by7IYq0NCF8rouz6Qg9T97jYU68kaClHPfGpQG2lCZpSYHtSPQF1kjnqBTd34RIqPKMbCa4DqCufirgr8HM5w==} + /@next/swc-linux-x64-gnu@15.0.3-canary.2: + resolution: {integrity: sha512-PEpD1RinW/+IK/zLilM8dhinLhZXduY0+PYN7V5lKDbzQs5y0yp4vneXAtEt5oHGoi7bWA2arlVO5e2AWqRpFA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -1435,8 +1435,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-musl@15.0.1: - resolution: {integrity: sha512-lmYr6H3JyDNBJLzklGXLfbehU3ay78a+b6UmBGlHls4xhDXBNZfgb0aI67sflrX+cGBnv1LgmWzFlYrAYxS1Qw==} + /@next/swc-linux-x64-musl@15.0.3-canary.2: + resolution: {integrity: sha512-bCGz+q00/mzA3K4Jsb/kzH5ivFrHgXpZY+zWxC9sgfxObhvl9bx/MlPdoYI4FwOGuQC+mbgLUOHpNvXSswbrjw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -1444,8 +1444,8 @@ packages: dev: false optional: true - /@next/swc-win32-arm64-msvc@15.0.1: - resolution: {integrity: sha512-DS8wQtl6diAj0eZTdH0sefykm4iXMbHT4MOvLwqZiIkeezKpkgPFcEdFlz3vKvXa2R/2UEgMh48z1nEpNhjeOQ==} + /@next/swc-win32-arm64-msvc@15.0.3-canary.2: + resolution: {integrity: sha512-W5MCeg0LVV3xxUoLt5fIV1d+M6LSLkp4vvg32ZTSkshf5lPvWG612U/8rWAoJacfYue8FaPTFOQ7Gg10E+Qhig==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -1453,8 +1453,8 @@ packages: dev: false optional: true - /@next/swc-win32-x64-msvc@15.0.1: - resolution: {integrity: sha512-4Ho2ggvDdMKlZ/0e9HNdZ9ngeaBwtc+2VS5oCeqrbXqOgutX6I4U2X/42VBw0o+M5evn4/7v3zKgGHo+9v/VjA==} + /@next/swc-win32-x64-msvc@15.0.3-canary.2: + resolution: {integrity: sha512-o1RAgC6m5wY0TpDIMTw+V1wQp9gOC/+WqKBWE0YslF9B9jg7Tj3+/cOcs4t6T/cvm1S8ILtD0qUCZqkWSDtcrQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -2373,7 +2373,7 @@ packages: /@ungap/structured-clone@1.2.0: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - /@vercel/analytics@1.3.2(next@15.0.1)(react@19.0.0-rc-45804af1-20241021): + /@vercel/analytics@1.3.2(next@15.0.3-canary.2)(react@19.0.0-rc-45804af1-20241021): resolution: {integrity: sha512-n/Ws7skBbW+fUBMeg+jrT30+GP00jTHvCcL4fuVrShuML0uveEV/4vVUdvqEVnDgXIGfLm0GXW5EID2mCcRXhg==} peerDependencies: next: '>= 13' @@ -2384,7 +2384,7 @@ packages: react: optional: true dependencies: - next: 15.0.1(react-dom@19.0.0-rc-45804af1-20241021)(react@19.0.0-rc-45804af1-20241021) + next: 15.0.3-canary.2(react-dom@19.0.0-rc-45804af1-20241021)(react@19.0.0-rc-45804af1-20241021) react: 19.0.0-rc-45804af1-20241021 server-only: 0.0.1 dev: false @@ -4019,12 +4019,12 @@ packages: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} dev: true - /geist@1.3.1(next@15.0.1): + /geist@1.3.1(next@15.0.3-canary.2): resolution: {integrity: sha512-Q4gC1pBVPN+D579pBaz0TRRnGA4p9UK6elDY/xizXdFk/g4EKR5g0I+4p/Kj6gM0SajDBZ/0FvDV9ey9ud7BWw==} peerDependencies: next: '>=13.2.0' dependencies: - next: 15.0.1(react-dom@19.0.0-rc-45804af1-20241021)(react@19.0.0-rc-45804af1-20241021) + next: 15.0.3-canary.2(react-dom@19.0.0-rc-45804af1-20241021)(react@19.0.0-rc-45804af1-20241021) dev: false /get-intrinsic@1.2.4: @@ -5188,7 +5188,7 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true - /next-auth@5.0.0-beta.25(next@15.0.1)(react@19.0.0-rc-45804af1-20241021): + /next-auth@5.0.0-beta.25(next@15.0.3-canary.2)(react@19.0.0-rc-45804af1-20241021): resolution: {integrity: sha512-2dJJw1sHQl2qxCrRk+KTQbeH+izFbGFPuJj5eGgBZFYyiYYtvlrBeUw1E/OJJxTRjuxbSYGnCTkUIRsIIW0bog==} peerDependencies: '@simplewebauthn/browser': ^9.0.1 @@ -5205,7 +5205,7 @@ packages: optional: true dependencies: '@auth/core': 0.37.2 - next: 15.0.1(react-dom@19.0.0-rc-45804af1-20241021)(react@19.0.0-rc-45804af1-20241021) + next: 15.0.3-canary.2(react-dom@19.0.0-rc-45804af1-20241021)(react@19.0.0-rc-45804af1-20241021) react: 19.0.0-rc-45804af1-20241021 dev: false @@ -5219,16 +5219,16 @@ packages: react-dom: 19.0.0-rc-45804af1-20241021(react@19.0.0-rc-45804af1-20241021) dev: false - /next@15.0.1(react-dom@19.0.0-rc-45804af1-20241021)(react@19.0.0-rc-45804af1-20241021): - resolution: {integrity: sha512-PSkFkr/w7UnFWm+EP8y/QpHrJXMqpZzAXpergB/EqLPOh4SGPJXv1wj4mslr2hUZBAS9pX7/9YLIdxTv6fwytw==} - engines: {node: '>=18.18.0'} + /next@15.0.3-canary.2(react-dom@19.0.0-rc-45804af1-20241021)(react@19.0.0-rc-45804af1-20241021): + resolution: {integrity: sha512-vGutHxoPrZuZNVxD/HZRRyOY1X2+StTlbwzJA2Ck4lGofVsccdQjDuc89WAmg9vFYXjHf+mYqi8WYcXM5SJymw==} + engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} hasBin: true peerDependencies: '@opentelemetry/api': ^1.1.0 '@playwright/test': ^1.41.2 babel-plugin-react-compiler: '*' - react: ^18.2.0 || 19.0.0-rc-69d4b800-20241021 - react-dom: ^18.2.0 || 19.0.0-rc-69d4b800-20241021 + react: ^18.2.0 || 19.0.0-rc-603e6108-20241029 + react-dom: ^18.2.0 || 19.0.0-rc-603e6108-20241029 sass: ^1.3.0 peerDependenciesMeta: '@opentelemetry/api': @@ -5240,7 +5240,7 @@ packages: sass: optional: true dependencies: - '@next/env': 15.0.1 + '@next/env': 15.0.3-canary.2 '@swc/counter': 0.1.3 '@swc/helpers': 0.5.13 busboy: 1.6.0 @@ -5250,14 +5250,14 @@ packages: react-dom: 19.0.0-rc-45804af1-20241021(react@19.0.0-rc-45804af1-20241021) styled-jsx: 5.1.6(react@19.0.0-rc-45804af1-20241021) optionalDependencies: - '@next/swc-darwin-arm64': 15.0.1 - '@next/swc-darwin-x64': 15.0.1 - '@next/swc-linux-arm64-gnu': 15.0.1 - '@next/swc-linux-arm64-musl': 15.0.1 - '@next/swc-linux-x64-gnu': 15.0.1 - '@next/swc-linux-x64-musl': 15.0.1 - '@next/swc-win32-arm64-msvc': 15.0.1 - '@next/swc-win32-x64-msvc': 15.0.1 + '@next/swc-darwin-arm64': 15.0.3-canary.2 + '@next/swc-darwin-x64': 15.0.3-canary.2 + '@next/swc-linux-arm64-gnu': 15.0.3-canary.2 + '@next/swc-linux-arm64-musl': 15.0.3-canary.2 + '@next/swc-linux-x64-gnu': 15.0.3-canary.2 + '@next/swc-linux-x64-musl': 15.0.3-canary.2 + '@next/swc-win32-arm64-msvc': 15.0.3-canary.2 + '@next/swc-win32-x64-msvc': 15.0.3-canary.2 sharp: 0.33.5 transitivePeerDependencies: - '@babel/core'