Commit Graph
455 Commits
Author SHA1 Message Date
Siddharth Kumar Sah aa1f87fc91 fix: resolve pipeline step race condition and infinite re-render loop
Two issues caused intermittent step addition failures in the automation
pipeline:

1. RemoveBgControls had onChange in its useEffect deps. Since onChange is
   a new function reference on every parent render, this created an
   infinite re-render loop (effect -> setState -> render -> effect).
   Fixed by using the onChangeRef pattern matching other settings
   components.

2. All step mutation callbacks read from stepsRef.current and passed
   values to setSteps. Concurrent callbacks (e.g. addStep + a settings
   effect) would overwrite each other. Fixed by switching to functional
   state updates (setSteps(prev => ...)) and removing stepsRef.

Also rewrites automate e2e tests to use manual step addition instead of
referencing templates that no longer exist in the UI.
2026-03-28 18:34:05 +08:00
Siddharth Kumar Sah 748ac607bc fix: sync stepsRef during render, not useEffect
Child component effects (Controls onChange) fire before the parent's
useEffect that synced stepsRef. This caused updateStepSettings to read
stepsRef.current as [] and wipe out newly added steps.

Fix: assign stepsRef.current = steps directly during render so the
ref is always current before any child effects execute.
2026-03-28 17:02:24 +08:00
Siddharth Kumar Sah 8b20fef2d8 fix: prevent stale closure in pipeline step callbacks
All step mutation callbacks (addStep, removeStep, moveStep,
updateStepSettings) captured `steps` in their useCallback closures.
When React batched state updates, rapid interactions could use a stale
steps array, causing clicks to silently fail.

Fix: use a stepsRef that always holds the latest value. Callbacks read
from stepsRef.current instead of the captured closure variable, and no
longer need `steps` in their dependency arrays.
2026-03-28 16:42:59 +08:00
Siddharth Kumar Sah 7b1b019b77 fix: clear search when adding a step from the tool picker
When a tool was selected via search, the search text persisted after
the picker closed. Reopening the picker showed a filtered list instead
of all tools, making it look like clicking tools without searching
didn't work.
2026-03-28 16:32:28 +08:00
Siddharth Kumar Sah 33cd575506 chore: standardize tool count to 30+ across all docs and UI 2026-03-28 16:32:28 +08:00
Siddharth Kumar Sah 9acbedf4b7 fix: prevent pipeline step settings from resetting on collapse
The settings panel used conditional rendering ({isExpanded && ...})
which unmounted the Controls component on collapse, losing all state.
Switch to CSS hidden class so the component stays mounted and settings
persist when the panel is collapsed and re-expanded.
2026-03-28 16:17:39 +08:00
Siddharth Kumar Sah 1c05bc76e5 refactor: replace TOOL_FIELDS with shared Controls components (DRY)
Extract a *Controls subcomponent from all 16 pipeline-compatible tool
settings components. Each Controls component holds the UI state and
settings controls, accepts an onChange callback, and uses useRef to
prevent infinite re-render loops. The standalone *Settings components
become thin wrappers that add useToolProcessor, useFileStore, and
action buttons.

pipeline-step-settings.tsx is rewritten from ~675 lines to ~55 lines:
the entire TOOL_FIELDS declarative map and generic renderer are deleted
and replaced with direct imports of the Controls components. Pipeline
steps now render the exact same UI as standalone tool pages.

