Commit Graph
217 Commits
Author SHA1 Message Date
SnapOtter 98b2e5a269 test: add Playwright e2e spec for color-blindness tool 2026-05-08 15:21:39 +08:00
SnapOtter eedc2443d6 feat: add color-blindness API route and integration tests 2026-05-08 15:18:38 +08:00
SnapOtter 0b6a970912 feat: add color blindness simulation image-engine operation
Add colorBlindness() operation with 8 simulation matrices (Vienot/Machado)
for protanopia, deuteranopia, tritanopia, protanomaly, deuteranomaly,
tritanomaly, achromatopsia, and blue cone monochromacy.
2026-05-08 15:11:36 +08:00
SnapOtter 1669e34909 Merge fix/129-face-enhancement-mediapipe: add mediapipe to upscale-enhance bundle
fix: add mediapipe to upscale-enhance bundle for face enhancement

The enhance-faces tool requires MediaPipe for face detection, but the
upscale-enhance feature bundle did not include mediapipe in its pip
packages. Added mediapipe to both amd64 and arm64 package lists.

Added 25 regression tests validating bundle dependency completeness.

Closes #129
2026-05-07 22:24:03 +08:00
SnapOtter 6fc767523c fix: add mediapipe to upscale-enhance bundle for face enhancement
The enhance-faces tool requires MediaPipe for face detection, but the
upscale-enhance feature bundle did not include mediapipe in its pip
packages. Users who installed only the upscale-enhance bundle got
"Face detection requires MediaPipe" errors. Added mediapipe to both
amd64 and arm64 package lists, matching the pattern used by the
face-detection and photo-restoration bundles.

Also added feature-manifest.test.ts with 25 tests validating bundle
dependency completeness to prevent similar missing-dependency bugs.

Closes #129
2026-05-07 22:21:45 +08:00
SnapOtter 14810c3c78 fix: prevent repeated redirect when switching from grid to sidebar view
The default-view redirect in HomePage fired on every mount, not just the
initial page load. A module-level flag now gates the redirect so it only
applies once per session, allowing users to switch to sidebar view when
grid is the default.

Closes #128
2026-05-07 22:16:26 +08:00
SnapOtter 16af9c573a feat: remove app name and logo customization feature
Users can no longer customize the app name or logo. The branding API
endpoints, permission, frontend UI, env vars (APP_NAME, MAX_LOGO_SIZE_KB),
and all related tests are removed. Includes a migration to clean up
branding data from existing databases.
2026-05-07 19:41:30 +08:00
SnapOtter 25a1dd7aba Merge fix/131-content-aware-resize-registry: add frontend registry for content-aware resize
fix: add frontend registry entry for content-aware resize tool

Closes #131
2026-05-07 09:44:14 +08:00
SnapOtter cc15821c5e fix: add frontend registry entry for content-aware resize tool
The content-aware-resize tool had a full backend implementation (API route,
caire binary, seam-carving bridge) but was missing from the frontend
toolRegistry Map. Navigating to /content-aware-resize showed "Tool not found"
because ToolPage could not resolve a registry entry for the tool ID.

Added a dedicated ContentAwareResizeSettings component and registered it in
the tool registry with side-by-side display mode. Also added a guard test
that verifies every tool in the shared TOOLS[] array has a matching registry
entry, preventing this class of bug from recurring.

Closes #131
2026-05-07 09:38:38 +08:00
SnapOtter 979a833978 fix: resolve analytics data gaps and resize validation failures
- Fix resize 20% failure rate: add Zod refine requiring at least one
  dimension, enforce integer/max constraints, clamp percentage scaling
  to minimum 1px, and guard against missing metadata in withoutEnlargement
- Fix PostHog init race condition: move consent check before async import
  so frontend events (search, pageview) are no longer silently dropped
- Fix identify() passing nested $set/$set_once wrappers instead of flat
  properties, so version person property now appears on PostHog profiles
- Add error_code and error_message to failed tool_used analytics events
  for debugging tool failures from PostHog
2026-05-06 23:21:45 +08:00
SnapOtter d705c863e3 Merge feat/transparency-fixer: add PNG Transparency Fixer tool
New AI-powered tool that fixes fake transparent PNGs in one click.
Uses BiRefNet HR-matting (2048x2048) with Sharp defringe post-processing.
2026-05-06 21:57:46 +08:00
SnapOtter 8f9ba701be fix: QR code logo causes preview to vanish and become unrecoverable
The QR code generator's logo feature was broken in production (Docker)
due to three interacting issues:

1. The CSP connect-src directive did not include data:, so the
   qr-code-styling library's internal XHR to convert logo data URLs to
   blobs was silently blocked. The library has no onerror handler, so the
   render promise hung forever after the container was already cleared.

2. crossOrigin: "anonymous" was unnecessarily set on imageOptions for
   data URLs, which can cause canvas taint issues.

3. The logo options used a conditional spread that omitted the image key
   when no logo was set. The library's update() deep-merges options, so
   removing the logo preserved the stale data URL and the QR stayed
   broken even after logo removal.

