Skip to content

refactor(compose): split the 1579-line compose modal into hooks and a publish helper - #385

Merged
PastaPastaPasta merged 2 commits into
stagingfrom
refactor/compose-split
Sep 8, 2026
Merged

refactor(compose): split the 1579-line compose modal into hooks and a publish helper#385
PastaPastaPasta merged 2 commits into
stagingfrom
refactor/compose-split

Conversation

@PastaPastaPasta

Copy link
Copy Markdown
Owner

Summary

components/compose/compose-modal.tsx (1579 lines) is now 598 lines of composition. What moved out:

  • hooks/use-compose-image.ts: pick / paste / upload / preview-URL lifecycle and the storage-provider gate. File-select and paste shared 30 duplicated lines; they now share one attach.
  • hooks/use-compose-private-feed.ts: private-feed status on open, plus the enable flow (add key to identity → enter key → enable → apply the requested visibility).
  • hooks/use-inherited-encryption.ts: the reply-to-private-post source lookup with cancellation and retry (the old file had this logic twice: once in an effect, once in a retry callback).
  • hooks/use-compose-poll.ts: draft / created-id / unconfirmed state and the detach-with-toast rule.
  • lib/compose/publish-thread.ts: planPosts and publishThread, the per-document creation loop (encryption options, reply linkage, unconfirmed-reference gate, retry, SYNC_REQUIRED, timeout, index registration, events). It returns an outcome; the modal turns that into toasts, markThreadPostAsPosted and the active-post cursor.

Behaviour preserved: every canPost / canAddThread / canAttachPoll guard, poll-first ordering and the unconfirmed-poll retry gate, the encrypted-thread trim, character accounting for the image URL, partial-success reporting and the thread events, hashtag/mention indexing rules (teaser only for private, nothing for inherited), Ctrl/⌘+Enter.

Not touched: compose-sub-components.tsx, thread-post-editor.tsx, poll-editor.tsx, visibility-selector.tsx.

Part of the anti-slop cleanup series (after #370#384).

Test plan

  • npm run lint (zero warnings), tsc --noEmit, npm run test, npx knip, npm run build all green locally
  • CI
  • Manual: public post, thread of three, reply, quote, private post and private-with-teaser (incl. enabling a private feed from the selector), reply to a private post, image attach via button and paste, poll attach + post, NSFW toggle, Ctrl+Enter

🤖 Generated with Claude Code

… publish helper

compose-modal.tsx owned the image attachment (pick, paste, upload, preview URL), the private-feed enable flow, the inherited-encryption check for replies, the poll attachment, and a 570-line post handler that created the thread one document at a time. It is 598 lines now and composes hooks/use-compose-image.ts, use-compose-private-feed.ts, use-inherited-encryption.ts and use-compose-poll.ts, with the per-document loop in lib/compose/publish-thread.ts returning an outcome the modal turns into toasts and store updates.

Behaviour kept: the same guards on canPost and canAddThread, the poll-first ordering and the unconfirmed-poll retry gate, the SYNC_REQUIRED abort, timeout-as-retry, partial-thread reporting, hashtag/mention indexing rules for private and inherited posts, and the created events. The file-select and paste paths now share one attach routine.
@coderabbitai

coderabbitai Bot commented Sep 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: 8b16719d-381c-4025-bd0c-467f4907c8ec

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying yappr with  Cloudflare Pages  Cloudflare Pages

Latest commit: fa536ae
Status: ✅  Deploy successful!
Preview URL: https://aa6c6278.yappr.pages.dev
Branch Preview URL: https://refactor-compose-split.yappr.pages.dev

View logs

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 8, 2026

Copy link
Copy Markdown

Deploying yappr-v2 with  Cloudflare Pages  Cloudflare Pages

Latest commit: ffce600
Status:⚡️  Build in progress...

View logs

CHARACTER_LIMIT moves to lib/compose/limits.ts so lib no longer imports a component; publish-thread drops its pass-through re-exports and its nested ternaries; planPosts gets a spec. In the modal the five stopPosting calls shadowed by the finally block go, the dead Complete! progress goes, the upload progress only shows when an upload is pending, the dark-mode teaser placeholder colour is restored, and the encrypted-thread guard drops a redundant conjunct. remove() in the image hook leaves revocation to the effect that owns it.
@PastaPastaPasta
PastaPastaPasta merged commit a329ffe into staging Sep 8, 2026
8 of 9 checks passed
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