All CachedNetworkImage instances in list/card contexts now decode at
2x rendered size instead of full resolution. A 3000x2000 event photo
previously decoded to ~24MB in GPU memory even when shown at 96px —
now decodes to <1MB.
Affected screens (16 CachedNetworkImage instances total):
- home_screen.dart: hero (800w), top card (300w), stacked (192w),
horizontal (440x360), full-width (800x400), search (112x112),
filter sheet (160x160), type icons (112x112)
- home_desktop_screen.dart: mini (128x128), grid (600x280), horiz (600x296)
- calendar_screen.dart: event card (400x300)
- profile_screen.dart: avatar (size*2), event tile (120x120)
learn_more_screen.dart intentionally unchanged — full-res for detail view.
Estimated memory reduction: ~500MB → ~30MB for a typical home screen.
profile_screen: SingleChildScrollView + Column eagerly built every event
card (all images, shadows, tiles) at once even when off-screen. Replaced
with CustomScrollView + SliverList so only visible tiles are built per
frame. Also switches to BouncingScrollPhysics for natural momentum.
contribute_screen: Each _formCard wrapped in RepaintBoundary so form
cards are isolated render layers — one card's repaint doesn't invalidate
its siblings. Added BouncingScrollPhysics to the form SingleChildScrollView.
calendar_screen: Blue gradient banner was Positioned(top:0) making it
sticky even as the user scrolled. Removed the fixed Positioned layer and
moved the gradient inside the CustomScrollView as the first sliver in a
Stack alongside the calendar card (which keeps its y=110 visual overlap).
Now the entire page — gradient, calendar, events — scrolls as one unit.
Three root causes of the perceived scroll/animation lag:
1. profile_screen.dart — AnimationController listener called setState() on
every animation frame (60fps × 2s = 120 full-tree rebuilds). The entire
ProfileScreen with its nested lists and images was rebuilding 60 times per
second just to update two small widgets (EXP bar + stat counters).
Fix: remove setState() from listeners entirely; wrap only the EXP bar
(LayoutBuilder) and stat row (IntrinsicHeight) in AnimatedBuilder so
only those two leaf widgets re-render per frame.
2. learn_more_screen.dart — PageView.onPageChanged called setState() on
every swipe, rebuilding the full event detail screen (blurred bg image,
map, about section, etc.) just to update the 6px dot indicators.
Fix: int _currentPage → ValueNotifier<int> _pageNotifier; wrap only the
dot row and the blurred background image in ValueListenableBuilder.
3. search_screen.dart — BackdropFilter(ImageFilter.blur) without a
RepaintBoundary forces Flutter to read every pixel behind the blur widget
and composite it every frame. When the user scrolls the underlying list,
the blur repaints continuously causing frame drops.
Fix: wrap BackdropFilter in RepaintBoundary to isolate its repaint layer.
Critical — Image.network → CachedNetworkImage:
- home_screen.dart: hero/carousel banner image now cached with placeholder
- profile_screen.dart: avatar and event list tile images now cached
- calendar_screen.dart: event card images now cached with placeholder
High:
- profile_screen.dart: TextEditingControllers in dialogs now properly
disposed via .then() and after await to prevent memory leaks
Medium:
- search_screen.dart: shrinkWrap:true → ConstrainedBox(maxHeight:320) +
ClampingScrollPhysics for smooth search result scrolling
- learn_more_screen.dart: MediaQuery.of(context) cached once per method
instead of being called multiple times on every frame
- Replace banner gradient with pink→sky→cyan→blue matching web visual
- Restore edit pencil button (revert Follow toggle)
- Remove bio/title text (web has none)
- Fix stat values to 1.2K/45/3.4K matching web
- Remove rainbow bar from card bottom
- Update social icons and exp label styling
- Clean up unused state variables
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add animated EXP progress bar (0% → 65% with ease-out on gray track)
- Add animated stat counters (count up from 0 to 72.9K/828/342.9K)
- Expand rainbow gradient to 6 colors (purple→pink→orange→yellow→green→blue)
- Add Follow/Following toggle button on cover banner
- Add title/bio text between name and email
- Add top/bottom borders to stats section
- Add _formatNumber() helper for K/M formatting
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>