Skip to content

refactor(app): extract prompt-input derived state into derived-state.ts - #1083

Merged
Astro-Han merged 2 commits into
devfrom
claude/prompt-input-derived-state
Jun 3, 2026
Merged

refactor(app): extract prompt-input derived state into derived-state.ts#1083
Astro-Han merged 2 commits into
devfrom
claude/prompt-input-derived-state

Conversation

@Astro-Han

@Astro-Han Astro-Han commented Jun 3, 2026

Copy link
Copy Markdown
Owner

Summary

Slice 1 of the prompt-input.tsx component-slimming line (continuation of the #1066 submit.ts/question-dock line, same prompt-input/ family). Pure extraction, no behavior change.

Moves the 12 read-only derived memos out of the PromptInput component into a new prompt-input/derived-state.ts factory createPromptDerivedState(deps):

  • info, status, working, imageAttachments, actionReady, abortReady
  • commentCount, blank, stopping, contextItems, placeholder, accepting

The factory takes injected deps (store, prompt, sync, sdk, permission, language, activeSessionID accessor, and actionReadyProp/abortReadyProp thunks wrapping props.actionReady?.() / props.abortReady?.()). Logic moved byte-faithfully; actionReady = actionReadyProp() ?? true and abortReady = abortReadyProp() ?? actionReady() preserved. Removed now-unused imports (isWorkInFlightStatus, promptPlaceholder, ImageAttachmentPart).

prompt-input.tsx: 659 -> 638 lines.

Test plan

  • bun run typecheck — 8/8 successful
  • bun test src/components/prompt-input — 382 pass, 2 fail identical to clean dev base (pre-existing command-prepend / path-b-integration env failures, unrelated)
  • eslint clean on both changed production files
  • /codex review — no P1/P2

Summary by CodeRabbit

  • Refactor
    • Internal code organization improvements to the prompt input component for better maintainability and code clarity.

Move the 12 read-only derived memos (info/status/working/imageAttachments/
actionReady/abortReady/commentCount/blank/stopping/contextItems/placeholder/
accepting) out of the PromptInput component into createPromptDerivedState.
Pure extraction, no behavior change.
@Astro-Han Astro-Han added the task Narrow execution, audit, spike, migration, tracking, or upstream follow-up work label Jun 3, 2026
@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@Astro-Han, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 43 minutes and 14 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ccf78b21-dae8-4bb7-a717-9eafb0bb3002

📥 Commits

Reviewing files that changed from the base of the PR and between 048f71a and 484d535.

📒 Files selected for processing (2)
  • packages/app/src/components/prompt-input.tsx
  • packages/app/src/components/prompt-input/derived-state.ts
📝 Walkthrough

Walkthrough

This PR refactors the prompt input component by extracting 12+ inline createMemo computations (session state, attachment filtering, readiness flags, comment counts, placeholder generation, and auto-accept logic) into a new createPromptDerivedState() hook, then updates the component to destructure and use these derived values instead of computing them inline.

Changes

Prompt input derived state refactoring

Layer / File(s) Summary
Derived state hook implementation
packages/app/src/components/prompt-input/derived-state.ts
New PromptDerivedStateDeps interface contracts dependencies (store, prompt, sync, SDK, permission, language, activeSessionID, optional readiness props). createPromptDerivedState() implements memo computations for session info/status, working state, image attachments, action/abort readiness, comment counts, blank/stopping checks, shell-mode context filtering, placeholder generation, and accepting flag, returning all 12+ values as a single derived state object.
Component integration and usage sites
packages/app/src/components/prompt-input.tsx
Removes ImageAttachmentPart import, adds createPromptDerivedState and related prompt-input imports. Removes old inline memo definitions for info, status, working, imageAttachments, actionReady, abortReady, commentCount, blank, stopping, contextItems, placeholder, and accepting. Calls createPromptDerivedState() to destructure all derived values. All downstream usage sites (send/stop readiness, editor placeholder, context filtering, auto-accept wiring) now reference the derived state values.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • Astro-Han/pawwork#1071: Refactors the abort implementation (createAbort/pending) used by createPromptSubmit, complementing this PR's extraction of readiness state computation.

Suggested labels

P2, app, ui, tech-debt

Poem

🐰 Memos once scattered, now neatly composed,
In derived-state.ts, their logic reposed,
A hook extracts, a component consumes,
The prompt flows cleaner through refactored rooms!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main refactoring: extracting derived state logic from prompt-input.tsx into a new derived-state.ts module.
Description check ✅ Passed The PR description includes all required template sections: Summary, Why (context for continuation), Human Review Status (Pending), Review Focus, Risk Notes (None), How To Verify (test results), and Checklist items are addressed.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/prompt-input-derived-state

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 and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the PromptInput component by extracting its derived state memos into a new helper function, createPromptDerivedState, in a separate file. The review feedback suggests a minor cleanup: since the status memo is only used internally within the new helper function to compute working, it does not need to be returned or destructured in the main component.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread packages/app/src/components/prompt-input.tsx
Comment thread packages/app/src/components/prompt-input/derived-state.ts
@github-actions github-actions Bot added app Application behavior and product flows ui Design system and user interface P2 Medium priority labels Jun 3, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested priority: P2 (includes user-path files (packages/app/src/components/prompt-input.tsx, packages/app/src/components/prompt-input/derived-state.ts)).

P1/P0 are reserved for maintainer confirmation. Please relabel manually if this is a release blocker, security issue, data-loss risk, or updater/runtime failure.

The status memo is only consumed internally by working() inside the
factory, so it no longer needs to be returned or destructured in
prompt-input.tsx. Behavior unchanged; status is still computed lazily.

Addresses gemini-code-assist review on #1083.
@Astro-Han
Astro-Han merged commit 349fea1 into dev Jun 3, 2026
33 of 34 checks passed
@Astro-Han
Astro-Han deleted the claude/prompt-input-derived-state branch June 3, 2026 01:09
Astro-Han added a commit that referenced this pull request Jun 3, 2026
…ts (#1091)

Slice 2 of the serial prompt-input.tsx slimming line (slice 1 = #1083). Pure
extraction, no behavior/DOM/aria/copy/storage-key change.

Change boundary:
- New prompt-input/commands-mode.ts exposing createPromptCommandsAndMode(deps):
  owns the pick() file-picker action, setMode() + the shellModeKey/normalModeKey
  constants, and the command.register("prompt-input", ...) registration
  (file.attach / prompt.mode.shell / prompt.mode.normal). Returns only { pick }
  (setMode and the mode keybinds have no external consumers).
- prompt-input.tsx now calls the factory synchronously at the cluster's original
  position, so command.register's owner-scoped onCleanup and the registration
  order (vs createPromptAttachments and the props.edit effect) are unchanged.
  Removed the now-unused canUseNativeFilePicker and pickAttachments imports.

Late-binding handled by injection seams (the only textual changes):
- addPickedPaths is produced by createPromptAttachments later in the file, so it
  is injected as the accessor thunk () => addPickedPaths and resolved as
  addPickedPaths() inside pick — preserving the pre-existing forward-reference
  closure timing (pick runs only post-mount).
- editorRef?.focus() -> editorRef()?.focus() (editorRef injected as a getter).
- () => fileInputRef?.click() -> injected fallbackInputClick.
Command ids, mod+u / mod+shift+x / mod+shift+e keybinds, language.t keys, and the
three disabled expressions are verbatim.

prompt-input.tsx 637 -> 601; commands-mode.ts +84.

Verification: typecheck 8/8, eslint clean on both files, targeted tests
394 pass / 2 pre-existing dev-base failures (command-prepend, path-b-integration:
isPromptEqual-not-found bun ESM load-order flake; neither imports the changed
files, zero regression). Independent review (codex, xhigh) GATE PASS, no P1/P2:
confirmed byte-faithful logic, no construction-time TDZ on the thunk, owner-scoped
registration preserved, reactivity preserved, imports correct, order unchanged.
No review threads raised.

Residual risk: none — pure extraction. The file-picker fallback hits native
platform.openFilePickerDialog, but that code is unchanged.
Astro-Han added a commit that referenced this pull request Jun 3, 2026
…ffect.ts (#1093)

Slice 3 of the serial prompt-input.tsx slimming line (slice 1 = #1083, slice 2 = #1091). Pure extraction, no behavior/DOM/aria/copy/storage-key change.

Change boundary:
- New prompt-input/edit-load-effect.ts exposing createEditLoadEffect(deps): sets
  up the deferred createEffect that loads an edit/followup draft into the editor
  (keyed on props.edit?.id). Returns void.
- prompt-input.tsx calls the factory synchronously at the effect's original
  position, so it registers in the component owner with { defer: true } intact and
  no ordering change. All deps (prompt, setStore, editorRef getter, queueScroll,
  editDraft, onEditLoaded) are available there — no late-binding.

Injection seams (the only textual changes):
- props.edit -> editDraft (accessor () => props.edit); the on() source
  () => editDraft()?.id still tracks props.edit?.id, so reactivity is unchanged.
- editorRef.focus() -> editorRef().focus(); setCursorPosition(editorRef, ...) ->
  setCursorPosition(editorRef(), ...) (editorRef injected as a getter).
- props.onEditLoaded?.() -> onEditLoaded() (injected thunk wrapping the optional
  call; fire timing preserved — synchronously after scheduling the rAF).
The 7 copied context fields, the four setStore calls, prompt.set, and the rAF
block are verbatim. props.edit / props.onEditLoaded are used only by this effect.

prompt-input.tsx 601 -> 572; edit-load-effect.ts +63.

Verification: typecheck 8/8, eslint clean on both files, targeted tests 404 pass /
2 pre-existing dev-base failures (command-prepend, path-b-integration: these
deterministically fail locally because they value-import prompt.tsx which loads
@solidjs/router, a client-only module that throws in bun's server test env without
a router mock — neither imports the changed files, zero regression; a standalone
fix PR is queued next). Independent review (codex, xhigh) GATE PASS, no P1/P2:
byte-faithful effect body, equivalent reactivity, preserved defer, owner-scoped
registration, correct imports.

Residual risk: none — pure extraction.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app Application behavior and product flows P2 Medium priority task Narrow execution, audit, spike, migration, tracking, or upstream follow-up work ui Design system and user interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant