Skip to content

[GIT-260] fix(user): Profile cover image uses stale image after update#9285

Open
codingwolf-at wants to merge 1 commit into
previewfrom
git-260/cover-image-fix
Open

[GIT-260] fix(user): Profile cover image uses stale image after update#9285
codingwolf-at wants to merge 1 commit into
previewfrom
git-260/cover-image-fix

Conversation

@codingwolf-at

@codingwolf-at codingwolf-at commented Jun 22, 2026

Copy link
Copy Markdown

Description

Updated the updateCurrentUser method in UserStore to clone the current user data before making updates, ensuring that the original data remains unchanged during the update process. Additionally, added logic to update the local state with the new user data after a successful update.

fix(cover-image): return absolute URLs for cover images

Modified the handleCoverImageChange function to return absolute URLs for cover images, ensuring compatibility with the expected format. This change includes handling both uploaded images and new images, providing a consistent return structure.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)

Screenshots and Media (if applicable)

Before

Before.mov

After

After.mov

Test Scenarios

  1. Open profile settings modal
  2. Click Change Cover and select a new image
  3. Click Save Changes — the new cover image appears correctly
  4. Close the settings modal
  5. Reopen the settings modal
  6. Previously: old cover image is shown. Hit browser refresh → correct cover image now appears
  7. Now: new cover image is shown

References

NA

Summary by CodeRabbit

Bug Fixes

  • Improved synchronization of user profile data after updates to ensure consistency with server-side changes.
  • Fixed cover image handling to ensure consistent URL formatting for uploaded images.

Updated the `updateCurrentUser` method in `UserStore` to clone the current user data before making updates, ensuring that the original data remains unchanged during the update process. Additionally, added logic to update the local state with the new user data after a successful update.

fix(cover-image): return absolute URLs for cover images

Modified the `handleCoverImageChange` function to return absolute URLs for cover images, ensuring compatibility with the expected format. This change includes handling both uploaded images and new images, providing a consistent return structure.
@CLAassistant

CLAassistant commented Jun 22, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@codingwolf-at codingwolf-at changed the title [GIT-260 ] fix(user): Profile cover image uses stale image after update [GIT-260] fix(user): Profile cover image uses stale image after update Jun 22, 2026
@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Two targeted bug fixes: UserStore.updateCurrentUser now deep-clones this.data for rollback and syncs observable state from the API response (not the request payload) on success. handleCoverImageChange fixes the upload branch to return a full TCoverImagePayload instead of undefined.

Changes

User Store and Cover Image Data Handling Fixes

Layer / File(s) Summary
UserStore: deep-clone rollback and API-response sync
apps/web/core/store/user/index.ts
updateCurrentUser now uses cloneDeep(this.data) for the rollback snapshot instead of a direct reference, and on a successful userService.updateUser call syncs this.data by iterating Object.keys(user) from the returned response inside runInAction, replacing the previous pre-call optimistic update.
Cover image upload payload fix
apps/web/helpers/cover-image.helper.ts
The analysis.needsUpload branch in handleCoverImageChange now returns a complete object with cover_image (absolute URL via getFileURL(assetUrl) || assetUrl) and cover_image_url (raw assetUrl), fixing the prior implicit undefined return from that branch.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐇 A snapshot saved, a clone held tight,
No ghost of old data to haunt through the night.
The upload returned what it promised to bring,
Full payload in hand—not a missing-data thing.
Hop hop, little fixes, all tidy and neat! 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main bugfix: profile cover image displays stale data after update, which is the primary issue addressed by both code changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Description check ✅ Passed The pull request description includes a detailed explanation of changes, clearly marks the type as a bug fix, provides comprehensive test scenarios, and demonstrates the fix with before/after videos.

✏️ 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 git-260/cover-image-fix

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.

@makeplane

makeplane Bot commented Jun 22, 2026

Copy link
Copy Markdown

Linked to Plane Work Item(s)

This comment was auto-generated by Plane

@coderabbitai coderabbitai Bot left a comment

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.

Caution

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

⚠️ Outside diff range comments (1)
apps/web/core/store/user/index.ts (1)

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

Wrap rollback logic in runInAction for MobX reactivity.

The rollback at lines 176-179 mutates the observable this.data but is not wrapped in runInAction. This is inconsistent with the success path (lines 165-172) and MobX best practices. MobX may not properly track these mutations, leading to missed re-renders or reactivity issues.

🔧 Proposed fix
    } catch (error) {
-     if (currentUserData) {
-       Object.keys(currentUserData).forEach((key: string) => {
-         const userKey: keyof IUser = key as keyof IUser;
-         if (this.data) set(this.data, userKey, currentUserData[userKey]);
-       });
-     }
      runInAction(() => {
+       if (currentUserData) {
+         Object.keys(currentUserData).forEach((key: string) => {
+           const userKey: keyof IUser = key as keyof IUser;
+           if (this.data) set(this.data, userKey, currentUserData[userKey]);
+         });
+       }
        this.error = {
          status: "user-update-error",
          message: "Failed to update current user",
        };
      });
🤖 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 `@apps/web/core/store/user/index.ts` around lines 174 - 180, The rollback logic
in the catch block mutates the observable this.data property without wrapping it
in runInAction, which is inconsistent with the success path and violates MobX
best practices. Wrap the entire forEach loop that restores currentUserData keys
back to this.data (where set is called for each userKey) inside a runInAction
function call to ensure MobX properly tracks these mutations and maintains
reactivity.
🧹 Nitpick comments (1)
apps/web/core/store/user/index.ts (1)

158-163: 🧹 Nitpick | 🔵 Trivial | ⚖️ Poor tradeoff

Remove redundant optimistic update or wrap in runInAction.

Lines 158-163 apply an optimistic update using the request payload before the API call, but lines 165-172 immediately overwrite those fields with the API response. This double-update is redundant.

According to the stack context and AI summary, the intent was to sync from the API response instead of applying the request payload before the call. The optimistic update should likely be removed entirely.

If immediate UI feedback is required and the optimistic update is intentional, it must be wrapped in runInAction(() => { ... }) to ensure MobX tracks the state changes properly, consistent with the pattern used at lines 165-172 and elsewhere in this file (e.g., lines 125-129).

♻️ Recommended fix: remove optimistic update
  updateCurrentUser = async (data: Partial<IUser>): Promise<IUser> => {
    const currentUserData = cloneDeep(this.data);
    try {
-     if (currentUserData) {
-       Object.keys(data).forEach((key: string) => {
-         const userKey: keyof IUser = key as keyof IUser;
-         if (this.data) set(this.data, userKey, data[userKey]);
-       });
-     }
      const user = await this.userService.updateUser(data);
      if (user && this.data) {
        runInAction(() => {
🤖 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 `@apps/web/core/store/user/index.ts` around lines 158 - 163, The forEach loop
that iterates through data keys and updates this.data using the set function is
redundant because the API response immediately overwrites those same fields in
the subsequent block. Either remove this entire optimistic update block
entirely, or if immediate UI feedback is required, wrap the forEach loop and its
contents in runInAction(() => { ... }) to ensure MobX properly tracks the state
changes, consistent with the pattern used elsewhere in the file.
🤖 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.

Outside diff comments:
In `@apps/web/core/store/user/index.ts`:
- Around line 174-180: The rollback logic in the catch block mutates the
observable this.data property without wrapping it in runInAction, which is
inconsistent with the success path and violates MobX best practices. Wrap the
entire forEach loop that restores currentUserData keys back to this.data (where
set is called for each userKey) inside a runInAction function call to ensure
MobX properly tracks these mutations and maintains reactivity.

---

Nitpick comments:
In `@apps/web/core/store/user/index.ts`:
- Around line 158-163: The forEach loop that iterates through data keys and
updates this.data using the set function is redundant because the API response
immediately overwrites those same fields in the subsequent block. Either remove
this entire optimistic update block entirely, or if immediate UI feedback is
required, wrap the forEach loop and its contents in runInAction(() => { ... })
to ensure MobX properly tracks the state changes, consistent with the pattern
used elsewhere in the file.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 229c73f3-5559-4efb-9dff-cf3f9816e8eb

📥 Commits

Reviewing files that changed from the base of the PR and between 4a0746b and 955ee49.

📒 Files selected for processing (2)
  • apps/web/core/store/user/index.ts
  • apps/web/helpers/cover-image.helper.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants