Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions components/chat-panel.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'

import { useEffect, useState, useRef, ChangeEvent } from 'react'
import { useEffect, useState, useRef, ChangeEvent, forwardRef, useImperativeHandle } from 'react'
import type { AI, UIState } from '@/app/actions'
import { useUIState, useActions } from 'ai/rsc'
// Removed import of useGeospatialToolMcp as it's no longer used/available
Expand All @@ -17,7 +17,11 @@ interface ChatPanelProps {
setInput: (value: string) => void
}

export function ChatPanel({ messages, input, setInput }: ChatPanelProps) {
export interface ChatPanelRef {
handleAttachmentClick: () => void;
}

export const ChatPanel = forwardRef<ChatPanelRef, ChatPanelProps>(({ messages, input, setInput }, ref) => {
const [, setMessages] = useUIState<typeof AI>()
const { submit, clearChat } = useActions()
// Removed mcp instance as it's no longer passed to submit
Expand All @@ -27,6 +31,12 @@ export function ChatPanel({ messages, input, setInput }: ChatPanelProps) {
const formRef = useRef<HTMLFormElement>(null)
const fileInputRef = useRef<HTMLInputElement>(null)

useImperativeHandle(ref, () => ({
handleAttachmentClick() {
fileInputRef.current?.click()
}
}));
Comment on lines +34 to +38
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider refactoring to eliminate code duplication.

The imperative handle directly calls fileInputRef.current?.click(), duplicating the logic in the internal handleAttachmentClick function (lines 61-63). Consider having the imperative handle call the internal function instead for better maintainability.

Apply this diff:

 useImperativeHandle(ref, () => ({
   handleAttachmentClick() {
-    fileInputRef.current?.click()
+    handleAttachmentClick()
   }
 }));

Note: This change requires moving the internal handleAttachmentClick function definition before the useImperativeHandle call to avoid referencing it before declaration.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In components/chat-panel.tsx around lines 34 to 38, the useImperativeHandle
implementation duplicates the attachment-click logic by directly calling
fileInputRef.current?.click(); move the internal handleAttachmentClick function
(currently at lines ~61-63) above the useImperativeHandle call so it is declared
before use, then change the imperative handle to call that internal function
(e.g., handleAttachmentClick()) instead of duplicating the click logic to
eliminate redundancy and improve maintainability.


// Detect mobile layout
useEffect(() => {
const checkMobile = () => {
Expand Down Expand Up @@ -243,4 +253,5 @@ export function ChatPanel({ messages, input, setInput }: ChatPanelProps) {
</form>
</div>
)
}
})
ChatPanel.displayName = 'ChatPanel'
13 changes: 9 additions & 4 deletions components/chat.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
'use client'

import { useEffect, useState } from 'react'
import { useEffect, useState, useRef } from 'react'
import { usePathname, useRouter } from 'next/navigation'
import { ChatPanel } from './chat-panel'
import { ChatPanel, ChatPanelRef } from './chat-panel'
import { ChatMessages } from './chat-messages'
import { EmptyScreen } from './empty-screen'
import { Mapbox } from './map/mapbox-map'
Expand All @@ -26,6 +26,11 @@ export function Chat({ id }: ChatProps) {
const { activeView } = useProfileToggle();
const [input, setInput] = useState('')
const [showEmptyScreen, setShowEmptyScreen] = useState(false)
const chatPanelRef = useRef<ChatPanelRef>(null);

const handleAttachment = () => {
chatPanelRef.current?.handleAttachmentClick();
};

useEffect(() => {
setShowEmptyScreen(messages.length === 0)
Expand Down Expand Up @@ -80,10 +85,10 @@ export function Chat({ id }: ChatProps) {
{activeView ? <SettingsView /> : <Mapbox />}
</div>
<div className="mobile-icons-bar">
<MobileIconsBar />
<MobileIconsBar onAttachmentClick={handleAttachment} />
</div>
<div className="mobile-chat-input-area">
<ChatPanel messages={messages} input={input} setInput={setInput} />
<ChatPanel ref={chatPanelRef} messages={messages} input={input} setInput={setInput} />
</div>
<div className="mobile-chat-messages-area">
{showEmptyScreen ? (
Expand Down
8 changes: 6 additions & 2 deletions components/mobile-icons-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ import { History } from '@/components/history'
import { MapToggle } from './map-toggle'
import { ModeToggle } from './mode-toggle'

export const MobileIconsBar: React.FC = () => {
interface MobileIconsBarProps {
onAttachmentClick: () => void;
}

export const MobileIconsBar: React.FC<MobileIconsBarProps> = ({ onAttachmentClick }) => {
const [, setMessages] = useUIState<typeof AI>()
const { clearChat } = useActions()

Expand All @@ -45,7 +49,7 @@ export const MobileIconsBar: React.FC = () => {
<Button variant="ghost" size="icon">
<TentTree className="h-[1.2rem] w-[1.2rem] transition-all rotate-0 scale-100" />
</Button>
<Button variant="ghost" size="icon">
<Button variant="ghost" size="icon" onClick={onAttachmentClick}>
<Paperclip className="h-[1.2rem] w-[1.2rem] transition-all rotate-0 scale-100" />
</Button>
Comment on lines +52 to 54
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Icon-only buttons should provide an accessible name. The paperclip button currently lacks an aria-label, which makes it hard for screen readers to announce its purpose.

Suggestion

Add an accessible label to the button:

<Button variant="ghost" size="icon" onClick={onAttachmentClick} aria-label="Attach file">
  <Paperclip className="h-[1.2rem] w-[1.2rem] transition-all rotate-0 scale-100" />
</Button>

Alternatively, add visually hidden text via an sr-only span.

Reply with "@CharlieHelps yes please" if you'd like me to add a commit with this change.

<Button variant="ghost" size="icon">
Expand Down
7 changes: 7 additions & 0 deletions dev.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
⚠ Port 3000 is in use, using available port 3001 instead.
▲ Next.js 15.3.3 (Turbopack)
- Local: http://localhost:3001
- Network: http://192.168.0.2:3001
- Environments: .env.local, .env

✓ Starting...
Comment on lines +1 to +7
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Committing dev logs is a maintainability and hygiene issue. This file appears to contain local development diagnostics and should not be versioned. It risks repository noise and potential leakage of environment info. Please remove it and add it to .gitignore.

Suggestion

Remove dev.log from the repo and add it to .gitignore to prevent future commits. For example, add the following to your .gitignore:

# Local dev logs
/dev.log
*.log

Reply with "@CharlieHelps yes please" if you'd like me to add a commit with this suggestion