diff --git a/lib/widgets/common/highlight_title.dart b/lib/widgets/common/highlight_title.dart index 671e61740..11c8ba448 100644 --- a/lib/widgets/common/highlight_title.dart +++ b/lib/widgets/common/highlight_title.dart @@ -11,7 +11,7 @@ class HighlightTitle extends StatelessWidget { this.name, { this.fontSize = 20, this.enabled = true, - }); + }) : assert(name != null); static const disabledColor = Colors.grey; diff --git a/lib/widgets/fullscreen/info/metadata_section.dart b/lib/widgets/fullscreen/info/metadata_section.dart index f7ce36e0b..fccd18ed4 100644 --- a/lib/widgets/fullscreen/info/metadata_section.dart +++ b/lib/widgets/fullscreen/info/metadata_section.dart @@ -5,6 +5,7 @@ import 'package:aves/services/metadata_service.dart'; import 'package:aves/utils/constants.dart'; import 'package:aves/utils/durations.dart'; import 'package:aves/widgets/common/aves_expansion_tile.dart'; +import 'package:aves/widgets/common/highlight_title.dart'; import 'package:aves/widgets/common/icons.dart'; import 'package:aves/widgets/fullscreen/info/common.dart'; import 'package:aves/widgets/fullscreen/info/metadata_thumbnail.dart'; @@ -122,15 +123,15 @@ class _MetadataSectionSliverState extends State with Auto } Widget _buildDirTileWithTitle(_MetadataDirectory dir) { + if (dir.name == xmpDirectory) { + return _buildXmpDirTile(dir); + } Widget thumbnail; final prefixChildren = []; switch (dir.name) { case exifThumbnailDirectory: thumbnail = MetadataThumbnails(source: MetadataThumbnailSource.exif, entry: entry); break; - case xmpDirectory: - thumbnail = MetadataThumbnails(source: MetadataThumbnailSource.xmp, entry: entry); - break; case mediaDirectory: thumbnail = MetadataThumbnails(source: MetadataThumbnailSource.embedded, entry: entry); Widget builder(IconData data) => Padding( @@ -153,8 +154,7 @@ class _MetadataSectionSliverState extends State with Auto title: dir.name, expandedNotifier: _expandedDirectoryNotifier, children: [ - if (prefixChildren.isNotEmpty) - Wrap(children: prefixChildren), + if (prefixChildren.isNotEmpty) Wrap(children: prefixChildren), if (thumbnail != null) thumbnail, Padding( padding: EdgeInsets.only(left: 8, right: 8, bottom: 8), @@ -164,6 +164,42 @@ class _MetadataSectionSliverState extends State with Auto ); } + Widget _buildXmpDirTile(_MetadataDirectory dir) { + final thumbnail = MetadataThumbnails(source: MetadataThumbnailSource.xmp, entry: entry); + final byNamespace = SplayTreeMap.of( + groupBy, String>(dir.tags.entries, (kv) { + final fullKey = kv.key; + final i = fullKey.indexOf(':'); + if (i == -1) return ''; + return fullKey.substring(0, i); + }), + compareAsciiLowerCase, + ); + return AvesExpansionTile( + title: dir.name, + expandedNotifier: _expandedDirectoryNotifier, + children: [ + if (thumbnail != null) thumbnail, + Padding( + padding: EdgeInsets.only(left: 8, right: 8, bottom: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: byNamespace.entries.expand((kv) { + final ns = kv.key; + final hasNamespace = ns.isNotEmpty; + final i = hasNamespace ? ns.length + 1 : 0; + final tags = Map.fromEntries(kv.value.map((kv) => MapEntry(kv.key.substring(i), kv.value))); + return [ + if (hasNamespace) HighlightTitle(ns), + InfoRowGroup(tags, maxValueLength: Constants.infoGroupMaxValueLength), + ]; + }).toList(), + ), + ), + ], + ); + } + void _onMetadataChanged() { _loadedMetadataUri.value = null; _metadata = []; @@ -192,6 +228,7 @@ class _MetadataSectionSliverState extends State with Auto _metadata = []; _loadedMetadataUri.value = null; } + _expandedDirectoryNotifier.value = null; } @override