Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Upload files#1

Merged
wobiR99 merged 4 commits into
mainfrom
upload-files
Apr 28, 2026
Merged

Upload files#1
wobiR99 merged 4 commits into
mainfrom
upload-files

Conversation

@wobiR99
Copy link
Copy Markdown
Owner

@wobiR99 wobiR99 commented Apr 26, 2026

Summary by CodeRabbit

  • New Features

    • Added image upload interface with drag-and-drop, file preview, progress tracking and automatic navigation to a visualizer page after completion
    • Added a new visualizer page reachable via unique URL identifiers
  • Chores

    • Introduced centralized configuration for upload/render timing, limits, and UI parameters

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 26, 2026

Warning

Rate limit exceeded

@wobiR99 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 43 minutes and 33 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0b9e386d-a358-48cf-b9d4-01473433c39a

📥 Commits

Reviewing files that changed from the base of the PR and between 024ff5d and d205fb8.

📒 Files selected for processing (1)
  • components/Upload.tsx
📝 Walkthrough

Walkthrough

Introduces an upload-driven visualization flow: a new Upload component handles image selection, progress, and base64 output; Home routes completed uploads to a new dynamic /visualizer/:id route; application constants added for configuration and rendering.

Changes

Cohort / File(s) Summary
Route Configuration
app/routes.ts, app/routes/visualizer.$id.tsx
Added route("visualizer/:id", "./routes/visualizer.$id.tsx") to exported RouteConfig; scaffolded Visualizer route component.
Home Integration
app/routes/home.tsx
Replaced placeholder with Upload usage; adds useNavigate() and an onComplete that generates a timestamp ID and navigates to /visualizer/:id.
Upload Component
components/Upload.tsx
New Upload component: drag-and-drop and file input, base64 DataURL conversion, progress interval, redirect delay, signed-in gating, and cleanup on unmount.
Constants
lib/constants.ts
New centralized constants: worker URL, storage paths, timing/progress values, grid/ui values, auth statuses, image/render limits, allowed types, and ROOMIFY_RENDER_PROMPT template.

Sequence Diagram

sequenceDiagram
    actor User
    participant Home as Home Route
    participant Upload as Upload Component
    participant Visualizer as Visualizer Route

    User->>Home: Open home page
    Home->>Upload: Render with onComplete callback
    User->>Upload: Selects or drops image
    activate Upload
    Upload->>Upload: Read file -> base64
    Upload->>Upload: Increment progress until 100%
    Upload->>Home: Call onComplete(base64)
    deactivate Upload
    Home->>Home: Create timestamp ID
    Home->>Visualizer: Navigate to /visualizer/:id
    User->>Visualizer: View visualizer page
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐇 I nibble bytes and spin a loop,
Drop a plan, I hum and swoop—
Bars climb high, then off we dart,
To a viz that springs from heart. ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Upload files' is vague and generic, using a broad term that doesn't clearly convey the specific implementation changes in the changeset. Consider a more descriptive title that captures the main feature, such as 'Add visualizer route and file upload component' or 'Implement file upload with visualizer navigation flow'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch upload-files

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (7)
lib/constants.ts (3)

12-15: PROGRESS_INCREMENT vs PROGRESS_STEP — pick one.

Both look like the per-tick progress bump but with different values (15 vs 5). Upload.tsx only uses PROGRESS_STEP. Either rename one to clarify intent or remove the unused constant before more code starts importing the wrong one.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/constants.ts` around lines 12 - 15, There are two similar constants
PROGRESS_INCREMENT and PROGRESS_STEP—only PROGRESS_STEP is used by Upload.tsx—so
remove the unused PROGRESS_INCREMENT (or, if both are intended, rename one to
clarify distinct intent) and update any references; specifically, delete
PROGRESS_INCREMENT from lib/constants.ts (or rename it to a descriptive name if
used elsewhere) and ensure Upload.tsx continues to import and use PROGRESS_STEP
consistently.

4-8: Derive sub-paths from ROOT to avoid drift.

SOURCES and RENDERS repeat the literal "roomify". If ROOT ever changes, the others must be updated in lock-step.

♻️ Proposed refactor
-export const STORAGE_PATHS = {
-  ROOT: "roomify",
-  SOURCES: "roomify/sources",
-  RENDERS: "roomify/renders",
-} as const;
+const STORAGE_ROOT = "roomify";
+export const STORAGE_PATHS = {
+  ROOT: STORAGE_ROOT,
+  SOURCES: `${STORAGE_ROOT}/sources`,
+  RENDERS: `${STORAGE_ROOT}/renders`,
+} as const;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/constants.ts` around lines 4 - 8, STORAGE_PATHS repeats the literal
"roomify" causing drift; change SOURCES and RENDERS to derive from
STORAGE_PATHS.ROOT (i.e., set SOURCES to `${STORAGE_PATHS.ROOT}/sources` and
RENDERS to `${STORAGE_PATHS.ROOT}/renders`) so they automatically reflect any
ROOT change while keeping the exported STORAGE_PATHS as const; update any
consuming code if types change accordingly.

1-1: Silent empty-string fallback for PUTER_WORKER_URL will produce confusing failures.

If VITE_PUTER_WORKER_URL is missing, every consumer will end up with an empty base URL, causing requests to resolve as relative paths against the app origin instead of failing fast. Consider throwing in development (or at least a console.warn) so misconfigured environments are obvious.

const url = import.meta.env.VITE_PUTER_WORKER_URL;
if (!url && import.meta.env.DEV) {
  console.warn("VITE_PUTER_WORKER_URL is not set; Puter API calls will fail.");
}
export const PUTER_WORKER_URL = url ?? "";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/constants.ts` at line 1, The current constant PUTER_WORKER_URL falls back
silently to an empty string causing confusing runtime failures; update the
module so it reads import.meta.env.VITE_PUTER_WORKER_URL into a local variable,
and if it's falsy and import.meta.env.DEV is true emit a clear console.warn (or
throw in dev) indicating VITE_PUTER_WORKER_URL is not set, then export
PUTER_WORKER_URL from that validated variable instead of defaulting silently to
""; reference PUTER_WORKER_URL and
import.meta.env.VITE_PUTER_WORKER_URL/import.meta.env.DEV to locate where to
change behavior.
components/Upload.tsx (2)

3-3: Unused useNavigate import.

useNavigate is imported but never used — navigation is delegated to the onComplete callback in the parent. Drop the import.

-import { useOutletContext, useNavigate } from "react-router";
+import { useOutletContext } from "react-router";

…and the corresponding const navigate = useNavigate(); at line 15.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/Upload.tsx` at line 3, Remove the unused navigation hook: delete
the `useNavigate` named import from the React Router import statement and remove
the `const navigate = useNavigate();` invocation in this file; keep
`useOutletContext` intact since it's used, and ensure no other references to
`navigate` remain (update any usages to use the parent `onComplete` callback if
present).

4-4: PROGRESS_STEP and PROGRESS_INCREMENT look like duplicates.

lib/constants.ts exports both PROGRESS_INCREMENT = 15 and PROGRESS_STEP = 5. Only PROGRESS_STEP is used here. If they represent different concepts, name them accordingly (e.g., UPLOAD_PROGRESS_STEP vs. something else); otherwise consolidate to one constant.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/Upload.tsx` at line 4, PROGRESS_STEP and PROGRESS_INCREMENT appear
duplicate; decide whether they represent distinct semantics or a single concept,
then update the constants and usages accordingly: if they are the same, remove
one (e.g., delete PROGRESS_INCREMENT) and export only PROGRESS_STEP, then update
imports (e.g., in Upload.tsx) to import the single constant; if they are
different, give them clear distinct names (e.g., UPLOAD_PROGRESS_STEP vs
UPLOAD_PROGRESS_INCREMENT), update their definitions and all references
(including the import in Upload.tsx) to use the new names, and ensure naming
reflects their meanings.
app/routes/visualizer.$id.tsx (1)

1-1: Unused React import with the modern JSX transform.

With the new JSX transform (default in React 19), the React default import isn't needed unless you reference React.* APIs. Safe to drop to keep the file minimal.

♻️ Proposed cleanup
-import React from "react";
-
-const visualizer = () => {
+const Visualizer = () => {
   return <div>visualizer</div>;
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/routes/visualizer`.$id.tsx at line 1, Remove the unused default React
import at the top of visualizer.$id.tsx (the line "import React from 'react'")
since the modern JSX transform doesn't require it; if any React APIs are used
via React.* replace with direct imports (e.g., useState, useEffect) or reference
them explicitly, otherwise delete that import line to clean up the file.
app/routes.ts (1)

3-6: Nit: inconsistent relative paths between the two route entries.

index("routes/home.tsx") and route("visualizer/:id", "./routes/visualizer.$id.tsx") both work, but pick one style for readability.

♻️ Suggested tweak
 export default [
-  index("routes/home.tsx"),
-  route("visualizer/:id", "./routes/visualizer.$id.tsx"),
+  index("routes/home.tsx"),
+  route("visualizer/:id", "routes/visualizer.$id.tsx"),
 ] satisfies RouteConfig;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/routes.ts` around lines 3 - 6, The two route entries use inconsistent
path styles: index("routes/home.tsx") vs route("visualizer/:id",
"./routes/visualizer.$id.tsx"); pick one convention and make both consistent
(either remove the leading "./" from the visualizer path or add "./" to the home
path) so that the array of routes exported by default (the index and route
entries) use the same relative-path style for readability and consistency.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/routes/home.tsx`:
- Around line 18-24: handleUploadComplete currently drops the received
base64Image and navigates to `/visualizer/${newId}` with no way for the
visualizer to access the image; persist or forward the data before navigating
and remove unused async/return. Fix options: (A) store base64Image keyed by
newId (e.g., in-memory map, sessionStorage/IndexedDB, or upload to the worker
referenced in lib/constants.ts) then navigate to `/visualizer/${newId}` so the
visualizer can retrieve it by id; or (B) pass the image via navigation state
using navigate(`/visualizer/${newId}`, { state: { image: base64Image } }) if
same-tab consumption is acceptable. Also remove the unnecessary async keyword
and the `return true` since onComplete expects a void callback.

In `@app/routes/visualizer`.$id.tsx:
- Around line 3-7: The React component is named with a lowercase identifier
(visualizer) which can be treated as a DOM tag; rename the component to
PascalCase (e.g., Visualizer) and update the default export to export the
PascalCase identifier so the component name follows React conventions and avoids
rendering/devtools issues—update the function name visualizer to Visualizer and
change the export default visualizer to export default Visualizer (also search
for any local references and update them).

In `@components/Upload.tsx`:
- Around line 22-39: The FileReader lacks error handling so a failed read leaves
progress stuck; add a reader.onerror handler alongside reader.onload that clears
any running interval, sets an error state (or calls an existing error callback),
resets/updates setProgress so the UI is not stuck, and surfaces a retry path to
the user; reference the existing reader, reader.onload, setProgress, onComplete,
REDIRECT_DELAY_MS, PROGRESS_STEP, PROGRESS_INTERVAL_MS and file when
implementing the error branch so the read failure cleans up timers and provides
a clear error/retry flow.
- Around line 18-40: The setInterval started inside processFile is never cleaned
up on unmount; change the local const interval to be tracked in a ref (e.g.,
intervalRef) and assign the interval ID to intervalRef.current, clear
intervalRef.current when progress reaches 100 (where you currently call
clearInterval) and also add a useEffect cleanup that clears intervalRef.current
on unmount; ensure you also clear any previous interval before starting a new
one and keep existing behavior of calling onComplete with base64Data after
REDIRECT_DELAY_MS.
- Around line 51-68: Update file-type and size validation to use centralized
constants from lib/constants.ts (e.g., ALLOWED and MAX_BYTES) and enforce them
before any progress UI starts: in handleDrop and handleChange (or better, inside
processFile) check that file.type is in ALLOWED and file.size <= MAX_BYTES, and
if not, surface a user-visible error message and return without invoking the
progress/processing flow; ensure the MIME whitelist (ALLOWED) matches the UI
copy (e.g., "image/jpeg","image/png") and remove duplicate/contradictory checks
so both drag-and-drop (handleDrop) and input selection
(handleChange/processFile) behave identically.
- Around line 26-37: The updater passed to setProgress contains side effects
(clearInterval and setTimeout/onComplete) which can double-fire under Strict
Mode; remove those from the setProgress updater and instead detect completion in
a useEffect that watches the progress state (e.g., when progress === 100) to run
clearInterval and schedule onComplete after REDIRECT_DELAY_MS; ensure the
interval handle (created with PROGRESS_INTERVAL_MS/PROGRESS_STEP) is stored in a
ref or state so the effect can clear it and also clean up on unmount to avoid
leaks.

