feat: add skeleton loading and error handling to ServerAvatar
I updated the ServerAvatar component in WorkspaceView to finally add a proper loading state and error handling. Earlier, the avatar area would just stay blank while the image was loading, and nothing showed up if the image failed. Now the user always sees something — either a skeleton, the real avatar, or a fallback icon.
Issue Fixes bug: #4809
Problem
- Avatar area looked empty and broken while loading
- No indication that something was happening
- If the image failed, the UI showed nothing
- In dark mode, avatars blended into the background
- There was already a TODO reminding that the skeleton was missing
What I Did
I added everything needed to make the avatar feel responsive and consistent with the rest of the app:
Skeleton Loader
Shows an animated grey placeholder while the avatar loads (same style used across the app).
Error Handling
If the image fails, a fallback "workspace" icon appears instead of a blank area.
Dark Mode Support
Added a grey background in dark mode so the avatar doesn’t disappear into a black background. Light mode remains transparent.
###Proper State Management
Used expo-image callbacks:
-
onLoadStart→ show skeleton -
onLoad→ hide skeleton -
onError→ show fallback
Also reset states when the image URL changes so the component always behaves correctly when switching servers.
Changes
In ServerAvatar.tsx:
- Added skeleton placeholder
- Added fallback icon
- Added dark mode background
- Wired up expo-image loading/error callbacks
- Ensured only one thing shows at a time (skeleton, image, or fallback)
- Cleaned up the existing TODO
- Added state reset on
imageUrichange
Walkthrough
The ServerAvatar component is refactored to include stateful image loading and error handling. Loading and error states are tracked, image lifecycle handlers manage state transitions, and conditional rendering displays either a skeleton overlay during loading, an image on success, or a fallback container with a custom icon on error. Dark mode support is added.
Changes
| Cohort / File(s) | Summary |
|---|---|
Avatar image state management and error handling app/views/WorkspaceView/ServerAvatar.tsx |
Added useState for tracking loading and error states; implemented image lifecycle handlers (onLoadStart, onLoad, onError); state resets on image URL change. Conditional rendering now displays skeleton overlay during loading, fallback container with CustomIcon on error or missing image, or the image itself on success. Dark mode support added by deriving isDarkMode from theme and applying conditional styling. New imports: useState, SkeletonPlaceholder, CustomIcon. New style blocks: imageContainer, skeletonOverlay, fallbackContainer. |
Sequence Diagram
sequenceDiagram
participant User
participant Component as ServerAvatar Component
participant ImageElement as Image Element
User->>Component: Render with image URL
Component->>Component: useState: loading=true, error=false
Component->>ImageElement: Render image (onLoadStart)
ImageElement->>Component: onLoad event
Component->>Component: Update state: loading=false, error=false
Component->>Component: Render image with skeletonOverlay hidden
alt Image Load Error
ImageElement->>Component: onError event
Component->>Component: Update state: error=true, loading=false
Component->>Component: Render fallbackContainer with CustomIcon
end
alt URL Change
User->>Component: New image URL prop
Component->>Component: Reset state: loading=true, error=false
Component->>ImageElement: Render new image
end
Estimated code review effort
🎯 3 (Moderate) | ⏱️ ~20 minutes
-
Focus areas for review:
- Verify state initialization, reset logic on URL change, and proper lifecycle handler invocation
- Confirm conditional rendering logic handles all three paths (loading, success, error) correctly
- Review dark mode implementation and ensure theme integration is consistent
- Check image container, skeleton overlay, and fallback container styling and layout behavior
- Validate no regressions in component API or parent component integration
Poem
🐰 A rabbit hops through avatar land, Where images load with gentle hand, With skeleton frames and errors caught, Dark mode styling all is sought— Now avatars shine, resilient and bright! ✨
Pre-merge checks and finishing touches
✅ Passed checks (3 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | The title accurately and concisely summarizes the main change: adding skeleton loading and error handling to ServerAvatar component. |
| Docstring Coverage | ✅ Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. |
✨ Finishing touches
- [ ] 📝 Generate docstrings
🧪 Generate unit tests (beta)
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
📜 Recent review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📥 Commits
Reviewing files that changed from the base of the PR and between 35324474ba7b5bcaf15c8d49c0a31b293d253c04 and a0dff0d3b8c28a42b2f4ef8109140e689bc8a945.
📒 Files selected for processing (1)
-
app/views/WorkspaceView/ServerAvatar.tsx(3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
app/views/WorkspaceView/ServerAvatar.tsx (3)
app/containers/LoginServices/styles.ts (1)
BORDER_RADIUS(6-6)app/theme.tsx (1)
useTheme(29-29)app/containers/CustomIcon/index.tsx (1)
CustomIcon(38-38)
🔇 Additional comments (7)
app/views/WorkspaceView/ServerAvatar.tsx (7)
1-12: LGTM! Clean imports and well-defined constants.The new imports (useState, SkeletonPlaceholder, CustomIcon) are all properly utilized, and the constants provide clear sizing configuration.
14-48: LGTM! Well-structured styles with consistent sizing.The positioning strategy (relative container + absolute overlay) correctly enables the skeleton to appear on top of the loading image, and all dimensions and border radii are consistent.
55-63: LGTM! Proper state initialization.The lazy initialization of
loadingstate to!!imageUriensures the skeleton appears immediately when an image is present, avoiding a blank flash before the image starts loading.
65-74: LGTM! Correct state reset on imageUri change.The effect properly handles state transitions when the avatar URL changes, ensuring the component always reflects the current loading/error status for the active image.
76-89: LGTM! Clean state machine for image lifecycle.The handlers correctly manage the loading → success/error transitions, ensuring the UI accurately reflects the image's current state.
110-138: LGTM! Elegant skeleton overlay implementation.The skeleton is correctly positioned absolutely over the image during loading, with matching dimensions and border radius. The use of
expo-image's lifecycle callbacks ensures smooth transitions between loading, success, and error states.
92-108: LGTM! The 'workspaces' icon has been verified to exist in the CustomIcon mapping.The fallback implementation is solid with appropriate dark mode support, consistent styling with the main image, and proper icon sizing at 50% of the container. The 'workspaces' icon is mapped at code 59870 in mappedIcons.js, confirming it's available for use.
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.
Comment @coderabbitai help to get the list of available commands and usage tips.