diff --git a/lib/widgets/fullscreen/image_page.dart b/lib/widgets/fullscreen/image_page.dart index 6f09176fa..7837c81e1 100644 --- a/lib/widgets/fullscreen/image_page.dart +++ b/lib/widgets/fullscreen/image_page.dart @@ -73,8 +73,20 @@ class FullscreenPageState extends State with SingleTickerProvide onPageChanged: (page) => setState(() => _currentHorizontalPage = page), onScaleChanged: (state) => setState(() => _isInitialScale = state == PhotoViewScaleState.initial), ), - InfoPage( - entry: entries[_currentHorizontalPage], + NotificationListener( + onNotification: (notification) { + if (notification is BackUpNotification) { + _verticalPager.animateToPage( + 0, + duration: const Duration(milliseconds: 400), + curve: Curves.easeInOut, + ); + } + return false; + }, + child: InfoPage( + entry: entries[_currentHorizontalPage], + ), ), ], ), diff --git a/lib/widgets/fullscreen/info_page.dart b/lib/widgets/fullscreen/info_page.dart index b7275ffef..153c599ea 100644 --- a/lib/widgets/fullscreen/info_page.dart +++ b/lib/widgets/fullscreen/info_page.dart @@ -15,6 +15,7 @@ class InfoPage extends StatefulWidget { class InfoPageState extends State { Future _metadataLoader; + bool _scrollStartFromTop = false; ImageEntry get entry => widget.entry; @@ -39,50 +40,74 @@ class InfoPageState extends State { final date = entry.getBestDate(); return Scaffold( appBar: AppBar( + leading: IconButton( + icon: Icon(Icons.arrow_upward), + onPressed: () => BackUpNotification().dispatch(context), + tooltip: 'Back to image', + ), title: Text('Info'), ), - body: ListView( - padding: EdgeInsets.all(8.0), - children: [ - SectionRow('File'), - InfoRow('Title', entry.title), - InfoRow('Date', '${DateFormat.yMMMd().format(date)} – ${DateFormat.Hm().format(date)}'), - InfoRow('Resolution', '${entry.width} × ${entry.height} (${entry.getMegaPixels()} MP)'), - InfoRow('Size', formatFilesize(entry.sizeBytes)), - InfoRow('Path', entry.path), - SectionRow('Location'), - SectionRow('XMP Tags'), - SectionRow('Metadata'), - FutureBuilder( - future: _metadataLoader, - builder: (futureContext, AsyncSnapshot snapshot) { - if (snapshot.hasError) { - return Text(snapshot.error); + body: NotificationListener( + onNotification: (notification) { + if (notification is ScrollNotification) { + if (notification is ScrollStartNotification) { + final metrics = notification.metrics; + _scrollStartFromTop = metrics.pixels == metrics.minScrollExtent; + } + if (_scrollStartFromTop) { + if (notification is ScrollEndNotification) { + _scrollStartFromTop = false; + } else if (notification is OverscrollNotification) { + if (notification.overscroll < 0) { + BackUpNotification().dispatch(context); + _scrollStartFromTop = false; + } } - if (snapshot.connectionState != ConnectionState.done) { - return CircularProgressIndicator(); - } - final metadataMap = snapshot.data.cast(); - final directoryNames = metadataMap.keys.toList()..sort(); - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: directoryNames.expand( - (directoryName) { - final directory = metadataMap[directoryName]; - final tagKeys = directory.keys.toList()..sort(); - return [ - Padding( - padding: EdgeInsets.symmetric(vertical: 4.0), - child: Text(directoryName, style: TextStyle(fontSize: 18)), - ), - ...tagKeys.map((tagKey) => InfoRow(tagKey, directory[tagKey])), - SizedBox(height: 16), - ]; - }, - ).toList()); - }, - ), - ], + } + } + return false; + }, + child: ListView( + padding: EdgeInsets.all(8.0), + children: [ + SectionRow('File'), + InfoRow('Title', entry.title), + InfoRow('Date', '${DateFormat.yMMMd().format(date)} – ${DateFormat.Hm().format(date)}'), + InfoRow('Resolution', '${entry.width} × ${entry.height} (${entry.getMegaPixels()} MP)'), + InfoRow('Size', formatFilesize(entry.sizeBytes)), + InfoRow('Path', entry.path), + SectionRow('Metadata'), + FutureBuilder( + future: _metadataLoader, + builder: (futureContext, AsyncSnapshot snapshot) { + if (snapshot.hasError) { + return Text(snapshot.error); + } + if (snapshot.connectionState != ConnectionState.done) { + return CircularProgressIndicator(); + } + final metadataMap = snapshot.data.cast(); + final directoryNames = metadataMap.keys.toList()..sort(); + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: directoryNames.expand( + (directoryName) { + final directory = metadataMap[directoryName]; + final tagKeys = directory.keys.toList()..sort(); + return [ + Padding( + padding: EdgeInsets.symmetric(vertical: 4.0), + child: Text(directoryName, style: TextStyle(fontSize: 18)), + ), + ...tagKeys.map((tagKey) => InfoRow(tagKey, directory[tagKey])), + SizedBox(height: 16), + ]; + }, + ).toList()); + }, + ), + ], + ), ), ); } @@ -96,7 +121,7 @@ class SectionRow extends StatelessWidget { @override Widget build(BuildContext context) { return Padding( - padding: EdgeInsets.symmetric(vertical: 4.0), + padding: EdgeInsets.symmetric(vertical: 8.0), child: Row( children: [ Expanded(child: Divider(color: Colors.white70)), @@ -131,3 +156,5 @@ class InfoRow extends StatelessWidget { ); } } + +class BackUpNotification extends Notification {} diff --git a/lib/widgets/fullscreen/overlay.dart b/lib/widgets/fullscreen/overlay.dart index fafe2199b..5ca7ff18b 100644 --- a/lib/widgets/fullscreen/overlay.dart +++ b/lib/widgets/fullscreen/overlay.dart @@ -2,8 +2,8 @@ import 'dart:math'; import 'dart:ui'; import 'package:aves/model/android_app_service.dart'; -import 'package:aves/model/metadata_service.dart'; import 'package:aves/model/image_entry.dart'; +import 'package:aves/model/metadata_service.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; @@ -43,7 +43,11 @@ class FullscreenTopOverlay extends StatelessWidget { title: Text('${index + 1}/${entries.length}'), actions: [ // IconButton(icon: Icon(Icons.delete), onPressed: delete), - IconButton(icon: Icon(Icons.share), onPressed: share), + IconButton( + icon: Icon(Icons.share), + onPressed: share, + tooltip: 'Share', + ), ], elevation: 0, backgroundColor: kOverlayBackground,