---

Nitpick comments:
In `@app/routes.ts`:
- Around line 3-6: The two route entries use inconsistent path styles:
index("routes/home.tsx") vs route("visualizer/:id",
"./routes/visualizer.$id.tsx"); pick one convention and make both consistent
(either remove the leading "./" from the visualizer path or add "./" to the home
path) so that the array of routes exported by default (the index and route
entries) use the same relative-path style for readability and consistency.

In `@app/routes/visualizer`.$id.tsx:
- Line 1: Remove the unused default React import at the top of
visualizer.$id.tsx (the line "import React from 'react'") since the modern JSX
transform doesn't require it; if any React APIs are used via React.* replace
with direct imports (e.g., useState, useEffect) or reference them explicitly,
otherwise delete that import line to clean up the file.

In `@components/Upload.tsx`:
- Line 3: Remove the unused navigation hook: delete the `useNavigate` named
import from the React Router import statement and remove the `const navigate =
useNavigate();` invocation in this file; keep `useOutletContext` intact since
it's used, and ensure no other references to `navigate` remain (update any
usages to use the parent `onComplete` callback if present).
- Line 4: PROGRESS_STEP and PROGRESS_INCREMENT appear duplicate; decide whether
they represent distinct semantics or a single concept, then update the constants
and usages accordingly: if they are the same, remove one (e.g., delete
PROGRESS_INCREMENT) and export only PROGRESS_STEP, then update imports (e.g., in
Upload.tsx) to import the single constant; if they are different, give them
clear distinct names (e.g., UPLOAD_PROGRESS_STEP vs UPLOAD_PROGRESS_INCREMENT),
update their definitions and all references (including the import in Upload.tsx)
to use the new names, and ensure naming reflects their meanings.

In `@lib/constants.ts`:
- Around line 12-15: There are two similar constants PROGRESS_INCREMENT and
PROGRESS_STEP—only PROGRESS_STEP is used by Upload.tsx—so remove the unused
PROGRESS_INCREMENT (or, if both are intended, rename one to clarify distinct
intent) and update any references; specifically, delete PROGRESS_INCREMENT from
lib/constants.ts (or rename it to a descriptive name if used elsewhere) and
ensure Upload.tsx continues to import and use PROGRESS_STEP consistently.
- Around line 4-8: STORAGE_PATHS repeats the literal "roomify" causing drift;
change SOURCES and RENDERS to derive from STORAGE_PATHS.ROOT (i.e., set SOURCES
to `${STORAGE_PATHS.ROOT}/sources` and RENDERS to
`${STORAGE_PATHS.ROOT}/renders`) so they automatically reflect any ROOT change
while keeping the exported STORAGE_PATHS as const; update any consuming code if
types change accordingly.
- Line 1: The current constant PUTER_WORKER_URL falls back silently to an empty
string causing confusing runtime failures; update the module so it reads
import.meta.env.VITE_PUTER_WORKER_URL into a local variable, and if it's falsy
and import.meta.env.DEV is true emit a clear console.warn (or throw in dev)
indicating VITE_PUTER_WORKER_URL is not set, then export PUTER_WORKER_URL from
that validated variable instead of defaulting silently to ""; reference
PUTER_WORKER_URL and import.meta.env.VITE_PUTER_WORKER_URL/import.meta.env.DEV
to locate where to change behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 95cb3ddc-6a95-45e7-814d-d40732fff5d6

