Skip to content

Prompt the user for attachement type after dragging the file#2563

Merged
wwwillchen merged 5 commits intodyad-sh:mainfrom
azizmejri1:file-attachement-type
Feb 12, 2026
Merged

Prompt the user for attachement type after dragging the file#2563
wwwillchen merged 5 commits intodyad-sh:mainfrom
azizmejri1:file-attachement-type

Conversation

@azizmejri1
Copy link
Copy Markdown
Collaborator

@azizmejri1 azizmejri1 commented Feb 8, 2026


Open with Devin

Summary by cubic

Show a dialog after dragging or pasting files into chat to choose how to attach them—as chat context or upload to codebase. This makes intent explicit and blocks submit, drop, and paste until you choose.

  • New Features

    • Added FileAttachmentTypeDialog; integrated in ChatInput and HomeChatInput. i18n (en, pt-BR, zh-CN) with singular/plural titles and descriptions.
    • Updated useAttachments with pendingFiles and confirm/cancel. Drag/paste set pendingFiles; prevent attaching while pending; clearAttachments also clears pendingFiles; submit blocked when dialog is open.
    • Fixed e2e to select “Attach file as chat context”; dialog buttons use type="button" with focus-visible ring.
  • Refactors

    • confirmPendingFiles reuses addAttachments to deduplicate logic.

Written for commit b625847. Summary will update on new commits.

@wwwillchen
Copy link
Copy Markdown
Collaborator

@BugBot run

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @azizmejri1, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the user experience for file attachments by introducing an intermediate step when files are dragged and dropped. Instead of automatically attaching files as chat context, users are now presented with a dialog to explicitly choose how they want the files to be handled: either as context for the AI or as files to be uploaded to the codebase. This provides greater control and clarity for the user regarding the purpose of their attached files.

Highlights

  • New Attachment Type Dialog: Introduced a new dialog that prompts users to select an attachment type ('Attach as chat context' or 'Upload to codebase') immediately after dragging and dropping files into the chat input.
  • Refactored Attachment Hook: The useAttachments hook has been updated to manage a pendingDroppedFiles state, along with new confirmDroppedFiles and cancelDroppedFiles functions, to support the new interactive attachment flow.
  • UI Integration: The new FileAttachmentTypeDialog component has been integrated into both ChatInput.tsx and HomeChatInput.tsx to provide a consistent user experience for file attachments.
  • E2E Test Update: An existing end-to-end test (attach_image.spec.ts) was updated to account for the new attachment type dialog, ensuring the automated flow correctly selects 'Attach as chat context'.
Changelog
  • e2e-tests/attach_image.spec.ts
    • Updated the e2e test to interact with the new attachment type dialog, specifically clicking the 'Attach as chat context' button after a file drag-and-drop.
  • src/components/chat/ChatInput.tsx
    • Imported the new FileAttachmentTypeDialog component.
    • Modified the useAttachments hook destructuring to include pendingDroppedFiles, confirmDroppedFiles, and cancelDroppedFiles.
    • Rendered the FileAttachmentTypeDialog within the ChatInput component, passing the necessary props for file handling.
  • src/components/chat/FileAttachmentTypeDialog.tsx
    • Added a new React component FileAttachmentTypeDialog responsible for displaying the attachment type selection dialog.
    • Implemented UI for two attachment options: 'Attach as chat context' and 'Upload to codebase', each with descriptive text and icons.
    • Manages its visibility based on the pendingFiles prop and triggers onConfirm or onCancel callbacks.
  • src/components/chat/HomeChatInput.tsx
    • Imported the new FileAttachmentTypeDialog component.
    • Modified the useAttachments hook destructuring to include pendingDroppedFiles, confirmDroppedFiles, and cancelDroppedFiles.
    • Rendered the FileAttachmentTypeDialog within the HomeChatInput component, mirroring the integration in ChatInput.tsx.
  • src/hooks/useAttachments.ts
    • Imported useCallback for memoizing functions.
    • Introduced a new state variable pendingDroppedFiles to temporarily store files after a drag-and-drop event, awaiting user confirmation.
    • Modified the handleDrop function to set pendingDroppedFiles instead of directly adding attachments.
    • Added confirmDroppedFiles function to process pendingDroppedFiles with the chosen attachment type and add them to the main attachments list.
    • Added cancelDroppedFiles function to clear pendingDroppedFiles if the user cancels the dialog.
    • Exported pendingDroppedFiles, confirmDroppedFiles, and cancelDroppedFiles from the hook for external consumption.
