ente/lib/ui/file_info_dialog.dart

461 lines
13 KiB
Dart
Raw Normal View History

import 'package:exif/exif.dart';
import 'package:flutter/cupertino.dart';
2021-07-06 11:50:35 +00:00
import 'package:flutter/material.dart';
import 'package:photos/models/file.dart';
import 'package:photos/models/file_type.dart';
import 'package:photos/services/collections_service.dart';
2021-07-06 16:03:39 +00:00
import 'package:photos/ui/exif_info_dialog.dart';
2021-07-06 11:50:35 +00:00
import 'package:photos/utils/date_time_util.dart';
2021-08-24 07:14:33 +00:00
import 'package:photos/utils/exif_util.dart';
import 'package:photos/utils/file_util.dart';
2021-07-10 05:48:00 +00:00
import 'package:photos/utils/toast_util.dart';
2021-07-06 11:50:35 +00:00
2021-07-10 05:48:00 +00:00
class FileInfoWidget extends StatefulWidget {
2021-07-06 11:50:35 +00:00
final File file;
2021-07-06 11:51:51 +00:00
const FileInfoWidget(
2021-07-07 01:01:14 +00:00
this.file, {
2021-07-06 11:51:51 +00:00
Key key,
}) : super(key: key);
2021-07-06 11:50:35 +00:00
2021-07-10 05:48:00 +00:00
@override
_FileInfoWidgetState createState() => _FileInfoWidgetState();
}
class _FileInfoWidgetState extends State<FileInfoWidget> {
Map<String, IfdTag> _exif;
2021-07-11 07:54:38 +00:00
bool _isImage = false;
2021-07-10 05:48:00 +00:00
@override
void initState() {
2021-08-09 06:33:47 +00:00
_isImage = widget.file.fileType == FileType.image ||
widget.file.fileType == FileType.livePhoto;
2021-07-11 07:54:38 +00:00
if (_isImage) {
2021-08-24 07:14:33 +00:00
getExif(widget.file).then((exif) {
2021-07-11 07:54:38 +00:00
setState(() {
_exif = exif;
});
2021-07-10 05:48:00 +00:00
});
2021-07-11 07:54:38 +00:00
}
2021-07-10 05:48:00 +00:00
super.initState();
}
2021-07-06 11:50:35 +00:00
@override
Widget build(BuildContext context) {
var items = <Widget>[
Row(
children: [
Icon(
Icons.calendar_today_outlined,
color: Colors.white.withOpacity(0.85),
),
2021-07-06 11:50:35 +00:00
Padding(padding: EdgeInsets.all(4)),
Text(
getFormattedTime(
2021-07-10 05:48:00 +00:00
DateTime.fromMicrosecondsSinceEpoch(widget.file.creationTime),
),
style: TextStyle(
color: Colors.white.withOpacity(0.85),
),
),
2021-07-06 11:50:35 +00:00
],
),
Padding(padding: EdgeInsets.all(6)),
2021-07-06 11:50:35 +00:00
Row(
children: [
Icon(
Icons.folder_outlined,
color: Colors.white.withOpacity(0.85),
),
2021-07-06 11:50:35 +00:00
Padding(padding: EdgeInsets.all(4)),
Text(
2021-07-10 05:48:00 +00:00
widget.file.deviceFolder ??
CollectionsService.instance
2021-07-10 05:48:00 +00:00
.getCollectionByID(widget.file.collectionID)
.name,
style: TextStyle(
color: Colors.white.withOpacity(0.85),
),
),
2021-07-06 11:50:35 +00:00
],
),
Padding(padding: EdgeInsets.all(6)),
2021-07-06 11:50:35 +00:00
];
2021-07-07 00:57:53 +00:00
items.addAll(
[
Row(
children: [
Icon(
Icons.sd_storage_outlined,
color: Colors.white.withOpacity(0.85),
),
Padding(padding: EdgeInsets.all(4)),
_getFileSize(),
],
),
Padding(padding: EdgeInsets.all(6)),
],
);
2021-07-11 07:54:38 +00:00
if (widget.file.localID != null && !_isImage) {
2021-07-07 00:41:49 +00:00
items.addAll(
[
2021-07-06 12:18:39 +00:00
Row(
children: [
Icon(
2021-07-07 00:57:53 +00:00
Icons.timer_outlined,
color: Colors.white.withOpacity(0.85),
),
2021-07-06 12:18:39 +00:00
Padding(padding: EdgeInsets.all(4)),
2021-07-07 01:01:14 +00:00
FutureBuilder(
2021-07-10 05:48:00 +00:00
future: widget.file.getAsset(),
2021-07-07 01:01:14 +00:00
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(
snapshot.data.videoDuration.toString().split(".")[0],
style: TextStyle(
color: Colors.white.withOpacity(0.85),
),
);
} else {
return Center(
child: SizedBox.fromSize(
size: Size.square(24),
child: CupertinoActivityIndicator(
radius: 8,
),
),
);
}
},
),
2021-07-06 12:18:39 +00:00
],
),
2021-07-07 00:41:49 +00:00
Padding(padding: EdgeInsets.all(6)),
],
);
2021-07-06 11:50:35 +00:00
}
2021-07-11 07:54:38 +00:00
if (_isImage && _exif != null) {
2021-07-10 05:48:00 +00:00
items.add(_getExifWidgets(_exif));
2021-07-06 12:18:39 +00:00
}
2021-07-10 05:48:00 +00:00
if (widget.file.uploadedFileID != null) {
items.addAll(
[
Row(
children: [
Icon(
Icons.cloud_upload_outlined,
color: Colors.white.withOpacity(0.85),
),
Padding(padding: EdgeInsets.all(4)),
Text(
2021-07-10 05:48:00 +00:00
getFormattedTime(DateTime.fromMicrosecondsSinceEpoch(
widget.file.updationTime)),
style: TextStyle(
color: Colors.white.withOpacity(0.85),
),
),
],
),
],
);
}
2021-07-06 12:18:39 +00:00
items.add(
Padding(padding: EdgeInsets.all(12)),
);
2021-07-10 05:48:00 +00:00
items.add(
Row(
mainAxisAlignment:
2021-07-11 07:54:38 +00:00
_isImage ? MainAxisAlignment.spaceBetween : MainAxisAlignment.end,
children: _getActions(),
2021-07-10 05:48:00 +00:00
),
);
return AlertDialog(
title: Text(widget.file.title),
content: SingleChildScrollView(
child: ListBody(
children: items,
),
),
);
}
2021-07-11 07:54:38 +00:00
List<Widget> _getActions() {
2021-07-06 20:49:46 +00:00
final List<Widget> actions = [];
2021-07-11 07:54:38 +00:00
if (_isImage) {
2021-07-10 05:48:00 +00:00
if (_exif == null) {
actions.add(
TextButton(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Center(
child: SizedBox.fromSize(
size: Size.square(24),
child: CupertinoActivityIndicator(
radius: 8,
),
),
),
Padding(padding: EdgeInsets.all(4)),
Text(
"exif",
style: TextStyle(
color: Colors.white.withOpacity(0.85),
),
),
],
),
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return ExifInfoDialog(widget.file);
},
barrierColor: Colors.black87,
);
},
),
);
} else if (_exif.isNotEmpty) {
actions.add(
TextButton(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Icon(
Icons.feed_outlined,
color: Colors.white.withOpacity(0.85),
2021-07-06 12:18:39 +00:00
),
2021-07-10 05:48:00 +00:00
Padding(padding: EdgeInsets.all(4)),
Text(
"view exif",
style: TextStyle(
color: Colors.white.withOpacity(0.85),
),
),
],
),
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return ExifInfoDialog(widget.file);
},
barrierColor: Colors.black87,
);
},
2021-07-06 12:18:39 +00:00
),
2021-07-10 05:48:00 +00:00
);
} else {
actions.add(
TextButton(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Icon(
Icons.feed_outlined,
color: Colors.white.withOpacity(0.5),
),
Padding(padding: EdgeInsets.all(4)),
Text(
"no exif",
style: TextStyle(
color: Colors.white.withOpacity(0.5),
),
),
],
),
onPressed: () {
showToast("this image has no exif data");
},
),
);
}
2021-07-06 20:49:46 +00:00
}
actions.add(
TextButton(
child: Text(
"close",
style: TextStyle(
color: Colors.white.withOpacity(0.8),
),
),
onPressed: () {
Navigator.of(context, rootNavigator: true).pop('dialog');
},
),
);
2021-07-10 05:48:00 +00:00
return actions;
2021-07-06 11:50:35 +00:00
}
Widget _getExifWidgets(Map<String, IfdTag> exif) {
final focalLength = exif["EXIF FocalLength"] != null
? (exif["EXIF FocalLength"].values.toList()[0] as Ratio).numerator /
(exif["EXIF FocalLength"].values.toList()[0] as Ratio).denominator
: null;
final fNumber = exif["EXIF FNumber"] != null
? (exif["EXIF FNumber"].values.toList()[0] as Ratio).numerator /
(exif["EXIF FNumber"].values.toList()[0] as Ratio).denominator
: null;
final List<Widget> children = [];
2021-07-07 00:41:49 +00:00
if (exif["EXIF ExifImageWidth"] != null &&
exif["EXIF ExifImageLength"] != null) {
children.addAll([
Row(
children: [
Icon(
Icons.photo_size_select_actual_outlined,
color: Colors.white.withOpacity(0.85),
),
Padding(padding: EdgeInsets.all(4)),
Text(
exif["EXIF ExifImageWidth"].toString() +
" x " +
exif["EXIF ExifImageLength"].toString(),
style: TextStyle(
color: Colors.white.withOpacity(0.85),
),
),
],
),
Padding(padding: EdgeInsets.all(6)),
]);
} else if (exif["Image ImageWidth"] != null &&
exif["Image ImageLength"] != null) {
children.addAll([
Row(
children: [
Icon(
Icons.photo_size_select_actual_outlined,
color: Colors.white.withOpacity(0.85),
),
Padding(padding: EdgeInsets.all(4)),
Text(
exif["Image ImageWidth"].toString() +
" x " +
exif["Image ImageLength"].toString(),
style: TextStyle(
color: Colors.white.withOpacity(0.85),
),
),
],
),
Padding(padding: EdgeInsets.all(6)),
]);
}
if (exif["Image Make"] != null && exif["Image Model"] != null) {
children.addAll(
[
Row(
children: [
Icon(
Icons.camera_outlined,
color: Colors.white.withOpacity(0.85),
),
Padding(padding: EdgeInsets.all(4)),
2021-07-23 10:15:54 +00:00
Flexible(
child: Text(
exif["Image Make"].toString() +
" " +
exif["Image Model"].toString(),
style: TextStyle(
color: Colors.white.withOpacity(0.85),
),
overflow: TextOverflow.clip,
),
),
],
),
Padding(padding: EdgeInsets.all(6)),
],
);
}
if (fNumber != null) {
children.addAll([
Row(
children: [
Icon(
CupertinoIcons.f_cursive,
color: Colors.white.withOpacity(0.85),
),
Padding(padding: EdgeInsets.all(4)),
Text(
fNumber.toString(),
style: TextStyle(
color: Colors.white.withOpacity(0.85),
),
),
],
),
Padding(padding: EdgeInsets.all(6)),
]);
}
if (focalLength != null) {
children.addAll([
Row(
children: [
Icon(
Icons.center_focus_strong_outlined,
color: Colors.white.withOpacity(0.85),
),
Padding(padding: EdgeInsets.all(4)),
Text(focalLength.toString() + " mm",
style: TextStyle(
color: Colors.white.withOpacity(0.85),
)),
],
),
Padding(padding: EdgeInsets.all(6)),
]);
}
if (exif["EXIF ExposureTime"] != null) {
children.addAll([
Row(
children: [
Icon(
Icons.shutter_speed,
color: Colors.white.withOpacity(0.85),
),
Padding(padding: EdgeInsets.all(4)),
Text(
exif["EXIF ExposureTime"].toString(),
style: TextStyle(
color: Colors.white.withOpacity(0.85),
),
),
],
),
Padding(padding: EdgeInsets.all(6)),
]);
}
return Column(
children: children,
);
}
2021-07-07 00:57:53 +00:00
Widget _getFileSize() {
return FutureBuilder(
2021-08-09 06:33:47 +00:00
future: getFile(widget.file).then((f) => f.length()),
2021-07-07 00:57:53 +00:00
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(
(snapshot.data / (1024 * 1024)).toStringAsFixed(2) + " MB",
style: TextStyle(
color: Colors.white.withOpacity(0.85),
),
);
} else {
return Center(
child: SizedBox.fromSize(
size: Size.square(24),
child: CupertinoActivityIndicator(
radius: 8,
),
),
);
}
},
);
}
2021-07-06 11:50:35 +00:00
}