info: back to image on top overscroll or button
This commit is contained in:
parent
9c8df80a48
commit
8f94af28d3
3 changed files with 89 additions and 46 deletions
|
@ -73,8 +73,20 @@ class FullscreenPageState extends State<FullscreenPage> 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],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -15,6 +15,7 @@ class InfoPage extends StatefulWidget {
|
|||
|
||||
class InfoPageState extends State<InfoPage> {
|
||||
Future<Map> _metadataLoader;
|
||||
bool _scrollStartFromTop = false;
|
||||
|
||||
ImageEntry get entry => widget.entry;
|
||||
|
||||
|
@ -39,50 +40,74 @@ class InfoPageState extends State<InfoPage> {
|
|||
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<Map> 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<String, Map>();
|
||||
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<Map> snapshot) {
|
||||
if (snapshot.hasError) {
|
||||
return Text(snapshot.error);
|
||||
}
|
||||
if (snapshot.connectionState != ConnectionState.done) {
|
||||
return CircularProgressIndicator();
|
||||
}
|
||||
final metadataMap = snapshot.data.cast<String, Map>();
|
||||
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 {}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue