Skip to content

[PB-1967]: feature/custom hook to upload attachments#59

Merged
xabg2 merged 4 commits into
masterfrom
feature/custom-hook-to-upload-attachments
Jun 4, 2026
Merged

[PB-1967]: feature/custom hook to upload attachments#59
xabg2 merged 4 commits into
masterfrom
feature/custom-hook-to-upload-attachments

Conversation

@xabg2

@xabg2 xabg2 commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Custom hook that handles the file attachments.

@xabg2 xabg2 requested a review from jzunigax2 June 3, 2026 13:33
@xabg2 xabg2 self-assigned this Jun 3, 2026
@xabg2 xabg2 added the enhancement New feature or request label Jun 3, 2026
@xabg2 xabg2 changed the base branch from master to feature/upload-attachment-manager June 3, 2026 13:34
@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2540e0c7-e0a8-4f03-a59f-8fb0ff6e3363

📥 Commits

Reviewing files that changed from the base of the PR and between 41ad2c3 and f9ffd3f.

📒 Files selected for processing (2)
  • src/components/compose-message/hooks/useAttachments.test.ts
  • src/components/compose-message/hooks/useAttachments.ts

📝 Walkthrough

Walkthrough

This PR implements a complete attachment upload system for mail compose: type contracts and a 25 MiB limit constant, a concurrency-managed UploadManager with retry/cancel semantics, a useAttachments React hook enforcing size validation, tests, and localized error messages (en/es/fr/it).

Changes

Attachment Upload Management

Layer / File(s) Summary
Upload Type Contracts and Configuration
src/types/mail/upload-manager/index.ts, src/constants.ts
Exports UploadAttachmentCallbacks, UploadHandle, and UploadAttachmentTask types, plus MAX_TOTAL_ATTACHMENT_BYTES_PER_MAIL = 25 * 1024 * 1024.
UploadManager Singleton with Concurrency and Retry
src/services/upload-manager/index.ts
Implements a concurrency-limited singleton using async.queue, with uploadWithRetries, transient-error classification (5xx/timeouts), bounded retries, task cancellation, and public run, retry, remove, and clear APIs.
UploadManager Test Suite
src/services/upload-manager/upload-manager.test.ts
Vitest coverage verifying handle stability, success/error callback dispatch, transient retry behavior up to configured attempts, non-retry for 4xx errors, retry semantics, and removal/cancellation behavior.
useAttachments Hook with Size Validation
src/components/compose-message/hooks/useAttachments.ts
React hook mapping UploadManager handles into AttachmentTask entries, enforcing the 25 MiB total-per-mail limit (with localized warning), tracking `uploading
useAttachments Hook Test Suite
src/components/compose-message/hooks/useAttachments.test.ts
Vitest tests for addFiles enqueuing, size-limit enforcement and cumulative rejection with a warning toast, callback-driven status transitions, retry/remove/clear wiring, and derived flags (totalSize, isUploading, hasErrors).
Multilingual Error Messages
src/i18n/locales/en.json, src/i18n/locales/es.json, src/i18n/locales/fr.json, src/i18n/locales/it.json
Localized modals.composeMessageDialog.errors.attachmentsTooLarge messages added with {{maxSize}} placeholders.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes


Suggested reviewers

  • jzunigax2
🚥 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 clearly summarizes the main change: introducing a custom hook for handling file attachment uploads, which is the primary focus of all code changes.
Description check ✅ Passed The description is related to the changeset, mentioning a custom hook that handles file attachments, which aligns with the implementation of useAttachments hook and supporting infrastructure.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/custom-hook-to-upload-attachments

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.

@coderabbitai coderabbitai 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.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
package.json (2)

41-69: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Justify async before adding two new packages for one queue.

The new upload manager only consumes queue/QueueObject from async in src/services/upload-manager/index.ts. That concurrency wrapper is small enough to keep local, so adding both async and @types/async does not meet the repo’s dependency policy unless you document a concrete need that a small in-repo implementation cannot cover. As per coding guidelines, "Dependency changes: don’t add packages unless justified by real problem/complexity vs implementing in ≤~100 LOC, and ensure TypeScript support/maintenance/licensing are acceptable."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` around lines 41 - 69, Remove the new external dependency
addition ("async" and "`@types/async`") unless you can justify it; instead
implement a small in-repo concurrency wrapper used by
src/services/upload-manager/index.ts (exporting the queue/QueueObject API the
code expects) — create a local utility (e.g., upload-manager/queue.ts) that
provides a createQueue(concurrency) or queue(tasks, concurrency) with
push/idle/drain semantics and appropriate TypeScript types matching QueueObject,
update imports in index.ts to use the local implementation, and add a short unit
test; if you choose to keep the external package, add a one-paragraph
justification in the PR explaining why an in-repo ~100 LOC implementation is
insufficient and confirm TypeScript typings and license compatibility instead of
adding the packages silently.

41-69: ⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy lift

