Skip to content

fix: route shoes try-on to the YouCam v2.0 feature - #47

Merged
jvsena42 merged 2 commits into
mainfrom
fix/youcam-shoes-v2-routing
Aug 2, 2026
Merged

fix: route shoes try-on to the YouCam v2.0 feature#47
jvsena42 merged 2 commits into
mainfrom
fix/youcam-shoes-v2-routing

Conversation

@jvsena42

@jvsena42 jvsena42 commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes #45. Selecting Shoes in TRY IT and tapping "See it on me" failed with an internal serializer message shown verbatim to the user:

Field 'data' is required for type with serial name 'com.github.worn.data.source.remote.YouCamFileResponse', but it was missing at path: $

YouCamApiClient.feature() routed shoes to /s2s/v1.0/..., but Perfect Corp's AI Shoes try-on lives in the v2.0 family. The v1.0 endpoint returns a legacy "result"-wrapped body, so decoding it as YouCamFileResponse — whose payload sits under "data" — failed at the root. The DTOs were reverse-engineered against cloth-v3 only, and shoes was never exercised end to end.

Fixing the version exposed two more problems: the shoes task takes different parameters (gender/style, no garment_category), and no decodeFromString call was guarded, which is why an internal class name reached the UI instead of the friendly messages every other failure path produces.

No Compose or SwiftUI changes and no new strings — gender and style are constants, so nothing reaches the UI layer.

Changes

  • Route shoes to v2.0. Both features now share one API_VERSION, so the Feature(version, type) holder collapses to a plain feature name (cloth-v3 / shoes).
  • Send the shoes task parameters. gender is pinned to "male" — Worn is an app for men, so this is a product decision rather than a parameter — and style to "random". Added explicitNulls = false so the fields that don't apply are omitted from the request body instead of sent as nulls (shoes was previously sending "garment_category": null).
  • Stop leaking serializer errors. A decode() helper wraps all four response decodes, mapping a contract mismatch to "YouCam returned an unexpected response." and logging the raw body so it stays debuggable.
  • Tests that can actually catch this. The old MockEngine matched path.contains("/file/") and would have accepted any version — a shoes test written against it would have passed while production failed. It now matches full paths and 404s otherwise.
  • Docs. README.md and ARCHITECTURE.md both still documented the v1.0/shoes routing.

Test plan

Verified here:

  • ./gradlew :shared:allTests — 124 pass, including three new cases: shoes happy path asserting "gender":"male" / "style":"random" / no garment_category; the inverse for clothes (guards the explicitNulls change in both directions); and a regression test that a {"result":{}} body yields a message with no com.github.worn in it.
  • Confirmed the tightened path matching bites — setting API_VERSION back to v1.0 fails 3 tests.
  • ./gradlew detekt clean, ./gradlew :composeApp:assembleDebug builds.

Still needs a real device + YouCam credentials:

  1. TRY IT → pick a shoe photo → Shoes → "See it on me". Watch logcat for [YouCam]: expect upload: creating slot ... at /s2s/v2.0/file/shoes, then status=runningstatus=success.
  2. Re-run one clothes category (Top) to confirm explicitNulls = false didn't regress cloth-v3.
  3. iOS: no Swift changed, but it shares the KMP client — worth one Shoes run.

Not verified from CI

No live call to Perfect Corp was made; the v2.0 shoes contract comes from their docs, not from an observed response. Their docs are also inconsistent about whether the upload path is per-feature (/s2s/v2.0/file/shoes) or shared (/s2s/v2.0/file). This PR uses per-feature, since that's what already works for cloth-v3. If upload/create 404s on device, drop the suffix on the file step only — task and poll stay per-feature either way.

Checklist

  • ./gradlew detekt passes
  • Tested on Android — not run; no device attached and no credentials in this environment
  • Tested on iOS — not built; no Xcode in this environment, and no Swift changed
  • Updated documentation (if applicable) — README.md and ARCHITECTURE.md both documented the old routing

Note

Pre-existing and left alone: the client's user-facing error strings — including the new decode message — are hardcoded English in shared code rather than pulled from strings.xml / Localizable.strings. That contradicts the project's localization rule but spans the whole file, so it belongs in its own change. It does mean pt-BR users see English for these errors.

🤖 Generated with Claude Code

jvsena42 and others added 2 commits August 2, 2026 20:36
Selecting Shoes in TRY IT failed with a raw serializer message shown to
the user: "Field 'data' is required for type with serial name
'...YouCamFileResponse', but it was missing at path: $".

Perfect Corp's AI Shoes try-on lives in the v2.0 family, not v1.0. The
v1.0 endpoint returns a legacy `result`-wrapped body, which none of the
response DTOs can decode. Both features now share one API_VERSION, so
the Feature(version, type) holder collapses to a plain feature name.

Two problems the version fix exposed:

- The shoes task takes `gender` and `style` instead of
  `garment_category`. Gender is pinned to "male" by product decision
  (Worn is an app for men) and style to "random"; both are constants,
  so nothing reaches the UI. `explicitNulls = false` keeps the fields
  that don't apply out of the request body rather than sending them as
  nulls, which shoes was previously doing for `garment_category`.
- No decodeFromString call was guarded, so a contract mismatch bypassed
  the friendly-message mapping in ensureSuccess and leaked an internal
  class name into the UI. A decode() helper now maps it to an
  actionable message and logs the raw body.

The existing tests could not have caught this: all four used TOP, and
the MockEngine matched on `path.contains("/file/")` without inspecting
the version segment. It now matches full paths, so a routing regression
404s and fails the test.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both files documented shoes as v1.0/shoes taking no garment category.
Shoes is v2.0/shoes and sends a fixed gender ("male", by product
decision) and style ("random") instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jvsena42
jvsena42 merged commit 220e105 into main Aug 2, 2026
2 checks passed
@jvsena42
jvsena42 deleted the fix/youcam-shoes-v2-routing branch August 2, 2026 23:55
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.

Bug trying shoe

1 participant