📥 Commits

Reviewing files that changed from the base of the PR and between 176fde8 and 14ee054.

📒 Files selected for processing (5)
  • app/routes.ts
  • app/routes/home.tsx
  • app/routes/visualizer.$id.tsx
  • components/Upload.tsx
  • lib/constants.ts

Comment thread app/routes/home.tsx
Comment on lines +18 to +24
const handleUploadComplete = async (base64Image: string) => {
const newId = Date.now().toString();

navigate(`/visualizer/${newId}`);

return true;
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Uploaded image is dropped on the floor before navigation.

handleUploadComplete receives base64Image but never persists or forwards it. After navigate(/visualizer/${newId}), the new route has no way to obtain the uploaded data — :id is just Date.now() with no associated storage. Unless this is intentionally a stub for a follow-up PR, the visualizer route will render with nothing to visualize.

Consider one of:

  • Persisting the base64 (e.g. into an in-memory store keyed by newId, sessionStorage, IndexedDB, or uploading to the worker referenced in lib/constants.ts) before navigating.
  • Passing it via navigate(..., { state: { image: base64Image } }) if same-tab consumption is acceptable.

Also, the function is marked async and return trues, but neither awaits anything nor has its return value consumed by Upload (whose onComplete is typed (base64Data: string) => void). The async and return true can be removed.

♻️ Minimal cleanup (still missing data plumbing)
-  const handleUploadComplete = async (base64Image: string) => {
-    const newId = Date.now().toString();
-
-    navigate(`/visualizer/${newId}`);
-
-    return true;
-  };
+  const handleUploadComplete = (base64Image: string) => {
+    const newId = Date.now().toString();
+    // TODO: persist `base64Image` so /visualizer/:id can retrieve it.
+    navigate(`/visualizer/${newId}`, { state: { image: base64Image } });
+  };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handleUploadComplete = async (base64Image: string) => {
const newId = Date.now().toString();
navigate(`/visualizer/${newId}`);
return true;
};
const handleUploadComplete = (base64Image: string) => {
const newId = Date.now().toString();
// TODO: persist `base64Image` so /visualizer/:id can retrieve it.
navigate(`/visualizer/${newId}`, { state: { image: base64Image } });
};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/routes/home.tsx` around lines 18 - 24, handleUploadComplete currently
drops the received base64Image and navigates to `/visualizer/${newId}` with no
way for the visualizer to access the image; persist or forward the data before
navigating and remove unused async/return. Fix options: (A) store base64Image
keyed by newId (e.g., in-memory map, sessionStorage/IndexedDB, or upload to the
worker referenced in lib/constants.ts) then navigate to `/visualizer/${newId}`
so the visualizer can retrieve it by id; or (B) pass the image via navigation
state using navigate(`/visualizer/${newId}`, { state: { image: base64Image } })
if same-tab consumption is acceptable. Also remove the unnecessary async keyword
and the `return true` since onComplete expects a void callback.

Comment thread app/routes/visualizer.$id.tsx Outdated
Comment thread components/Upload.tsx
Comment thread components/Upload.tsx
Comment thread components/Upload.tsx Outdated
Comment thread components/Upload.tsx
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (2)
components/Upload.tsx (2)

38-40: ⚠️ Potential issue | 🟡 Minor

Clear any existing upload interval before assigning a new one.

intervalRef.current is replaced directly on Line 38. If processFile is invoked again before completion, the previous timer can continue running.

Proposed fix
-      intervalRef.current = setInterval(() => {
+      if (intervalRef.current) {
+        clearInterval(intervalRef.current);
+        intervalRef.current = null;
+      }
+      intervalRef.current = setInterval(() => {
         setProgress((prev) => Math.min(prev + PROGRESS_STEP, 100));
       }, PROGRESS_INTERVAL_MS);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/Upload.tsx` around lines 38 - 40, Before assigning a new interval
in processFile, clear any existing timer stored in intervalRef.current so the
old interval doesn't keep running; call clearInterval(intervalRef.current)
(after checking it's set) immediately before setting intervalRef.current =
setInterval(...), ensuring you reference intervalRef.current, setInterval,
PROGRESS_STEP and PROGRESS_INTERVAL_MS in the same block so repeated invocations
safely replace the previous timer.

25-27: ⚠️ Potential issue | 🟠 Major

Enforce file type/size in one place before starting upload flow.

Line 60 applies a broad drag-drop check (image/*), while Line 68 allows any selected file path through, and there is still no max-size guard despite the UI claim on Line 122. This can cause inconsistent behavior and large-memory reads.

Proposed fix
 import {
   PROGRESS_INTERVAL_MS,
   PROGRESS_STEP,
   REDIRECT_DELAY_MS,
+  // add these in lib/constants.ts
+  // ALLOWED_UPLOAD_MIME_TYPES,
+  // MAX_UPLOAD_BYTES,
 } from "../lib/constants";

+// Temporary local fallback until centralized constants are added
+const ALLOWED_UPLOAD_MIME_TYPES = ["image/jpeg", "image/png"];
+const MAX_UPLOAD_BYTES = 50 * 1024 * 1024;
+
 const processFile = (file: File) => {
   if (!isSignedIn) return;
+
+  if (!ALLOWED_UPLOAD_MIME_TYPES.includes(file.type)) {
+    return;
+  }
+  if (file.size > MAX_UPLOAD_BYTES) {
+    return;
+  }
+
   setFile(file);

Also applies to: 54-63, 65-71, 103-107, 122-122

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/Upload.tsx` around lines 25 - 27, Centralize and enforce file type
and size validation before any upload flow by adding a single validator (e.g.
validateAndSetFile) and using it from processFile, the drag-drop handler
(handleDrop/onDrop) and the file input handler (handleFileSelect) instead of
directly calling setFile; the validator should check mime type against the
existing allowed pattern (image/* or a stricter whitelist) and enforce the UI
max-size constant (the claimed max on Line 122) and return/raise a user-facing
error if invalid so no large or wrong-type files are ever passed to setFile or
further processing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@components/Upload.tsx`:
- Around line 38-40: Before assigning a new interval in processFile, clear any
existing timer stored in intervalRef.current so the old interval doesn't keep
running; call clearInterval(intervalRef.current) (after checking it's set)
immediately before setting intervalRef.current = setInterval(...), ensuring you
reference intervalRef.current, setInterval, PROGRESS_STEP and
PROGRESS_INTERVAL_MS in the same block so repeated invocations safely replace
the previous timer.
- Around line 25-27: Centralize and enforce file type and size validation before
any upload flow by adding a single validator (e.g. validateAndSetFile) and using
it from processFile, the drag-drop handler (handleDrop/onDrop) and the file
input handler (handleFileSelect) instead of directly calling setFile; the
validator should check mime type against the existing allowed pattern (image/*
or a stricter whitelist) and enforce the UI max-size constant (the claimed max
on Line 122) and return/raise a user-facing error if invalid so no large or
wrong-type files are ever passed to setFile or further processing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d4976ae8-a575-4914-9ea1-4873d93cf42f

📥 Commits

Reviewing files that changed from the base of the PR and between 14ee054 and 024ff5d.

📒 Files selected for processing (3)
  • app/routes/visualizer.$id.tsx
  • components/Upload.tsx
  • lib/constants.ts
✅ Files skipped from review due to trivial changes (2)
  • app/routes/visualizer.$id.tsx
  • lib/constants.ts

@wobiR99 wobiR99 merged commit 0e5e388 into main Apr 28, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant