Skip to content

feat: preview selected links while composing - #4

Open
devjerry0 wants to merge 4 commits into
feat/draft-link-preview-apifrom
feat/composer-link-previews
Open

devjerry0 wants to merge 4 commits into
feat/draft-link-preview-apifrom
feat/composer-link-previews

Conversation

@devjerry0

@devjerry0 devjerry0 commented Oct 26, 2026 •

Copy link
Copy Markdown
Owner

Summary

Shows the selected link card while writing commits, replies, and quotes. Keeps the card mounted across writing/Preview and handles loading, cancellation, unavailable previews, and bounded polling.

Stack 5/6, split from closed #891. Depends on feat/draft-link-preview-api. This PR is in the fork to keep the review diff limited to this layer; open it upstream after its dependency lands.

Changes

Diff against this PR's base: 17 files, +1,238/-133. 64% of changed lines are tests, fixtures, or test support.

  • Debounce draft requests and abort stale client requests when the selected link changes. Keep an unavailable-card fallback.
  • Reuse the existing card renderer and extract its polling hook, including Retry-After handling and state resets between URLs/cycles.
  • Cover commits, replies, quotes, writing/Preview modes, stale responses, bounded polling, and unavailable/titleless previews.

Visual explanation

flowchart TD
    U["Selected composer URL"] --> D["400ms debounce; cancel stale request"]
    D --> C["Request shared draft preview"]
    C --> P{"Pending?"}
    P -- Yes --> Q["Bounded polling with Retry-After handling"]
    Q -- Completed --> P
    Q -- Exhausted --> R
    P -- No --> R["Render card or unavailable fallback"]
    R --> V["Same mounted card in writing and Preview"]
Loading

Stack and merge order

  1. Fetch boundaries and service contract — upstream
  2. External GIF verification
  3. Inline GIF playback
  4. Cached, queued draft API
  5. Composer link previews
  6. Optional mutation checks

Layers 2–6 target their immediate predecessor in the fork. Submit them upstream in order after their dependency lands; each review diff contains only its layer.

Validation

PreviewLink now lives under App\Contracts\Services (namespace-only follow-up, head dd4bf7522a00dbbfcf2e0a56f10ef93b848096ed). Focused fetching/verification suites and the final stack’s required checks passed after the move; the earlier per-layer results and implementation review below remain the baseline.

Container checks passed on PHP 8.5.12: 4,650 PHP tests / 25,764 assertions, 100% PHP coverage and type coverage, 223 Node tests, and 662 component tests across 53 files. PHPStan, TypeScript, lint, and production build pass (19 lint warnings, no errors).

Lint: Pint, Rector --dry-run --debug (same rules, serial execution), and Bun lint. Other commands: composer test:types, composer test:type-coverage, full parallel Pest CI coverage at exactly 100%, bun run test:unit, and bun run build.

Visual evidence

Selected GIF link preview before Commit

Desktop Chrome, dark theme, cropped to the relevant card/composer. Captured from the reassembled stack; no post was published and the existing draft was preserved.

The screenshot shows the selected card before Commit. Earlier desktop smoke also verified Giphy loading in quotes and retention when switching to Preview; no renewed before/after recording is attached.

Device verification

Desktop Chrome smoke only. No hardware/simulator mobile verification or renewed full viewport/theme/CLS matrix is claimed.

Independent review

Independent code review: PASS, base 5277cd0fc4549392fb4899e830f7505df7664d52, head b541a6cb256d955ff6e93d891e6188fc70d317c7. Full visual/device review remains incomplete.

Limitations

Hosted CI has not been verified for this new PR. The existing visual/device evidence gaps remain disclosed above.

Codex-Thread: 01a15b08-d4ad-7e72-8725-b3ea1fde71ce

Composer/quote/reply cards, debounce, resilient shared polling and fallback rendering.

Codex-Thread: 01a15b08-d4ad-7e72-8725-b3ea1fde71ce
Keep each layer based on the updated predecessor without rewriting history.

Codex-Thread: 01a15b08-d4ad-7e72-8725-b3ea1fde71ce
Keep the layer based on its updated predecessor without rewriting history.

Codex-Thread: 01a15b08-d4ad-7e72-8725-b3ea1fde71ce
Codex-Thread: 01a15b08-d4ad-7e72-8725-b3ea1fde71ce
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.

1 participant