From dcfbf8f8a55fa16a9bf4fa28ac06942edfe773f6 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Tue, 25 May 2021 20:41:37 +0200 Subject: [PATCH] fix: Image viewer --- lib/config/routes.dart | 11 -- lib/pages/image_viewer.dart | 20 +--- lib/pages/views/image_viewer_view.dart | 112 +++++++----------- .../event_extension.dart | 6 +- lib/widgets/event_content/image_bubble.dart | 21 +++- 5 files changed, 71 insertions(+), 99 deletions(-) diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 77e044fe..9fd35701 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -1,6 +1,5 @@ import 'package:fluffychat/pages/archive.dart'; import 'package:fluffychat/pages/homeserver_picker.dart'; -import 'package:fluffychat/pages/image_viewer.dart'; import 'package:fluffychat/pages/invitation_selection.dart'; import 'package:fluffychat/pages/settings_emotes.dart'; import 'package:fluffychat/pages/settings_multiple_emotes.dart'; @@ -52,11 +51,6 @@ class AppRoutes { widget: ChatList(), stackedRoutes: [ VWidget(path: ':roomid', widget: Chat(), stackedRoutes: [ - VWidget( - path: 'image/:eventid', - widget: ImageViewer(), - buildTransition: _fadeTransition, - ), VWidget( path: 'encryption', widget: ChatEncryptionSettings(), @@ -132,11 +126,6 @@ class AppRoutes { widget: EmptyPage(), buildTransition: _fadeTransition, ), - VWidget( - path: 'image/:eventid', - widget: ImageViewer(), - buildTransition: _fadeTransition, - ), VWidget( path: 'encryption', widget: ChatEncryptionSettings(), diff --git a/lib/pages/image_viewer.dart b/lib/pages/image_viewer.dart index ecede614..eba2a46d 100644 --- a/lib/pages/image_viewer.dart +++ b/lib/pages/image_viewer.dart @@ -8,9 +8,10 @@ import 'package:vrouter/vrouter.dart'; import '../utils/matrix_sdk_extensions.dart/event_extension.dart'; class ImageViewer extends StatefulWidget { + final Event event; final void Function() onLoaded; - const ImageViewer({Key key, this.onLoaded}) : super(key: key); + const ImageViewer(this.event, {Key key, this.onLoaded}) : super(key: key); @override ImageViewerController createState() => ImageViewerController(); @@ -18,14 +19,13 @@ class ImageViewer extends StatefulWidget { class ImageViewerController extends State { /// Forward this image to another room. - void forwardAction(Event event) { - Matrix.of(context).shareContent = event.content; + void forwardAction() { + Matrix.of(context).shareContent = widget.event.content; VRouter.of(context).push('/rooms'); } /// Open this file with a system call. - void openFileAction(Event event) => - event.openFile(context, downloadOnly: true); + void openFileAction() => widget.event.openFile(context, downloadOnly: true); /// Go back if user swiped it away void onInteractionEnds(ScaleEndDetails endDetails) { @@ -37,16 +37,6 @@ class ImageViewerController extends State { } } - Future getEvent() { - final roomId = VRouter.of(context).pathParameters['roomid']; - final eventId = VRouter.of(context).pathParameters['eventid']; - return Matrix.of(context).client.database.getEventById( - Matrix.of(context).client.id, - eventId, - Matrix.of(context).client.getRoomById(roomId), - ); - } - @override Widget build(BuildContext context) => ImageViewerView(this); } diff --git a/lib/pages/views/image_viewer_view.dart b/lib/pages/views/image_viewer_view.dart index 0a65b969..6bd5c30b 100644 --- a/lib/pages/views/image_viewer_view.dart +++ b/lib/pages/views/image_viewer_view.dart @@ -1,5 +1,3 @@ -import 'package:famedlysdk/famedlysdk.dart'; - import '../image_viewer.dart'; import 'package:fluffychat/widgets/event_content/image_bubble.dart'; import 'package:flutter/material.dart'; @@ -12,72 +10,50 @@ class ImageViewerView extends StatelessWidget { @override Widget build(BuildContext context) { - return FutureBuilder( - future: controller.getEvent(), - builder: (context, snapshot) { - if (!snapshot.hasData) { - return Scaffold( - backgroundColor: Colors.black, - appBar: AppBar( - elevation: 0, - backgroundColor: Color(0x44000000), - ), - body: Center( - child: snapshot.hasError - ? Text( - L10n.of(context).oopsSomethingWentWrong, - style: TextStyle(color: Colors.white), - textAlign: TextAlign.center, - ) - : CircularProgressIndicator()), - ); - } - final event = snapshot.data; - return Scaffold( + return Scaffold( + backgroundColor: Colors.black, + extendBodyBehindAppBar: true, + appBar: AppBar( + elevation: 0, + leading: IconButton( + icon: Icon(Icons.close), + onPressed: Navigator.of(context).pop, + color: Colors.white, + tooltip: L10n.of(context).close, + ), + backgroundColor: Color(0x44000000), + actions: [ + IconButton( + icon: Icon(Icons.reply_outlined), + onPressed: controller.forwardAction, + color: Colors.white, + tooltip: L10n.of(context).share, + ), + IconButton( + icon: Icon(Icons.download_outlined), + onPressed: controller.openFileAction, + color: Colors.white, + tooltip: L10n.of(context).downloadFile, + ), + ], + ), + body: InteractiveViewer( + minScale: 1.0, + maxScale: 10.0, + onInteractionEnd: controller.onInteractionEnds, + child: Center( + child: ImageBubble( + controller.widget.event, + tapToView: false, + onLoaded: controller.widget.onLoaded, + fit: BoxFit.contain, backgroundColor: Colors.black, - extendBodyBehindAppBar: true, - appBar: AppBar( - elevation: 0, - backgroundColor: Color(0x44000000), - leading: IconButton( - icon: Icon(Icons.close), - onPressed: Navigator.of(context, rootNavigator: false).pop, - color: Colors.white, - tooltip: L10n.of(context).close, - ), - actions: [ - IconButton( - icon: Icon(Icons.reply_outlined), - onPressed: () => controller.forwardAction(event), - color: Colors.white, - tooltip: L10n.of(context).share, - ), - IconButton( - icon: Icon(Icons.download_outlined), - onPressed: () => controller.openFileAction(event), - color: Colors.white, - tooltip: L10n.of(context).downloadFile, - ), - ], - ), - body: InteractiveViewer( - minScale: 1.0, - maxScale: 10.0, - onInteractionEnd: controller.onInteractionEnds, - child: Center( - child: ImageBubble( - event, - tapToView: false, - onLoaded: controller.widget.onLoaded, - fit: BoxFit.contain, - backgroundColor: Colors.black, - maxSize: false, - radius: 0.0, - thumbnailOnly: false, - ), - ), - ), - ); - }); + maxSize: false, + radius: 0.0, + thumbnailOnly: false, + ), + ), + ), + ); } } diff --git a/lib/utils/matrix_sdk_extensions.dart/event_extension.dart b/lib/utils/matrix_sdk_extensions.dart/event_extension.dart index 68a73009..8adfbee4 100644 --- a/lib/utils/matrix_sdk_extensions.dart/event_extension.dart +++ b/lib/utils/matrix_sdk_extensions.dart/event_extension.dart @@ -3,14 +3,16 @@ import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; -import 'package:vrouter/vrouter.dart'; import 'matrix_file_extension.dart'; +import '../../pages/image_viewer.dart'; extension LocalizedBody on Event { void openFile(BuildContext context, {bool downloadOnly = false}) async { if (!downloadOnly && [MessageTypes.Image, MessageTypes.Sticker].contains(messageType)) { - VRouter.of(context).push('/rooms/${room.id}/image/$eventId'); + await Navigator.of(context, rootNavigator: true).push( + MaterialPageRoute(builder: (_) => ImageViewer(this)), + ); return; } final matrixFile = await showFutureLoadingDialog( diff --git a/lib/widgets/event_content/image_bubble.dart b/lib/widgets/event_content/image_bubble.dart index 8bab8ff6..c690cb6e 100644 --- a/lib/widgets/event_content/image_bubble.dart +++ b/lib/widgets/event_content/image_bubble.dart @@ -1,10 +1,10 @@ import 'package:famedlysdk/famedlysdk.dart'; +import 'package:fluffychat/pages/image_viewer.dart'; import 'package:flutter/material.dart'; 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:vrouter/vrouter.dart'; import '../../utils/matrix_sdk_extensions.dart/event_extension.dart'; @@ -237,8 +237,23 @@ class _ImageBubbleState extends State { child: InkWell( onTap: () { if (!widget.tapToView) return; - VRouter.of(context).push( - '/rooms/${widget.event.room.id}/image/${widget.event.eventId}'); + Navigator.of(context, rootNavigator: true).push( + MaterialPageRoute( + builder: (_) => ImageViewer(widget.event, onLoaded: () { + // If the original file didn't load yet, we want to do that now. + // This is so that the original file displays after going on the image viewer, + // waiting for it to load, and then hitting back. This ensures that we always + // display the best image available, with requiring as little network as possible + if (_file == null) { + widget.event.isAttachmentCached().then((cached) { + if (cached) { + _requestFile(); + } + }); + } + }), + ), + ); }, child: Hero( tag: widget.event.eventId,