Skip to content

Commit 8e28057

Browse files
committed
fix: address code review - deduplicate extensions, preserve files through login gate
- Export SUPPORTED_EXTENSIONS from file-parser.ts as single source of truth - Parse files before login gate check so file content is preserved in pending debate config - Guard drag-and-drop on homepage during file parsing
1 parent 9f6f428 commit 8e28057

3 files changed

Lines changed: 54 additions & 50 deletions

File tree

src/app/page.tsx

Lines changed: 51 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { useSession, signIn, signOut } from "next-auth/react"
1212
import { shouldShowLoginGate, savePendingDebate } from "@/components/LoginGate"
1313
import LoginGateModal from "@/components/LoginGate"
1414
import { timeAgo } from "@/lib/time"
15-
import { parseFile } from "@/lib/file-parser"
15+
import { parseFile, SUPPORTED_EXTENSIONS } from "@/lib/file-parser"
1616

1717
/* ─── Model SVG Icons ─── */
1818

@@ -61,8 +61,6 @@ const MODELS: { id: Provider; color: string; icon: React.ElementType }[] = [
6161
{ id: "gpt", color: "#10B981", icon: GPTIcon },
6262
]
6363

64-
const SUPPORTED_EXTENSIONS = new Set(["pdf", "docx", "xlsx", "xls", "txt", "md", "csv"])
65-
6664
/* ─── Translations ─── */
6765

6866
type Tooltips = typeof t["en"]["tooltips"]
@@ -321,55 +319,61 @@ export default function Home() {
321319
return () => clearTimeout(timer)
322320
}, [fileError])
323321

322+
const buildPromptWithFiles = async (): Promise<string | null> => {
323+
let messageText = prompt.trim()
324+
325+
if (files.length > 0) {
326+
const results = await Promise.allSettled(
327+
files.map(async (af) => {
328+
const content = await parseFile(af.file)
329+
if (content && !content.startsWith("[Unsupported")) {
330+
return `--- File: ${af.file.name} ---\n${content}`
331+
}
332+
return null
333+
})
334+
)
335+
336+
const fileContents = results
337+
.map((r, i) => {
338+
if (r.status === "fulfilled" && r.value) return r.value
339+
if (r.status === "rejected") {
340+
console.error(`Failed to parse ${files[i].file.name}:`, r.reason)
341+
return `--- File: ${files[i].file.name} ---\n[Error: Could not read file]`
342+
}
343+
return null
344+
})
345+
.filter(Boolean) as string[]
346+
347+
if (fileContents.length > 0) {
348+
messageText = messageText
349+
? `${messageText}\n\n${fileContents.join("\n\n")}`
350+
: fileContents.join("\n\n")
351+
}
352+
}
353+
354+
return messageText || null
355+
}
356+
324357
const handleSubmit = async () => {
325358
if (isParsing || (!prompt.trim() && files.length === 0)) return
326-
if (shouldShowLoginGate(!!session?.user)) {
327-
savePendingDebate({
328-
prompt: prompt.trim(),
329-
models: selectedModels,
330-
responseLength,
331-
rounds,
332-
locale,
333-
})
334-
setShowGate(true)
335-
return
336-
}
337359

338360
setIsParsing(true)
339361
try {
340-
let messageText = prompt.trim()
341-
342-
if (files.length > 0) {
343-
const results = await Promise.allSettled(
344-
files.map(async (af) => {
345-
const content = await parseFile(af.file)
346-
if (content && !content.startsWith("[Unsupported")) {
347-
return `--- File: ${af.file.name} ---\n${content}`
348-
}
349-
return null
350-
})
351-
)
352-
353-
const fileContents = results
354-
.map((r, i) => {
355-
if (r.status === "fulfilled" && r.value) return r.value
356-
if (r.status === "rejected") {
357-
console.error(`Failed to parse ${files[i].file.name}:`, r.reason)
358-
return `--- File: ${files[i].file.name} ---\n[Error: Could not read file]`
359-
}
360-
return null
361-
})
362-
.filter(Boolean) as string[]
363-
364-
if (fileContents.length > 0) {
365-
messageText = messageText
366-
? `${messageText}\n\n${fileContents.join("\n\n")}`
367-
: fileContents.join("\n\n")
368-
}
369-
}
370-
362+
const messageText = await buildPromptWithFiles()
371363
if (!messageText) return
372364

365+
if (shouldShowLoginGate(!!session?.user)) {
366+
savePendingDebate({
367+
prompt: messageText,
368+
models: selectedModels,
369+
responseLength,
370+
rounds,
371+
locale,
372+
})
373+
setShowGate(true)
374+
return
375+
}
376+
373377
const config = {
374378
prompt: messageText,
375379
models: selectedModels,
@@ -563,12 +567,12 @@ export default function Home() {
563567
{/* Textarea */}
564568
<motion.div
565569
className={`relative group rounded-3xl p-[2px] overflow-hidden -mx-4 sm:-mx-6 ${isDragging ? "ring-4 ring-purple-500" : ""}`}
566-
onDragOver={(e) => { e.preventDefault(); setIsDragging(true) }}
570+
onDragOver={(e) => { e.preventDefault(); if (!isParsing) setIsDragging(true) }}
567571
onDragLeave={(e) => { e.preventDefault(); setIsDragging(false) }}
568572
onDrop={(e) => {
569573
e.preventDefault()
570574
setIsDragging(false)
571-
if (e.dataTransfer.files) addFiles(Array.from(e.dataTransfer.files))
575+
if (!isParsing && e.dataTransfer.files) addFiles(Array.from(e.dataTransfer.files))
572576
}}
573577
initial={false}
574578
animate={{ scale: isFocused ? 1.02 : 1 }}

src/components/MessageInput.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ import { motion, AnimatePresence } from "framer-motion"
55
import { Provider, Locale } from "@/types"
66
import { Send, Square, Paperclip, X, FileText, File, Loader2 } from "lucide-react"
77
import { cn } from "@/lib/utils"
8-
import { parseFile } from "@/lib/file-parser"
9-
10-
const SUPPORTED_EXTENSIONS = new Set(["pdf", "docx", "xlsx", "xls", "txt", "md", "csv"])
8+
import { parseFile, SUPPORTED_EXTENSIONS } from "@/lib/file-parser"
119

1210
const translations = {
1311
en: { placeholder: "Type your message...", send: "Send", stop: "Stop", attach: "Attach file", parsing: "Reading files...", unsupported: "Supported: PDF, DOCX, Excel, and text files" },

src/lib/file-parser.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
const MAX_FILE_CHARS = 50000
77

8+
export const SUPPORTED_EXTENSIONS = new Set(["pdf", "docx", "xlsx", "xls", "txt", "md", "csv"])
9+
810
export async function parseFile(file: File): Promise<string> {
911
const ext = file.name.split('.').pop()?.toLowerCase() ?? ''
1012

0 commit comments

Comments
 (0)