Skip to content

feat: implement event cover photo picker, resumable upload progress, and native caching#425

Open
Nicks-19 wants to merge 1 commit into
roshankumar0036singh:mainfrom
Nicks-19:feat/event-cover-photos
Open

feat: implement event cover photo picker, resumable upload progress, and native caching#425
Nicks-19 wants to merge 1 commit into
roshankumar0036singh:mainfrom
Nicks-19:feat/event-cover-photos

Conversation

@Nicks-19
Copy link
Copy Markdown
Contributor

@Nicks-19 Nicks-19 commented May 30, 2026

Description

This change fixes the problem with custom event cover photos in the Uni-Event application that was reported in issue #322.

Key Changes

  • Image Picker & Compression: We use expo-image-picker to let users pick images and we compress these images to make them smaller the quality is set to 0.7.

  • Validation: We check the size of the image before it is uploaded if the image is than 5MB we do not let the user upload it.

  • Upload: We use uploadBytesResumable from Firebase Storage so we can see how the upload is going in real time.

  • Upload Progress Overlay: When a user is uploading a cover photo we show an overlay on top of the photo slot this overlay is see through and it shows a progress bar and the percentage of the upload that is complete.

  • Native Caching: We use cache: force-cache on all the places where we show cover photos, like EventCard, EventDetail, and RemindersScreen . The photos load faster.

Verification Results

  • We ran all our tests, 22 test suites and 129 tests. They all worked fine.

Summary by CodeRabbit

  • New Features

    • Added resumable image uploads for event banners with progress bar and percentage display
    • Implemented 5MB file size validation with clear error alerts
  • Performance

    • Optimized image caching across event cards, detail views, and reminders for faster load times

Review Change Stack

…ogress bar, and caching for event cover photos
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 30, 2026

📝 Walkthrough

Walkthrough

The PR adds resumable image uploads with client-side validation and real-time progress feedback to event creation, while enforcing consistent force-cache directives for banner images across event display screens. CreateEvent now validates image size (≤ 5MB), compresses quality, uploads via Firebase resumable upload, and displays a progress overlay; event creation fails gracefully if upload errors occur. Four screens now use force-cache for banner images.

Changes

Image Upload and Caching Enhancements

Layer / File(s) Summary
Resumable upload infrastructure and state
app/src/screens/CreateEvent.js
Firebase Storage import updated to use uploadBytesResumable. New uploadProgress state tracks transfer bytes. Image picking enforces 5MB client-side limit with quality reduction to 0.7, and upload helper mirrors this limit while updating progress during transfer. Event creation catches upload failures, alerts with error message, resets loading state, and stops early.
Upload progress overlay and state management
app/src/screens/CreateEvent.js
Banner picker interaction disabled while loading. Upload progress overlay conditionally renders with activity indicator, "Uploading Cover Photo" percentage text, and progress bar during upload; pencil edit icon hidden during transfer. New stylesheet rules added for overlay background, text, and progress bar styling.
Force-cache directive across screens
app/src/components/EventCard.js, app/src/screens/EventDetail.js, app/src/screens/RemindersScreen.js
cache: 'force-cache' added to banner image source objects in EventCard, EventDetail header image, and RemindersScreen reminder cards.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested labels

level:intermediate, quality:clean

Poem

🐰 Hops with glee at uploads so smooth,
With progress bars showing each frame,
And caches now stay in the groove—
Five megs or less, that's the name!
Images sing their speed-boosted song. 🎨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the three main changes: event cover photo picker implementation, resumable upload progress tracking, and native caching optimization across multiple components.
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 unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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.

@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

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

Caution

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

⚠️ Outside diff range comments (1)
app/src/components/EventCard.js (1)

355-360: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Add platform handling for Image source.cache: 'force-cache' (iOS-documented; Android/Web parity isn’t guaranteed)

  • cache: 'force-cache' is set unconditionally in app/src/components/EventCard.js, app/src/screens/RemindersScreen.js, and app/src/screens/EventDetail.js; React Native docs describe these cache policies under iOS, so Android/Web behavior can be inconsistent/ignored.
  • Suggested fix: only pass cache on platforms you’ve validated, or switch to a cross-platform caching approach (there’s no react-native-fast-image/expo-image-style dependency in this repo right now).
<Image
  source={{
    uri: event.bannerUrl || 'https://dummyimage.com/800x400/cccccc/000000.png&text=No+Image',
    ...(Platform.OS === 'ios' && { cache: 'force-cache' }),
  }}
  /* ... */
/>

Using force-cache can also serve stale banners even after updates.

🤖 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 `@app/src/components/EventCard.js` around lines 355 - 360, EventCard.js
unconditionally sets Image source.cache to 'force-cache', which is iOS-specific;
update the Image source construction in the EventCard component to only include
cache when Platform.OS === 'ios' (import Platform from 'react-native') or remove
cache entirely and switch to a cross-platform caching strategy; specifically
modify the source object built for the Image that uses event.bannerUrl (and the
fallback URL) so cache is conditionally spread only for iOS to avoid
inconsistent behavior on Android/Web and stale images.
♻️ Duplicate comments (2)
app/src/screens/RemindersScreen.js (1)

219-224: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Platform compatibility issue: cache property is iOS-only.

This is the same iOS-only limitation affecting EventCard.js and EventDetail.js. Consider applying a consistent platform-specific approach across all three files to ensure uniform caching behavior.

🤖 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 `@app/src/screens/RemindersScreen.js` around lines 219 - 224, The Image usage
in RemindersScreen.js sets the iOS-only cache prop on the <Image> element
(source object with cache: 'force-cache'), causing platform incompatibility;
update the image source handling in the component that renders item.bannerUrl
(used with styles.cardImage) to apply caching only on iOS (e.g., wrap the source
prop creation with Platform.OS === 'ios' or use Platform.select) or switch to a
cross-platform image solution (like react-native-fast-image) and mirror the same
approach you used for EventCard.js and EventDetail.js so all three components
use the same platform-safe caching logic.
app/src/screens/EventDetail.js (1)

1368-1375: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Platform compatibility issue: cache property is iOS-only.

The cache property is only supported on iOS. This creates inconsistent behavior where iOS users get forced caching while Android and Web users don't. The same fix as suggested for EventCard.js applies here - use Platform.OS conditional or a cross-platform caching solution.

🤖 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 `@app/src/screens/EventDetail.js` around lines 1368 - 1375, The ImageBackground
usage in EventDetail.js sets a platform-specific `cache` prop (inside the source
object) which only works on iOS; update the ImageBackground `source`
construction (the object built with `uri: event.bannerUrl ||
'https://dummyimage.com/...'`) to include `cache: 'force-cache'` only when
Platform.OS === 'ios' (import Platform from 'react-native') or switch to a
cross-platform caching solution used elsewhere (same approach as fixed in
EventCard.js) so Android/Web consumers don't receive an unsupported prop; keep
the rest (styles.headerImage, event.bannerUrl fallback) unchanged.
🧹 Nitpick comments (1)
app/src/screens/CreateEvent.js (1)

158-191: 💤 Low value

Consider deduplicating the 5MB validation shared with pickImage.

The fetch(uri) → blob() → blob.size > 5 * 1024 * 1024 check and the 5 * 1024 * 1024 literal are repeated in both pickImage and uploadImage. Extracting a shared constant (and optionally a small helper) keeps the limit consistent if it ever changes.

♻️ Suggested extraction
+const MAX_IMAGE_BYTES = 5 * 1024 * 1024;
+
 const DEFAULT_BANNERS = [
-        if (blob.size > 5 * 1024 * 1024) {
+        if (blob.size > MAX_IMAGE_BYTES) {
             throw new Error('Image size exceeds 5MB limit.');
         }

The resumable upload, progress wiring, and error/completion handling otherwise look correct.

🤖 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 `@app/src/screens/CreateEvent.js` around lines 158 - 191, The image size check
(fetch(...).blob().size > 5 * 1024 * 1024) is duplicated between pickImage and
uploadImage; extract a shared constant (e.g., MAX_IMAGE_BYTES) and optionally a
small helper function (e.g., isImageTooLarge(blob) or validateImageSize(blob))
and replace the literal in both pickImage and uploadImage to use the
constant/helper so the limit stays consistent and changes only in one place.
🤖 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 `@app/src/components/EventCard.js`:
- Around line 355-360: EventCard.js unconditionally sets Image source.cache to
'force-cache', which is iOS-specific; update the Image source construction in
the EventCard component to only include cache when Platform.OS === 'ios' (import
Platform from 'react-native') or remove cache entirely and switch to a
cross-platform caching strategy; specifically modify the source object built for
the Image that uses event.bannerUrl (and the fallback URL) so cache is
conditionally spread only for iOS to avoid inconsistent behavior on Android/Web
and stale images.

---

Duplicate comments:
In `@app/src/screens/EventDetail.js`:
- Around line 1368-1375: The ImageBackground usage in EventDetail.js sets a
platform-specific `cache` prop (inside the source object) which only works on
iOS; update the ImageBackground `source` construction (the object built with
`uri: event.bannerUrl || 'https://dummyimage.com/...'`) to include `cache:
'force-cache'` only when Platform.OS === 'ios' (import Platform from
'react-native') or switch to a cross-platform caching solution used elsewhere
(same approach as fixed in EventCard.js) so Android/Web consumers don't receive
an unsupported prop; keep the rest (styles.headerImage, event.bannerUrl
fallback) unchanged.

In `@app/src/screens/RemindersScreen.js`:
- Around line 219-224: The Image usage in RemindersScreen.js sets the iOS-only
cache prop on the <Image> element (source object with cache: 'force-cache'),
causing platform incompatibility; update the image source handling in the
component that renders item.bannerUrl (used with styles.cardImage) to apply
caching only on iOS (e.g., wrap the source prop creation with Platform.OS ===
'ios' or use Platform.select) or switch to a cross-platform image solution (like
react-native-fast-image) and mirror the same approach you used for EventCard.js
and EventDetail.js so all three components use the same platform-safe caching
logic.

---

Nitpick comments:
In `@app/src/screens/CreateEvent.js`:
- Around line 158-191: The image size check (fetch(...).blob().size > 5 * 1024 *
1024) is duplicated between pickImage and uploadImage; extract a shared constant
(e.g., MAX_IMAGE_BYTES) and optionally a small helper function (e.g.,
isImageTooLarge(blob) or validateImageSize(blob)) and replace the literal in
both pickImage and uploadImage to use the constant/helper so the limit stays
consistent and changes only in one place.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2b394fc0-6e9b-4b11-ab3a-e956e045e6f6

📥 Commits

Reviewing files that changed from the base of the PR and between 8a535b2 and 1c2ce32.

📒 Files selected for processing (4)
  • app/src/components/EventCard.js
  • app/src/screens/CreateEvent.js
  • app/src/screens/EventDetail.js
  • app/src/screens/RemindersScreen.js

@roshankumar0036singh
Copy link
Copy Markdown
Owner

@Nicks-19 fix that one issue flagged by sonar keep it 0

@roshankumar0036singh
Copy link
Copy Markdown
Owner

fix this Size check in pickImage fetches the blob just to check size, then fetches it again in uploadImage
why twice?

@roshankumar0036singh
Copy link
Copy Markdown
Owner

force-cache on EventCard and EventDetail banners means updated banners won't show

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