From 2377899d721f3e6f852e9d86f1786b2df36c2a6a Mon Sep 17 00:00:00 2001 From: Patrick Britton Date: Mon, 9 Feb 2026 14:45:43 -0600 Subject: [PATCH] fix: web thumbnail loading - bypass signing on web, add fallback, improve error handling --- sojorn_app/lib/services/api_service.dart | 9 +++++- .../lib/widgets/media/signed_media_image.dart | 30 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/sojorn_app/lib/services/api_service.dart b/sojorn_app/lib/services/api_service.dart index 49e0d71..c27e876 100644 --- a/sojorn_app/lib/services/api_service.dart +++ b/sojorn_app/lib/services/api_service.dart @@ -938,8 +938,15 @@ class ApiService { // ========================================================================= Future getSignedMediaUrl(String path) async { + // For web platform, return the original URL since signing isn't needed + // for public CDN domains + if (path.startsWith('http')) { + return path; + } + // Migrate to Go API / Nginx Signed URLs - return '${ApiConfig.baseUrl}/media/signed?path=$path'; // Placeholder + // TODO: Implement proper signed URL generation + return '${ApiConfig.baseUrl}/media/signed?path=$path'; } Future> toggleReaction(String postId, String emoji) async { diff --git a/sojorn_app/lib/widgets/media/signed_media_image.dart b/sojorn_app/lib/widgets/media/signed_media_image.dart index c63cf82..db572b3 100644 --- a/sojorn_app/lib/widgets/media/signed_media_image.dart +++ b/sojorn_app/lib/widgets/media/signed_media_image.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter/foundation.dart'; import '../../providers/api_provider.dart'; class SignedMediaImage extends ConsumerStatefulWidget { @@ -62,6 +63,11 @@ class _SignedMediaImageState extends ConsumerState { final trimmed = url.trim(); if (trimmed.isEmpty) return false; + // On web platform, prefer direct URLs without signing for better performance + if (kIsWeb) { + return false; + } + final uri = Uri.tryParse(trimmed); if (uri == null || (!uri.hasScheme && !uri.hasAuthority)) { return true; @@ -159,6 +165,15 @@ class _SignedMediaImageState extends ConsumerState { return _buildLoading(context); }, errorBuilder: (context, error, stackTrace) { + // Debug: log the error and URL info + if (kDebugMode) { + print('SignedMediaImage error: $error'); + print('Original URL: ${widget.url}'); + print('Resolved URL: $_resolvedUrl'); + print('Needs signing: $_shouldSign'); + print('Platform: ${kIsWeb ? "web" : "native"}'); + } + if (_shouldSign && !_refreshing && !_hasRefreshed) { WidgetsBinding.instance.addPostFrameCallback((_) { if (!mounted) return; @@ -171,6 +186,21 @@ class _SignedMediaImageState extends ConsumerState { return widget.errorBuilder!(context, error, stackTrace); } + // On web, try fallback to direct URL if signing failed + if (kIsWeb && _shouldSign && _resolvedUrl == null) { + return Image.network( + widget.url, + width: widget.width, + height: widget.height, + fit: widget.fit, + errorBuilder: widget.errorBuilder, + loadingBuilder: (context, child, loadingProgress) { + if (loadingProgress == null) return child; + return _buildLoading(context); + }, + ); + } + return const SizedBox.shrink(); }, );