Vaani/lib/features/item_viewer/view/library_item_metadata.dart
Dr.Blank 4ebf46d2fd
chore: remove deprecated apis (#74)
* dart format + remove withopacity

* remove unused imports
2025-04-10 19:42:08 +05:30

148 lines
4.2 KiB
Dart

import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:vaani/api/library_item_provider.dart';
import 'package:vaani/shared/extensions/model_conversions.dart';
class LibraryItemMetadata extends HookConsumerWidget {
const LibraryItemMetadata({
super.key,
required this.id,
});
final String id;
@override
Widget build(BuildContext context, WidgetRef ref) {
final item = ref.watch(libraryItemProvider(id)).valueOrNull;
/// formats the duration of the book as `10h 30m`
///
/// will add up all the durations of the audio files first
/// then convert them to the given format
String? getDurationFormatted() {
final book = (item?.media.asBookExpanded);
if (book == null) {
return null;
}
final duration = book.audioFiles
.map((e) => e.duration)
.reduce((value, element) => value + element);
final hours = duration.inHours;
final minutes = duration.inMinutes.remainder(60);
return '${hours}h ${minutes}m';
}
/// will return the size of the book in MB
///
/// will add up all the sizes of the audio files first
/// then convert them to MB
String? getSizeFormatted() {
final book = (item?.media.asBookExpanded);
if (book == null) {
return null;
}
final size = book.audioFiles
.map((e) => e.metadata.size)
.reduce((value, element) => value + element);
return '${size / 1024 ~/ 1024} MB';
}
/// will return the codec and bitrate of the book
String? getCodecAndBitrate() {
final book = (item?.media.asBookExpanded);
if (book == null) {
return null;
}
final codec = book.audioFiles.first.codec.toUpperCase();
// final bitrate = book.audioFiles.first.bitRate;
return codec;
}
final itemBookMetadata = item?.media.metadata.asBookMetadataExpanded;
final children = [
// duration of the book
_MetadataItem(
title: switch (itemBookMetadata?.abridged) {
true => 'Abridged',
false => 'Unabridged',
_ => 'Length',
},
value: getDurationFormatted() ?? 'time is just a concept',
),
_MetadataItem(
title: 'Published',
value: itemBookMetadata?.publishedDate ??
itemBookMetadata?.publishedYear ??
'Unknown',
),
_MetadataItem(
title: getCodecAndBitrate() ?? 'Codec & Bitrate',
value: getSizeFormatted() ?? 'Unknown',
),
];
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: IntrinsicHeight(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
// alternate between metadata and vertical divider
children: List.generate(
children.length * 2 - 1,
(index) {
if (index.isEven) {
return children[index ~/ 2];
}
return VerticalDivider(
indent: 6,
endIndent: 6,
color: Theme.of(context)
.colorScheme
.onSurface
.withValues(alpha: 0.6),
);
},
),
),
),
);
}
}
/// key-value pair to display as column
class _MetadataItem extends StatelessWidget {
const _MetadataItem({
required this.title,
required this.value,
});
final String title;
final String value;
@override
Widget build(BuildContext context) {
final themeData = Theme.of(context);
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
style: themeData.textTheme.titleMedium?.copyWith(
color: themeData.colorScheme.onSurface.withValues(alpha: 0.90),
),
value,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
Text(
style: themeData.textTheme.bodySmall?.copyWith(
color: themeData.colorScheme.onSurface.withValues(alpha: 0.7),
),
title,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
],
);
}
}