fix(embeds): GIF previews keep their own size and shape (#341) #344

Merged
jared merged 2 commits from fix/gif-card-aspect into lotus 2026-10-11 00:53:26 -04:00
Owner

Fixes #341

Giphy and Tenor link previews forced every GIF into one box: full card width, max 200 px tall, object-fit: cover. Square GIFs lost half their height, portrait ones three quarters, and small ones were blown up 4×.

Change

  • utils/gifPreviewSize.ts (+ 6 unit tests): fit the GIF inside 400×320 from og:image:width/height, keeping its aspect ratio and enlarging small GIFs at most 2×.
  • GifCard: centres the GIF on the surface colour with object-fit: contain and reserves the box before load. The "GIF" badge sits on the GIF's own corner.
    • Without dimensions it shows at natural size, capped by the card.
    • The >10 MB thumbnail fallback is requested at 800×640.

Before → after (headless Chromium, fixture previews shaped like Synapse's Giphy response)

GIF before after (desktop) after (320 px phone)
480×200 398×166, 100% 398×166, 100% 292×122, 100%
300×300 398×200, 50% of height 320×320, 100% 292×292, 100%
240×480 398×200, 25% of height 160×320, 100% 160×320, 100%
100×80 398×200, upscaled 4×, 63% 200×160, 100% 200×160, 100%

Checks: tsc clean · unit tests 1325 pass / 2 skipped · ESLint 0 errors (36 warnings, unchanged) · Prettier clean.

Before (lotus): tall 240×480 GIF

Before (lotus): tall 240×480 GIF

After: wide, square, tall and small test GIFs, each shown whole

After: wide, square, tall and small test GIFs, each shown whole

🤖 Generated with Claude Code

https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA

Fixes #341 Giphy and Tenor link previews forced every GIF into one box: full card width, max 200 px tall, `object-fit: cover`. Square GIFs lost half their height, portrait ones three quarters, and small ones were blown up 4×. **Change** - `utils/gifPreviewSize.ts` (+ 6 unit tests): fit the GIF inside 400×320 from `og:image:width/height`, keeping its aspect ratio and enlarging small GIFs at most 2×. - `GifCard`: centres the GIF on the surface colour with `object-fit: contain` and reserves the box before load. The "GIF" badge sits on the GIF's own corner. - Without dimensions it shows at natural size, capped by the card. - The >10 MB thumbnail fallback is requested at 800×640. **Before → after** (headless Chromium, fixture previews shaped like Synapse's Giphy response) | GIF | before | after (desktop) | after (320 px phone) | |---|---|---|---| | 480×200 | 398×166, 100% | 398×166, 100% | 292×122, 100% | | 300×300 | 398×200, 50% of height | 320×320, 100% | 292×292, 100% | | 240×480 | 398×200, 25% of height | 160×320, 100% | 160×320, 100% | | 100×80 | 398×200, upscaled 4×, 63% | 200×160, 100% | 200×160, 100% | **Checks:** `tsc` clean · unit tests 1325 pass / 2 skipped · ESLint 0 errors (36 warnings, unchanged) · Prettier clean. **Before (lotus): tall 240×480 GIF** ![Before (lotus): tall 240×480 GIF](https://code.lotusguild.org/attachments/bda7a72c-21e3-44b1-9884-d72ff80049c3) **After: wide, square, tall and small test GIFs, each shown whole** ![After: wide, square, tall and small test GIFs, each shown whole](https://code.lotusguild.org/attachments/52166136-7a78-4c3f-851f-85218640dc70) 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
jared added 1 commit 2026-10-10 22:16:11 -04:00
fix(embeds): GIF previews keep their own size and shape (#341)
CI / Build & Quality Checks (pull_request) Failing after 3m21s
CI / Trigger Desktop Build (pull_request) Skipped
CI / Docker image build & smoke test (pull_request) Skipped
CI / Playwright smoke (e2e) (pull_request) Skipped
CI / Secret scan (gitleaks) (pull_request) Successful in 8s
68f44f0f1c
Giphy and Tenor link previews forced every GIF into the same box — full
card width, max 200px tall, object-fit: cover — whatever its shape: a
square GIF lost half its height, a portrait one three quarters (only the
middle band showed, so captions and faces at the top/bottom were cut), and
a 100×80 GIF was blown up 4×.

utils/gifPreviewSize.ts (unit-tested) fits the GIF inside 400×320 from
og:image:width/height, keeping its aspect ratio and enlarging small GIFs
at most 2×. The card centres the GIF on the surface colour with
object-fit: contain, reserves the box before it loads, and the GIF badge
sits on the GIF's corner. Without dimensions it shows at natural size,
capped by the card. The >10 MB thumbnail fallback is requested at 2× the
box (800×640) so it isn't upscaled.

Verified headless (fixture previews, desktop / Pixel 7 / 320px phone):
480×200 → 398×166, 300×300 → 320×320 (292×292 on 320px), 240×480 →
160×320, 100×80 → 200×160, all 100% visible; the no-dimension fallback
and narrow cards keep the ratio. tsc clean, 1325 unit tests pass, eslint
0 errors (36 warnings, unchanged), prettier clean.

Fixes #341

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
Author
Owner

CI note: the only failing step is npm audit --audit-level=high (new source-map-js advisory, unrelated to this change; tracked in #345). Build, ESLint, unit tests and boot-check passed in run 2417.

CI note: the only failing step is `npm audit --audit-level=high` (new source-map-js advisory, unrelated to this change; tracked in #345). Build, ESLint, unit tests and boot-check passed in run 2417.
Author
Owner

Merged deps/npm-audit-fixes (#346) into this branch so the CI audit step passes here too. Once #346 is merged into lotus, that commit drops out of this diff. Merge order: #346, then this one.

Merged `deps/npm-audit-fixes` (#346) into this branch so the CI audit step passes here too. Once #346 is merged into lotus, that commit drops out of this diff. Merge order: #346, then this one.
jared added 2 commits 2026-10-10 22:45:11 -04:00
deps: fix the npm audit advisories that turned CI red (#345)
CI / Build & Quality Checks (pull_request) Successful in 2m58s
CI / Trigger Desktop Build (pull_request) Skipped
CI / Docker image build & smoke test (pull_request) Skipped
CI / Secret scan (gitleaks) (pull_request) Successful in 7s
CI / Playwright smoke (e2e) (pull_request) Successful in 12m35s
c9d276d2a5
`npm audit --audit-level=high --omit=dev` (Build & Quality Checks) started
failing on every branch after new advisories were published:

- source-map-js 1.2.1 → 1.2.2 (high, GHSA-68fv-2mgg-jv7q; transitive via
  sanitize-html → postcss, in range — lockfile only)
- i18next-http-backend 4.0.0 → 4.0.2 (low, GHSA-xvq9-wjp8-hwqf)
- katex 0.16.47 → 0.18.11 (low, GHSA-238p-pmpm-9mq7; fixed in 0.18.2).
  0.17/0.18's breaking changes are an internal __defineFunction API and
  prefixed internal CSS classes; Lotus uses neither (KaTeX.tsx calls
  renderToString and imports the package's own stylesheet).

Only these four lockfile entries change (plus katex's own CLI dependency
commander 8 → 15). npm audit --omit=dev: 0 vulnerabilities.

Verified headless against Vite with a fresh dep cache (katex 0.18.11
served): inline and display math render (\frac, \sqrt, \sum with limits),
KaTeX fonts load, no page errors; translations still load (en strings,
no raw keys). tsc clean, 1319 unit tests pass, eslint 0 errors (36
warnings, unchanged), prettier clean, production build OK.

Fixes #345

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
Merge branch 'deps/npm-audit-fixes' into fix/gif-card-aspect
CI / Build & Quality Checks (pull_request) Successful in 3m0s
CI / Trigger Desktop Build (pull_request) Skipped
CI / Docker image build & smoke test (pull_request) Skipped
CI / Secret scan (gitleaks) (pull_request) Successful in 7s
CI / Playwright smoke (e2e) (pull_request) Successful in 11m31s
747714b2f3
Brings in #346 (npm audit fixes) so this PR's CI audit step passes; the
shared commit drops out of this PR's diff once #346 is merged into lotus.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
jared merged commit 022e5e6987 into lotus 2026-10-11 00:53:26 -04:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/cinny#344