From f23482db2f2ebfc5982d68d087f490c0432433f3 Mon Sep 17 00:00:00 2001 From: vgcman16 <155417613+vgcman16@users.noreply.github.com> Date: Thu, 5 Jun 2025 19:07:41 -0500 Subject: [PATCH] fix: address lint issues and type errors --- app/components/chat/BaseChat.tsx | 11 ++++++++--- app/components/workbench/FileTree.tsx | 6 +++--- app/lib/hooks/usePromptEnhancer.ts | 1 + app/lib/persistence/targetedFiles.ts | 21 ++++++++++++++++++++- app/lib/stores/files.ts | 9 ++++----- app/routes/figma.tsx | 5 +---- app/utils/figmaImport.ts | 19 ++++++++++--------- app/utils/fileExtract.ts | 6 ++++-- app/utils/fileUtils.ts | 5 +---- 9 files changed, 52 insertions(+), 31 deletions(-) diff --git a/app/components/chat/BaseChat.tsx b/app/components/chat/BaseChat.tsx index 05f7bd8d..07e98068 100644 --- a/app/components/chat/BaseChat.tsx +++ b/app/components/chat/BaseChat.tsx @@ -288,8 +288,7 @@ export const BaseChat = React.forwardRef( const handleFileUpload = () => { const input = document.createElement('input'); input.type = 'file'; - input.accept = - 'image/*,.pdf,.docx,.txt,.md,.js,.ts,.tsx,.html,.css,.json'; + input.accept = 'image/*,.pdf,.docx,.txt,.md,.js,.ts,.tsx,.html,.css,.json'; input.onchange = async (e) => { const file = (e.target as HTMLInputElement).files?.[0]; @@ -297,6 +296,7 @@ export const BaseChat = React.forwardRef( if (file) { if (file.type.startsWith('image/')) { const reader = new FileReader(); + reader.onload = (ev) => { const base64Image = ev.target?.result as string; setUploadedFiles?.([...uploadedFiles, file]); @@ -326,11 +326,16 @@ export const BaseChat = React.forwardRef( for (const item of items) { if (item.kind === 'file') { const file = item.getAsFile(); - if (!file) continue; + + if (!file) { + continue; + } + e.preventDefault(); if (file.type.startsWith('image/')) { const reader = new FileReader(); + reader.onload = (ev) => { const base64Image = ev.target?.result as string; setUploadedFiles?.([...uploadedFiles, file]); diff --git a/app/components/workbench/FileTree.tsx b/app/components/workbench/FileTree.tsx index bcf8415f..fd1d7217 100644 --- a/app/components/workbench/FileTree.tsx +++ b/app/components/workbench/FileTree.tsx @@ -449,6 +449,7 @@ function FileContextMenu({ } const success = workbenchStore.targetFile(fullPath); + if (success) { toast.success(`File targeted`); } @@ -465,6 +466,7 @@ function FileContextMenu({ } const success = workbenchStore.unTargetFile(fullPath); + if (success) { toast.success(`File un-targeted`); } @@ -761,9 +763,7 @@ function File({ title={'File is locked'} /> )} - {isTargeted && ( - - )} + {isTargeted && } {unsavedChanges && } diff --git a/app/lib/hooks/usePromptEnhancer.ts b/app/lib/hooks/usePromptEnhancer.ts index eddb03c5..1c861b6a 100644 --- a/app/lib/hooks/usePromptEnhancer.ts +++ b/app/lib/hooks/usePromptEnhancer.ts @@ -47,6 +47,7 @@ export function usePromptEnhancer() { const decoder = new TextDecoder(); _input = ''; + let _error; try { diff --git a/app/lib/persistence/targetedFiles.ts b/app/lib/persistence/targetedFiles.ts index a0602351..c9f716db 100644 --- a/app/lib/persistence/targetedFiles.ts +++ b/app/lib/persistence/targetedFiles.ts @@ -12,6 +12,7 @@ function getChatSet(chatId: string, create = false): Set | undefined { if (create && !targetedFilesMap.has(chatId)) { targetedFilesMap.set(chatId, new Set()); } + return targetedFilesMap.get(chatId); } @@ -19,17 +20,22 @@ function initializeCache(): TargetedFile[] { if (targetedFilesCache !== null) { return targetedFilesCache; } + try { if (typeof localStorage !== 'undefined') { const json = localStorage.getItem(TARGETED_FILES_KEY); + if (json) { const items = JSON.parse(json) as TargetedFile[]; targetedFilesCache = items; rebuildLookup(items); + return items; } } + targetedFilesCache = []; + return []; } catch { targetedFilesCache = []; @@ -39,12 +45,15 @@ function initializeCache(): TargetedFile[] { function rebuildLookup(items: TargetedFile[]): void { targetedFilesMap.clear(); + for (const item of items) { let set = targetedFilesMap.get(item.chatId); + if (!set) { set = new Set(); targetedFilesMap.set(item.chatId, set); } + set.add(item.path); } } @@ -52,6 +61,7 @@ function rebuildLookup(items: TargetedFile[]): void { export function saveTargetedFiles(items: TargetedFile[]): void { targetedFilesCache = [...items]; rebuildLookup(items); + try { if (typeof localStorage !== 'undefined') { localStorage.setItem(TARGETED_FILES_KEY, JSON.stringify(items)); @@ -67,6 +77,7 @@ export function addTargetedFile(chatId: string, path: string): void { const files = getTargetedFiles(); const set = getChatSet(chatId, true)!; set.add(path); + const filtered = files.filter((f) => !(f.chatId === chatId && f.path === path)); filtered.push({ chatId, path }); saveTargetedFiles(filtered); @@ -75,20 +86,28 @@ export function addTargetedFile(chatId: string, path: string): void { export function removeTargetedFile(chatId: string, path: string): void { const files = getTargetedFiles(); const set = getChatSet(chatId); - if (set) set.delete(path); + + if (set) { + set.delete(path); + } + const filtered = files.filter((f) => !(f.chatId === chatId && f.path === path)); saveTargetedFiles(filtered); } export function isFileTargeted(chatId: string, path: string): boolean { initializeCache(); + const set = getChatSet(chatId); + return set ? set.has(path) : false; } export function getTargetedFilesForChat(chatId: string): string[] { initializeCache(); + const set = getChatSet(chatId); + return set ? Array.from(set) : []; } diff --git a/app/lib/stores/files.ts b/app/lib/stores/files.ts index 8097df4b..b5a9614f 100644 --- a/app/lib/stores/files.ts +++ b/app/lib/stores/files.ts @@ -20,11 +20,7 @@ import { migrateLegacyLocks, clearCache, } from '~/lib/persistence/lockedFiles'; -import { - getTargetedFilesForChat, - addTargetedFile, - removeTargetedFile, -} from '~/lib/persistence/targetedFiles'; +import { getTargetedFilesForChat, addTargetedFile, removeTargetedFile } from '~/lib/persistence/targetedFiles'; import { getCurrentChatId } from '~/utils/fileLocks'; const logger = createScopedLogger('FilesStore'); @@ -101,6 +97,7 @@ export class FilesStore { // Load locked files from localStorage this.#loadLockedFiles(); + // Load targeted files from localStorage this.#loadTargetedFiles(); @@ -377,6 +374,7 @@ export class FilesStore { this.files.setKey(filePath, { ...file, isTargeted: true }); addTargetedFile(currentChatId, filePath); + return true; } @@ -394,6 +392,7 @@ export class FilesStore { this.files.setKey(filePath, { ...file, isTargeted: false }); removeTargetedFile(currentChatId, filePath); + return true; } diff --git a/app/routes/figma.tsx b/app/routes/figma.tsx index bcf9105d..48dcbd02 100644 --- a/app/routes/figma.tsx +++ b/app/routes/figma.tsx @@ -7,10 +7,7 @@ import { Header } from '~/components/header/Header'; import BackgroundRays from '~/components/ui/BackgroundRays'; export const meta: MetaFunction = () => { - return [ - { title: 'Bolt' }, - { name: 'description', content: 'Talk with Bolt, an AI assistant from StackBlitz' }, - ]; + return [{ title: 'Bolt' }, { name: 'description', content: 'Talk with Bolt, an AI assistant from StackBlitz' }]; }; export async function loader(args: LoaderFunctionArgs) { diff --git a/app/utils/figmaImport.ts b/app/utils/figmaImport.ts index d7c79d19..dcedd5ec 100644 --- a/app/utils/figmaImport.ts +++ b/app/utils/figmaImport.ts @@ -8,9 +8,11 @@ import { escapeBoltTags } from './projectCommands'; */ function extractFileKey(url: string): string { const match = url.match(/file\/(\w+)/); + if (!match) { throw new Error('Invalid Figma URL'); } + return match[1]; } @@ -26,8 +28,9 @@ function collectFrames(node: any, frames: any[]) { if (node.type === 'FRAME') { frames.push(node); } + if (Array.isArray(node.children)) { - node.children.forEach((child) => collectFrames(child, frames)); + node.children.forEach((child: any) => collectFrames(child, frames)); } } @@ -35,6 +38,7 @@ function figmaFramesToComponents(frames: any[]): GeneratedComponent[] { return frames.map((frame) => { const name = frame.name.replace(/[^a-zA-Z0-9]/g, '') || 'Component'; const code = `export function ${name}() {\n return
${frame.name}
;\n}`; + return { name, code }; }); } @@ -42,10 +46,7 @@ function figmaFramesToComponents(frames: any[]): GeneratedComponent[] { /** * Create chat messages from a Figma design */ -export async function createChatFromFigma( - figmaUrl: string, - token: string, -): Promise { +export async function createChatFromFigma(figmaUrl: string, token: string): Promise { const fileKey = extractFileKey(figmaUrl); const res = await fetch(`https://api.figma.com/v1/files/${fileKey}`, { headers: { 'X-Figma-Token': token }, @@ -55,14 +56,14 @@ export async function createChatFromFigma( throw new Error(`Failed to fetch Figma file: ${res.status}`); } - const data = await res.json(); + const data = (await res.json()) as { document: unknown }; const frames: any[] = []; - collectFrames(data.document, frames); + collectFrames((data as any).document, frames); + const components = figmaFramesToComponents(frames); const componentActions = components .map( - (c) => - `${escapeBoltTags(c.code)}`, + (c) => `${escapeBoltTags(c.code)}`, ) .join('\n'); diff --git a/app/utils/fileExtract.ts b/app/utils/fileExtract.ts index c71c4706..0c8fd736 100644 --- a/app/utils/fileExtract.ts +++ b/app/utils/fileExtract.ts @@ -9,21 +9,23 @@ export async function extractTextFromFile(file: File): Promise { const arrayBuffer = await file.arrayBuffer(); const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise; const texts: string[] = []; + for (let i = 1; i <= pdf.numPages; i++) { const page = await pdf.getPage(i); const content = await page.getTextContent(); texts.push(content.items.map((item: any) => item.str).join(' ')); } + return texts.join('\n'); } if ( - file.type === - 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' || + file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' || file.name.toLowerCase().endsWith('.docx') ) { const arrayBuffer = await file.arrayBuffer(); const result = await mammoth.extractRawText({ arrayBuffer }); + return result.value; } diff --git a/app/utils/fileUtils.ts b/app/utils/fileUtils.ts index 331e95c4..c1d2ced5 100644 --- a/app/utils/fileUtils.ts +++ b/app/utils/fileUtils.ts @@ -120,10 +120,7 @@ ${files[filePath].content} `; }; -export const uploadedFilesToArtifacts = ( - files: { [path: string]: string }, - id: string, -): string => { +export const uploadedFilesToArtifacts = (files: { [path: string]: string }, id: string): string => { return ` ${Object.keys(files)