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

@@ -2,6 +2,7 @@
import 'dart:async';
import 'dart:ui';
import '../core/utils/error_utils.dart';
import 'package:flutter/foundation.dart' show kDebugMode, debugPrint;
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../core/auth/auth_guard.dart';
@@ -136,15 +137,16 @@ class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateM
_loading = false;
});
}
} catch (e) {
} catch (e, st) {
if (kDebugMode) debugPrint('HomeScreen._loadUserDataAndEvents error: $e\n$st');
if (mounted) {
setState(() => _loading = false);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(userFriendlyError(e))));
}
}
// Refresh notification badge count (fire-and-forget)
if (mounted) {
// Refresh notification badge count (fire-and-forget, skip for guests — endpoint is authed)
if (mounted && !AuthGuard.isGuest) {
context.read<NotificationProvider>().refreshUnreadCount();
}
}
@@ -263,6 +265,8 @@ class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateM
imageUrl: imageUrl,
memCacheWidth: 112,
memCacheHeight: 112,
maxWidthDiskCache: 224,
maxHeightDiskCache: 224,
fit: BoxFit.contain,
placeholder: (_, __) => Icon(
icon ?? Icons.category,
@@ -475,6 +479,8 @@ class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateM
imageUrl: img,
memCacheWidth: 112,
memCacheHeight: 112,
maxWidthDiskCache: 224,
maxHeightDiskCache: 224,
width: 56,
height: 56,
fit: BoxFit.cover,
@@ -956,6 +962,8 @@ class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateM
imageUrl: imageUrl,
memCacheWidth: 160,
memCacheHeight: 160,
maxWidthDiskCache: 320,
maxHeightDiskCache: 320,
width: 80,
height: 80,
fit: BoxFit.cover,
@@ -1288,6 +1296,8 @@ class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateM
imageUrl: currentImg,
memCacheWidth: 200,
memCacheHeight: 200,
maxWidthDiskCache: 400,
maxHeightDiskCache: 400,
fit: BoxFit.cover,
placeholder: (_, __) => const SizedBox.shrink(),
errorWidget: (_, __, ___) => const SizedBox.shrink(),
@@ -1524,6 +1534,8 @@ class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateM
imageUrl: img,
memCacheWidth: 700,
memCacheHeight: 400,
maxWidthDiskCache: 1200,
maxHeightDiskCache: 700,
fit: BoxFit.cover,
placeholder: (_, __) => const _HeroShimmer(radius: radius),
errorWidget: (_, __, ___) =>
@@ -1951,6 +1963,8 @@ class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateM
imageUrl: img,
memCacheWidth: 300,
memCacheHeight: 200,
maxWidthDiskCache: 600,
maxHeightDiskCache: 400,
fit: BoxFit.cover,
width: double.infinity,
height: double.infinity,
@@ -2147,6 +2161,8 @@ class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateM
imageUrl: img,
memCacheWidth: 192,
memCacheHeight: 192,
maxWidthDiskCache: 384,
maxHeightDiskCache: 384,
width: 96,
height: double.infinity,
fit: BoxFit.cover,
@@ -2214,6 +2230,8 @@ class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateM
imageUrl: img,
memCacheWidth: 440,
memCacheHeight: 360,
maxWidthDiskCache: 880,
maxHeightDiskCache: 720,
width: 220,
height: 180,
fit: BoxFit.cover,
@@ -2387,6 +2405,8 @@ class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateM
imageUrl: img,
memCacheWidth: 800,
memCacheHeight: 400,
maxWidthDiskCache: 1200,
maxHeightDiskCache: 600,
width: double.infinity,
height: 200,
fit: BoxFit.cover,