Activity
  • The pull request was created by azizmejri1.
  • No other activity (comments, reviews, or progress updates) has been recorded yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 5 files

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 5 additional findings.

Open in Devin Review

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Feb 8, 2026

Greptile Overview

Greptile Summary

This PR adds a dialog to prompt users for attachment type (chat context vs. upload to codebase) after dragging or pasting files. The implementation introduces a pendingFiles state that blocks submission until the user makes a choice, ensuring explicit intent.

  • Added FileAttachmentTypeDialog component with i18n support for English, Portuguese, and Chinese
  • Updated useAttachments hook to manage pendingFiles state and provide confirmPendingFiles/cancelPendingFiles callbacks
  • Integrated dialog into both ChatInput and HomeChatInput components with submission blocking
  • Updated e2e tests to handle the new dialog interaction
  • Prevented drag/drop and paste operations when pendingFiles already exists

Issues Found:

  • Critical: Missing dependency addAttachments in confirmPendingFiles useCallback (src/hooks/useAttachments.ts:82-90) causes stale closure bug

Confidence Score: 3/5

  • This PR has a critical dependency array bug that needs fixing before merge
  • The feature implementation is solid with proper i18n, dialog UX, and submission blocking. However, there's a critical React hooks bug in useAttachments.ts where confirmPendingFiles is missing addAttachments from its dependency array (line 89). This creates a stale closure that could cause unexpected behavior. Once this dependency is added, the PR would be safe to merge.
  • Pay close attention to src/hooks/useAttachments.ts - the missing dependency in the useCallback must be fixed

Important Files Changed

Filename Overview
src/hooks/useAttachments.ts Added pendingFiles state and dialog flow; missing dependency in useCallback causes stale closure bug
src/components/chat/FileAttachmentTypeDialog.tsx New dialog component for choosing attachment type; clean implementation with i18n support
src/components/chat/ChatInput.tsx Integrated FileAttachmentTypeDialog and pendingFiles blocking logic correctly
src/components/chat/HomeChatInput.tsx Integrated FileAttachmentTypeDialog and pendingFiles blocking logic correctly

Sequence Diagram

sequenceDiagram
    participant User
    participant ChatInput
    participant useAttachments
    participant FileAttachmentTypeDialog
    participant attachmentsAtom

    User->>ChatInput: Drag/Paste files
    ChatInput->>useAttachments: handleDrop/handlePaste
    useAttachments->>useAttachments: setPendingFiles(files)
    useAttachments-->>ChatInput: pendingFiles updated
    ChatInput->>FileAttachmentTypeDialog: Show dialog (pendingFiles)
    FileAttachmentTypeDialog-->>User: Display options
    User->>FileAttachmentTypeDialog: Select attachment type
    FileAttachmentTypeDialog->>useAttachments: confirmPendingFiles(type)
    useAttachments->>useAttachments: addAttachments(pendingFiles, type)
    useAttachments->>attachmentsAtom: setAttachments([...attachments, ...new])
    useAttachments->>useAttachments: setPendingFiles(null)
    useAttachments-->>FileAttachmentTypeDialog: pendingFiles = null
    FileAttachmentTypeDialog-->>User: Dialog closes
    User->>ChatInput: Submit message
    ChatInput->>useAttachments: Check pendingFiles
    alt pendingFiles exists
        ChatInput-->>User: Block submission
    else pendingFiles is null
        ChatInput-->>User: Allow submission
    end
Loading

Copy link
Copy Markdown
Contributor

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

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 introduces a dialog that prompts the user to select an attachment type ('chat context' or 'upload to codebase') after dragging and dropping files into the chat input. The changes are well-implemented across the useAttachments hook, a new FileAttachmentTypeDialog component, and updates to ChatInput and HomeChatInput. The e2e tests have also been updated to cover this new user flow. My feedback includes a suggestion to improve the implementation of useCallback in the useAttachments hook for better stability and adherence to React best practices.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 8, 2026

🔍 Multi-Agent Code Review

Found 3 new issue(s) flagged by 3 independent reviewers.

Summary

Severity Count
🟡 MEDIUM 3

Issues to Address

Severity File Issue
🟡 MEDIUM src/hooks/useAttachments.ts:65 Rapid successive drops silently discard pending files
🟡 MEDIUM src/components/chat/FileAttachmentTypeDialog.tsx:42 Dialog buttons missing type="button" attribute
🟡 MEDIUM src/hooks/useAttachments.ts:69 Inconsistent useCallback memoization pattern
🟢 Low Priority Issues (2 items)
  • E2E test only covers 'chat-context' path for drag-and-drop - e2e-tests/attach_image.spec.ts:154 - No test for the 'Upload to codebase' option via drag-and-drop dialog
  • E2E test does not verify cancel/dismiss behavior - e2e-tests/attach_image.spec.ts - No test verifies that dismissing the dialog results in no files attached

See inline comments for details.

Generated by multi-agent consensus review (3 independent agents)

Copy link
Copy Markdown
Collaborator

@wwwillchen wwwillchen left a comment

Choose a reason for hiding this comment

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

feedback from mtg: should do this same UX for pasting via keyboard shortcut

@wwwillchen
Copy link
Copy Markdown
Collaborator

@BugBot run

@wwwillchen
Copy link
Copy Markdown
Collaborator

@BugBot run

Copy link
Copy Markdown
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Swarm review: 3 issue(s) found

@github-actions
Copy link
Copy Markdown
Contributor

🔍 Dyadbot Code Review Summary

Verdict: 🤔 NOT SURE - Potential issues

Reviewed by 3 specialized agents: Correctness Expert, Code Health Expert, UX Wizard.

Issues Summary

# Severity File Issue Found By Endorsed By
1 🟡 MEDIUM src/hooks/useAttachments.ts:10 handleFileSelect bypasses pending files dialog Correctness Code Health, UX
2 🟡 MEDIUM src/components/chat/FileAttachmentTypeDialog.tsx:42 No file name preview in dialog UX Correctness, Code Health
3 🟡 MEDIUM src/components/chat/FileAttachmentTypeDialog.tsx:48 Custom buttons lack focus ring styles UX Correctness
🟢 Low Priority Notes (4 items)
  • Duplicated dialog integration - ChatInput.tsx & HomeChatInput.tsx have identical 7-line dialog blocks (Code Health, endorsed by Correctness)
  • E2e test only covers "chat context" path - e2e-tests/attach_image.spec.ts:157 - no test for "upload to codebase" or cancel flow (Correctness)
  • No visual distinction between file types - Dialog doesn't indicate whether files are images vs documents (UX)
  • Naming note - pendingFiles naming is fine; existing comment references to pendingDroppedFiles are from an earlier revision (Code Health)

Generated by Dyadbot swarm code review (3 agents, consensus-based)

@github-actions
Copy link
Copy Markdown
Contributor

🔍 Dyadbot Code Review Summary (Updated)

Verdict: ⛔ NO - Do NOT merge — Has significant data-integrity and UX regression issues that need to be fixed.

Reviewed by 3 specialized agents: Correctness Expert, Code Health Expert, UX Wizard.

Issues Summary

# Severity File Issue Found By Endorsed By
1 🔴 HIGH src/hooks/useAttachments.ts:75 User can submit while dialog is open, silently losing files Correctness
2 🟡 MEDIUM src/hooks/useAttachments.ts:133 Paste now requires dialog for all images — UX regression Correctness UX
3 🟡 MEDIUM src/components/chat/FileAttachmentTypeDialog.tsx:42 No file name preview in dialog UX Correctness, Code Health
4 🟡 MEDIUM src/components/chat/FileAttachmentTypeDialog.tsx:48 Custom buttons lack focus ring styles UX Correctness

Note: Issue #1 was upgraded to HIGH after cross-discussion — all three reviewers agreed this is a real data-loss scenario where files are silently dropped.

🟢 Low Priority Notes (4 items)
  • handleFileSelect bypasses dialog — Intentionally correct: the file picker dropdown already asks for type upfront. Add a code comment explaining this. (Correctness, all 3 endorsed)
  • Duplicated dialog integrationChatInput.tsx & HomeChatInput.tsx have identical 7-line dialog blocks (Code Health, Correctness)
  • E2e test only covers "chat context" path — No test for "upload to codebase" or cancel flow (Correctness)
  • addAttachments helper underusedconfirmPendingFiles, handleFileChange, handleFileSelect all duplicate the same File→FileAttachment mapping instead of calling addAttachments (Code Health)

Generated by Dyadbot swarm code review (3 agents, consensus-based)

@wwwillchen
Copy link
Copy Markdown
Collaborator

@BugBot run

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 11, 2026

🔍 Dyadbot Swarm Code Review Summary

Verdict: ⛔ NO - Do NOT merge — Has a HIGH severity data-loss issue plus multiple MEDIUM issues that should be addressed.

Reviewed by 3 specialized agents (Correctness Expert, Code Health Expert, UX Wizard) using consensus-based discussion.

Issues Summary

# Severity File Issue Found By
1 🔴 HIGH src/hooks/useAttachments.ts:75 User can submit chat while dialog is open, silently losing pending files Correctness (existing)
2 🟡 MEDIUM src/hooks/useAttachments.ts:133 handlePaste now requires dialog for ALL pasted images — UX regression Correctness (existing)
3 🟡 MEDIUM src/hooks/useAttachments.ts:91 clearAttachments doesn't clear pendingFiles — orphaned dialog state Correctness 🆕
4 🟡 MEDIUM src/hooks/useAttachments.ts:73 confirmPendingFiles duplicates addAttachments logic (4x duplication) Code Health 🆕
5 🟡 MEDIUM src/components/chat/FileAttachmentTypeDialog.tsx:35 Dialog strings not internationalized (8 sibling components use i18n) UX 🆕
6 🟡 MEDIUM src/components/chat/FileAttachmentTypeDialog.tsx:43 Raw <button> instead of project's Button component UX 🆕
7 🟡 MEDIUM src/components/chat/FileAttachmentTypeDialog.tsx:44 Dialog buttons missing type="button" attribute Code Health (existing)
8 🟡 MEDIUM src/components/chat/FileAttachmentTypeDialog.tsx:48 Custom buttons lack focus ring styles UX (existing)
9 🟡 MEDIUM src/components/chat/FileAttachmentTypeDialog.tsx:42 No file name preview in dialog UX (existing)
10 🟡 MEDIUM src/hooks/useAttachments.ts:10 handleFileSelect bypasses the pending files dialog Correctness (existing)

🆕 = newly found by this swarm review (not in prior reviews)

Recommendation

Issue #1 (HIGH) is a data-loss scenario that must be addressed. Issue #2 (MEDIUM) is a significant UX regression for the common screenshot paste workflow. Issues #3-#6 are new findings from this swarm review that should also be addressed.

🟢 Low Priority Notes (6 items)
  • pendingFiles is local state while attachments is global jotai atom — state mismatch if multiple hook instances exist simultaneously (Correctness) 🆕
  • cancelPendingFiles doesn't need useCallback with empty deps — inconsistent with rest of hook (Code Health)
  • handlePaste calls e.preventDefault() before confirming files were extracted — paste silently swallowed if getAsFile() returns null (Correctness) 🆕
  • "Upload to codebase" shown on Home screen — misleading when no codebase exists yet (UX) 🆕
  • E2E test only covers "chat context" path — no test for "upload to codebase" or cancel flow (Correctness)
  • handleFileChange not guarded by pendingFiles — file input can add files while dialog is open (UX) 🆕

Generated by Dyadbot swarm code review (3 agents, consensus-based)

Copy link
Copy Markdown
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Swarm review (round 2): 4 additional issue(s) found

@wwwillchen
Copy link
Copy Markdown
Collaborator

@BugBot run

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 11, 2026

🔍 Dyadbot Code Review Summary

Verdict: ✅ YES - Ready to merge

Reviewed by 3 specialized agents: Correctness Expert, Code Health Expert, UX Wizard.

Issues Summary

# Severity File Issue Found By
1 🟡 MEDIUM FileAttachmentTypeDialog.tsx:46-80 No visual feedback showing which file(s) the user is deciding about UX
2 🟡 MEDIUM FileAttachmentTypeDialog.tsx:47-79 Card-style buttons could benefit from aria-label for screen readers UX
🟢 Low Priority Notes (4 items)
  • Send button not visually disabled while dialog is open - ChatInput.tsx:602 / HomeChatInput.tsx:146 - Button appears clickable but silently no-ops. Add pendingFiles to disabled condition. (Correctness)
  • Pasting while dialog open silently ignored - useAttachments.ts:101 - No user feedback when paste is blocked during pending state. Consider a subtle toast. (UX)
  • No keyboard shortcut hints for power users - FileAttachmentTypeDialog.tsx:47 - Dialog appears on every drag/paste; power users may want shortcuts or "remember my choice". (UX)
  • Duplicated button CSS class string - FileAttachmentTypeDialog.tsx:47-79 - Two buttons share identical long className. Minor since only 2 instances. (Code Health)
ℹ️ Pre-existing Notes (not blocking)
  • Duplication in useAttachments.ts - handleFileChange, handleFileSelect, and addAttachments contain near-identical file-to-attachment mapping logic. Pre-existing issue, not introduced by this PR. (Code Health)

Reviewer Assessments

  • 🛡️ Correctness: Clean. State management is sound, edge cases handled (blocking drops/paste while dialog open, clearing pending state). One minor disabled-state UX gap noted.
  • 🧹 Code Health: Clean. New code is well-structured and consistent with existing patterns. Pre-existing duplication noted but not blocking.
  • 🎨 UX: Good overall concept. Showing filenames in the dialog and improving screen reader support would polish the experience. The extra step for every attachment may benefit from a "remember choice" option long-term.

Bottom line: No HIGH issues. The MEDIUM UX suggestions (showing filenames, accessibility improvements) are nice-to-haves that could be addressed in a follow-up. The core implementation is solid and the feature meaningfully improves the attachment flow.


Generated by Dyadbot code review

@azizmejri1
Copy link
Copy Markdown
Collaborator Author

feedback from mtg: should do this same UX for pasting via keyboard shortcut

@wwwillchen done

Copy link
Copy Markdown
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Swarm review: 2 MEDIUM issues, 4 LOW notes found

</div>
</div>
</button>
</div>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 MEDIUM | interaction | Found by: UX

No visual feedback showing which file(s) the user is deciding about

When the dialog appears after a drag/drop or paste, the user sees "How would you like to attach this file?" but has no indication of WHICH file(s) they just dropped. For a single file, showing the filename would help confirm they dropped the right file. For multiple files, a brief list would give the user confidence about what they're attaching.

💡 Suggestion: Display the filename(s) in the dialog body below the description. For multiple files, show a compact list (max 3-4 visible, rest behind a "+ N more" indicator).

<div className="text-xs text-muted-foreground mt-0.5">
{t("attachFileContextExample")}
</div>
</div>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 MEDIUM | accessibility | Found by: UX

Card-style buttons could benefit from aria-label for screen readers

The two option buttons are styled as card-like elements with title + description text. While they are semantic <button> elements (good), screen reader users will hear the full inner text concatenated which may be confusing (e.g. "Attach file as chat context Example use case: screenshot of the app to point out a UI issue").

💡 Suggestion: Add aria-label attributes to each button with concise labels (e.g., "Attach as chat context" and "Upload to codebase"), or use aria-describedby to separate the title from the description for screen readers.

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

8 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@github-actions github-actions bot added the needs-human:review-issue ai agent flagged an issue that requires human review label Feb 11, 2026
@wwwillchen
Copy link
Copy Markdown
Collaborator

@BugBot run