Special cases:
- CropControls: numeric inputs for pipeline (standalone uses canvas)
- RotateControls: resetSignal prop for post-processing reset
- ColorControls: accepts toolId for tab selection
- StripMetadataControls: checkboxes only (no file inspection)
- RemoveBgControls: already extracted, unchanged
2026-03-28 16:04:42 +08:00
Siddharth Kumar Sah 5a50aecd0b refactor: extract RemoveBgControls for DRY reuse in pipeline steps
Extract the settings controls (subject type, quality, background color)
from RemoveBgSettings into a shared RemoveBgControls component that
accepts settings + onChange props. Both the standalone tool page and the
pipeline step configurator now render the same component, so the UI is
identical and changes only need to be made in one place.
2026-03-28 15:40:39 +08:00
Siddharth Kumar Sah 017a71562a fix: add remove-background settings to pipeline step configurator
The pipeline step settings had an empty array for remove-background,
showing "No configurable settings" even though the tool supports
model selection and background color. Add AI model selector (u2net,
birefnet-general-lite, birefnet-general, birefnet-portrait, bria-rmbg)
and background color picker matching the standalone tool's options.
2026-03-28 15:32:28 +08:00
Siddharth Kumar Sah c48bfba879 feat: make AI tools pipeline-compatible and add search to tool picker
Register remove-background, upscale, and blur-faces in the pipeline
tool registry via registerToolProcessFn(). These tools keep their
custom HTTP routes (with progress callbacks) for direct use, but now
also provide a simple process function for pipeline/batch execution.

Add a search bar to the pipeline tool picker so users can quickly
find tools by name or description. Uses the existing SearchBar
component and the same filtering pattern as the main tool panel.

Update tests to reflect that these 3 AI tools are now pipeline-
compatible (moved from excluded to included assertions).
2026-03-28 15:09:23 +08:00
Siddharth Kumar Sah 4a504281a3 fix: surface hidden errors and add batch rejection tests
Fix empty catch blocks in settings dialog (logo upload/delete) and
automate page (pipeline save) that silently swallowed errors. Users
now see error messages when these operations fail.

Add 5 integration tests verifying batch endpoint returns 404 for
custom-route tools (remove-background, upscale, ocr, blur-faces,
erase-object), matching the pipeline rejection tests.
2026-03-28 14:45:14 +08:00
Siddharth Kumar Sah 658954ea19 fix: remove Google Drive coming soon placeholder from files nav 2026-03-28 14:40:23 +08:00
Siddharth Kumar Sah 0410bf3461 fix: pipeline only shows compatible tools and displays errors
The pipeline tool picker was showing all tools, but only tools
registered via createToolRoute() support pipeline execution. Tools
with custom routes (remove-background, upscale, ocr, etc.) would
silently fail with "Tool not found" and the empty catch block hid
the error from users.

Add GET /api/v1/pipeline/tools endpoint that returns the IDs of
pipeline-compatible tools. The frontend fetches this list and filters
the tool picker accordingly. Also surface pipeline execution errors
in the UI instead of swallowing them.
2026-03-28 14:38:48 +08:00
Siddharth Kumar Sah 565b4805c7 fix: trigger browser password save prompt on password change
Safari, Chrome, and Firefox only offer to save passwords when they see
a real form submission with page navigation, not fetch() + redirect.

After the change-password API call succeeds, dynamically create a form
with the username and new password (autocomplete=username + new-password),
POST it to "/" causing a real navigation. The browser detects the form
submission with credential fields and prompts to save.

Also make the username field visible (read-only) on the change-password
page since Safari ignores hidden inputs for password detection, and add
autocomplete attributes to the login page fields.
2026-03-28 14:24:13 +08:00
Siddharth Kumar Sah 7c76c2a2a0 feat: add password generator and browser save prompt on change-password page
Add a "Generate strong password" button that creates a random 16-char
password meeting all requirements (uppercase, lowercase, digit).
Generated passwords are shown in plain text so users can copy them.
Add autocomplete attributes (current-password, new-password, username)
so browsers prompt to save the new credentials after submission.
2026-03-28 14:12:46 +08:00
Siddharth Kumar Sah 01cd1d9f71 feat: add forced password change page on first login
The backend sets mustChangePassword=true for all new accounts and
blocks API calls until the password is changed. The frontend was not
handling this flag - it logged the user in and redirected to the
dashboard where every API call silently failed with 403.

Add a /change-password page that is shown when mustChangePassword is
true. The login page now redirects there instead of home, and the
AuthGuard intercepts any direct navigation to force the change first.
2026-03-28 14:02:13 +08:00
Siddharth Kumar Sah 6cfa3b0c38 feat: multi-arch Docker support, security hardening, and test improvements
Remove hardcoded --platform=linux/amd64 from Dockerfile so buildx produces
native arm64 images for Apple Silicon and Raspberry Pi. Add audit logging
for auth events, harden file storage with extension whitelists and
double-extension attack prevention, reject null-byte buffers in validation,
add data-testid attributes to all tool settings components, update
deployment docs with architecture notes and correct CI workflow references,
and fix unit test mock to match throwWithMessage error extraction.
2026-03-28 11:19:09 +08:00
Siddharth Kumar Sah 620b8ad038 fix(api): resolve team name lookup and show server error messages
- Backend: look up teams by name first (frontend sends name, not ID)
- Frontend: parse response body on API errors instead of showing
  generic "API error: 400" — now shows the actual server message
  (e.g. "Password must be at least 8 characters...")
2026-03-27 16:41:44 +08:00
Siddharth Kumar Sah e3a8558134 fix(ui): clean up settings, automate page, fullscreen logo, and README
- README: simplify to match Stirling-PDF style, add dashboard screenshot
- Settings: remove unsupported languages from dropdown, remove unused
  experimental tools toggle
