Add listing drafts, flip photos and a Firefox listing helper #23

Merged
kubus merged 2 commits from feat/listing-extension into feat/ios-reseller 2026-10-01 12:42:55 +00:00
Owner

Stacked on #22 → #21 → #20. Merge those in order, then switch this PR's base to main.

List a flip on OLX, Allegro Lokalnie and Vinted without typing it three times. Only OLX has a listing API (partner program), and scripting the other two would risk your accounts. So this is a Firefox extension that fills the form in your own browser; you check it and publish. Nothing is submitted automatically.

What's in it

  • Listing draft per flip (web: megaphone button on an unsold flip):
    • title, description, condition, and an asking price per platform
    • prices suggested from your fee presets so each platform leaves the same amount (1450 → Lokalnie 1525)
    • up to 20 photos: upload, reorder, delete, resized in the browser to 2000 px
  • Photos from the phone: the iOS flip editor gets a photo picker. HEIC becomes a 2000 px JPEG and is uploaded immediately; long-press a photo to delete it.
  • Server: migration 032 adds flips.listing_json and flip_photos.
    • Photos are checked by their bytes: JPEG, PNG or WebP only, 10 MB each, 20 per flip.
    • They are served only with auth and a sandboxing CSP.
    • Like the ledger, they are never pruned and are hidden from the Debug API: table list, read-only SQL and snapshots.
  • Extension (extension/), Manifest V2 for Firefox 115+:
    • The toolbar popup lists unsold flips with one button per platform. It opens that site's form, and a small Scout panel offers Fill this form.
    • Fields are found by their visible Polish labels (Tytuł, Opis, Cena, Stan). Values are set so React forms register them, and photos are attached to the site's file input.
    • I published it ticks the platform in "Listed on", which feeds the delist checklist.
    • Report form fields copies a description of the form's controls (names and labels, no data) for tuning after a redesign. Download photos is the fallback for dragging photos in by hand.
    • The API token stays in the background page; marketplace pages never see it. The extension declares no data collection.
    • Install steps (temporary, signed unlisted, or Developer Edition) are in extension/README.md. npm run extension:lint and npm run extension:build are added.

Verification

  • npm run typecheck, npm test (260/260), npm run build; web-ext lint reports 0 errors, 0 warnings and 0 notices; ScoutKit swift test passes 62/62 on Linux, with new photo round-trip and decoding tests.
  • Server with sign-in and an API token:
    • Listing drafts and photo upload work.
    • An SVG disguised as PNG gets 415, 11 MB gets 413, and photo reads without a token get 401.
  • The real background.js (Firefox APIs stubbed) against that server:
    • lists flips and opens the Lokalnie form
    • hands the job only to that tab
    • delivers both photos byte-exact
    • "I published it" updates listedOn and clears the job
    • a wrong token gets a clear message
  • filler.js in Chromium on a React form served at www.olx.pl:
    • title, multi-line description and price reach React state
    • condition "Używane" is picked from a custom dropdown
    • both photos land in the hidden multi-file input
    • the search box is left alone, and there are no page errors
  • Not verified: the real OLX, Lokalnie and Vinted forms (they require login), Firefox itself (the content-script sandbox differs slightly from Chromium), and the iOS photo picker (no Swift UI build on Linux). "Report form fields" is there to tune the matching quickly.

🤖 Generated with Claude Code

**Stacked on #22 → #21 → #20.** Merge those in order, then switch this PR's base to `main`. List a flip on OLX, Allegro Lokalnie and Vinted without typing it three times. Only OLX has a listing API (partner program), and scripting the other two would risk your accounts. So this is a **Firefox extension that fills the form in your own browser; you check it and publish**. Nothing is submitted automatically. ## What's in it - **Listing draft per flip** (web: megaphone button on an unsold flip): - title, description, condition, and an asking price per platform - prices suggested from your fee presets so each platform leaves the same amount (1450 → Lokalnie 1525) - up to 20 photos: upload, reorder, delete, resized in the browser to 2000 px - **Photos from the phone:** the iOS flip editor gets a photo picker. HEIC becomes a 2000 px JPEG and is uploaded immediately; long-press a photo to delete it. - **Server:** migration 032 adds `flips.listing_json` and `flip_photos`. - Photos are checked by their bytes: JPEG, PNG or WebP only, 10 MB each, 20 per flip. - They are served only with auth and a sandboxing CSP. - Like the ledger, they are never pruned and are hidden from the Debug API: table list, read-only SQL and snapshots. - **Extension (`extension/`)**, Manifest V2 for Firefox 115+: - The toolbar popup lists unsold flips with one button per platform. It opens that site's form, and a small Scout panel offers **Fill this form**. - Fields are found by their visible Polish labels (Tytuł, Opis, Cena, Stan). Values are set so React forms register them, and photos are attached to the site's file input. - **I published it** ticks the platform in "Listed on", which feeds the delist checklist. - **Report form fields** copies a description of the form's controls (names and labels, no data) for tuning after a redesign. **Download photos** is the fallback for dragging photos in by hand. - The API token stays in the background page; marketplace pages never see it. The extension declares no data collection. - Install steps (temporary, signed unlisted, or Developer Edition) are in `extension/README.md`. `npm run extension:lint` and `npm run extension:build` are added. ## Verification - `npm run typecheck`, `npm test` (260/260), `npm run build`; `web-ext lint` reports 0 errors, 0 warnings and 0 notices; ScoutKit `swift test` passes 62/62 on Linux, with new photo round-trip and decoding tests. - **Server with sign-in and an API token:** - Listing drafts and photo upload work. - An SVG disguised as PNG gets 415, 11 MB gets 413, and photo reads without a token get 401. - **The real `background.js`** (Firefox APIs stubbed) against that server: - lists flips and opens the Lokalnie form - hands the job only to that tab - delivers both photos byte-exact - "I published it" updates `listedOn` and clears the job - a wrong token gets a clear message - **`filler.js` in Chromium** on a React form served at `www.olx.pl`: - title, multi-line description and price reach React state - condition "Używane" is picked from a custom dropdown - both photos land in the hidden multi-file input - the search box is left alone, and there are no page errors - **Not verified:** the real OLX, Lokalnie and Vinted forms (they require login), Firefox itself (the content-script sandbox differs slightly from Chromium), and the iOS photo picker (no Swift UI build on Linux). "Report form fields" is there to tune the matching quickly. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Add listing drafts, flip photos and a Firefox listing helper
Some checks failed
ci / verify (pull_request) Has been cancelled
128bd24400
Each unsold flip can hold what to post: title, description, condition, an
asking price per platform (suggested from the fee presets so every platform
leaves the same amount) and up to 20 photos. The new Scout listing helper
extension for Firefox opens the OLX, Allegro Lokalnie or Vinted listing
form, fills it from the flip, attaches the photos, and marks the platform
as listed once the operator has published. It never submits a form.

- Server: listing_json on flips and a flip_photos table (migration 032).
  Photos are checked by their bytes (JPEG, PNG, WebP; 10 MB; 20 per flip),
  served only to authenticated clients with a sandboxing CSP, never pruned,
  and hidden from the Debug API like the ledger.
- Web: a listing dialog per flip with price suggestions and photo upload,
  reorder and delete; photos are resized in the browser to 2000 px.
- Extension (extension/): Manifest V2 for Firefox 115+. The token stays in
  the background page; content scripts find fields by their visible Polish
  labels, set values so React forms register them, attach photos to the
  site's file input, and offer "Report form fields" for tuning after a
  redesign. Lints clean with web-ext.
- iOS: add listing photos to a flip from the phone (HEIC becomes a 2000 px
  JPEG), long-press to delete; ScoutKit client calls, demo routes and tests.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Merge feat/ios-reseller (with main) into feat/listing-extension
Some checks failed
ci / verify (pull_request) Has been cancelled
1d1da61a00
Keeps the photo and listing imports alongside main's dashboardTopParam and
the event-stream subscription FlipsPage now uses, and orders 032_flip_listings
after main's 030_perf_indexes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
kubus merged commit 59a3c2cb64 into feat/ios-reseller 2026-10-01 12:42:55 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
kubus/scout!23
No description provided.