Closes #121
2026-05-06 21:38:12 +08:00
SnapOtter 84e62e6132 refactor: rename tool display name to "PNG Transparency Fixer" 2026-05-06 18:53:37 +08:00
SnapOtter 75e48f2738 test: add transparency-fixer to GUI AI tools and tools-all E2E tests 2026-05-06 10:39:15 +08:00
SnapOtter eb3d0828cb docs: add transparency-fixer endpoint documentation 2026-05-05 23:24:22 +08:00
SnapOtter 4745e435a4 test: add Playwright E2E tests for transparency-fixer tool 2026-05-05 23:17:24 +08:00
SnapOtter c263834037 test: add integration tests for transparency-fixer tool 2026-05-05 23:14:42 +08:00
SnapOtter 5e45cb292b test: increase QR max-size test timeout to 180s for CI
The 10000x10000 QR generation exceeds 120s on GitHub-hosted runners.
2026-05-05 22:31:53 +08:00
SnapOtter 83fa0a39dc test: add fake transparency PNG fixture for transparency-fixer tool 2026-05-05 21:50:43 +08:00
SnapOtter d46510138f fix: custom logo not showing in sidebar and silent upload failures
The desktop sidebar never rendered the custom logo because only mobile
views used the customLogo state. Added a logo section at the top of
the desktop sidebar that displays the custom logo (or the default
OtterLogo when none is set).

The upload handler used raw fetch() without checking response.ok, so
HTTP 4xx errors (e.g. file too large) were silently ignored and the UI
falsely reported success. Now checks response status and surfaces the
server error message.

Closes #125
2026-05-05 21:45:51 +08:00
SnapOtter f856c26fcb fix: upscale tool times out on CPU-only systems (NAS/low-power hardware)
The upscale function called runPythonWithProgress without a timeout parameter,
defaulting to the bridge's 10-minute hard limit. On CPU-only systems like
Synology NAS devices, Real-ESRGAN 4x upscaling easily exceeds this for modest
images. Additionally, when the timeout fired on the dispatcher path, the Python
process was left running and blocked all subsequent AI operations.

This fix adds an adaptive timeout based on input megapixels, scale factor, and
GPU availability (180s/effective-MP on CPU, 30s/effective-MP on GPU, floor of
10 minutes). It also kills the dispatcher on timeout so subsequent requests can
proceed via a fresh restart.

Closes #119
2026-05-05 21:14:56 +08:00
SnapOtter 7ff100c4f9 docs: update tagline to "Your images never leave your home" 2026-05-05 21:12:44 +08:00
SnapOtter a85f4db97c test: add portrait fixture images and extreme-height regression test
Add test-portrait-tall.png (200x4000) and test-portrait-extreme.png
(100x6000) fixtures. Update crop overflow tests to use fixture files
instead of generating images at runtime, and add a second test case
for extremely tall images.
2026-05-05 20:53:02 +08:00
SnapOtter 1807a43f2d fix: crop tool overflows viewport with tall portrait images
The crop area flex container lacked min-h-0, preventing it from shrinking
below its content's intrinsic height. For tall images, react-image-crop's
CSS (max-height: inherit at specificity 0-1-1) overrides the Tailwind
max-h constraint, and without min-h-0 the flex item refuses to shrink,
causing viewport overflow.

Closes #122
2026-05-05 17:51:01 +08:00
SnapOtter e358634f8b fix: production CSP blocking PostHog/Sentry/Scalar and silent failure hardening
The production CSP had connect-src/script-src/font-src set to 'self' only,
silently blocking all analytics and error reporting in production while
working fine in dev (where CSP is not applied).

CSP fixes:
- Add PostHog ingest + assets origins to connect-src and script-src
- Add Sentry ingest origin to connect-src
- Add Scalar fonts origin to font-src for API docs pages
- Extract CSP construction into testable buildCsp() function

Silent failure hardening:
- Settings/features stores now set loadError flag and allow retry on
  subsequent fetch() calls instead of permanently caching failed state
- Analytics init no longer sets initialized=true before the try block,
  allowing retry on failure
- Settings dialog Tools section disables save button when settings
  failed to load, preventing accidental config wipe
- Branding logo storage moved from process.cwd() to FILES_STORAGE_PATH
  so logos persist across Docker container recreation

Test coverage:
- 16 CSP directive tests covering all external service domains
- Store retry-on-error behavior tests for settings and features stores
- Analytics init retry-after-failure test
2026-05-05 17:16:19 +08:00
SnapOtter 69deeb075f fix: increase vectorize HEIF test timeout to 180s for CI
Vectorize + HEIF decoding is particularly slow on CI runners.
120s was not enough; bump to 180s.
2026-05-01 20:25:12 +08:00
SnapOtter d1f2f63453 fix: add 120s timeout to all HEIF/HEIC integration tests for CI
Comprehensively adds { timeout: 120_000 } to every HEIF/HEIC
integration test across 40 test files. HEIF decoding on CI runners
is significantly slower than local, causing sporadic timeouts at
the default 5s or previous 60s limits.
2026-05-01 19:51:47 +08:00
SnapOtter 332c79f4ce fix: increase all HEIF/HEIC integration test timeouts to 120s for CI
The sharpening HEIF test was timing out at 60s in GitHub Actions.
Bumps all remaining HEIF/HEIC test timeouts from 60s to 120s across
14 integration test files for consistency with vectorize.
2026-05-01 19:05:51 +08:00
SnapOtter 66211ed6a7 fix: resolve 20 Sentry issues and fix navbar test flakiness
Sentry fixes:
- Only send 5xx errors to Sentry (was sending 4xx rate-limit, media type errors)
- Encode non-ASCII chars in X-Output-Filename header (encodeURIComponent)
- Handle FK constraint failures gracefully in file upload, pipeline save, API keys
- Harden getDirSize against ENOENT race on readdirSync

Test fixes:
- Wrap navbar test renders in act() to flush async useEffect state updates
- Add useEffect cleanup to navbar to prevent state updates on unmounted component
- Fixes timeout when running in full test suite
2026-05-01 19:01:05 +08:00
SnapOtter b50e1e0fb3 fix: increase vectorize HEIF test timeout to 120s for CI
Vectorize + HEIF decoding exceeds 60s on CI runners because potrace
(CPU-intensive bitmap tracing) runs on top of slow HEIF decoding.
2026-05-01 15:24:19 +08:00
SnapOtter e466c06cad fix: add 60s timeout to all HEIF integration tests for CI
HEIF decoding via heif-convert is slow on CI runners (~15-30s per
image) and exceeds the default 30s Vitest timeout. Add explicit
60s timeouts to all 16 HEIF input tests across integration suite.
2026-05-01 14:50:03 +08:00
SnapOtter fa479dcee4 fix: resolve 3 pre-existing issues found during test coverage expansion
1. passport-photo 404 vs 501: add base route at /api/v1/tools/passport-photo
   that returns 501 FEATURE_NOT_INSTALLED when the AI bundle is missing,
   matching other AI tools. The /generate sub-route is Sharp-only (no
   sidecar) so it correctly skips the isToolInstalled guard.

2. AuthGuard analytics consent race: don't evaluate shouldShowConsent()
   until analyticsConfig has been fetched (guard on analyticsConfig !== null).
   Prevents redirect to /analytics-consent before config is loaded.

3. Fragile sidebar Settings selector: add openSettings(page) helper to
   E2E helpers that checks sidebar visibility with fallback to button role.
   Replace all 134 occurrences of page.locator("aside").getByText("Settings")
   across 18 test files.
2026-05-01 13:44:04 +08:00
SnapOtter 7ce0f7b431 Merge branch 'worktree-agent-a5c6c830' 2026-05-01 05:28:37 +08:00
SnapOtter 8e3e212146 Merge branch 'worktree-agent-ab98adb0' 2026-05-01 05:28:37 +08:00
SnapOtter d05337ad49 Merge branch 'worktree-agent-a8a8fe4d' 2026-05-01 05:28:37 +08:00
SnapOtter 1889f00554 test: comprehensive GUI settings E2E including API Keys tab and full RBAC coverage 2026-05-01 05:28:00 +08:00
SnapOtter ae241cec19 test: deepen GUI resilience, accessibility, and performance tests 2026-05-01 04:47:55 +08:00
SnapOtter 7342d9d8fd test: add tablet visual regression baselines and cross-browser tests 2026-05-01 04:17:19 +08:00
SnapOtter 43cac02331 Merge branch 'worktree-agent-a3a33bf5' 2026-05-01 04:13:56 +08:00
SnapOtter b5b66248f1 Merge branch 'worktree-agent-a062c389' 2026-05-01 04:13:56 +08:00
SnapOtter d40adb9789 Merge branch 'worktree-agent-a63c6a97' 2026-05-01 04:13:56 +08:00
SnapOtter e071c2868b test: comprehensive GUI E2E for all 47 tools including 13 AI tools 2026-05-01 04:12:57 +08:00
SnapOtter 241dedc31f test: deepen GUI navigation with mobile viewport, footer, responsive, and keyboard tests 2026-05-01 03:35:07 +08:00
SnapOtter b6ee96ed04 test: deepen GUI batch, pipeline, and file-carry E2E tests 2026-05-01 03:33:52 +08:00
SnapOtter 27a144e4d7 Merge branch 'worktree-agent-ae5b9f86' 2026-05-01 03:05:31 +08:00
SnapOtter 6762a4b367 Merge branch 'worktree-agent-aedfd941' 2026-05-01 03:05:31 +08:00
SnapOtter 548d2a30fe Merge branch 'worktree-agent-ac2de4e3' 2026-05-01 03:05:31 +08:00
SnapOtter b193a8321f Merge branch 'worktree-agent-a19378fc' 2026-05-01 03:05:31 +08:00
SnapOtter c9ed48b30e test: deepen integration tests for 8 complex tools (HEIC, large file, batch, edge cases) 2026-05-01 03:05:08 +08:00
SnapOtter e3c5279b92 test: expand E2E-Docker coverage to all 47 tools with auth-failure tests 2026-05-01 02:51:42 +08:00