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),
|
onPageChanged: (page) => setState(() => _currentHorizontalPage = page),
|
||||||
onScaleChanged: (state) => setState(() => _isInitialScale = state == PhotoViewScaleState.initial),
|
onScaleChanged: (state) => setState(() => _isInitialScale = state == PhotoViewScaleState.initial),
|
||||||
),
|
),
|
||||||
InfoPage(
|
NotificationListener(
|
||||||
entry: entries[_currentHorizontalPage],
|
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> {
|
class InfoPageState extends State<InfoPage> {
|
||||||
Future<Map> _metadataLoader;
|
Future<Map> _metadataLoader;
|
||||||
|
bool _scrollStartFromTop = false;
|
||||||
|
|
||||||
ImageEntry get entry => widget.entry;
|
ImageEntry get entry => widget.entry;
|
||||||
|
|
||||||
|
@ -39,50 +40,74 @@ class InfoPageState extends State<InfoPage> {
|
||||||
final date = entry.getBestDate();
|
final date = entry.getBestDate();
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
|
leading: IconButton(
|
||||||
|
icon: Icon(Icons.arrow_upward),
|
||||||
|
onPressed: () => BackUpNotification().dispatch(context),
|
||||||
|
tooltip: 'Back to image',
|
||||||
|
),
|
||||||
title: Text('Info'),
|
title: Text('Info'),
|
||||||
),
|
),
|
||||||
body: ListView(
|
body: NotificationListener(
|
||||||
padding: EdgeInsets.all(8.0),
|
onNotification: (notification) {
|
||||||
children: [
|
if (notification is ScrollNotification) {
|
||||||
SectionRow('File'),
|
if (notification is ScrollStartNotification) {
|
||||||
InfoRow('Title', entry.title),
|
final metrics = notification.metrics;
|
||||||
InfoRow('Date', '${DateFormat.yMMMd().format(date)} – ${DateFormat.Hm().format(date)}'),
|
_scrollStartFromTop = metrics.pixels == metrics.minScrollExtent;
|
||||||
InfoRow('Resolution', '${entry.width} × ${entry.height} (${entry.getMegaPixels()} MP)'),
|
}
|
||||||
InfoRow('Size', formatFilesize(entry.sizeBytes)),
|
if (_scrollStartFromTop) {
|
||||||
InfoRow('Path', entry.path),
|
if (notification is ScrollEndNotification) {
|
||||||
SectionRow('Location'),
|
_scrollStartFromTop = false;
|
||||||
SectionRow('XMP Tags'),
|
} else if (notification is OverscrollNotification) {
|
||||||
SectionRow('Metadata'),
|
if (notification.overscroll < 0) {
|
||||||
FutureBuilder(
|
BackUpNotification().dispatch(context);
|
||||||
future: _metadataLoader,
|
_scrollStartFromTop = false;
|
||||||
builder: (futureContext, AsyncSnapshot<Map> snapshot) {
|
}
|
||||||
if (snapshot.hasError) {
|
|
||||||
return Text(snapshot.error);
|
|
||||||
}
|
}
|
||||||
if (snapshot.connectionState != ConnectionState.done) {
|
}
|
||||||
return CircularProgressIndicator();
|
}
|
||||||
}
|
return false;
|
||||||
final metadataMap = snapshot.data.cast<String, Map>();
|
},
|
||||||
final directoryNames = metadataMap.keys.toList()..sort();
|
child: ListView(
|
||||||
return Column(
|
padding: EdgeInsets.all(8.0),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
||||||
children: directoryNames.expand(
|
SectionRow('File'),
|
||||||
(directoryName) {
|
InfoRow('Title', entry.title),
|
||||||
final directory = metadataMap[directoryName];
|
InfoRow('Date', '${DateFormat.yMMMd().format(date)} – ${DateFormat.Hm().format(date)}'),
|
||||||
final tagKeys = directory.keys.toList()..sort();
|
InfoRow('Resolution', '${entry.width} × ${entry.height} (${entry.getMegaPixels()} MP)'),
|
||||||
return [
|
InfoRow('Size', formatFilesize(entry.sizeBytes)),
|
||||||
Padding(
|
InfoRow('Path', entry.path),
|
||||||
padding: EdgeInsets.symmetric(vertical: 4.0),
|
SectionRow('Metadata'),
|
||||||
child: Text(directoryName, style: TextStyle(fontSize: 18)),
|
FutureBuilder(
|
||||||
),
|
future: _metadataLoader,
|
||||||
...tagKeys.map((tagKey) => InfoRow(tagKey, directory[tagKey])),
|
builder: (futureContext, AsyncSnapshot<Map> snapshot) {
|
||||||
SizedBox(height: 16),
|
if (snapshot.hasError) {
|
||||||
];
|
return Text(snapshot.error);
|
||||||
},
|
}
|
||||||
).toList());
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.symmetric(vertical: 4.0),
|
padding: EdgeInsets.symmetric(vertical: 8.0),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(child: Divider(color: Colors.white70)),
|
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 'dart:ui';
|
||||||
|
|
||||||
import 'package:aves/model/android_app_service.dart';
|
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/image_entry.dart';
|
||||||
|
import 'package:aves/model/metadata_service.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
@ -43,7 +43,11 @@ class FullscreenTopOverlay extends StatelessWidget {
|
||||||
title: Text('${index + 1}/${entries.length}'),
|
title: Text('${index + 1}/${entries.length}'),
|
||||||
actions: [
|
actions: [
|
||||||
// IconButton(icon: Icon(Icons.delete), onPressed: delete),
|
// 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,
|
elevation: 0,
|
||||||
backgroundColor: kOverlayBackground,
|
backgroundColor: kOverlayBackground,
|
||||||
|
|
Loading…
Reference in a new issue