- Automate: remove hardcoded template pipelines from sidebar
- Fullscreen: add GemLogo icon to header
2026-03-27 13:50:04 +08:00
Siddharth Kumar Sah fadf0a8a22 refactor(branding): extract GemLogo to shared component and add to About section 2026-03-27 13:50:03 +08:00
Siddharth Kumar Sah d47548a1d7 fix(a11y): add aria-hidden to decorative GemLogo SVG 2026-03-27 13:50:02 +08:00
Siddharth Kumar Sah 39dfb93679 feat(branding): show gem icon in app header as default logo 2026-03-27 13:50:02 +08:00
Siddharth Kumar Sah 40656a0452 feat(erase-object): replace mask upload with in-browser brush painting
Replace the external mask file upload workflow with an interactive
canvas-based brush tool. Users now paint directly on the image to
mark areas for erasure. Adds EraserCanvas component with adjustable
brush size, undo/clear, and mask export. Switch Python inpainting
from broken lama-cleaner to OpenCV cv2.inpaint (Telea algorithm).
Add before/after comparison slider after processing.
2026-03-26 17:33:17 +08:00
Siddharth Kumar Sah 0401900a69 chore(ui): remove technical jargon and update tool count
Remove approximate processing times from remove-bg quality options.
Update tool count from 37 to 33 across README, settings dialog, login
page, and i18n strings to reflect the accurate count.
2026-03-26 16:02:12 +08:00
Siddharth Kumar Sah f15102c632 fix(blur-faces): switch from MediaPipe to OpenCV and auto-orient images
Fix face detection failure caused by MediaPipe 0.10.33 removing the
mp.solutions API. Replace with OpenCV Haar cascade which works reliably
in headless Docker. Add autoOrient() call before detection to handle
EXIF-rotated phone photos. Remove technical jargon from UI.
2026-03-26 16:01:56 +08:00
Siddharth Kumar Sah 8ee4d7b2fb fix(upscale): auto-orient images before upscaling and improve UI
Fix rotated output by calling autoOrient() before passing images to
the Python upscaler, correcting EXIF orientation metadata. Replace
2x/4x buttons with 2x-8x slider plus quick-select buttons (2x, 3x,
4x, 6x, 8x). Remove technical jargon about Real-ESRGAN/Lanczos from
the UI and progress bar.
2026-03-26 16:01:40 +08:00
Siddharth Kumar Sah f357b18ced feat(adjustments): add real-time live preview for all color tools
Add CSS filter-based live preview for brightness, contrast, saturation,
color effects (grayscale/sepia/invert), and color channels (via SVG
feColorMatrix). The image in the right panel updates instantly as
sliders are adjusted. Adds cssFilter prop to ImageViewer, onPreviewFilter
callback to ColorSettings, and wires them through the tool page.
2026-03-26 16:01:18 +08:00
Siddharth Kumar Sah ddde152545 feat(image-to-pdf): add live PDF page preview with margin visualization
Add a miniature page preview in the settings panel that shows how the
image will look in the PDF. The preview updates in real-time as the
user changes page size, orientation, or margin. Uses the same scaling
logic as the backend to accurately represent image placement. Preview
tracks the currently selected image when multiple files are uploaded.
2026-03-26 16:01:00 +08:00
Siddharth Kumar Sah bf62820064 feat(rotate): add editable angle input and fine-tune +/- buttons
Replace the static angle display between Left/Right buttons with an
editable input field that accepts direct angle entry. Add - and +
buttons for 1-degree fine-tuned control. All controls update the
rotation state which triggers real-time CSS preview on the image.
2026-03-26 16:00:44 +08:00
Siddharth Kumar Sah 627ff8a82c chore: remove internal docs from repo, update public documentation
Remove docs/superpowers/, .claude/ config, and PRD.md from version
control (kept locally via .gitignore). Update README, CHANGELOG,
VitePress docs, and .env.example to reflect recent features: Files
page, teams, admin settings, persistent storage, and various API
improvements.
2026-03-26 01:11:40 +08:00
Siddharth Kumar Sah 3b4f522bf4 fix: prevent useAuth infinite loop causing rate limit storms
checkAuth was defined as a plain function and used as a useEffect
dependency, causing it to fire on every render. Moved it inside the
effect with an empty dependency array so it runs once on mount.
2026-03-26 01:10:51 +08:00
Siddharth Kumar Sah 4b2621d9f2 feat(ui): add teams, tools, feature flags, temp files, logo to settings dialog
- Add Teams section with CRUD (create, rename, delete) and member count display
- Add Tools section with per-tool enable/disable toggles grouped by category
- Add logo upload/delete, experimental tools toggle, file management settings to System Settings
- Replace free-text team input with dropdown populated from teams API in People section
- Filter disabled/experimental tools in tool panel, pipeline builder, and fullscreen grid
- Display custom logo in mobile header and sidebar when configured
2026-03-26 01:10:51 +08:00
Siddharth Kumar Sah 585d66f0c9 refactor: rename Tool.alpha to Tool.experimental 2026-03-26 01:10:51 +08:00
Siddharth Kumar Sah 62fbb5484c feat: implement Files page with persistent storage and version tracking
Three-panel file manager (nav, list, details) modeled after Stirling-PDF.
- Backend: user_files table, /api/v1/files/* CRUD routes, file storage
  helpers, thumbnail generation via Sharp, recursive CTE version chains
- Frontend: FilesNav, FileList, FileDetails, FileUploadArea components,
  Zustand store, mobile layout with bottom sheet
- Integration: tool-factory auto-saves results as new versions when
  fileId is provided, "Open File" loads file into tool processing flow
- Search, bulk select/delete/download, version badges, tool chain tags
2026-03-26 01:10:51 +08:00
Siddharth Kumar Sah c99f43fe60 feat(files): add mobile layout for Files page
Replace static desktop-only layout with responsive version: mobile gets a
tab bar (Recent / Upload) and a bottom-sheet drawer for file details, while
desktop retains the existing three-column panel layout. FileDetails gains
updated mobile wrapper classes (removes border/width, uses flex gap).
2026-03-26 01:10:50 +08:00
Siddharth Kumar Sah 20f153d611 feat(files): wire serverFileId for version tracking
Add serverFileId to FileEntry, pass fileId in tool processor formData when
a file originates from the Files page, and set serverFileId on the loaded
entry so subsequent tool runs create new file versions instead of duplicates.
2026-03-26 01:10:50 +08:00
Siddharth Kumar Sah 788b8c8bad feat(files): add Files page with nav, list, details, upload, and routing
Creates the full Files page UI (Tasks 8 & 9): FilesNav, FileListItem,
FileList, FileDetails, FileUploadArea components, FilesPage layout, and
wires up the /files route plus sidebar/mobile-nav entries.
2026-03-26 01:10:50 +08:00
Siddharth Kumar Sah 24644c1c10 feat(stores): add Zustand store for Files page state management
Implements useFilesPageStore with file listing, upload, bulk delete,
selection, checkbox management, search, and tab switching actions.
2026-03-26 01:10:50 +08:00
Siddharth Kumar Sah 8a3a731267 feat(api): add persistent file management helpers to frontend api module
Adds UserFile/UserFileDetail types plus apiListFiles, apiGetFileDetails,
apiUploadUserFiles, apiDeleteUserFiles, getFileThumbnailUrl, and
getFileDownloadUrl to support the Files page.
2026-03-26 01:10:50 +08:00
Siddharth Kumar Sah adc7e1c037 feat(pipeline): add inline settings configuration for automation steps
Replace placeholder "default settings" message with actual form controls
when expanding pipeline steps. Each tool now shows its configurable fields
(dimensions, quality, colors, modes, etc.) directly in the pipeline builder.

Covers all 30+ tools with data-driven field definitions: number inputs,
select groups, checkboxes, color pickers, and conditional fields.
2026-03-24 21:38:16 +08:00
Siddharth Kumar Sah 0aa2a5e5de chore: remove swagger deps, parallelize CI jobs
- Remove @fastify/swagger and @fastify/swagger-ui (API docs live on GitHub Pages)
- Run typecheck, build, and docker CI jobs in parallel instead of sequentially
2026-03-24 00:41:54 +08:00
Siddharth Kumar Sah fbdbe0949a fix(crop): use percentCrop from onChange to fix inflated pixel values
react-image-crop's onChange passes (pixelCrop, percentCrop) — we were
using the first arg (display pixels) but treating them as percentages,
causing values to exceed image dimensions.
2026-03-24 00:41:30 +08:00
Siddharth Kumar Sah 786a671c39 feat(crop): wire CropCanvas and CropSettings into tool-page with bidirectional state 2026-03-23 19:22:53 +08:00
Siddharth Kumar Sah 70c73d85c9 fix: white screen crash when uploading photos with null GPS EXIF data
Samsung Galaxy phones (and others) can have GPS EXIF tags with null
coordinate values when location is disabled. The server returned
_latitude: null, and the client guard used !== undefined which passed
for null, causing null.toFixed() to crash React with no ErrorBoundary.

- Server: validate GPS array values are actual numbers before computing
- Client: use != null guard (catches both null and undefined)
- App: add ErrorBoundary to prevent white screens from any future crash
2026-03-23 19:22:52 +08:00
Siddharth Kumar Sah c2c256a180 feat(crop): redesign CropSettings with aspect presets, pixel inputs, and grid toggle 2026-03-23 19:19:56 +08:00
Siddharth Kumar Sah 1a076be9b2 feat(crop): add CropCanvas component with visual overlay, grid, and keyboard controls 2026-03-23 19:18:03 +08:00
Siddharth Kumar Sah 80756d1591 feat: merge multi-image UX — batch processing, filmstrip navigation, resize/rotate redesign
Integrates feature/multi-image-ux branch with 20 commits including:
- Multi-image viewer with arrow navigation and filmstrip thumbnails
- Batch processing across all tool settings components
- File store rewrite with FileEntry model for multi-image support
- Resize settings redesigned with tab-based UI (presets, custom, scale)
- Side-by-side comparison for resize results
- Per-file metadata caching in strip-metadata
- Client-side ZIP extraction via fflate
- SSE progress correlation via clientJobId
2026-03-23 17:13:10 +08:00
Siddharth Kumar Sah 0e7348a0be fix: unify project on port 1349, improve strip-metadata and UI components
Consolidate all access to localhost:1349 — Vite dev server serves on 1349
and proxies API calls to an internal dev port (13490). Production API
defaults to 1349. Also includes strip-metadata improvements, UI component
updates, and compress operation fixes.
2026-03-23 16:38:27 +08:00
Siddharth Kumar Sah 989e8dc6e4 feat: conditional result views — side-by-side for resize, live preview for rotate 2026-03-23 15:14:34 +08:00
Siddharth Kumar Sah 31a943962d feat: add live preview callback to RotateSettings, rename button to Apply 2026-03-23 15:14:34 +08:00