-
-
Notifications
You must be signed in to change notification settings - Fork 7
fix(chat): Remove isButtonPressed state from ChatPanel #278
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| DATABASE_URL="postgresql://user:password@host:port/db" | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -248,6 +248,17 @@ async function submit(formData?: FormData, skip?: boolean) { | |||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| async function clearChat() { | ||||||||||||||||||||||||||||||||||||||||||||||
| 'use server' | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const aiState = getMutableAIState<typeof AI>() | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| aiState.done({ | ||||||||||||||||||||||||||||||||||||||||||||||
| chatId: nanoid(), | ||||||||||||||||||||||||||||||||||||||||||||||
| messages: [] | ||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+251
to
+260
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Return new chatId and preserve other AI state on clear. Return the generated chatId so clients can sync the URL, and keep other fields (e.g., isSharePage). -async function clearChat() {
- 'use server'
-
- const aiState = getMutableAIState<typeof AI>()
-
- aiState.done({
- chatId: nanoid(),
- messages: []
- })
-}
+async function clearChat() {
+ 'use server'
+ const aiState = getMutableAIState<typeof AI>()
+ const prev = aiState.get()
+ const newChatId = nanoid()
+ aiState.done({
+ ...prev,
+ chatId: newChatId,
+ messages: []
+ })
+ return { chatId: newChatId }
+}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| export type AIState = { | ||||||||||||||||||||||||||||||||||||||||||||||
| messages: AIMessage[]; | ||||||||||||||||||||||||||||||||||||||||||||||
| chatId: string; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -272,6 +283,7 @@ const initialUIState: UIState = []; | |||||||||||||||||||||||||||||||||||||||||||||
| export const AI = createAI<AIState, UIState>({ | ||||||||||||||||||||||||||||||||||||||||||||||
| actions: { | ||||||||||||||||||||||||||||||||||||||||||||||
| submit, | ||||||||||||||||||||||||||||||||||||||||||||||
| clearChat, | ||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+286
to
287
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Expose typed actions to clients expecting clearChat result. After returning 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||
| initialUIState, | ||||||||||||||||||||||||||||||||||||||||||||||
| initialAIState, | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,6 @@ | ||
| 'use client' | ||
|
|
||
| import { useEffect, useState, useRef } from 'react' | ||
| import { useRouter } from 'next/navigation' | ||
| import type { AI, UIState } from '@/app/actions' | ||
| import { useUIState, useActions } from 'ai/rsc' | ||
| // Removed import of useGeospatialToolMcp as it's no longer used/available | ||
|
|
@@ -20,13 +19,11 @@ interface ChatPanelProps { | |
|
|
||
| export function ChatPanel({ messages, input, setInput }: ChatPanelProps) { | ||
| const [, setMessages] = useUIState<typeof AI>() | ||
| const { submit } = useActions() | ||
| const { submit, clearChat } = useActions() | ||
| // Removed mcp instance as it's no longer passed to submit | ||
| const [isButtonPressed, setIsButtonPressed] = useState(false) | ||
| const [isMobile, setIsMobile] = useState(false) | ||
| const inputRef = useRef<HTMLTextAreaElement>(null) | ||
| const formRef = useRef<HTMLFormElement>(null) | ||
| const router = useRouter() | ||
|
|
||
| // Detect mobile layout | ||
| useEffect(() => { | ||
|
|
@@ -38,19 +35,8 @@ export function ChatPanel({ messages, input, setInput }: ChatPanelProps) { | |
| return () => window.removeEventListener('resize', checkMobile) | ||
| }, []) | ||
|
|
||
| useEffect(() => { | ||
| if (isButtonPressed) { | ||
| inputRef.current?.focus() | ||
| setIsButtonPressed(false) | ||
| } | ||
| }, [isButtonPressed]) | ||
|
|
||
| const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => { | ||
| e.preventDefault() | ||
| if (isButtonPressed) { | ||
| handleClear() | ||
| setIsButtonPressed(false) | ||
| } | ||
| setMessages(currentMessages => [ | ||
| ...currentMessages, | ||
| { | ||
|
|
@@ -64,16 +50,17 @@ export function ChatPanel({ messages, input, setInput }: ChatPanelProps) { | |
| setMessages(currentMessages => [...currentMessages, responseMessage as any]) | ||
| } | ||
|
|
||
| const handleClear = () => { | ||
| router.push('/') | ||
| const handleClear = async () => { | ||
| setMessages([]) | ||
| await clearChat() | ||
| } | ||
|
Comment on lines
+53
to
56
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Consider URL-and-state alignment after “New” on desktop.
Also applies to: 63-83 🤖 Prompt for AI Agents |
||
|
|
||
| useEffect(() => { | ||
| inputRef.current?.focus(); | ||
| }, []) | ||
|
|
||
| // New chat button (appears when there are messages) | ||
| if (messages.length > 0 && !isButtonPressed && !isMobile) { | ||
| if (messages.length > 0 && !isMobile) { | ||
| return ( | ||
| <div | ||
| className={cn( | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,7 +1,8 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'use client' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import React from 'react' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useRouter } from 'next/navigation' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useUIState, useActions } from 'ai/rsc' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { AI } from '@/app/actions' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Button } from '@/components/ui/button' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Search, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -18,10 +19,12 @@ import { MapToggle } from './map-toggle' | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ModeToggle } from './mode-toggle' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const MobileIconsBar: React.FC = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const router = useRouter() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [, setMessages] = useUIState<typeof AI>() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { clearChat } = useActions() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const handleNewChat = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| router.push('/') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const handleNewChat = async () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setMessages([]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await clearChat() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+25
to
28
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) 🛠️ Refactor suggestion Guard against double taps; optionally update route after clear. Add a pending flag to prevent repeated clears, and (once clearChat returns the new chatId) replace the URL so it matches the fresh chat. export const MobileIconsBar: React.FC = () => {
- const [, setMessages] = useUIState<typeof AI>()
- const { clearChat } = useActions<typeof AI>()
+ const [, setMessages] = useUIState<typeof AI>()
+ const { clearChat } = useActions<typeof AI>()
+ const [isClearing, setIsClearing] = React.useState(false)
- const handleNewChat = async () => {
- setMessages([])
- await clearChat()
+ const handleNewChat = async () => {
+ if (isClearing) return
+ setIsClearing(true)
+ try {
+ setMessages([])
+ const result = await clearChat() // expect { chatId }
+ if (result?.chatId && window.location.pathname.startsWith('/search/')) {
+ window.history.replaceState({}, '', `/search/${result.chatId}`)
+ }
+ } finally {
+ setIsClearing(false)
+ }
}And disable the button while clearing: - <Button variant="ghost" size="icon" onClick={handleNewChat}>
+ <Button variant="ghost" size="icon" onClick={handleNewChat} disabled={isClearing}>
<Plus className="h-[1.2rem] w-[1.2rem]" />
</Button>📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
🛠️ Refactor suggestion
Do not commit .env; move to .env.example and drop quotes.
Committing environment files is risky. Replace this with an example file and ensure .env is gitignored. Also fix the dotenv-linter warning by removing quotes.
Apply:
Also:
🧰 Tools
🪛 dotenv-linter (3.3.0)
[warning] 1-1: [QuoteCharacter] The value has quote characters (', ")
(QuoteCharacter)
🤖 Prompt for AI Agents