fix: Improve GIF loading logic and handle HTTP image URLs in MxcImage widget

This commit is contained in:
Ariq Pradipa Santoso 2025-08-19 07:04:36 +07:00
parent 50aaead30c
commit ecd82fab0a
3 changed files with 77 additions and 30 deletions

View file

@ -104,8 +104,9 @@ class GifPickerDialogState extends State<GifPickerDialog> {
}
Future<void> _loadMoreGifs() async {
if (_isLoadingMore || !_hasMoreResults || isLoading || _nextPos == '0')
if (_isLoadingMore || !_hasMoreResults || isLoading || _nextPos == '0') {
return;
}
setState(() {
_isLoadingMore = true;

View file

@ -65,13 +65,15 @@ class TenorApiResponse {
class TenorApi {
static const String _baseUrl = 'https://tenor.googleapis.com/v2';
static const String _apiKey =
'<tenor-api-key>'; // Test API key from documentation
'AIzaSyC5xwpkbdAnIH4NSyjUwg_t9Huoy19YVH4'; // Test API key from documentation
static const String _clientKey =
'fluffychat_app'; // Client key for integration tracking
static const int _limit = 20;
static Future<TenorApiResponse> searchGifs(String query,
{String? pos}) async {
static Future<TenorApiResponse> searchGifs(
String query, {
String? pos,
}) async {
if (query.trim().isEmpty) {
return getFeaturedGifs(pos: pos);
}

View file

@ -3,6 +3,7 @@ import 'dart:math';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:matrix/matrix.dart';
@ -75,36 +76,79 @@ class _MxcImageState extends State<MxcImage> {
final event = widget.event;
if (uri != null) {
final devicePixelRatio = MediaQuery.devicePixelRatioOf(context);
final width = widget.width;
final realWidth = width == null ? null : width * devicePixelRatio;
final height = widget.height;
final realHeight = height == null ? null : height * devicePixelRatio;
// Handle direct HTTP/HTTPS URLs
if (uri.scheme == 'http' || uri.scheme == 'https') {
try {
final response = await http.get(uri);
if (response.statusCode == 200) {
if (!mounted) return;
setState(() {
_imageData = response.bodyBytes;
});
return;
}
} catch (e) {
Logs().w('Failed to load HTTP image: $uri', e);
}
} else if (uri.scheme == 'mxc') {
// Handle MXC URLs
final devicePixelRatio = MediaQuery.devicePixelRatioOf(context);
final width = widget.width;
final realWidth = width == null ? null : width * devicePixelRatio;
final height = widget.height;
final realHeight = height == null ? null : height * devicePixelRatio;
final remoteData = await client.downloadMxcCached(
uri,
width: realWidth,
height: realHeight,
thumbnailMethod: widget.thumbnailMethod,
isThumbnail: widget.isThumbnail,
animated: widget.animated,
);
if (!mounted) return;
setState(() {
_imageData = remoteData;
});
final remoteData = await client.downloadMxcCached(
uri,
width: realWidth,
height: realHeight,
thumbnailMethod: widget.thumbnailMethod,
isThumbnail: widget.isThumbnail,
animated: widget.animated,
);
if (!mounted) return;
setState(() {
_imageData = remoteData;
});
}
}
if (event != null) {
final data = await event.downloadAndDecryptAttachment(
getThumbnail: widget.isThumbnail,
);
if (data.detectFileType is MatrixImageFile || widget.isThumbnail) {
if (!mounted) return;
setState(() {
_imageData = data.bytes;
});
return;
// Check if the event has a direct HTTP URL
final eventUrl = event.content.tryGet<String>('url');
if (eventUrl != null) {
final eventUri = Uri.tryParse(eventUrl);
if (eventUri != null &&
(eventUri.scheme == 'http' || eventUri.scheme == 'https')) {
try {
final response = await http.get(eventUri);
if (response.statusCode == 200) {
if (!mounted) return;
setState(() {
_imageData = response.bodyBytes;
});
return;
}
} catch (e) {
Logs().w('Failed to load HTTP image from event: $eventUrl', e);
}
}
}
// Fallback to Matrix attachment handling for MXC URLs
try {
final data = await event.downloadAndDecryptAttachment(
getThumbnail: widget.isThumbnail,
);
if (data.detectFileType is MatrixImageFile || widget.isThumbnail) {
if (!mounted) return;
setState(() {
_imageData = data.bytes;
});
return;
}
} catch (e) {
Logs().w('Failed to download Matrix attachment', e);
}
}
}