diff --git a/mobile/lib/models/ffmpeg/ffprobe_props.dart b/mobile/lib/models/ffmpeg/ffprobe_props.dart index 7133626896..e2d0138102 100644 --- a/mobile/lib/models/ffmpeg/ffprobe_props.dart +++ b/mobile/lib/models/ffmpeg/ffprobe_props.dart @@ -105,7 +105,7 @@ class FFProbeProps { switch (stringKey) { case FFProbeKeys.bitrate: case FFProbeKeys.bps: - result.bitrate = _formatMetric(json[key], 'b/s'); + result.bitrate = formatBitrate(json[key], 'b/s'); parsedData[stringKey] = result.bitrate; break; case FFProbeKeys.byteCount: @@ -369,7 +369,7 @@ class FFProbeProps { return null; } - static String? _formatMetric(dynamic size, String unit, {int round = 2}) { + static String? formatBitrate(dynamic size, String unit, {int round = 2}) { if (size == null) return null; if (size is String) { final parsed = int.tryParse(size); diff --git a/mobile/lib/ui/viewer/file/file_app_bar.dart b/mobile/lib/ui/viewer/file/file_app_bar.dart index 96a5a25f7d..70461edcfd 100644 --- a/mobile/lib/ui/viewer/file/file_app_bar.dart +++ b/mobile/lib/ui/viewer/file/file_app_bar.dart @@ -300,7 +300,8 @@ class FileAppBarState extends State { ); } } - if (flagService.internalUser) { + if (flagService.internalUser && + PreviewVideoStore.instance.isVideoStreamingEnabled) { items.add( PopupMenuItem( value: 99, diff --git a/mobile/lib/ui/viewer/file/file_details_widget.dart b/mobile/lib/ui/viewer/file/file_details_widget.dart index e378233e47..96f4455163 100644 --- a/mobile/lib/ui/viewer/file/file_details_widget.dart +++ b/mobile/lib/ui/viewer/file/file_details_widget.dart @@ -32,6 +32,7 @@ import 'package:photos/ui/viewer/file_details/exif_item_widgets.dart'; import "package:photos/ui/viewer/file_details/faces_item_widget.dart"; import "package:photos/ui/viewer/file_details/file_properties_item_widget.dart"; import "package:photos/ui/viewer/file_details/location_tags_widget.dart"; +import "package:photos/ui/viewer/file_details/preview_properties_item_widget.dart"; import "package:photos/ui/viewer/file_details/video_exif_item.dart"; import "package:photos/utils/exif_util.dart"; import "package:photos/utils/file_util.dart"; @@ -177,6 +178,18 @@ class _FileDetailsWidgetState extends State { ), ), const FileDetailsDivider(), + if (widget.file.pubMagicMetadata?.previewSize != null) ...[ + ValueListenableBuilder( + valueListenable: _exifNotifier, + builder: (context, _, __) => PreviewPropertiesItemWidget( + file, + _isImage, + _exifData, + _currentUserID, + ), + ), + const FileDetailsDivider(), + ], ]); fileDetailsTiles.add( ValueListenableBuilder( diff --git a/mobile/lib/ui/viewer/file/preview_status_widget.dart b/mobile/lib/ui/viewer/file/preview_status_widget.dart index c81b5fa199..1ad79e15c0 100644 --- a/mobile/lib/ui/viewer/file/preview_status_widget.dart +++ b/mobile/lib/ui/viewer/file/preview_status_widget.dart @@ -70,9 +70,9 @@ class _PreviewStatusWidgetState extends State { ?.containsKey(widget.file.uploadedFileID) ?? false); - // if (widget.file.localID != null && preview == null) { - // return const SizedBox(); - // } + if (widget.file.localID != null && preview == null) { + return const SizedBox(); + } final isInProgress = preview?.status == PreviewItemStatus.compressing || preview?.status == PreviewItemStatus.uploading; final isInQueue = preview?.status == PreviewItemStatus.inQueue || diff --git a/mobile/lib/ui/viewer/file_details/file_properties_item_widget.dart b/mobile/lib/ui/viewer/file_details/file_properties_item_widget.dart index a92b99374d..0640f92eeb 100644 --- a/mobile/lib/ui/viewer/file_details/file_properties_item_widget.dart +++ b/mobile/lib/ui/viewer/file_details/file_properties_item_widget.dart @@ -48,6 +48,7 @@ class _FilePropertiesItemWidgetState extends State { } Future> _subTitleSection() async { + final textStyle = getEnteTextTheme(context).miniMuted; final StringBuffer dimString = StringBuffer(); if (widget.exifData["resolution"] != null && widget.exifData["megaPixels"] != null) { @@ -66,7 +67,7 @@ class _FilePropertiesItemWidgetState extends State { subSectionWidgets.add( Text( dimString.toString(), - style: getEnteTextTheme(context).miniMuted, + style: textStyle, ), ); } @@ -80,7 +81,7 @@ class _FilePropertiesItemWidgetState extends State { subSectionWidgets.add( Text( formatBytes(fileSize), - style: getEnteTextTheme(context).miniMuted, + style: textStyle, ), ); @@ -90,7 +91,7 @@ class _FilePropertiesItemWidgetState extends State { subSectionWidgets.add( Text( secondsToHHMMSS(widget.file.duration!), - style: getEnteTextTheme(context).miniMuted, + style: textStyle, ), ); } else { @@ -98,7 +99,7 @@ class _FilePropertiesItemWidgetState extends State { subSectionWidgets.add( Text( asset?.videoDuration.toString().split(".")[0] ?? "", - style: getEnteTextTheme(context).miniMuted, + style: textStyle, ), ); } diff --git a/mobile/lib/ui/viewer/file_details/preview_properties_item_widget.dart b/mobile/lib/ui/viewer/file_details/preview_properties_item_widget.dart new file mode 100644 index 0000000000..8e93eaa88e --- /dev/null +++ b/mobile/lib/ui/viewer/file_details/preview_properties_item_widget.dart @@ -0,0 +1,81 @@ +import "package:flutter/material.dart"; +import "package:photos/models/ffmpeg/ffprobe_props.dart"; +import 'package:photos/models/file/file.dart'; +import "package:photos/models/file/file_type.dart"; +import "package:photos/theme/ente_theme.dart"; +import "package:photos/ui/components/info_item_widget.dart"; +import "package:photos/utils/data_util.dart"; + +class PreviewPropertiesItemWidget extends StatefulWidget { + final EnteFile file; + final bool isImage; + final Map exifData; + final int currentUserID; + const PreviewPropertiesItemWidget( + this.file, + this.isImage, + this.exifData, + this.currentUserID, { + super.key, + }); + @override + State createState() => + _PreviewPropertiesItemWidgetState(); +} + +class _PreviewPropertiesItemWidgetState + extends State { + @override + Widget build(BuildContext context) { + return InfoItemWidget( + key: const ValueKey("Stream properties"), + leadingIcon: Icons.play_circle_outline, + title: "Stream Details", + subtitleSection: _subTitleSection(), + ); + } + + Future> _subTitleSection() async { + final textStyle = getEnteTextTheme(context).miniMuted; + final subSectionWidgets = []; + + if (widget.file.pubMagicMetadata?.previewWidth != null && + widget.file.pubMagicMetadata?.previewHeight != null) { + subSectionWidgets.add( + Text( + "${widget.file.pubMagicMetadata?.previewWidth}x${widget.file.pubMagicMetadata?.previewHeight}", + style: textStyle, + ), + ); + } + + if (widget.file.pubMagicMetadata?.previewSize != null) { + subSectionWidgets.add( + Text( + formatBytes(widget.file.pubMagicMetadata!.previewSize!), + style: textStyle, + ), + ); + } + + if ((widget.file.fileType == FileType.video) && + (widget.file.localID != null || widget.file.duration != 0) && + widget.file.pubMagicMetadata!.previewSize != null) { + // show bitrate, i.e. size * 8 / duration formatted + final result = FFProbeProps.formatBitrate( + widget.file.pubMagicMetadata!.previewSize! * 8 / widget.file.duration!, + "b/s", + ); + if (result != null) { + subSectionWidgets.add( + Text( + result, + style: textStyle, + ), + ); + } + } + + return Future.value(subSectionWidgets); + } +}