exif_item_widgets.dart 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import "package:exif/exif.dart";
  2. import "package:flutter/material.dart";
  3. import "package:photos/generated/l10n.dart";
  4. import "package:photos/models/file.dart";
  5. import "package:photos/theme/colors.dart";
  6. import "package:photos/theme/ente_theme.dart";
  7. import "package:photos/ui/components/info_item_widget.dart";
  8. import "package:photos/ui/viewer/file/exif_info_dialog.dart";
  9. import "package:photos/utils/toast_util.dart";
  10. class BasicExifItemWidget extends StatelessWidget {
  11. final Map<String, dynamic> exifData;
  12. const BasicExifItemWidget(this.exifData, {super.key});
  13. @override
  14. Widget build(BuildContext context) {
  15. final subtitleTextTheme = getEnteTextTheme(context).miniMuted;
  16. return InfoItemWidget(
  17. key: const ValueKey("Basic EXIF"),
  18. leadingIcon: Icons.camera_outlined,
  19. title: exifData["takenOnDevice"] ?? "--",
  20. subtitleSection: Future.value([
  21. if (exifData["fNumber"] != null)
  22. Text(
  23. 'ƒ/' + exifData["fNumber"].toString(),
  24. style: subtitleTextTheme,
  25. ),
  26. if (exifData["exposureTime"] != null)
  27. Text(
  28. exifData["exposureTime"],
  29. style: subtitleTextTheme,
  30. ),
  31. if (exifData["focalLength"] != null)
  32. Text(
  33. exifData["focalLength"].toString() + "mm",
  34. style: subtitleTextTheme,
  35. ),
  36. if (exifData["ISO"] != null)
  37. Text(
  38. "ISO" + exifData["ISO"].toString(),
  39. style: subtitleTextTheme,
  40. ),
  41. ]),
  42. );
  43. }
  44. }
  45. class AllExifItemWidget extends StatefulWidget {
  46. final File file;
  47. final Map<String, IfdTag>? exif;
  48. const AllExifItemWidget(
  49. this.file,
  50. this.exif, {
  51. super.key,
  52. });
  53. @override
  54. State<AllExifItemWidget> createState() => _AllExifItemWidgetState();
  55. }
  56. class _AllExifItemWidgetState extends State<AllExifItemWidget> {
  57. VoidCallback? _onTap;
  58. @override
  59. void initState() {
  60. super.initState();
  61. }
  62. @override
  63. Widget build(BuildContext context) {
  64. return InfoItemWidget(
  65. leadingIcon: Icons.text_snippet_outlined,
  66. title: S.of(context).exif,
  67. subtitleSection: _exifButton(context, widget.file, widget.exif),
  68. onTap: _onTap,
  69. );
  70. }
  71. Future<List<Widget>> _exifButton(
  72. BuildContext context,
  73. File file,
  74. Map<String, IfdTag>? exif,
  75. ) async {
  76. late final String label;
  77. late final VoidCallback? onTap;
  78. if (exif == null) {
  79. label = S.of(context).loadingExifData;
  80. onTap = null;
  81. } else if (exif.isNotEmpty) {
  82. label = S.of(context).viewAllExifData;
  83. onTap = () => showDialog(
  84. context: context,
  85. builder: (BuildContext context) {
  86. return ExifInfoDialog(file);
  87. },
  88. barrierColor: backdropFaintDark,
  89. );
  90. } else {
  91. label = S.of(context).noExifData;
  92. onTap =
  93. () => showShortToast(context, S.of(context).thisImageHasNoExifData);
  94. }
  95. setState(() {
  96. _onTap = onTap;
  97. });
  98. return Future.value([
  99. Text(label, style: getEnteTextTheme(context).miniBoldMuted),
  100. ]);
  101. }
  102. }