azizmejri1 and others added 5 commits February 12, 2026 00:38
- Add type="button" and focus-visible ring styles to dialog buttons
- Prevent submit while attachment type dialog is open
- Clear pendingFiles in clearAttachments to avoid orphaned state
- Deduplicate confirmPendingFiles by reusing addAttachments
- Add i18n translations for FileAttachmentTypeDialog (en, pt-BR, zh-CN)

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@wwwillchen
Copy link
Copy Markdown
Collaborator

@BugBot run

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

8 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +82 to +90
const confirmPendingFiles = useCallback(
(type: "chat-context" | "upload-to-codebase") => {
if (pendingFiles) {
addAttachments(pendingFiles, type);
setPendingFiles(null);
}
},
[pendingFiles, addAttachments],
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

addAttachments missing from dependency array causes stale closure

The useCallback depends on addAttachments but doesn't include it in the dependency array. This will capture a stale version of addAttachments and could cause bugs if addAttachments behavior changes.

Suggested change
const confirmPendingFiles = useCallback(
(type: "chat-context" | "upload-to-codebase") => {
if (pendingFiles) {
addAttachments(pendingFiles, type);
setPendingFiles(null);
}
},
[pendingFiles, addAttachments],
);
const confirmPendingFiles = useCallback(
(type: "chat-context" | "upload-to-codebase") => {
if (pendingFiles) {
addAttachments(pendingFiles, type);
setPendingFiles(null);
}
},
[pendingFiles, addAttachments],
);
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/hooks/useAttachments.ts
Line: 82:90

Comment:
`addAttachments` missing from dependency array causes stale closure

The `useCallback` depends on `addAttachments` but doesn't include it in the dependency array. This will capture a stale version of `addAttachments` and could cause bugs if `addAttachments` behavior changes.

```suggestion
  const confirmPendingFiles = useCallback(
    (type: "chat-context" | "upload-to-codebase") => {
      if (pendingFiles) {
        addAttachments(pendingFiles, type);
        setPendingFiles(null);
      }
    },
    [pendingFiles, addAttachments],
  );
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Dyadbot swarm review: 1 issue found

setPendingFiles(null);
}
},
[pendingFiles, addAttachments],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 MEDIUM | code-health | Found by: Code Health, Endorsed by: Correctness, UX

addAttachments is not memoized, making confirmPendingFiles useCallback ineffective

addAttachments is listed in the dependency array of confirmPendingFiles's useCallback, but addAttachments itself is not wrapped in useCallback. Since it's a plain function declared in the hook body, it's recreated on every render — which means confirmPendingFiles also gets a new reference on every render, defeating the purpose of the useCallback wrapper.

💡 Suggestion: Either wrap addAttachments in useCallback as well, or inline the attachment-creation logic directly within confirmPendingFiles to avoid the stale dependency.

@github-actions
Copy link
Copy Markdown
Contributor

🔍 Dyadbot Code Review Summary

Verdict: ✅ YES - Ready to merge

Reviewed by 3 specialized agents: Correctness Expert, Code Health Expert, UX Wizard.

Issues Summary

# Severity File Issue Found By Endorsed By
1 🟡 MEDIUM src/hooks/useAttachments.ts:89 addAttachments not memoized, making confirmPendingFiles useCallback ineffective Code Health Correctness, UX
🟢 Low Priority Notes (2 items)
  • Duplicate button class stringssrc/components/chat/FileAttachmentTypeDialog.tsx:54,72 — The two card-style buttons share an identical long className string. Could extract to a constant, but not blocking. (Code Health)
  • pendingFiles truthiness check is slightly imprecisesrc/components/chat/ChatInput.tsx:248 — The condition || pendingFiles would be true for an empty array [], though the current code never sets pendingFiles to []. Using pendingFiles !== null would be more explicit. (UX, downgraded after discussion)
🚫 Dropped Issues (0 items)

No issues were dropped during discussion.


Generated by Dyadbot swarm code review

@github-actions
Copy link
Copy Markdown
Contributor

🔍 Dyadbot Code Review — Additional Finding from Discussion

After the initial review was posted, the cross-reviewer discussion surfaced one additional consensus issue:

🟡 MEDIUM — Send button disabled state does not account for pendingFiles

Found independently by: Correctness Expert + UX Wizard | Endorsed by: all 3 reviewers

Files: src/components/chat/ChatInput.tsx:602-604, src/components/chat/HomeChatInput.tsx:146

The handleSubmit function correctly blocks submission when pendingFiles is truthy, but the send button's disabled prop doesn't include pendingFiles in its condition. This means when a user has typed text and the attachment type dialog is open, the send button appears fully enabled (not grayed out) but clicking it silently does nothing — the UI state misleads the user.

Suggestion: Add || !!pendingFiles to the disabled prop in both components.


This updates the verdict to: 🤔 NOT SURE — Potential issues (one new MEDIUM from discussion round, plus the addAttachments memoization MEDIUM from the initial review)


Generated by Dyadbot swarm code review

@github-actions
Copy link
Copy Markdown
Contributor

🎭 Playwright Test Results

❌ Some tests failed

OS Passed Failed Flaky Skipped
🍎 macOS 346 2 3 110
🪟 Windows 348 1 5 110

Summary: 694 passed, 3 failed, 8 flaky, 220 skipped

Failed Tests

🍎 macOS

  • security_review.spec.ts > security review - edit and use knowledge
    • Error: expect(string).toMatchSnapshot(expected) failed
  • select_component.spec.ts > select component next.js
    • Error: expect(locator).toMatchAriaSnapshot(expected) failed

🪟 Windows

  • setup_flow.spec.ts > Setup Flow > node.js install flow
    • Error: expect(locator).toBeVisible() failed

📋 Re-run Failing Tests (macOS)

Copy and paste to re-run all failing spec files locally:

npm run e2e \
  e2e-tests/security_review.spec.ts \
  e2e-tests/select_component.spec.ts

⚠️ Flaky Tests

🍎 macOS

  • context_manage.spec.ts > manage context - exclude paths (passed after 1 retry)
  • engine.spec.ts > regular auto should send message to engine (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > ai provider setup flow (passed after 1 retry)

🪟 Windows

  • chat_input.spec.ts > send button disabled during pending proposal (passed after 2 retries)
  • chat_input.spec.ts > send button disabled during pending proposal - reject (passed after 1 retry)
  • chat_mode.spec.ts > chat mode selector - ask mode (passed after 1 retry)
  • reject.spec.ts > reject (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > setup banner shows correct state when node.js is installed (passed after 1 retry)

📊 View full report

Copy link
Copy Markdown
Collaborator

@wwwillchen wwwillchen left a comment

Choose a reason for hiding this comment

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

thanks!

@wwwillchen wwwillchen merged commit 8f87e0f into dyad-sh:main Feb 12, 2026
14 of 16 checks passed
azizmejri1 added a commit to azizmejri1/dyad that referenced this pull request Feb 12, 2026
…#2563)

<!-- devin-review-badge-begin -->

---

<a href="https://app.devin.ai/review/dyad-sh/dyad/pull/2563"
target="_blank">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->

<!-- This is an auto-generated description by cubic. -->
---
Show a dialog after dragging or pasting files into chat to choose how to
attach them—as chat context or upload to codebase. This makes intent
explicit and blocks submit, drop, and paste until you choose.

- **New Features**
- Added FileAttachmentTypeDialog; integrated in ChatInput and
HomeChatInput. i18n (en, pt-BR, zh-CN) with singular/plural titles and
descriptions.
- Updated useAttachments with pendingFiles and confirm/cancel.
Drag/paste set pendingFiles; prevent attaching while pending;
clearAttachments also clears pendingFiles; submit blocked when dialog is
open.
- Fixed e2e to select “Attach file as chat context”; dialog buttons use
type="button" with focus-visible ring.

- **Refactors**
  - confirmPendingFiles reuses addAttachments to deduplicate logic.

<sup>Written for commit b625847.
Summary will update on new commits.</sup>

<!-- End of auto-generated description by cubic. -->

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-human:review-issue ai agent flagged an issue that requires human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants