Skip to content

[_]: feat/mail API queries#32

Merged
xabg2 merged 5 commits intomasterfrom
feature/list-emails-and-preview
Mar 30, 2026
Merged

[_]: feat/mail API queries#32
xabg2 merged 5 commits intomasterfrom
feature/list-emails-and-preview

Conversation

@xabg2
Copy link
Copy Markdown
Contributor

@xabg2 xabg2 commented Mar 27, 2026

Implements the RTK Query layer for the mail feature, including all endpoints needed to list, read and interact with emails.

  • New queries (they generate a custom hook to consume the data, handles the loading/fetching state, etc):
  • getMailboxesInfo — fetches all mailboxes and their unread counts
  • getListFolder — fetches paginated email list for a given folder
  • getMailMessage — fetches full email content by ID
  • markAsRead — marks an email as read with optimistic updates: instantly sets isRead: true in the list cache and decrements unreadEmails in the mailbox cache, rolling back both on API failure

@xabg2 xabg2 self-assigned this Mar 27, 2026
@xabg2 xabg2 added the enhancement New feature or request label Mar 27, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 27, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 10f17cfb-9b63-4b68-a6bb-0f0e4d4cb20b

📥 Commits

Reviewing files that changed from the base of the PR and between 8e57831 and 307c0a0.

📒 Files selected for processing (1)
  • src/components/user-chip/index.tsx

📝 Walkthrough

Walkthrough

Consolidates RTK Query into a shared base API, adds a mail API with optimistic mark-as-read, introduces mail-specific error classes, adds mail message fetching and date formatting utilities, updates UI to use live mail/store data, and adjusts tests, fixtures, store wiring, and config.

Changes

Cohort / File(s) Summary
RTK Query base & store wiring
src/store/api/base.ts, src/store/api/storage/index.ts, src/store/index.ts, src/test-utils/createTestStore.ts
Added shared api (fakeBaseQuery + tagTypes), migrated storage to storageApi via api.injectEndpoints, and updated store reducers/middleware and test store to use api/storageApi.
Mail API & RTK Query tests
src/store/api/mail/index.ts, src/store/api/mail/mail.api.test.ts
New mailApi endpoints: getMailboxesInfo, getListFolder, getMailMessage, markAsRead with optimistic updates and rollback; added comprehensive endpoint tests covering success/failure and optimistic flows.
Mail errors
src/errors/mail/index.ts, src/errors/index.ts
Added four Error subclasses (FetchMailboxesInfoError, FetchListFolderError, FetchMessageError, UpdateMailError) and re-exported ./mail from src/errors/index.ts.
Mail service & service tests
src/services/sdk/mail/index.ts, src/services/sdk/mail/mail.service.test.ts
Added MailService.getMessage(emailId) and tests for fetching a message (success and failure) using mocked client responses.
Mail UI: view & tray
src/features/mail/MailView.tsx, src/features/mail/components/tray/index.tsx
MailView now uses live queries and activeMailId, adds useMarkAsReadMutation, conditional preview rendering; Tray accepts listFolder/loading/activeId/onMailSelected and maps mailbox API shape to Tray props.
Sidenav & navigation hooks
src/hooks/navigation/useSidenavNavigation.tsx, src/components/Sidenav/index.tsx
Sidenav hook polls useGetMailboxesInfoQuery, builds unread counts per mailbox, and Sidenav imports switched to storage API hooks.
Date service & tests
src/services/date/index.ts, src/services/date/date.service.test.ts
Added DateService.formatMailTimestamp(date) with conditional formats (same-day, same-year, other-year) and corresponding tests.
App init & user chip
src/App.tsx, src/components/user-chip/index.tsx
App initialization refactored to an async initializeUser helper that sequentially awaits thunks; UserChip computes userName more robustly, adjusts tooltip offset and passes fullName fallback.
Constants
src/constants.ts
Added exported DEFAULT_FOLDER_LIMIT = 15.
Test fixtures & config
src/test-utils/fixtures.ts, vitest.config.ts
Typed fixtures to SDK types (EmailResponse, EmailListResponse, MailboxResponse[]), adjusted mocked fields; Vitest test env set TZ = UTC.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • CandelR
  • larryrider
🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Title check ✅ Passed The title '[_]: feat/mail API queries' directly summarizes the main change—implementing RTK Query endpoints for the mail feature.
Description check ✅ Passed The description clearly explains the RTK Query layer implementation with specific details about the new queries and mutation, including the optimistic update behavior.

✏️ 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/list-emails-and-preview

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.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

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: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/App.tsx`:
- Around line 21-24: The initializeUser async wrapper calls
dispatch(initializeUserThunk()).unwrap() and
dispatch(refreshAvatarThunk()).unwrap() which can throw, and it's invoked inside
useEffect without handling rejections; update the useEffect invocation (or the
initializeUser function) to catch and handle errors from initializeUser — e.g.,
wrap the await calls in try/catch inside initializeUser or append .catch(...) to
the call in useEffect, and use process/UI-safe handling (logging via
console.error or dispatching an error action / setting local error state) so
unhandled promise rejections are avoided.

In `@src/components/user-chip/index.tsx`:
- Line 17: The userName derivation uses name.split(' ')[0] which can return an
empty token for leading or repeated spaces; update both occurrences (the
userName assignment and the similar logic at the other location) to normalize
whitespace first — e.g., use name.trim().split(/\s+/)[0] (or equivalent
normalization) before falling back to email.split('@')[0] so the first non-empty
name token is used.

In `@src/errors/mail/index.ts`:
- Around line 1-11: The constructors redundantly reassign the requestId property
created by the public parameter declaration; remove the explicit this.requestId
= requestId; line from FetchMailboxesInfoError (and the same redundant
assignment in the other three error classes) so the public requestId?: string
parameter alone defines and assigns the property.

In `@src/features/mail/components/tray/index.tsx`:
- Around line 12-14: The Tray component's props include hasMoreItems and
loadMore but MailView.tsx doesn't pass them; add a clear TODO comment next to
the props declaration (hasMoreItems?: boolean; loadMore?: () => void;)
explaining these are reserved for future pagination support and should be wired
up by MailView.tsx when implemented, or alternatively remove those two props
from the Tray props interface if you prefer not to keep unused API surface;
reference the Tray props and the parent MailView.tsx when making the change.

In `@src/features/mail/MailView.tsx`:
- Around line 52-58: TrayList is missing pagination props — pass its
hasMoreItems and loadMore props using the query response and a loader function:
use listFolder?.hasMore (or the appropriate pagination flag on listFolder) for
hasMoreItems, and provide a loadMore handler that calls the same query/fetch
function used to populate listFolder with a next position/cursor (e.g., current
listFolder.emails.length or listFolder.nextCursor) to request the next page;
wire these to TrayList as hasMoreItems={...} and loadMore={...} so infinite
scroll/pagination works with the existing listFolder and isLoadingListFolder
state.
- Around line 38-47: The onSelectEmail handler awaits markAsRead but doesn't
handle failures; wrap the await call in a try/catch inside onSelectEmail so
errors from markAsRead are caught, log the error (or send to monitoring) and
surface user feedback (e.g., trigger a toast/notification or set an error state)
so the user knows the action failed—keep setActiveMailId as-is, perform the
optimistic markAsRead call, and on catch revert or rely on the mutation rollback
while showing the error message to the user.

In `@src/store/queries/mail/mail.query.test.ts`:
- Line 1: Update the top-of-file comment that currently reads
"store/queries/__tests__/storage.query.test.ts" to the correct test filename
"store/queries/__tests__/mail.query.test.ts" so the comment matches this file
(mail.query.test.ts); locate the header comment in the test file (the initial
comment line) and replace the incorrect filename string accordingly to avoid the
copy-paste mismatch.

In `@src/store/queries/mail/mail.query.ts`:
- Line 35: The current providesTags use global strings ('ListFolder') which
broadens invalidation; change getListFolder's providesTags to return
argument-scoped tags (e.g., provide [{ type: 'ListFolder', id:
JSON.stringify(args) } or use folderId/page as the id]) and change
getMailMessage's providesTags to include the specific emailId (e.g., { type:
'MailMessage', id: emailId }); then update any mutating endpoints such as
markAsRead to invalidate or update only those specific tags (invalidate [{ type:
'MailMessage', id: emailId }] and/or the corresponding ListFolder id) so cache
reconciliation is precise.
- Around line 59-80: The optimistic mailbox counter is decremented
unconditionally; change onQueryStarted so the mailbox counter (patchMailboxes
via mailQuery.util.updateQueryData('getMailboxesInfo', ...)) only decrements
when the email actually transitioned from unread to read by detecting that
change in the same patch that updates the email (use the result of the email
lookup in the patchEmailList operation or a local flag set when mail &&
!mail.isRead). Apply the counter decrement only if that flag is true, and on
catch() do not call patchMailboxes.undo(); instead dispatch a refetch of the
mailbox info (e.g., dispatch(mailQuery.util.invalidateTags or trigger a refetch
of 'getMailboxesInfo')) so overlapping optimistic updates cannot restore stale
scalar counts.
🪄 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: a9c3c5fc-21db-45a2-8f08-dbd473a237d2

📥 Commits

Reviewing files that changed from the base of the PR and between 4a82ac7 and fa85b5f.

📒 Files selected for processing (18)
  • src/App.tsx
  • src/components/user-chip/index.tsx
  • src/constants.ts
  • src/errors/index.ts
  • src/errors/mail/index.ts
  • src/features/mail/MailView.tsx
  • src/features/mail/components/tray/index.tsx
  • src/hooks/navigation/useSidenavNavigation.tsx
  • src/services/date/date.service.test.ts
  • src/services/date/index.ts
  • src/services/sdk/mail/index.ts
  • src/services/sdk/mail/mail.service.test.ts
  • src/store/index.ts
  • src/store/queries/mail/mail.query.test.ts
  • src/store/queries/mail/mail.query.ts
  • src/test-utils/createTestStore.ts
  • src/test-utils/fixtures.ts
  • vitest.config.ts

@xabg2 xabg2 requested a review from larryrider March 27, 2026 12:59
@xabg2 xabg2 assigned CandelR and unassigned CandelR Mar 27, 2026
@xabg2 xabg2 requested a review from CandelR March 27, 2026 12:59
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

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: 3

♻️ Duplicate comments (2)
src/features/mail/MailView.tsx (1)

44-52: ⚠️ Potential issue | 🟡 Minor

Call .unwrap() here or this catch stays dead.

RTK Query mutation triggers resolve to { data | error }; they only reject on .unwrap(). As written, failed markAsRead calls skip this catch and nothing is logged/cast.

💡 Minimal fix
     try {
       await markAsRead({
         emailId: id,
         query,
-      });
+      }).unwrap();
     } catch (error) {
       const err = ErrorService.instance.castError(error);
       console.error(`Error while marking as read the email ${id}: `, err);
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/mail/MailView.tsx` around lines 44 - 52, The try/catch around
the RTK Query mutation markAsRead is ineffective because RTK returns a
{data|error} object unless you call .unwrap(); update the call in MailView.tsx
to await markAsRead({ emailId: id, query }).unwrap() so that failures throw and
the existing catch (which uses ErrorService.instance.castError and
console.error) will run; keep the same error handling logic in the catch block.
src/store/queries/mail/mail.query.ts (1)

74-85: ⚠️ Potential issue | 🟠 Major

Refetch mailbox counts on failure instead of undo()ing the counter patch.

patchMailboxes.undo() restores an old scalar snapshot. If two markAsRead mutations overlap and an earlier request fails after a later one succeeds, this rollback can erase the later success and overstate unreadEmails.

💡 Safer rollback
         try {
           await queryFulfilled;
         } catch {
           patchEmailList.undo();
-          patchMailboxes.undo();
+          dispatch(mailQuery.util.invalidateTags(['Mailbox']));
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/store/queries/mail/mail.query.ts` around lines 74 - 85, The rollback
currently calls patchMailboxes.undo(), which can revert a newer successful
update when overlapping markAsRead mutations occur; instead, on catch stop
undoing the scalar snapshot and trigger a fresh refetch of mailbox counts: keep
patchEmailList.undo() as-is, remove patchMailboxes.undo(), and dispatch
mailQuery.endpoints.getMailboxesInfo.initiate(undefined, { forceRefetch: true })
(using the same dispatch visible in this scope) so the mailbox counts
(getMailboxesInfo) are re-fetched when queryFulfilled fails.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/user-chip/index.tsx`:
- Line 56: The tooltip fullName currently uses the raw expression name || email
which allows whitespace-only names to win; change the logic used when rendering
<UserCheap ... fullName={...} /> so the name is normalized (trimmed) and treated
as empty if it contains only whitespace—e.g., compute a normalizedFullName =
(name || '').trim() || email and pass normalizedFullName into the fullName prop
of UserCheap to ensure the email is used as the fallback.

In `@src/features/mail/MailView.tsx`:
- Around line 1-30: The MailView component keeps activeMailId across mailbox
changes causing the previous message to remain visible; add a useEffect in
MailView that listens for changes to the folder prop and calls
setActiveMailId(undefined) to clear the selection on mailbox switch, and ensure
useEffect is imported from React (so reference useEffect, setActiveMailId,
activeMailId, and the MailView component).

In `@src/store/queries/mail/mail.query.ts`:
- Around line 18-20: The current catch blocks in
src/store/queries/mail/mail.query.ts return custom Error instances (e.g., new
FetchMailboxesInfoError(...)) into RTK Query, which is non-serializable; change
those return values to plain serializable objects like { error: { message:
err.message, requestId: err.requestId } } instead of returning Error objects.
Locate the catch blocks that create FetchMailboxesInfoError,
FetchMailboxMessagesError, FetchMessageError (and the other similar
error-returning branches at the commented ranges) and replace the returned Error
instances with plain objects containing at minimum message and optional
requestId so consumers can reconstruct Error instances where needed.

---

Duplicate comments:
In `@src/features/mail/MailView.tsx`:
- Around line 44-52: The try/catch around the RTK Query mutation markAsRead is
ineffective because RTK returns a {data|error} object unless you call .unwrap();
update the call in MailView.tsx to await markAsRead({ emailId: id, query
}).unwrap() so that failures throw and the existing catch (which uses
ErrorService.instance.castError and console.error) will run; keep the same error
handling logic in the catch block.

In `@src/store/queries/mail/mail.query.ts`:
- Around line 74-85: The rollback currently calls patchMailboxes.undo(), which
can revert a newer successful update when overlapping markAsRead mutations
occur; instead, on catch stop undoing the scalar snapshot and trigger a fresh
refetch of mailbox counts: keep patchEmailList.undo() as-is, remove
patchMailboxes.undo(), and dispatch
mailQuery.endpoints.getMailboxesInfo.initiate(undefined, { forceRefetch: true })
(using the same dispatch visible in this scope) so the mailbox counts
(getMailboxesInfo) are re-fetched when queryFulfilled fails.
🪄 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: 7cc457de-60d0-4a1c-9ce8-3c67f1d7d2f8

📥 Commits

Reviewing files that changed from the base of the PR and between fa85b5f and b531444.

📒 Files selected for processing (7)
  • src/App.tsx
  • src/components/user-chip/index.tsx
  • src/errors/mail/index.ts
  • src/features/mail/MailView.tsx
  • src/services/sdk/mail/index.ts
  • src/store/queries/mail/mail.query.test.ts
  • src/store/queries/mail/mail.query.ts

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

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: 2

♻️ Duplicate comments (3)
src/features/mail/MailView.tsx (3)

1-1: ⚠️ Potential issue | 🟠 Major

Clear the selected message when folder changes.

activeMailId is folder-agnostic state here, so switching folders can keep rendering the previous folder’s message until the user clicks another item.

💡 Minimal fix
-import { useState } from 'react';
+import { useEffect, useState } from 'react';
...
   const [activeMailId, setActiveMailId] = useState<string | undefined>(undefined);
+
+  useEffect(() => {
+    setActiveMailId(undefined);
+  }, [folder]);

Also applies to: 18-29

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/mail/MailView.tsx` at line 1, The component-level state
activeMailId in MailView is folder-agnostic and must be reset when folder
changes; add an effect that watches the folder prop/variable and calls
setActiveMailId(null) (or undefined) to clear the selection whenever folder
updates so the previous folder’s message is not rendered; locate the
activeMailId state and its setter (setActiveMailId) in MailView and implement a
useEffect(() => { setActiveMailId(null); }, [folder]) to fix it.

39-52: ⚠️ Potential issue | 🟡 Minor

Use .unwrap() here or this catch never runs.

RTK Query mutation triggers resolve to { data | error } unless you call .unwrap(). A failed markAsRead will still roll back the optimistic patch, but this try/catch will not log or surface the failure as written.

In Redux Toolkit RTK Query 2.11.2, when a mutation trigger is awaited directly (for example `await markAsRead(args)`), does it reject on request failure, or is `.unwrap()` required for `try/catch` to run?
🔧 Minimal fix
     try {
       await markAsRead({
         emailId: id,
         query,
-      });
+      }).unwrap();
     } catch (error) {
       const err = ErrorService.instance.castError(error);
       console.error(`Error while marking as read the email ${id}: `, err);
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/mail/MailView.tsx` around lines 39 - 52, The try/catch in
onSelectEmail won't catch RTK Query mutation failures because markAsRead returns
a fulfilled result object unless unwrapped; update the call in onSelectEmail to
await markAsRead({ emailId: id, query }).unwrap() so that failed requests reject
and trigger the existing catch block (ensure you import/keep ErrorService
handling as-is and keep the optimistic rollback behavior intact).

19-28: ⚠️ Potential issue | 🟠 Major

The folder query is still pinned to page 0.

position never moves off 0, and TrayList already exposes hasMoreItems / loadMore (src/features/mail/components/tray/index.tsx:7-24) but does not receive them here. Any folder with more than DEFAULT_FOLDER_LIMIT messages is therefore truncated to the first batch.

Also applies to: 58-64

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/mail/MailView.tsx` around lines 19 - 28, The query always sets
position: 0 so pagination never advances; update MailView to track the folder
position (e.g., use state like position or page keyed by folder) and pass that
dynamic position into the query object used by useGetListFolderQuery (instead of
the hardcoded 0), and forward TrayList's hasMoreItems and loadMore props into
MailView so loadMore increments the stored position (or updates the cursor) and
triggers a refetch; reference symbols: query, position, useGetListFolderQuery,
DEFAULT_FOLDER_LIMIT, TrayList, hasMoreItems, loadMore.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/store/api/mail/mail.api.test.ts`:
- Around line 145-164: Add a test that covers the zero-unread boundary so
optimistic decrement cannot underflow: create a variant of the existing
optimistic-store fixture (use setupOptimisticStore or mutate the returned
store/cache) so the mailboxState for the 'inbox' starts with unreadEmails: 0 and
an email with isRead: false, then spy MailService.instance.updateEmailStatus to
resolve and dispatch mailApi.endpoints.markAsRead.initiate({ emailId, query:
mailboxQuery }) and assert unreadEmails stays 0 (not -1) and the email becomes
read; also add the failing case (mockRejectedValue) and assert unreadEmails
remains 0 after rollback. Reference setupOptimisticStore,
mailApi.endpoints.markAsRead.initiate, MailService.instance.updateEmailStatus
and the mailboxState.unreadEmails field.
- Around line 21-23: Replace vi.clearAllMocks() in the test suite setup with
vi.restoreAllMocks() so mocked implementations (not just call history) are reset
between tests; this prevents leftover mockResolvedValue/mockRejectedValue on the
singleton MailService.instance from affecting later tests. Also add a boundary
unit test for the optimistic-update behavior of the markAsRead flow (the
functions used in tests around markAsRead and unreadEmails) that starts with
unreadEmails = 1, invokes the optimistic mark-as-read action, and asserts the
count becomes 0 (and never negative) both on success and on rollback scenarios
to cover the zero-underflow case.

---

Duplicate comments:
In `@src/features/mail/MailView.tsx`:
- Line 1: The component-level state activeMailId in MailView is folder-agnostic
and must be reset when folder changes; add an effect that watches the folder
prop/variable and calls setActiveMailId(null) (or undefined) to clear the
selection whenever folder updates so the previous folder’s message is not
rendered; locate the activeMailId state and its setter (setActiveMailId) in
MailView and implement a useEffect(() => { setActiveMailId(null); }, [folder])
to fix it.
- Around line 39-52: The try/catch in onSelectEmail won't catch RTK Query
mutation failures because markAsRead returns a fulfilled result object unless
unwrapped; update the call in onSelectEmail to await markAsRead({ emailId: id,
query }).unwrap() so that failed requests reject and trigger the existing catch
block (ensure you import/keep ErrorService handling as-is and keep the
optimistic rollback behavior intact).
- Around line 19-28: The query always sets position: 0 so pagination never
advances; update MailView to track the folder position (e.g., use state like
position or page keyed by folder) and pass that dynamic position into the query
object used by useGetListFolderQuery (instead of the hardcoded 0), and forward
TrayList's hasMoreItems and loadMore props into MailView so loadMore increments
the stored position (or updates the cursor) and triggers a refetch; reference
symbols: query, position, useGetListFolderQuery, DEFAULT_FOLDER_LIMIT, TrayList,
hasMoreItems, loadMore.
🪄 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: 769ededb-7228-4d4d-ac90-34f20a3dce5c

📥 Commits

Reviewing files that changed from the base of the PR and between b531444 and 3723f78.

📒 Files selected for processing (10)
  • src/components/Sidenav/index.tsx
  • src/features/mail/MailView.tsx
  • src/hooks/navigation/useSidenavNavigation.tsx
  • src/store/api/base.ts
  • src/store/api/mail/index.ts
  • src/store/api/mail/mail.api.test.ts
  • src/store/api/storage/index.ts
  • src/store/api/storage/storage.api.test.ts
  • src/store/index.ts
  • src/test-utils/createTestStore.ts

textBody: faker.lorem.paragraphs(2),
htmlBody: `<p>${faker.lorem.paragraphs(2)}</p>`,
textBody: faker.lorem.paragraphs(2) as unknown as null,
htmlBody: `<p>${faker.lorem.paragraphs(2)}</p>` as unknown as null,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

why as unknown as null ?? 🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure why the type is incorrect in the SDK. It defines htmlBody as Record<string, never> (empty object) | null, which prevents us from assigning a string to this field. However, the backend actually returns a string, so I had to temporarily set it to null to satisfy the type constraints. I'll investigate the SDK type generation to understand where this mismatch is coming from.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

maybe we should fix the sdk then 🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ok, I already fixed it in the backend (and in a new SDK version). I will fix this in another PR @larryrider

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yep, I fixed the SDK (by fixing the server types). But I will update the SDK version in another PR as I have to update some types/params.

@xabg2 xabg2 merged commit 8ed714f into master Mar 30, 2026
2 of 3 checks passed
@xabg2 xabg2 deleted the feature/list-emails-and-preview branch March 30, 2026 13:19
@sonarqubecloud
Copy link
Copy Markdown

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.

3 participants