diff --git a/lib/widgets/event_content/image_bubble.dart b/lib/widgets/event_content/image_bubble.dart index d3ec7f04..a741ff90 100644 --- a/lib/widgets/event_content/image_bubble.dart +++ b/lib/widgets/event_content/image_bubble.dart @@ -1,3 +1,5 @@ +import 'dart:typed_data'; + import 'package:matrix/matrix.dart'; import 'package:fluffychat/pages/image_viewer.dart'; import 'package:flutter/material.dart'; @@ -5,6 +7,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter_blurhash/flutter_blurhash.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:lottie/lottie.dart'; import '../../utils/matrix_sdk_extensions.dart/event_extension.dart'; import '../matrix.dart'; @@ -42,10 +45,15 @@ class _ImageBubbleState extends State { MatrixFile _thumbnail; bool _requestedThumbnailOnFailure = false; - bool get isSvg => - widget.event.attachmentMimetype.split('+').first == 'image/svg'; - bool get isThumbnailSvg => - widget.event.thumbnailMimetype.split('+').first == 'image/svg'; + // overrides for certain mimetypes if they need different images to render + // memory are for in-memory renderers (e2ee rooms), network for network url renderers. + // The map values themself are set in initState() as they need to be able to access + // `this`. + final _contentRenderers = {}; + + String getMimetype([bool thumbnail = false]) => thumbnail + ? widget.event.thumbnailMimetype + : widget.event.attachmentMimetype; MatrixFile get _displayFile => _file ?? _thumbnail; String get displayUrl => widget.thumbnailOnly ? thumbnailUrl : attachmentUrl; @@ -81,6 +89,32 @@ class _ImageBubbleState extends State { @override void initState() { + _contentRenderers['image/svg+xml'] = _ImageBubbleContentRenderer( + memory: (Uint8List bytes, String key) => SvgPicture.memory( + bytes, + key: ValueKey(key), + fit: widget.fit, + ), + network: (String url) => SvgPicture.network( + url, + key: ValueKey(url), + placeholderBuilder: (context) => getPlaceholderWidget(), + fit: widget.fit, + ), + ); + _contentRenderers['image/lottie+json'] = _ImageBubbleContentRenderer( + memory: (Uint8List bytes, String key) => Lottie.memory( + bytes, + key: ValueKey(key), + fit: widget.fit, + ), + network: (String url) => Lottie.network( + url, + key: ValueKey(url), + fit: widget.fit, + ), + ); + thumbnailUrl = widget.event .getAttachmentUrl(getThumbnail: true, animated: true) ?.toString(); @@ -148,12 +182,9 @@ class _ImageBubbleState extends State { final key = isOriginal ? widget.event.attachmentMxcUrl : widget.event.thumbnailMxcUrl; - if (isOriginal ? isSvg : isThumbnailSvg) { - return SvgPicture.memory( - _displayFile.bytes, - key: ValueKey(key), - fit: widget.fit, - ); + final mimetype = getMimetype(!isOriginal); + if (_contentRenderers.containsKey(mimetype)) { + return _contentRenderers[mimetype].memory(_displayFile.bytes, key); } else { return Image.memory( _displayFile.bytes, @@ -164,14 +195,10 @@ class _ImageBubbleState extends State { } Widget getNetworkWidget() { + final mimetype = getMimetype(!_requestedThumbnailOnFailure); if (displayUrl == attachmentUrl && - (_requestedThumbnailOnFailure ? isSvg : isThumbnailSvg)) { - return SvgPicture.network( - displayUrl, - key: ValueKey(displayUrl), - placeholderBuilder: (context) => getPlaceholderWidget(), - fit: widget.fit, - ); + _contentRenderers.containsKey(mimetype)) { + return _contentRenderers[mimetype].network(displayUrl); } else { return CachedNetworkImage( // as we change the url on-error we need a key so that the widget actually updates @@ -272,3 +299,10 @@ class _ImageBubbleState extends State { ); } } + +class _ImageBubbleContentRenderer { + final Widget Function(Uint8List, String) memory; + final Widget Function(String) network; + + _ImageBubbleContentRenderer({this.memory, this.network}); +} diff --git a/pubspec.lock b/pubspec.lock index 236ea6cf..57924d0e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -36,6 +36,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.2" args: dependency: transitive description: @@ -604,6 +611,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.1" + lottie: + dependency: "direct main" + description: + name: lottie + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" markdown: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 3f7b7e8b..dbb094bd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -42,6 +42,7 @@ dependencies: image_picker: ^0.8.1+3 intl: any localstorage: ^4.0.0+1 + lottie: ^1.1.0 matrix: ^0.1.7 native_imaging: git: