feat(ui): support authenticated image loading with cache manager
Add Riverpod-aware image header and cache manager support for network images used in avatar and markdown widgets. Convert AvatarImage to a ConsumerWidget and read a self-signed cache manager and HTTP headers from Riverpod so CachedNetworkImage can send auth/custom headers and use the provided cache manager. In Markdown image builder, obtain headers and cache manager from a ProviderContainer (via ProviderScope.containerOf) to enable the same authenticated loading in non-consumer contexts. Introduce image_header_utils.dart to centralize building Authorization and custom headers from auth/api providers, with helpers for Ref, WidgetRef, and ProviderContainer. Add dependency adjustments in pubspec.lock for flutter_cache_manager and http marked as direct main. These changes ensure protected images (self-signed or auth-required) load correctly across the app and reuse the configured cache manager.
This commit is contained in:
@@ -13,6 +13,8 @@ import 'package:conduit/l10n/app_localizations.dart';
|
||||
import '../../../core/providers/app_providers.dart';
|
||||
import '../../auth/providers/unified_auth_providers.dart';
|
||||
import '../../../core/utils/debug_logger.dart';
|
||||
import '../../../core/network/self_signed_image_cache_manager.dart';
|
||||
import '../../../core/network/image_header_utils.dart';
|
||||
|
||||
// Simple global cache to prevent reloading
|
||||
final _globalImageCache = <String, String>{};
|
||||
@@ -414,29 +416,15 @@ class _EnhancedImageAttachmentState
|
||||
|
||||
Widget _buildNetworkImage() {
|
||||
// Get authentication headers if available
|
||||
final api = ref.read(apiServiceProvider);
|
||||
final authToken = ref.read(authTokenProvider3);
|
||||
final headers = <String, String>{};
|
||||
|
||||
// Add auth token from unified auth provider
|
||||
if (authToken != null && authToken.isNotEmpty) {
|
||||
headers['Authorization'] = 'Bearer $authToken';
|
||||
} else if (api?.serverConfig.apiKey != null &&
|
||||
api!.serverConfig.apiKey!.isNotEmpty) {
|
||||
// Fallback to API key from server config
|
||||
headers['Authorization'] = 'Bearer ${api.serverConfig.apiKey}';
|
||||
}
|
||||
|
||||
// Add any custom headers from server config
|
||||
if (api != null && api.serverConfig.customHeaders.isNotEmpty) {
|
||||
headers.addAll(api.serverConfig.customHeaders);
|
||||
}
|
||||
final headers = buildImageHeadersFromWidgetRef(ref);
|
||||
|
||||
final cacheManager = ref.read(selfSignedImageCacheManagerProvider);
|
||||
final imageWidget = CachedNetworkImage(
|
||||
key: ValueKey('image_${widget.attachmentId}'),
|
||||
imageUrl: _cachedImageData!,
|
||||
fit: BoxFit.cover,
|
||||
httpHeaders: headers.isNotEmpty ? headers : null,
|
||||
cacheManager: cacheManager,
|
||||
httpHeaders: headers,
|
||||
fadeInDuration: widget.disableAnimation
|
||||
? Duration.zero
|
||||
: const Duration(milliseconds: 200),
|
||||
@@ -559,28 +547,14 @@ class FullScreenImageViewer extends ConsumerWidget {
|
||||
|
||||
if (imageData.startsWith('http')) {
|
||||
// Get authentication headers if available
|
||||
final api = ref.read(apiServiceProvider);
|
||||
final authToken = ref.read(authTokenProvider3);
|
||||
final headers = <String, String>{};
|
||||
|
||||
// Add auth token from unified auth provider
|
||||
if (authToken != null && authToken.isNotEmpty) {
|
||||
headers['Authorization'] = 'Bearer $authToken';
|
||||
} else if (api?.serverConfig.apiKey != null &&
|
||||
api!.serverConfig.apiKey!.isNotEmpty) {
|
||||
// Fallback to API key from server config
|
||||
headers['Authorization'] = 'Bearer ${api.serverConfig.apiKey}';
|
||||
}
|
||||
|
||||
// Add any custom headers from server config
|
||||
if (api != null && api.serverConfig.customHeaders.isNotEmpty) {
|
||||
headers.addAll(api.serverConfig.customHeaders);
|
||||
}
|
||||
final headers = buildImageHeadersFromWidgetRef(ref);
|
||||
|
||||
final cacheManager = ref.read(selfSignedImageCacheManagerProvider);
|
||||
imageWidget = CachedNetworkImage(
|
||||
imageUrl: imageData,
|
||||
fit: BoxFit.contain,
|
||||
httpHeaders: headers.isNotEmpty ? headers : null,
|
||||
cacheManager: cacheManager,
|
||||
httpHeaders: headers,
|
||||
placeholder: (context, url) => Center(
|
||||
child: CircularProgressIndicator(
|
||||
color: context.conduitTheme.buttonPrimary,
|
||||
|
||||
Reference in New Issue
Block a user