From 91965b141d865dee50be7d7b66fdd3c55877bff6 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Tue, 25 May 2021 15:35:14 +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, 99 insertions(+), 71 deletions(-) diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 9fd35701..77e044fe 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -1,5 +1,6 @@ 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'; @@ -51,6 +52,11 @@ class AppRoutes { widget: ChatList(), stackedRoutes: [ VWidget(path: ':roomid', widget: Chat(), stackedRoutes: [ + VWidget( + path: 'image/:eventid', + widget: ImageViewer(), + buildTransition: _fadeTransition, + ), VWidget( path: 'encryption', widget: ChatEncryptionSettings(), @@ -126,6 +132,11 @@ 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 eba2a46d..ecede614 100644 --- a/lib/pages/image_viewer.dart +++ b/lib/pages/image_viewer.dart @@ -8,10 +8,9 @@ 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(this.event, {Key key, this.onLoaded}) : super(key: key); + const ImageViewer({Key key, this.onLoaded}) : super(key: key); @override ImageViewerController createState() => ImageViewerController(); @@ -19,13 +18,14 @@ class ImageViewer extends StatefulWidget { class ImageViewerController extends State { /// Forward this image to another room. - void forwardAction() { - Matrix.of(context).shareContent = widget.event.content; + void forwardAction(Event event) { + Matrix.of(context).shareContent = event.content; VRouter.of(context).push('/rooms'); } /// Open this file with a system call. - void openFileAction() => widget.event.openFile(context, downloadOnly: true); + void openFileAction(Event event) => + event.openFile(context, downloadOnly: true); /// Go back if user swiped it away void onInteractionEnds(ScaleEndDetails endDetails) { @@ -37,6 +37,16 @@ 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 5caac3c7..0a65b969 100644 --- a/lib/pages/views/image_viewer_view.dart +++ b/lib/pages/views/image_viewer_view.dart @@ -1,3 +1,5 @@ +import 'package:famedlysdk/famedlysdk.dart'; + import '../image_viewer.dart'; import 'package:fluffychat/widgets/event_content/image_bubble.dart'; import 'package:flutter/material.dart'; @@ -10,50 +12,72 @@ class ImageViewerView extends StatelessWidget { @override Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.black, - extendBodyBehindAppBar: true, - appBar: AppBar( - elevation: 0, - leading: IconButton( - icon: Icon(Icons.close), - onPressed: Navigator.of(context, rootNavigator: false).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, + 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( backgroundColor: Colors.black, - maxSize: false, - radius: 0.0, - thumbnailOnly: false, - ), - ), - ), - ); + 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, + ), + ), + ), + ); + }); } } diff --git a/lib/utils/matrix_sdk_extensions.dart/event_extension.dart b/lib/utils/matrix_sdk_extensions.dart/event_extension.dart index 8a56f097..68a73009 100644 --- a/lib/utils/matrix_sdk_extensions.dart/event_extension.dart +++ b/lib/utils/matrix_sdk_extensions.dart/event_extension.dart @@ -3,16 +3,14 @@ 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)) { - await Navigator.of(context, rootNavigator: false).push( - MaterialPageRoute(builder: (_) => ImageViewer(this)), - ); + VRouter.of(context).push('/rooms/${room.id}/image/$eventId'); return; } final matrixFile = await showFutureLoadingDialog( diff --git a/lib/widgets/event_content/image_bubble.dart b/lib/widgets/event_content/image_bubble.dart index 0f25f7cc..8bab8ff6 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,23 +237,8 @@ class _ImageBubbleState extends State { child: InkWell( onTap: () { if (!widget.tapToView) return; - Navigator.of(context, rootNavigator: false).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(); - } - }); - } - }), - ), - ); + VRouter.of(context).push( + '/rooms/${widget.event.room.id}/image/${widget.event.eventId}'); }, child: Hero( tag: widget.event.eventId,