Rocket.Chat.ReactNative icon indicating copy to clipboard operation
Rocket.Chat.ReactNative copied to clipboard

fix: profile avatar cache busting and refresh mechanism

Open deepak0x opened this issue 1 month ago • 3 comments

I fixed an issue where updating a profile avatar wasn’t showing the new image immediately after going back to the ProfileView. The old cached image would keep showing until the user saved again or manually refreshed.

Issue(s) Fixes bug: #6794

Problem

When a user updates their avatar and goes back to the ProfileView, the old avatar still appears. This happens because:

  • expo-image caches images very aggressively
  • The avatarETag wasn't updating correctly across databases
  • The useAvatarETag hook didn’t re-run when the value changed
  • There was no proper cache-busting or refresh mechanism

What I Did

I added a few coordinated fixes to make sure the avatar updates instantly:

  1. useAvatarETag

    • Made it always listen for changes (removed the old condition)
    • Set the initial value right away
    • Fixed the effect dependencies so it re-runs correctly
  2. Avatar component

    • Added a cache-busting _cb=${avatarETag} query param to the image URL
    • Added a key based on avatarETag so the image remounts when updated
    • Used useMemo to generate the final avatar URL
  3. ProfileView

    • Added a refresh key that updates when returning to the view
    • Used it to force the avatar container to remount
    • Cleared the in-memory image cache on focus
  4. connect.ts

    • When updating the avatar, I now also sync the logged-in user’s avatarETag in Redux
    • This triggers the saga to update the database, so the hook immediately detects changes

Summary by CodeRabbit

  • Bug Fixes
    • More reliable avatar updates: avatar images now remount when their source changes to ensure fresh display.
    • Improved avatar synchronization: avatar change events are propagated to remote servers to keep records consistent.
  • Performance
    • Enhanced image caching using a memory-disk policy for faster load and reduced network use.
  • Stability
    • More robust avatar observation and cleanup to avoid stale updates after unmount.

✏️ Tip: You can customize this high-level summary in your review settings.

deepak0x avatar Nov 14 '25 09:11 deepak0x

Walkthrough

Image remounting and cache policy were added to Avatar; the ETag observation hook now runs unconditionally and tracks more dependencies; avatarETag updates for the logged-in user are synchronized to the servers database after updateAvatar events.

Changes

Cohort / File(s) Summary
Avatar component rendering
app/containers/Avatar/Avatar.tsx
Image now receives key={${uri}-${avatarETag
Avatar ETag observation hook
app/containers/Avatar/useAvatarETag.ts
Removed outer guard so observeAvatarETag runs unconditionally; inlined direct-user logic; added local isSubscribed flag for lifecycle safety; consolidated record resolution inline; extended useEffect deps to [username, text, id, rid, type].
Server synchronization
app/lib/services/connect.ts
After local avatarETag update, if the updated username matches the logged-in user, update that user's avatarETag in the servers database; includes handling for missing server records.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Avatar as Avatar Component
    participant Hook as useAvatarETag Hook
    participant DB as App DB
    participant ServerDB as Servers DB
    participant Connect as connect service

    User->>Avatar: update avatar
    Avatar->>Hook: effect re-evaluates (deps: username,text,id,rid,type)
    Hook->>DB: observeAvatarETag (unconditional)
    DB-->>Hook: record observable
    Hook-->>Avatar: avatarETag updated
    Avatar->>Avatar: Image remount (new key)
    Avatar-->>User: render updated avatar

    Note over Connect,ServerDB: sync logged-in user's ETag
    DB->>Connect: emit updateAvatar event
    Connect->>ServerDB: update avatarETag for logged-in user (if username matches)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Pay attention to lifecycle and subscription correctness in useAvatarETag.ts (isSubscribed flag, cleanup).
  • Verify remount implications and performance for Avatar.tsx when forcing Image key changes.
  • Confirm connect.ts correctly locates and updates server records and handles missing-record errors.

Suggested reviewers

  • OtavioStasiak

Poem

🐇 I hop through bytes and tags so bright,

Remounting faces into light,
ETags flutter, servers sing,
A little sync, a joyful spring,
Your avatar bounces — what a sight! ✨

Pre-merge checks and finishing touches

❌ 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%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main objective of the PR—fixing avatar cache busting and refresh mechanisms to resolve the issue where updated profile avatars didn't appear immediately.
✨ Finishing touches
  • [ ] 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • [ ] Create PR with unit tests
  • [ ] Post copyable unit tests in a comment

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[bot] avatar Nov 14 '25 09:11 coderabbitai[bot]

This change is done by AI and i don't think you have done the testing in iOS and Android.

  1. You have added react-native-skeleton-placeholder but package.json, package-lock.json, ios/Podfile.lock files are missing from the PR. Screenshot 2025-11-18 at 3 16 09 AM

  2. Please explain why we have to clear all images from the memory cache after one user avatar changes

Image.clearMemoryCache().catch(() => {
    // Ignore errors if cache clearing fails
});
Screenshot 2025-11-18 at 3 21 18 AM
  1. Can you provide a recording of this feature as working

Rohit3523 avatar Nov 17 '25 21:11 Rohit3523

It was showing the old avatar due to cache... so i clear cache after avatar change so that it request fresh fetch of avatar from server...

https://github.com/user-attachments/assets/d6be4946-abd8-464f-a8e3-f4e37696a39f

here's the recording

Thanks

deepak0x avatar Nov 17 '25 22:11 deepak0x