- Replace Image.network (no cache) with CachedNetworkImage in contributor_profile_screen
- Replace NetworkImage (no cache) with CachedNetworkImageProvider in desktop_topbar and contribute_screen (leaderboard avatars)
- Add maxWidthDiskCache + maxHeightDiskCache to all 23 CachedNetworkImage calls
- Add missing memCacheWidth/Height to review_card (36x36 avatar) and learn_more related events (140x100)
- Add dynamic memCache sizing to tier_avatar_ring based on widget size
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds all fields to the edit profile bottom sheet:
- First Name / Last Name (side by side), Email, Phone
- Location section: Home District (locked with "Next change" date),
Place, Pincode, State, Country
- Saves all fields via update-profile API and persists to prefs
- Loads existing values from prefs on open; refreshes from status API
on every profile open so fields stay in sync with server
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace RepaintBoundary widget capture approach with a pure
dart:ui PictureRecorder + Canvas implementation.
- Add share_card_generator.dart: generates 1080×1920 PNG via
Canvas without embedding any widget in the tree
- Remove share_rank_card.dart (widget approach no longer needed)
- Remove GlobalKey, _buildHiddenShareCard, RepaintBoundary,
_fmtEp from profile_screen.dart
- Simplify desktop + mobile Stacks to direct ScrollViews
- Fix Android GPU compositing timing crash (no retry needed)
- Add avatarImage.dispose() to prevent GPU memory leak
- Guard byteData null return with StateError
- Replace MaterialIcons bolt with Unicode ⚡ (tree-shake safe)
- Align tier in share text with tier rendered on card
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
LearnMoreScreen now accepts an optional initialEvent parameter so it
can render immediately from already-loaded data instead of re-fetching
from the event-details API. This fixes the guest-mode flow where the
unauthenticated API call was failing. Also changed getEventDetails to
requiresAuth: true so logged-in users send their token when the API
path is used.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>