aves/lib/image_fullscreen_overlay.dart

173 lines
5.3 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:math';
import 'dart:ui';
import 'package:aves/model/android_app_service.dart';
import 'package:aves/model/image_decode_service.dart';
import 'package:aves/model/image_entry.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
const kOverlayBackground = Colors.black26;
class Blurred extends StatelessWidget {
final Widget child;
const Blurred({Key key, this.child}) : super(key: key);
@override
Widget build(BuildContext context) {
return ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 4, sigmaY: 4),
child: child,
),
);
}
}
class FullscreenTopOverlay extends StatelessWidget {
final List<ImageEntry> entries;
final int index;
ImageEntry get entry => entries[index];
const FullscreenTopOverlay({Key key, this.entries, this.index}) : super(key: key);
@override
Widget build(BuildContext context) {
return Blurred(
child: SafeArea(
child: Container(
height: kToolbarHeight,
child: AppBar(
title: Text('${index + 1}/${entries.length}'),
actions: [
// IconButton(icon: Icon(Icons.delete), onPressed: delete),
IconButton(icon: Icon(Icons.share), onPressed: share),
],
elevation: 0,
backgroundColor: kOverlayBackground,
),
),
),
);
}
delete() {}
share() {
AndroidAppService.share(entry.uri, entry.mimeType);
}
}
class FullscreenBottomOverlay extends StatefulWidget {
final List<ImageEntry> entries;
final int index;
const FullscreenBottomOverlay({Key key, this.entries, this.index}) : super(key: key);
@override
State<StatefulWidget> createState() => _FullscreenBottomOverlayState();
}
class _FullscreenBottomOverlayState extends State<FullscreenBottomOverlay> {
Future<Map> _detailLoader;
Map _lastDetails;
ImageEntry get entry => widget.entries[widget.index];
@override
void initState() {
super.initState();
initDetailLoader();
}
@override
void didUpdateWidget(FullscreenBottomOverlay oldWidget) {
super.didUpdateWidget(oldWidget);
initDetailLoader();
}
initDetailLoader() {
_detailLoader = ImageDecodeService.getOverlayMetadata(entry.path);
}
@override
Widget build(BuildContext context) {
var mediaQuery = MediaQuery.of(context);
final screenWidth = mediaQuery.size.width;
final viewInsets = mediaQuery.viewInsets;
final date = entry.getBestDate();
final subRowWidth = min(400.0, screenWidth);
return Blurred(
child: IgnorePointer(
child: Padding(
padding: EdgeInsets.only(bottom: viewInsets.bottom),
child: Container(
padding: EdgeInsets.all(8.0),
color: kOverlayBackground,
child: DefaultTextStyle(
style: TextStyle(
shadows: [
Shadow(
color: Colors.black87,
offset: Offset(0.0, 1.0),
)
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: screenWidth,
child: Text(
entry.title,
overflow: TextOverflow.ellipsis,
),
),
SizedBox(height: 4),
SizedBox(
width: subRowWidth,
child: Row(
children: [
Icon(Icons.calendar_today, size: 16),
SizedBox(width: 8),
Expanded(child: Text('${DateFormat.yMMMd().format(date)} ${DateFormat.Hm().format(date)}')),
Expanded(child: Text('${entry.width} × ${entry.height}')),
],
),
),
SizedBox(height: 4),
FutureBuilder(
future: _detailLoader,
builder: (futureContext, AsyncSnapshot<Map> snapshot) {
if (snapshot.connectionState == ConnectionState.done && !snapshot.hasError) {
_lastDetails = snapshot.data;
}
return (_lastDetails == null || _lastDetails.isEmpty)
? SizedBox.shrink()
: SizedBox(
width: subRowWidth,
child: Row(
children: [
Icon(Icons.camera, size: 16),
SizedBox(width: 8),
Expanded(child: Text((_lastDetails['aperture'] as String).replaceAll('f', 'ƒ'))),
Expanded(child: Text(_lastDetails['exposureTime'])),
Expanded(child: Text(_lastDetails['focalLength'])),
Expanded(child: Text(_lastDetails['iso'])),
],
),
);
},
)
],
),
),
),
),
),
);
}
}