Bump @internxt/sdk or rewrite the attachment integration to match 1.17.2. @internxt/sdk@1.17.2’s TypeScript declarations don’t define MailApi.uploadAttachment/downloadAttachment nor UploadAttachmentResponse/DownloadAttachmentResponse, but this code imports/types/calls them (e.g., src/services/sdk/mail/index.ts, src/services/upload-manager/index.ts), so npm run build can’t pass without upgrading the SDK or adapting to the 1.17.2 API.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` around lines 41 - 69, The build breaks because the code
references MailApi.uploadAttachment, MailApi.downloadAttachment and types
UploadAttachmentResponse/DownloadAttachmentResponse (used in
src/services/sdk/mail/index.ts and src/services/upload-manager/index.ts) but
`@internxt/sdk`@1.17.2’s typings don’t expose them; fix by either updating
package.json to a compatible `@internxt/sdk` version that includes those
methods/types (bump to the SDK release that added
uploadAttachment/downloadAttachment) or refactor the two modules to use the
current 1.17.2 SDK API and exported types (replace calls/types with the SDK’s
actual attachment upload/download functions and response types), ensuring all
imports and type references in src/services/sdk/mail/index.ts and
src/services/upload-manager/index.ts are updated accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/compose-message/hooks/useAttachments.test.ts`:
- Around line 35-50: Test mocks are only restored in afterEach, allowing
spies/mocks from a test to leak into the next test; move vi.restoreAllMocks()
into the beforeEach and reapply the shared run.mockImplementation setup there so
each test starts with a clean slate. Update the beforeEach block to call
vi.restoreAllMocks() at its start, then reset the specific mocks (run, retry,
remove, clear, show), set lastCallbacks = undefined, and re-establish
run.mockImplementation(...) as currently written; remove or keep
afterEach.restore depending on preference but ensure beforeEach restores mocks
before applying run.mockImplementation.
- Line 3: The test is using a relative internal import for the useAttachments
hook instead of the repository alias. Update the import in
useAttachments.test.ts to use the
`@/components/compose-message/hooks/useAttachments` path so it follows the
internal-module import rule and stays consistent with the rest of the repo.

In `@src/components/compose-message/hooks/useAttachments.ts`:
- Line 60: The MIME type fallback is wrong because browsers set File.type to an
empty string; update the assignment that currently uses "type: file.type ??
'application/octet-stream'" in useAttachments.ts to use a truthy fallback so
empty strings fall back (e.g., use file.type || 'application/octet-stream'),
ensuring the file.type check treats '' as unknown; locate the assignment where
the File object (variable name "file") is mapped and replace the nullish
coalescing with a truthy OR for the MIME type.
- Around line 55-63: The issue is that UploadManager.instance.run(...) can
invoke onSuccess/onError before setAttachments(...pending) commits, so callbacks
map an empty state and leave tasks stuck; fix by creating the AttachmentTask
entries and registering them in state before starting the upload: generate
handles/IDs (or map the incoming file list to pending AttachmentTask objects
with stable ids), call setAttachments(prev => [...prev, ...pending]) first, then
invoke UploadManager.instance.run(...) passing callbacks that reference those
same ids (or modify run to accept the precomputed ids/handles). Update code
around UploadManager.instance.run, handles, pending, setAttachments, and the
onSuccess/onError callback logic to rely on pre-registered AttachmentTask ids.
- Line 6: Remove the invalid SDK import of AttachmentRef from useAttachments.ts
and replace it with a local inline type that matches what the hook actually
uses: an interface (e.g., LocalAttachment or AttachmentShape) with properties
name: string, size: number, type: string, and an optional blobId?: string; then
update the useAttachments hook code (references to AttachmentRef) to use this
local type so the file compiles without referencing `@internxt/sdk` exports.

In `@src/services/upload-manager/index.ts`:
- Around line 95-110: The uploadWithRetries function currently retries transient
errors synchronously; modify uploadWithRetries to wait with a bounded
exponential backoff plus jitter before each retry attempt (only when
isTransientError(error) and task.cancelled is false) instead of looping
immediately; compute backoff using attempt index (capped to a MAX_BACKOFF_MS)
and add random jitter, await a sleep/timeout before creating the next
MailService.instance.uploadAttachment promise, and preserve existing behavior
for non-transient errors and cancelation while keeping task.canceler cleared in
the finally block.

In `@src/services/upload-manager/upload-manager.test.ts`:
- Line 2: The test imports the UploadManager via a relative path; change the
import to use the repository path alias instead. Update the import statement
that currently references './index' to import UploadManager from
'`@/services/upload-manager`' so the test uses the project-wide alias and matches
other internal module imports (symbol: UploadManager).
- Around line 30-37: Tests leave mutable state in the UploadManager singleton
(UploadManager.instance) between runs so resetting mocks isn't enough; call
UploadManager.instance.clear() in the test lifecycle (e.g., add
UploadManager.instance.clear() to beforeEach or afterEach alongside
vi.restoreAllMocks() and vi.useRealTimers()) to purge queued/failed tasks and
ensure test isolation, referencing UploadManager.instance.clear() to locate the
method to invoke.

In `@src/types/mail/upload-manager/index.ts`:
- Around line 13-20: The exported type UploadAttachmentTask exposes internal
mutable state (cancelled, failed) that should be encapsulated by UploadManager;
either move the UploadAttachmentTask definition into
src/services/upload-manager/index.ts and make it non-exported so only
UploadManager manipulates it, or mark it `@internal` in its JSDoc and document
that external mutation is unsupported, or change the shape so fields are
readonly and have UploadManager maintain mutable state separately (refer to
UploadManager, UploadAttachmentCallbacks, and RequestCanceler to locate usages)
— pick one approach and update all imports/usages accordingly to prevent
external code from mutating the manager's internal state.

---

Outside diff comments:
In `@package.json`:
- Around line 41-69: Remove the new external dependency addition ("async" and
"`@types/async`") unless you can justify it; instead implement a small in-repo
concurrency wrapper used by src/services/upload-manager/index.ts (exporting the
queue/QueueObject API the code expects) — create a local utility (e.g.,
upload-manager/queue.ts) that provides a createQueue(concurrency) or
queue(tasks, concurrency) with push/idle/drain semantics and appropriate
TypeScript types matching QueueObject, update imports in index.ts to use the
local implementation, and add a short unit test; if you choose to keep the
external package, add a one-paragraph justification in the PR explaining why an
in-repo ~100 LOC implementation is insufficient and confirm TypeScript typings
and license compatibility instead of adding the packages silently.
- Around line 41-69: The build breaks because the code references
MailApi.uploadAttachment, MailApi.downloadAttachment and types
UploadAttachmentResponse/DownloadAttachmentResponse (used in
src/services/sdk/mail/index.ts and src/services/upload-manager/index.ts) but
`@internxt/sdk`@1.17.2’s typings don’t expose them; fix by either updating
package.json to a compatible `@internxt/sdk` version that includes those
methods/types (bump to the SDK release that added
uploadAttachment/downloadAttachment) or refactor the two modules to use the
current 1.17.2 SDK API and exported types (replace calls/types with the SDK’s
actual attachment upload/download functions and response types), ensuring all
imports and type references in src/services/sdk/mail/index.ts and
src/services/upload-manager/index.ts are updated accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ce24a1b5-0c77-4fe5-9404-da20d6dacbfb

📥 Commits

Reviewing files that changed from the base of the PR and between 3e5ede1 and c88b374.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (12)
  • package.json
  • src/components/compose-message/hooks/useAttachments.test.ts
  • src/components/compose-message/hooks/useAttachments.ts
  • src/constants.ts
  • src/i18n/locales/en.json
  • src/i18n/locales/es.json
  • src/i18n/locales/fr.json
  • src/i18n/locales/it.json
  • src/services/sdk/mail/index.ts
  • src/services/upload-manager/index.ts
  • src/services/upload-manager/upload-manager.test.ts
  • src/types/mail/upload-manager/index.ts

@coderabbitai coderabbitai 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.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
package.json (2)

41-69: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Justify async before adding two new packages for one queue.

The new upload manager only consumes queue/QueueObject from async in src/services/upload-manager/index.ts. That concurrency wrapper is small enough to keep local, so adding both async and @types/async does not meet the repo’s dependency policy unless you document a concrete need that a small in-repo implementation cannot cover. As per coding guidelines, "Dependency changes: don’t add packages unless justified by real problem/complexity vs implementing in ≤~100 LOC, and ensure TypeScript support/maintenance/licensing are acceptable."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` around lines 41 - 69, Remove the new external dependency
addition ("async" and "`@types/async`") unless you can justify it; instead
implement a small in-repo concurrency wrapper used by
src/services/upload-manager/index.ts (exporting the queue/QueueObject API the
code expects) — create a local utility (e.g., upload-manager/queue.ts) that
provides a createQueue(concurrency) or queue(tasks, concurrency) with
push/idle/drain semantics and appropriate TypeScript types matching QueueObject,
update imports in index.ts to use the local implementation, and add a short unit
test; if you choose to keep the external package, add a one-paragraph
justification in the PR explaining why an in-repo ~100 LOC implementation is
insufficient and confirm TypeScript typings and license compatibility instead of
adding the packages silently.

41-69: ⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy lift

Bump @internxt/sdk or rewrite the attachment integration to match 1.17.2. @internxt/sdk@1.17.2’s TypeScript declarations don’t define MailApi.uploadAttachment/downloadAttachment nor UploadAttachmentResponse/DownloadAttachmentResponse, but this code imports/types/calls them (e.g., src/services/sdk/mail/index.ts, src/services/upload-manager/index.ts), so npm run build can’t pass without upgrading the SDK or adapting to the 1.17.2 API.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` around lines 41 - 69, The build breaks because the code
references MailApi.uploadAttachment, MailApi.downloadAttachment and types
UploadAttachmentResponse/DownloadAttachmentResponse (used in
src/services/sdk/mail/index.ts and src/services/upload-manager/index.ts) but
`@internxt/sdk`@1.17.2’s typings don’t expose them; fix by either updating
package.json to a compatible `@internxt/sdk` version that includes those
methods/types (bump to the SDK release that added
uploadAttachment/downloadAttachment) or refactor the two modules to use the
current 1.17.2 SDK API and exported types (replace calls/types with the SDK’s
actual attachment upload/download functions and response types), ensuring all
imports and type references in src/services/sdk/mail/index.ts and
src/services/upload-manager/index.ts are updated accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/compose-message/hooks/useAttachments.test.ts`:
- Around line 35-50: Test mocks are only restored in afterEach, allowing
spies/mocks from a test to leak into the next test; move vi.restoreAllMocks()
into the beforeEach and reapply the shared run.mockImplementation setup there so
each test starts with a clean slate. Update the beforeEach block to call
vi.restoreAllMocks() at its start, then reset the specific mocks (run, retry,
remove, clear, show), set lastCallbacks = undefined, and re-establish
run.mockImplementation(...) as currently written; remove or keep
afterEach.restore depending on preference but ensure beforeEach restores mocks
before applying run.mockImplementation.
- Line 3: The test is using a relative internal import for the useAttachments
hook instead of the repository alias. Update the import in
useAttachments.test.ts to use the
`@/components/compose-message/hooks/useAttachments` path so it follows the
internal-module import rule and stays consistent with the rest of the repo.

In `@src/components/compose-message/hooks/useAttachments.ts`:
- Line 60: The MIME type fallback is wrong because browsers set File.type to an
empty string; update the assignment that currently uses "type: file.type ??
'application/octet-stream'" in useAttachments.ts to use a truthy fallback so
empty strings fall back (e.g., use file.type || 'application/octet-stream'),
ensuring the file.type check treats '' as unknown; locate the assignment where
the File object (variable name "file") is mapped and replace the nullish
coalescing with a truthy OR for the MIME type.
- Around line 55-63: The issue is that UploadManager.instance.run(...) can
invoke onSuccess/onError before setAttachments(...pending) commits, so callbacks
map an empty state and leave tasks stuck; fix by creating the AttachmentTask
entries and registering them in state before starting the upload: generate
handles/IDs (or map the incoming file list to pending AttachmentTask objects
with stable ids), call setAttachments(prev => [...prev, ...pending]) first, then
invoke UploadManager.instance.run(...) passing callbacks that reference those
same ids (or modify run to accept the precomputed ids/handles). Update code
around UploadManager.instance.run, handles, pending, setAttachments, and the
onSuccess/onError callback logic to rely on pre-registered AttachmentTask ids.
- Line 6: Remove the invalid SDK import of AttachmentRef from useAttachments.ts
and replace it with a local inline type that matches what the hook actually
uses: an interface (e.g., LocalAttachment or AttachmentShape) with properties
name: string, size: number, type: string, and an optional blobId?: string; then
update the useAttachments hook code (references to AttachmentRef) to use this
local type so the file compiles without referencing `@internxt/sdk` exports.

In `@src/services/upload-manager/index.ts`:
- Around line 95-110: The uploadWithRetries function currently retries transient
errors synchronously; modify uploadWithRetries to wait with a bounded
exponential backoff plus jitter before each retry attempt (only when
isTransientError(error) and task.cancelled is false) instead of looping
immediately; compute backoff using attempt index (capped to a MAX_BACKOFF_MS)
and add random jitter, await a sleep/timeout before creating the next
MailService.instance.uploadAttachment promise, and preserve existing behavior
for non-transient errors and cancelation while keeping task.canceler cleared in
the finally block.

In `@src/services/upload-manager/upload-manager.test.ts`:
- Line 2: The test imports the UploadManager via a relative path; change the
import to use the repository path alias instead. Update the import statement
that currently references './index' to import UploadManager from
'`@/services/upload-manager`' so the test uses the project-wide alias and matches
other internal module imports (symbol: UploadManager).
- Around line 30-37: Tests leave mutable state in the UploadManager singleton
(UploadManager.instance) between runs so resetting mocks isn't enough; call
UploadManager.instance.clear() in the test lifecycle (e.g., add
UploadManager.instance.clear() to beforeEach or afterEach alongside
vi.restoreAllMocks() and vi.useRealTimers()) to purge queued/failed tasks and
ensure test isolation, referencing UploadManager.instance.clear() to locate the
method to invoke.

In `@src/types/mail/upload-manager/index.ts`:
- Around line 13-20: The exported type UploadAttachmentTask exposes internal
mutable state (cancelled, failed) that should be encapsulated by UploadManager;
either move the UploadAttachmentTask definition into
src/services/upload-manager/index.ts and make it non-exported so only
UploadManager manipulates it, or mark it `@internal` in its JSDoc and document
that external mutation is unsupported, or change the shape so fields are
readonly and have UploadManager maintain mutable state separately (refer to
UploadManager, UploadAttachmentCallbacks, and RequestCanceler to locate usages)
— pick one approach and update all imports/usages accordingly to prevent
external code from mutating the manager's internal state.

---

Outside diff comments:
In `@package.json`:
- Around line 41-69: Remove the new external dependency addition ("async" and
"`@types/async`") unless you can justify it; instead implement a small in-repo
concurrency wrapper used by src/services/upload-manager/index.ts (exporting the
queue/QueueObject API the code expects) — create a local utility (e.g.,
upload-manager/queue.ts) that provides a createQueue(concurrency) or
queue(tasks, concurrency) with push/idle/drain semantics and appropriate
TypeScript types matching QueueObject, update imports in index.ts to use the
local implementation, and add a short unit test; if you choose to keep the
external package, add a one-paragraph justification in the PR explaining why an
in-repo ~100 LOC implementation is insufficient and confirm TypeScript typings
and license compatibility instead of adding the packages silently.
- Around line 41-69: The build breaks because the code references
MailApi.uploadAttachment, MailApi.downloadAttachment and types
UploadAttachmentResponse/DownloadAttachmentResponse (used in
src/services/sdk/mail/index.ts and src/services/upload-manager/index.ts) but
`@internxt/sdk`@1.17.2’s typings don’t expose them; fix by either updating
package.json to a compatible `@internxt/sdk` version that includes those
methods/types (bump to the SDK release that added
uploadAttachment/downloadAttachment) or refactor the two modules to use the
current 1.17.2 SDK API and exported types (replace calls/types with the SDK’s
actual attachment upload/download functions and response types), ensuring all
imports and type references in src/services/sdk/mail/index.ts and
src/services/upload-manager/index.ts are updated accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ce24a1b5-0c77-4fe5-9404-da20d6dacbfb

📥 Commits

Reviewing files that changed from the base of the PR and between 3e5ede1 and c88b374.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (12)
  • package.json
  • src/components/compose-message/hooks/useAttachments.test.ts
  • src/components/compose-message/hooks/useAttachments.ts
  • src/constants.ts
  • src/i18n/locales/en.json
  • src/i18n/locales/es.json
  • src/i18n/locales/fr.json
  • src/i18n/locales/it.json
  • src/services/sdk/mail/index.ts
  • src/services/upload-manager/index.ts
  • src/services/upload-manager/upload-manager.test.ts
  • src/types/mail/upload-manager/index.ts
🛑 Comments failed to post (9)
src/components/compose-message/hooks/useAttachments.test.ts (2)

3-3: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Use the repo alias for this internal import.

This test should import the hook via @/components/compose-message/hooks/useAttachments to stay consistent with the repository’s internal-module import rule. As per coding guidelines, “Use the path alias @/*src/* when importing internal modules.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/compose-message/hooks/useAttachments.test.ts` at line 3, The
test is using a relative internal import for the useAttachments hook instead of
the repository alias. Update the import in useAttachments.test.ts to use the
`@/components/compose-message/hooks/useAttachments` path so it follows the
internal-module import rule and stays consistent with the rest of the repo.

35-50: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Restore mocks in beforeEach, not only in afterEach.

Right now only the four known mocks are reset before each test. Any future spy/mock added in a test can still bleed into the next Arrange phase until afterEach runs. Move vi.restoreAllMocks() into beforeEach and re-apply the shared run.mockImplementation(...) setup there. Based on learnings, “Reset mocks in beforeEach with vi.restoreAllMocks().”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/compose-message/hooks/useAttachments.test.ts` around lines 35
- 50, Test mocks are only restored in afterEach, allowing spies/mocks from a
test to leak into the next test; move vi.restoreAllMocks() into the beforeEach
and reapply the shared run.mockImplementation setup there so each test starts
with a clean slate. Update the beforeEach block to call vi.restoreAllMocks() at
its start, then reset the specific mocks (run, retry, remove, clear, show), set
lastCallbacks = undefined, and re-establish run.mockImplementation(...) as
currently written; remove or keep afterEach.restore depending on preference but
ensure beforeEach restores mocks before applying run.mockImplementation.
src/components/compose-message/hooks/useAttachments.ts (3)

6-6: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In @internxt/sdkversion 1.17.2, what types are exported from@internxt/sdk/dist/mail/types, and what is the correct replacement for AttachmentRef?

💡 Result:

In @internxt/sdk version 1.17.2, the @internxt/sdk/dist/mail/types module is used for mail-related type definitions. While a specific public replacement for the deprecated AttachmentRef is not explicitly documented in the official SDK repository's public release notes or current export files, the Internxt SDK architecture extensively utilizes standardized interfaces for handling file attachments [1][2]. Users encountering issues with AttachmentRef should examine the updated attachment-handling interfaces within the SDK's shared type definitions or the specific mail service modules. The SDK has undergone significant refactoring to align its types with backend Swagger schemas [3], which typically involves renaming or replacing older, custom reference types with standardized objects containing fields like id, filename, and size [4]. It is recommended to replace AttachmentRef with the relevant Attachment or AttachmentData interface currently exported by the SDK, ensuring the new type aligns with the current backend schema expectations [4][5]. For specific implementation guidance, reviewing the current exports in @internxt/sdk/dist/mail/types directly via IDE autocompletion or by inspecting the local node_modules/@internxt/sdk/dist/mail/types.d.ts file is the most authoritative way to identify the current type name.

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Find any usage of AttachmentRef in the repo
rg -n "AttachmentRef" . || true

# 2) Try to locate the SDK type definition in the repo (if node_modules exist in this sandbox)
#    We intentionally keep output small and only print the relevant d.ts file(s).
if [ -d "node_modules/@internxt/sdk" ]; then
  fd -a "dist/mail/types.*" node_modules/@internxt/sdk -t f || true
  # Print matching d.ts contents if found
  fd -a "dist/mail/types.*\.d\.ts$" node_modules/@internxt/sdk -t f -x sh -c 'echo "==== $1 ===="; sed -n "1,200p" "$1"' -- {} || true
  # Also search within the found types.d.ts for exported symbols
  fd -a "dist/mail/types.*\.d\.ts$" node_modules/@internxt/sdk -t f -x sh -c 'rg -n "export (type|interface|class) " "$1" || true' -- {} || true
else
  echo "node_modules/@internxt/sdk not present in this sandbox; skipping local .d.ts inspection."
fi

Repository: internxt/mail-web

Length of output: 320


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check node_modules presence =="
ls -la node_modules/@internxt 2>/dev/null || true
ls -la node_modules/@internxt/sdk 2>/dev/null || true

echo
echo "== Look for SDK dist/mail/types typings =="
if [ -d "node_modules/@internxt/sdk/dist/mail" ]; then
  fd -a "types*.d.ts" node_modules/@internxt/sdk/dist/mail -t f || true
  fd -a "types*.ts" node_modules/@internxt/sdk/dist/mail -t f || true
else
  echo "No node_modules/@internxt/sdk/dist/mail in this environment."
fi

echo
echo "== If a types.d.ts exists, print first 200 lines =="
if [ -d "node_modules/@internxt/sdk/dist/mail" ]; then
  fd -a "types*.d.ts" node_modules/@internxt/sdk/dist/mail -t f | head -n 5 | while read -r f; do
    echo "---- $f ----"
    sed -n '1,200p' "$f"
  done
fi

Repository: internxt/mail-web

Length of output: 4289


🏁 Script executed:

#!/bin/bash
set -euo pipefail

TYPES_DTS="node_modules/@internxt/sdk/dist/mail/types.d.ts"

echo "== Search for AttachmentRef =="
rg -n "AttachmentRef" "$TYPES_DTS" || true

echo
echo "== Search for blobId =="
rg -n "blobId" "$TYPES_DTS" || true

echo
echo "== Search for Attachment-related exports (Attachment/AttachmentDto/encAttachments) =="
rg -n "export type .*Attachment|Attachment.*Dto|encAttachments|attachments" "$TYPES_DTS" || true

echo
echo "== Show matching lines around any blobId occurrences (if present) =="
if rg -n "blobId" "$TYPES_DTS" >/dev/null 2>&1; then
  rg -n -C 3 "blobId" "$TYPES_DTS"
fi

Repository: internxt/mail-web

Length of output: 308


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== useAttachments.ts (show relevant sections with line numbers) =="
FILE="src/components/compose-message/hooks/useAttachments.ts"
nl -ba "$FILE" | sed -n '1,140p'

echo
echo "== Search SDK typings for attachment/attachment dto/blobId symbols =="
SDK_MAIL_DIR="node_modules/@internxt/sdk/dist/mail"
rg -n "AttachmentRef|AttachmentDto|BlobId|blobId|attachments" "$SDK_MAIL_DIR" --glob '*.d.ts' || true

echo
echo "== If schema typings exist, search there too (broader) =="
rg -n "Attachment|blobId|BlobId" "$SDK_MAIL_DIR" --glob '*.ts' --glob '*.d.ts' || true

Repository: internxt/mail-web

Length of output: 189


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== useAttachments.ts (show relevant sections with line numbers) =="
FILE="src/components/compose-message/hooks/useAttachments.ts"
cat -n "$FILE" | sed -n '1,200p'

echo
echo "== Search SDK typings for attachment/attachment dto/blobId symbols =="
SDK_MAIL_DIR="node_modules/@internxt/sdk/dist/mail"
rg -n "AttachmentRef|AttachmentDto|BlobId|blobId|encAttachments|Attachment" "$SDK_MAIL_DIR" --glob '*.d.ts' --glob '*.ts' || true

Repository: internxt/mail-web

Length of output: 4586


🏁 Script executed:

#!/bin/bash
set -euo pipefail

SDK_MAIL_DIR="node_modules/@internxt/sdk/dist/mail"

echo "== Find likely attachment DTO/type names in schema.d.ts =="
rg -n "Attachment|attachment" "$SDK_MAIL_DIR/schema.d.ts" || true

echo
echo "== List exported component schema aliases that include 'Attachment' =="
rg -n "export type .*Attachment" "$SDK_MAIL_DIR/schema.d.ts" || true

Repository: internxt/mail-web

Length of output: 487


🏁 Script executed:

#!/bin/bash
set -euo pipefail

SDK_DIR="node_modules/@internxt/sdk/dist/mail"

echo "== Search for AttachmentRef anywhere in sdk dist/mail =="
rg -n "AttachmentRef" "$SDK_DIR" --glob '*.d.ts' --glob '*.ts' --glob '*.js' || true

echo
echo "== Search for blobId in sdk dist/mail =="
rg -n "blobId" "$SDK_DIR" --glob '*.d.ts' --glob '*.ts' || true

echo
echo "== Search for 'Attachment' identifier in sdk dist/mail typdefs =="
rg -n "Attachment" "$SDK_DIR" --glob '*.d.ts' --glob '*.ts' || true

echo
echo "== Search for file fields used by the hook (name/size/type) in sdk mail d.ts =="
rg -n "name: string;|size:|type:" "$SDK_DIR" --glob '*.d.ts' || true

Repository: internxt/mail-web

Length of output: 1265


Fix broken SDK type import in useAttachments (TS2305 build blocker)

src/components/compose-message/hooks/useAttachments.ts imports AttachmentRef from @internxt/sdk/dist/mail/types, but AttachmentRef is not exported by the SDK typings (the module only exports mail DTO/operation types). Remove the AttachmentRef import and inline a local attachment shape for what this hook actually needs (name, size, type, optional blobId) so the hook compiles.

🧰 Tools
🪛 GitHub Actions: Mail Web CI / 0_ci (24.x).txt

[error] 6-6: TypeScript (tsc -b) failed: TS2305 Module "@internxt/sdk/dist/mail/types" has no exported member "AttachmentRef".

🪛 GitHub Actions: Mail Web CI / ci (24.x)

[error] 6-6: TypeScript build failed (tsc -b). TS2305: Module "@internxt/sdk/dist/mail/types" has no exported member "AttachmentRef".

🪛 GitHub Check: ci (24.x)

[failure] 6-6:
Module '"@internxt/sdk/dist/mail/types"' has no exported member 'AttachmentRef'.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/compose-message/hooks/useAttachments.ts` at line 6, Remove the
invalid SDK import of AttachmentRef from useAttachments.ts and replace it with a
local inline type that matches what the hook actually uses: an interface (e.g.,
LocalAttachment or AttachmentShape) with properties name: string, size: number,
type: string, and an optional blobId?: string; then update the useAttachments
hook code (references to AttachmentRef) to use this local type so the file
compiles without referencing `@internxt/sdk` exports.

55-63: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Register local tasks before uploads can complete.

UploadManager.instance.run() starts work immediately, and its callbacks can fire before the setAttachments(...pending) update is committed. In that case onSuccess/onError maps over an empty array, drops the transition, and the later append leaves the task stuck in uploading. This needs an API/order change so IDs exist in state before the manager can call back.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/compose-message/hooks/useAttachments.ts` around lines 55 - 63,
The issue is that UploadManager.instance.run(...) can invoke onSuccess/onError
before setAttachments(...pending) commits, so callbacks map an empty state and
leave tasks stuck; fix by creating the AttachmentTask entries and registering
them in state before starting the upload: generate handles/IDs (or map the
incoming file list to pending AttachmentTask objects with stable ids), call
setAttachments(prev => [...prev, ...pending]) first, then invoke
UploadManager.instance.run(...) passing callbacks that reference those same ids
(or modify run to accept the precomputed ids/handles). Update code around
UploadManager.instance.run, handles, pending, setAttachments, and the
onSuccess/onError callback logic to rely on pre-registered AttachmentTask ids.

60-60: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use a truthy fallback for unknown MIME types.

Browsers report unknown File.type as '', not undefined, so ?? preserves the empty string and never falls back to application/octet-stream. Use file.type || 'application/octet-stream' here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/compose-message/hooks/useAttachments.ts` at line 60, The MIME
type fallback is wrong because browsers set File.type to an empty string; update
the assignment that currently uses "type: file.type ??
'application/octet-stream'" in useAttachments.ts to use a truthy fallback so
empty strings fall back (e.g., use file.type || 'application/octet-stream'),
ensuring the file.type check treats '' as unknown; locate the assignment where
the File object (variable name "file") is mapped and replace the nullish
coalescing with a truthy OR for the MIME type.
src/services/upload-manager/index.ts (1)

95-110: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add bounded backoff between transient retry attempts.

uploadWithRetries() retries 5xx/network failures in a tight loop. That turns one transient outage into three immediate requests per file, which both contradicts the PR’s stated retry behavior and can amplify backend pressure during incidents. Insert a delay/jitter before each retry instead of retrying synchronously.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/services/upload-manager/index.ts` around lines 95 - 110, The
uploadWithRetries function currently retries transient errors synchronously;
modify uploadWithRetries to wait with a bounded exponential backoff plus jitter
before each retry attempt (only when isTransientError(error) and task.cancelled
is false) instead of looping immediately; compute backoff using attempt index
(capped to a MAX_BACKOFF_MS) and add random jitter, await a sleep/timeout before
creating the next MailService.instance.uploadAttachment promise, and preserve
existing behavior for non-transient errors and cancelation while keeping
task.canceler cleared in the finally block.
src/services/upload-manager/upload-manager.test.ts (2)

2-2: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Use the repo path alias for this internal import.

Import UploadManager through @/services/upload-manager instead of ./index to match the repo-wide alias rule. As per coding guidelines, "Use the path alias @/*src/* when importing internal modules."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/services/upload-manager/upload-manager.test.ts` at line 2, The test
imports the UploadManager via a relative path; change the import to use the
repository path alias instead. Update the import statement that currently
references './index' to import UploadManager from '`@/services/upload-manager`' so
the test uses the project-wide alias and matches other internal module imports
(symbol: UploadManager).

30-37: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Clear the singleton manager between tests.

UploadManager.instance keeps mutable queue/task state across the whole suite, and failed uploads remain stored until retry/remove/clear. Resetting mocks alone is not enough here, so these cases can become order-dependent. Add UploadManager.instance.clear() in test setup/teardown to keep the suite isolated.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/services/upload-manager/upload-manager.test.ts` around lines 30 - 37,
Tests leave mutable state in the UploadManager singleton
(UploadManager.instance) between runs so resetting mocks isn't enough; call
UploadManager.instance.clear() in the test lifecycle (e.g., add
UploadManager.instance.clear() to beforeEach or afterEach alongside
vi.restoreAllMocks() and vi.useRealTimers()) to purge queued/failed tasks and
ensure test isolation, referencing UploadManager.instance.clear() to locate the
method to invoke.
src/types/mail/upload-manager/index.ts (1)

13-20: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Consider making UploadAttachmentTask internal to the UploadManager.

This type contains mutable state fields (cancelled, failed) that are managed internally by the UploadManager. Exporting it exposes implementation details and could allow external code to mutate these fields, potentially breaking the manager's state guarantees.

Consider one of:

  • Move this type into src/services/upload-manager/index.ts as a non-exported type
  • Add a JSDoc comment marking it as @internal and documenting that external mutation is unsupported
  • Refactor to use readonly fields with the manager maintaining mutable state separately
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/types/mail/upload-manager/index.ts` around lines 13 - 20, The exported
type UploadAttachmentTask exposes internal mutable state (cancelled, failed)
that should be encapsulated by UploadManager; either move the
UploadAttachmentTask definition into src/services/upload-manager/index.ts and
make it non-exported so only UploadManager manipulates it, or mark it `@internal`
in its JSDoc and document that external mutation is unsupported, or change the
shape so fields are readonly and have UploadManager maintain mutable state
separately (refer to UploadManager, UploadAttachmentCallbacks, and
RequestCanceler to locate usages) — pick one approach and update all
imports/usages accordingly to prevent external code from mutating the manager's
internal state.

Base automatically changed from feature/upload-attachment-manager to master June 3, 2026 14:51
Comment thread src/components/compose-message/hooks/useAttachments.ts
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 4, 2026

Copy link
Copy Markdown

Deploying mail-web with  Cloudflare Pages  Cloudflare Pages

Latest commit: a6c8c21
Status: ✅  Deploy successful!
Preview URL: https://5c11294b.mail-web-ea0.pages.dev
Branch Preview URL: https://feature-custom-hook-to-uploa.mail-web-ea0.pages.dev

View logs

@xabg2 xabg2 requested a review from jzunigax2 June 4, 2026 07:24

@coderabbitai coderabbitai 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.

Warning

CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.

Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.

👉 Steps to fix this

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/components/compose-message/hooks/useAttachments.test.ts (2)

35-50: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Reset mocks in beforeEach using vi.restoreAllMocks() per test policy.

Current setup restores in afterEach; move restore to beforeEach to match the required test lifecycle rule.

Suggested fix
   beforeEach(() => {
+    vi.restoreAllMocks();
     run.mockReset();
     retry.mockReset();
     remove.mockReset();
     clear.mockReset();
     show.mockReset();
     lastCallbacks = undefined;
@@
-  afterEach(() => {
-    vi.restoreAllMocks();
-  });

As per coding guidelines, “Reset mocks in beforeEach with vi.restoreAllMocks().”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/compose-message/hooks/useAttachments.test.ts` around lines 35
- 50, Move the vi.restoreAllMocks() call from the afterEach block into the
beforeEach block so mocks are restored at test setup; specifically, in the test
file adjust the lifecycle hooks so beforeEach calls vi.restoreAllMocks() before
run.mockReset()/retry.mockReset()/remove.mockReset()/clear.mockReset()/show.mockReset()
and the afterEach no longer calls vi.restoreAllMocks(); update references in the
setup where run.mockImplementation and lastCallbacks are initialized to run
after the restore.

3-3: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Use the project alias for internal imports instead of relative paths.

./useAttachments should use the @/* alias policy for src imports.

Suggested fix
-import useAttachments from './useAttachments';
+import useAttachments from '`@/components/compose-message/hooks/useAttachments`';

As per coding guidelines, “Use the path alias @/*src/* when importing internal modules.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/compose-message/hooks/useAttachments.test.ts` at line 3,
Update the internal import in useAttachments.test.ts to use the project alias
instead of a relative path: replace import useAttachments from
'./useAttachments' with the aliased path import useAttachments from
'`@/components/compose-message/hooks/useAttachments`' so it follows the `@/*` →
`src/*` convention and resolves correctly across the codebase.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/compose-message/hooks/useAttachments.ts`:
- Around line 23-26: The current totalSize memo only sums attachments with
status === 'done', so the limit check later (referencing totalSize) ignores
in-flight uploads and allows final size to exceed 25 MiB; update the useMemo
that computes totalSize (and any checks that reference it) to include
attachments with status 'uploading' (and any other non-failed/non-removed states
you use) so in-flight bytes are counted (or create a new variable like
totalSizeIncludingUploading and use that in the limit check), then use that
value in the existing limit enforcement logic to prevent accepting batches that
would exceed the cap.

---

Outside diff comments:
In `@src/components/compose-message/hooks/useAttachments.test.ts`:
- Around line 35-50: Move the vi.restoreAllMocks() call from the afterEach block
into the beforeEach block so mocks are restored at test setup; specifically, in
the test file adjust the lifecycle hooks so beforeEach calls
vi.restoreAllMocks() before
run.mockReset()/retry.mockReset()/remove.mockReset()/clear.mockReset()/show.mockReset()
and the afterEach no longer calls vi.restoreAllMocks(); update references in the
setup where run.mockImplementation and lastCallbacks are initialized to run
after the restore.
- Line 3: Update the internal import in useAttachments.test.ts to use the
project alias instead of a relative path: replace import useAttachments from
'./useAttachments' with the aliased path import useAttachments from
'`@/components/compose-message/hooks/useAttachments`' so it follows the `@/*` →
`src/*` convention and resolves correctly across the codebase.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: bc5935ca-73a3-4d04-b323-14edc720cea2

📥 Commits

Reviewing files that changed from the base of the PR and between c88b374 and 41ad2c3.

📒 Files selected for processing (2)
  • src/components/compose-message/hooks/useAttachments.test.ts
  • src/components/compose-message/hooks/useAttachments.ts

Comment thread src/components/compose-message/hooks/useAttachments.ts Outdated
@sonarqubecloud

sonarqubecloud Bot commented Jun 4, 2026

Copy link
Copy Markdown

@xabg2 xabg2 merged commit f7519c8 into master Jun 4, 2026
6 checks passed
@xabg2 xabg2 deleted the feature/custom-hook-to-upload-attachments branch June 4, 2026 13:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants