perf: fix image loading performance across all screens

- 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>
This commit is contained in:
2026-04-19 20:03:03 +05:30
parent 5e00e431e3
commit 754b04dc05
10 changed files with 90 additions and 11 deletions

View File

@@ -3,6 +3,7 @@
// 3 tabs: My Events · Submit Event · Reward Shop
import 'dart:io';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@@ -11,6 +12,7 @@ import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:share_plus/share_plus.dart';
import '../core/auth/auth_guard.dart';
import '../core/utils/error_utils.dart';
import '../features/gamification/models/gamification_models.dart';
import '../features/gamification/providers/gamification_provider.dart';
@@ -104,6 +106,9 @@ class _ContributeScreenState extends State<ContributeScreen>
super.initState();
PostHogService.instance.screen('Contribute');
WidgetsBinding.instance.addPostFrameCallback((_) {
// Gamification endpoints are authed — guests would hit 401 and pollute logs.
// AuthGuard.requireLogin prompts guests when they tap any gated action.
if (AuthGuard.isGuest) return;
final p = context.read<GamificationProvider>();
p.loadAll();
p.loadLeaderboard(); // independent — always fires regardless of loadAll TTL
@@ -389,7 +394,7 @@ class _ContributeScreenState extends State<ContributeScreen>
CircleAvatar(
radius: 20,
backgroundColor: _lightBlueBg,
backgroundImage: entry.avatarUrl != null ? NetworkImage(entry.avatarUrl!) : null,
backgroundImage: entry.avatarUrl != null ? CachedNetworkImageProvider(entry.avatarUrl!, maxWidth: 80, maxHeight: 80) : null,
child: entry.avatarUrl == null
? const Icon(Icons.person_outline, color: _blue, size: 20)
: null,
@@ -1334,12 +1339,14 @@ class _ContributeScreenState extends State<ContributeScreen>
}
Widget _textField(TextEditingController ctl, String placeholder, {
Key? key,
int maxLines = 1,
String? Function(String?)? validator,
TextInputType? keyboardType,
List<TextInputFormatter>? inputFormatters,
}) {
return TextFormField(
key: key,
controller: ctl,
maxLines: maxLines,
keyboardType: keyboardType,
@@ -1473,12 +1480,14 @@ class _ContributeScreenState extends State<ContributeScreen>
children: [
Expanded(
child: _textField(_latCtl, 'Latitude (e.g. 9.93123)',
key: const ValueKey('coord_lat'),
keyboardType: const TextInputType.numberWithOptions(decimal: true, signed: true),
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'[0-9.\-]'))]),
),
const SizedBox(width: 12),
Expanded(
child: _textField(_lngCtl, 'Longitude (e.g. 76.26730)',
key: const ValueKey('coord_lng'),
keyboardType: const TextInputType.numberWithOptions(decimal: true, signed: true),
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'[0-9.\-]'))]),
),
@@ -1488,7 +1497,9 @@ class _ContributeScreenState extends State<ContributeScreen>
Row(
children: [
Expanded(
child: _textField(_mapsLinkCtl, 'Paste Google Maps URL here'),
child: _textField(_mapsLinkCtl, 'Paste Google Maps URL here',
key: const ValueKey('coord_maps_url'),
keyboardType: TextInputType.url),
),
const SizedBox(width: 8),
SizedBox(