From 73e37c104952a9eebc39867e91279c2448760078 Mon Sep 17 00:00:00 2001 From: Mati Date: Wed, 25 Oct 2023 14:06:23 -0300 Subject: [PATCH 1/7] feat(image preview): implements the preview widget PE-4709 --- .../fs_entry_preview_cubit.dart | 33 ++++- .../fs_entry_preview_state.dart | 4 + .../components/fs_entry_preview_widget.dart | 131 +++++++++++++++++- 3 files changed, 156 insertions(+), 12 deletions(-) diff --git a/lib/blocs/fs_entry_preview/fs_entry_preview_cubit.dart b/lib/blocs/fs_entry_preview/fs_entry_preview_cubit.dart index 4e01584c74..695d197a84 100644 --- a/lib/blocs/fs_entry_preview/fs_entry_preview_cubit.dart +++ b/lib/blocs/fs_entry_preview/fs_entry_preview_cubit.dart @@ -7,8 +7,8 @@ import 'package:ardrive/models/models.dart'; import 'package:ardrive/pages/pages.dart'; import 'package:ardrive/services/services.dart'; import 'package:ardrive/utils/constants.dart'; -import 'package:ardrive/utils/mime_lookup.dart'; import 'package:ardrive_http/ardrive_http.dart'; +import 'package:ardrive_io/ardrive_io.dart'; import 'package:cryptography/cryptography.dart'; import 'package:drift/drift.dart'; import 'package:equatable/equatable.dart'; @@ -79,7 +79,12 @@ class FsEntryPreviewCubit extends Cubit { final data = await _getPreviewData(file, previewUrl); if (data != null) { - emit(FsEntryPreviewImage(imageBytes: data, previewUrl: previewUrl)); + emit(FsEntryPreviewImage( + imageBytes: data, + previewUrl: previewUrl, + filename: file.name, + contentType: file.contentType, + )); } else { emit(FsEntryPreviewUnavailable()); } @@ -278,7 +283,13 @@ class FsEntryPreviewCubit extends Cubit { switch (drive.privacy) { case DrivePrivacy.public: emit( - FsEntryPreviewImage(imageBytes: dataBytes, previewUrl: dataUrl), + FsEntryPreviewImage( + imageBytes: dataBytes, + previewUrl: dataUrl, + filename: file.name, + contentType: file.dataContentType ?? + lookupMimeTypeWithDefaultType(file.name), + ), ); break; case DrivePrivacy.private: @@ -289,7 +300,13 @@ class FsEntryPreviewCubit extends Cubit { if (isPinFile) { emit( - FsEntryPreviewImage(imageBytes: dataBytes, previewUrl: dataUrl), + FsEntryPreviewImage( + imageBytes: dataBytes, + previewUrl: dataUrl, + filename: file.name, + contentType: file.dataContentType ?? + lookupMimeTypeWithDefaultType(file.name), + ), ); break; } @@ -314,7 +331,13 @@ class FsEntryPreviewCubit extends Cubit { fileKey, ); emit( - FsEntryPreviewImage(imageBytes: decodedBytes, previewUrl: dataUrl), + FsEntryPreviewImage( + imageBytes: decodedBytes, + previewUrl: dataUrl, + filename: file.name, + contentType: file.dataContentType ?? + lookupMimeTypeWithDefaultType(file.name), + ), ); break; diff --git a/lib/blocs/fs_entry_preview/fs_entry_preview_state.dart b/lib/blocs/fs_entry_preview/fs_entry_preview_state.dart index f7ed5d9a4f..c2ac51a34f 100644 --- a/lib/blocs/fs_entry_preview/fs_entry_preview_state.dart +++ b/lib/blocs/fs_entry_preview/fs_entry_preview_state.dart @@ -26,9 +26,13 @@ class FsEntryPreviewLoading extends FsEntryPreviewSuccess { class FsEntryPreviewImage extends FsEntryPreviewSuccess { final Uint8List imageBytes; + final String filename; + final String contentType; const FsEntryPreviewImage({ required this.imageBytes, + required this.filename, + required this.contentType, required String previewUrl, }) : super(previewUrl: previewUrl); diff --git a/lib/pages/drive_detail/components/fs_entry_preview_widget.dart b/lib/pages/drive_detail/components/fs_entry_preview_widget.dart index 18018e536c..e872d1eaca 100644 --- a/lib/pages/drive_detail/components/fs_entry_preview_widget.dart +++ b/lib/pages/drive_detail/components/fs_entry_preview_widget.dart @@ -32,13 +32,11 @@ class _FsEntryPreviewWidgetState extends State { ); case FsEntryPreviewImage: - return ArDriveImage( - fit: BoxFit.contain, - height: double.maxFinite, - width: double.maxFinite, - image: MemoryImage( - (widget.state as FsEntryPreviewImage).imageBytes, - ), + return ImagePreviewWidget( + filename: (widget.state as FsEntryPreviewImage).filename, + contentType: (widget.state as FsEntryPreviewImage).contentType, + imageBytes: (widget.state as FsEntryPreviewImage).imageBytes, + isSharePage: widget.isSharePage, ); case FsEntryPreviewAudio: @@ -1028,6 +1026,125 @@ class _FullScreenVideoPlayerWidgetState } } +class ImagePreviewWidget extends StatefulWidget { + final Uint8List imageBytes; + final String filename; + final String contentType; + final bool isSharePage; + + const ImagePreviewWidget({ + super.key, + required this.filename, + required this.contentType, + required this.imageBytes, + required this.isSharePage, + }); + + @override + State createState() { + return _ImagePreviewWidgetState(); + } +} + +class _ImagePreviewWidgetState extends State { + @override + Widget build(BuildContext context) { + if (!widget.isSharePage) { + return _buildImage(); + } else { + final theme = ArDriveTheme.of(context); + + return Column( + children: [ + Flexible(child: _buildImage()), + Container( + color: theme.themeData.colors.themeBgCanvas, + child: _buildActionBar(), + ), + ], + ); + } + } + + Widget _buildImage() { + return ArDriveImage( + fit: BoxFit.contain, + height: double.maxFinite, + width: double.maxFinite, + image: MemoryImage( + widget.imageBytes, + ), + ); + } + + Widget _buildActionBar() { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + height: 96, + child: Padding( + padding: const EdgeInsets.only( + left: 24, + top: 24, + bottom: 24, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + _getFileNameWithNoExtension(), + style: ArDriveTypography.body.smallBold700( + color: ArDriveTheme.of(context) + .themeData + .colors + .themeFgDefault, + ), + ), + Text( + _getFileExtension(), + style: ArDriveTypography.body.smallRegular( + color: ArDriveTheme.of(context) + .themeData + .colors + .themeFgDisabled, + ), + ), + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.only( + right: 24, + top: 24, + bottom: 24, + ), + child: IconButton( + onPressed: goFullScreen, + icon: const Icon(Icons.fullscreen_outlined, size: 24), + ), + ), + ], + ); + } + + String _getFileNameWithNoExtension() { + return widget.filename.substring(0, widget.filename.lastIndexOf('.')); + } + + String _getFileExtension() { + return widget.contentType + .substring( + widget.contentType.lastIndexOf('/') + 1, + ) + .toUpperCase(); + } + + void goFullScreen() {} +} + class AudioPlayerWidget extends StatefulWidget { final String audioUrl; final String filename; From 8102148a4211481cc8d17efe410744b6e361e998 Mon Sep 17 00:00:00 2001 From: Mati Date: Wed, 25 Oct 2023 15:46:08 -0300 Subject: [PATCH 2/7] feat(image preview): implements full screen mode PE-4709 --- .../components/fs_entry_preview_widget.dart | 83 ++++++++++++++++++- 1 file changed, 79 insertions(+), 4 deletions(-) diff --git a/lib/pages/drive_detail/components/fs_entry_preview_widget.dart b/lib/pages/drive_detail/components/fs_entry_preview_widget.dart index e872d1eaca..053de0464e 100644 --- a/lib/pages/drive_detail/components/fs_entry_preview_widget.dart +++ b/lib/pages/drive_detail/components/fs_entry_preview_widget.dart @@ -37,6 +37,7 @@ class _FsEntryPreviewWidgetState extends State { contentType: (widget.state as FsEntryPreviewImage).contentType, imageBytes: (widget.state as FsEntryPreviewImage).imageBytes, isSharePage: widget.isSharePage, + isFullScreen: false, ); case FsEntryPreviewAudio: @@ -1026,18 +1027,74 @@ class _FullScreenVideoPlayerWidgetState } } +class ImagePreviewFullScreenWidget extends StatefulWidget { + final Uint8List imageBytes; + final String filename; + final String contentType; + + const ImagePreviewFullScreenWidget({ + super.key, + required this.filename, + required this.contentType, + required this.imageBytes, + }); + + @override + State createState() { + return _ImagePreviewFullScreenWidgetState(); + } +} + +class _ImagePreviewFullScreenWidgetState + extends State { + bool fullScreenMode = false; + + @override + void initState() { + SystemChrome.setPreferredOrientations([ + DeviceOrientation.landscapeRight, + DeviceOrientation.landscapeLeft, + ]); + + super.initState(); + } + + @override + void dispose() { + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + ]); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: ImagePreviewWidget( + filename: widget.filename, + contentType: widget.contentType, + imageBytes: widget.imageBytes, + isFullScreen: true, + ), + ); + } +} + class ImagePreviewWidget extends StatefulWidget { final Uint8List imageBytes; final String filename; final String contentType; final bool isSharePage; + final bool isFullScreen; const ImagePreviewWidget({ super.key, required this.filename, required this.contentType, required this.imageBytes, - required this.isSharePage, + this.isSharePage = false, + this.isFullScreen = false, }); @override @@ -1049,7 +1106,7 @@ class ImagePreviewWidget extends StatefulWidget { class _ImagePreviewWidgetState extends State { @override Widget build(BuildContext context) { - if (!widget.isSharePage) { + if (!widget.isSharePage && !widget.isFullScreen) { return _buildImage(); } else { final theme = ArDriveTheme.of(context); @@ -1123,7 +1180,9 @@ class _ImagePreviewWidgetState extends State { ), child: IconButton( onPressed: goFullScreen, - icon: const Icon(Icons.fullscreen_outlined, size: 24), + icon: widget.isFullScreen + ? const Icon(Icons.fullscreen_exit_outlined) + : const Icon(Icons.fullscreen_outlined, size: 24), ), ), ], @@ -1142,7 +1201,23 @@ class _ImagePreviewWidgetState extends State { .toUpperCase(); } - void goFullScreen() {} + void goFullScreen() { + if (widget.isFullScreen) { + Navigator.of(context).pop(); + } else { + Navigator.of(context).push( + PageRouteBuilder( + transitionDuration: Duration.zero, + reverseTransitionDuration: Duration.zero, + pageBuilder: (context, _, __) => ImagePreviewFullScreenWidget( + filename: widget.filename, + contentType: widget.contentType, + imageBytes: widget.imageBytes, + ), + ), + ); + } + } } class AudioPlayerWidget extends StatefulWidget { From c20329aba63a779a3178ca34318daa95703d7f15 Mon Sep 17 00:00:00 2001 From: Mati Date: Mon, 30 Oct 2023 18:47:26 -0300 Subject: [PATCH 3/7] feat(video preview): re-organizes the layout for the shared file page PE-4710 --- .../components/fs_entry_preview_widget.dart | 356 ++++++++++++------ 1 file changed, 233 insertions(+), 123 deletions(-) diff --git a/lib/pages/drive_detail/components/fs_entry_preview_widget.dart b/lib/pages/drive_detail/components/fs_entry_preview_widget.dart index 18018e536c..a2c01df828 100644 --- a/lib/pages/drive_detail/components/fs_entry_preview_widget.dart +++ b/lib/pages/drive_detail/components/fs_entry_preview_widget.dart @@ -52,6 +52,7 @@ class _FsEntryPreviewWidgetState extends State { return VideoPlayerWidget( filename: (widget.state as FsEntryPreviewVideo).filename, videoUrl: (widget.state as FsEntryPreviewVideo).previewUrl, + isSharePage: widget.isSharePage, ); } } @@ -83,10 +84,14 @@ String getTimeString(Duration duration) { class VideoPlayerWidget extends StatefulWidget { final String videoUrl; final String filename; + final bool isSharePage; - const VideoPlayerWidget( - {Key? key, required this.filename, required this.videoUrl}) - : super(key: key); + const VideoPlayerWidget({ + Key? key, + required this.filename, + required this.videoUrl, + required this.isSharePage, + }) : super(key: key); @override // ignore: library_private_types_in_public_api @@ -179,6 +184,7 @@ class _VideoPlayerWidgetState extends State }); } }, + isSharePage: widget.isSharePage, ), ), ); @@ -260,82 +266,117 @@ class _VideoPlayerWidgetState extends State style: ArDriveTypography.body .smallBold700(color: colors.themeFgDefault)), const SizedBox(height: 8), - SliderTheme( - data: SliderThemeData( - trackHeight: 4, - trackShape: - _NoAdditionalHeightRoundedRectSliderTrackShape(), - inactiveTrackColor: colors.themeBgSubtle, - disabledThumbColor: colors.themeAccentBrand, - disabledInactiveTrackColor: colors.themeBgSubtle, - overlayShape: SliderComponentShape.noOverlay, - thumbShape: const RoundSliderThumbShape( - enabledThumbRadius: 8, - )), - child: Slider( - value: min( - videoValue.position.inMilliseconds.toDouble(), - videoValue.duration.inMilliseconds.toDouble()), - secondaryTrackValue: bufferedValue, - min: 0.0, - max: videoValue.duration.inMilliseconds.toDouble(), - onChangeStart: !controlsEnabled - ? null - : (v) async { - if (_videoPlayerController.value.duration > - Duration.zero) { - _wasPlaying = - _videoPlayerController.value.isPlaying; - if (_wasPlaying) { + Row( + children: [ + ScreenTypeLayout.builder( + desktop: (context) => Row(children: [ + Text(currentTime), + const SizedBox(width: 8), + ]), + mobile: (context) => const SizedBox.shrink(), + ), + Expanded( + child: SliderTheme( + data: SliderThemeData( + trackHeight: 4, + trackShape: + _NoAdditionalHeightRoundedRectSliderTrackShape(), + inactiveTrackColor: colors.themeBgSubtle, + disabledThumbColor: colors.themeAccentBrand, + disabledInactiveTrackColor: colors.themeBgSubtle, + overlayShape: SliderComponentShape.noOverlay, + thumbShape: const RoundSliderThumbShape( + enabledThumbRadius: 8, + )), + child: Slider( + value: min( + videoValue.position.inMilliseconds.toDouble(), + videoValue.duration.inMilliseconds.toDouble()), + secondaryTrackValue: bufferedValue, + min: 0.0, + max: videoValue.duration.inMilliseconds.toDouble(), + onChangeStart: !controlsEnabled + ? null + : (v) async { + if (_videoPlayerController.value.duration > + Duration.zero) { + _wasPlaying = + _videoPlayerController.value.isPlaying; + if (_wasPlaying) { + await _lock.synchronized(() async { + await _videoPlayerController + .pause() + .catchError((e) { + logger.e('Error pausing video: $e'); + }); + }); + setState(() {}); + } + } + }, + onChanged: !controlsEnabled + ? null + : (v) async { + setState(() { + final milliseconds = v.toInt(); + + if (_videoPlayerController.value.duration > + Duration.zero) { + _videoPlayerController.seekTo( + Duration(milliseconds: milliseconds)); + } + }); + }, + onChangeEnd: !controlsEnabled + ? null + : (v) async { + if (_videoPlayerController.value.duration > + Duration.zero && + _wasPlaying) { await _lock.synchronized(() async { await _videoPlayerController - .pause() + .play() .catchError((e) { - logger.e('Error pausing video: $e'); + logger.e('Error playing video: $e'); }); }); setState(() {}); } - } - }, - onChanged: !controlsEnabled - ? null - : (v) async { - setState(() { - final milliseconds = v.toInt(); - - if (_videoPlayerController.value.duration > - Duration.zero) { - _videoPlayerController.seekTo( - Duration(milliseconds: milliseconds)); - } - }); - }, - onChangeEnd: !controlsEnabled - ? null - : (v) async { - if (_videoPlayerController.value.duration > - Duration.zero && - _wasPlaying) { - await _lock.synchronized(() async { - await _videoPlayerController - .play() - .catchError((e) { - logger.e('Error playing video: $e'); - }); - }); - setState(() {}); - } - })), - const SizedBox(height: 4), - Row( - children: [ - Text(currentTime), - const Expanded(child: SizedBox.shrink()), - Text(duration) + }, + ), + ), + ), + ScreenTypeLayout.builder( + desktop: (context) => Row(children: [ + const SizedBox(width: 8), + Text(duration), + ]), + mobile: (context) => const SizedBox.shrink(), + ), ], ), - const SizedBox(height: 8), + const SizedBox(height: 4), + ScreenTypeLayout.builder( + mobile: (BuildContext context) => const SizedBox.shrink(), + desktop: (BuildContext context) { + if (widget.isSharePage) { + return const SizedBox.shrink(); + } + + return Column( + children: [ + Row( + children: [ + Text(currentTime), + const Expanded(child: SizedBox.shrink()), + Text(duration) + ], + ), + const SizedBox(height: 8), + ], + ); + }, + ), MouseRegion( onExit: (event) { setState(() { @@ -350,14 +391,36 @@ class _VideoPlayerWidgetState extends State child: Align( alignment: Alignment.centerLeft, child: ScreenTypeLayout.builder( - mobile: (context) => IconButton( - onPressed: !controlsEnabled - ? null - : () { - goFullScreen(); - }, - icon: const Icon(Icons.fullscreen_outlined, - size: 24)), + mobile: (context) { + if (widget.isSharePage) { + return IconButton( + onPressed: () { + _displaySpeedOptionsModal(context, (v) { + setState(() { + _videoPlayerController + .setPlaybackSpeed(v); + }); + }); + }, + icon: const Icon( + Icons.settings_outlined, + size: 24, + ), + ); + } else { + return IconButton( + onPressed: !controlsEnabled + ? null + : () { + goFullScreen(); + }, + icon: const Icon( + Icons.fullscreen_outlined, + size: 24, + ), + ); + } + }, desktop: (context) => VolumeSliderWidget( volume: _videoPlayerController.value.volume, setVolume: (v) { @@ -373,6 +436,20 @@ class _VideoPlayerWidgetState extends State }, ), ))), + if (widget.isSharePage) + ScreenTypeLayout.builder( + desktop: (context) => IconButton.outlined( + onPressed: () { + setState(() { + _videoPlayerController.seekTo( + _videoPlayerController.value.position - + const Duration(seconds: 10)); + }); + }, + icon: const Icon(Icons.replay_10, size: 24), + ), + mobile: (_) => const SizedBox.shrink(), + ), MaterialButton( onPressed: !controlsEnabled ? null @@ -424,6 +501,20 @@ class _VideoPlayerWidgetState extends State color: colors.themeFgOnAccent, )), ), + if (widget.isSharePage) + ScreenTypeLayout.builder( + desktop: (context) => IconButton.outlined( + onPressed: () { + setState(() { + _videoPlayerController.seekTo( + _videoPlayerController.value.position + + const Duration(seconds: 10)); + }); + }, + icon: const Icon(Icons.forward_10, size: 24), + ), + mobile: (context) => const SizedBox.shrink(), + ), Expanded( child: Align( alignment: Alignment.centerRight, @@ -431,41 +522,52 @@ class _VideoPlayerWidgetState extends State mainAxisAlignment: MainAxisAlignment.end, children: [ ScreenTypeLayout.builder( - desktop: (context) => MenuAnchor( - menuChildren: [ - ..._speedOptions.map((v) { - return ListTile( - tileColor: colors.themeBgSurface, - onTap: () { - setState(() { - _videoPlayerController - .setPlaybackSpeed(v); - _menuController.close(); - }); - }, - title: Text( - v == 1.0 - ? appLocalizationsOf(context) - .normal - : '$v', - style: ArDriveTypography.body - .buttonNormalBold( - color: colors - .themeFgDefault), - ), - ); - }) - ], - controller: _menuController, - child: IconButton( - onPressed: () { - _menuController.open(); + desktop: (context) => MenuAnchor( + menuChildren: [ + ..._speedOptions.map((v) { + return ListTile( + tileColor: colors.themeBgSurface, + onTap: () { + setState(() { + _videoPlayerController + .setPlaybackSpeed(v); + _menuController.close(); + }); + }, + title: Text( + v == 1.0 + ? appLocalizationsOf(context).normal + : '$v', + style: ArDriveTypography.body + .buttonNormalBold( + color: colors.themeFgDefault), + ), + ); + }) + ], + controller: _menuController, + child: IconButton( + onPressed: () { + _menuController.open(); + }, + icon: const Icon(Icons.settings_outlined, + size: 24)), + ), + mobile: (context) { + if (widget.isSharePage) { + return IconButton( + onPressed: !controlsEnabled + ? null + : () { + goFullScreen(); }, - icon: const Icon( - Icons.settings_outlined, - size: 24)), + icon: const Icon( + Icons.fullscreen_outlined, + size: 24, ), - mobile: (context) => IconButton( + ); + } else { + return IconButton( onPressed: () { _displaySpeedOptionsModal(context, (v) { setState(() { @@ -474,8 +576,14 @@ class _VideoPlayerWidgetState extends State }); }); }, - icon: const Icon(Icons.settings_outlined, - size: 24))), + icon: const Icon( + Icons.settings_outlined, + size: 24, + ), + ); + } + }, + ), ScreenTypeLayout.builder( desktop: (context) => IconButton( onPressed: !controlsEnabled @@ -508,16 +616,18 @@ class FullScreenVideoPlayerWidget extends StatefulWidget { final bool initialIsPlaying; final double initialVolume; final Function(Duration, bool, double) onClose; + final bool isSharePage; - const FullScreenVideoPlayerWidget( - {Key? key, - required this.filename, - required this.videoUrl, - required this.initialPosition, - required this.initialIsPlaying, - required this.initialVolume, - required this.onClose}) - : super(key: key); + const FullScreenVideoPlayerWidget({ + Key? key, + required this.filename, + required this.videoUrl, + required this.initialPosition, + required this.initialIsPlaying, + required this.initialVolume, + required this.onClose, + required this.isSharePage, + }) : super(key: key); @override // ignore: library_private_types_in_public_api @@ -816,7 +926,7 @@ class _FullScreenVideoPlayerWidgetState } }))), const SizedBox(width: 8), - Text(duration) + Text(duration), ], ), const SizedBox(height: 8), From e04a1cc6191bd1f4c81e146a676cbc8bf98ed4ab Mon Sep 17 00:00:00 2001 From: Mati Date: Thu, 2 Nov 2023 12:10:12 -0300 Subject: [PATCH 4/7] feat(preview widget): corrects the duplicate time indicators for video preview in drive explorer PE-4928 --- .../components/fs_entry_preview_widget.dart | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/pages/drive_detail/components/fs_entry_preview_widget.dart b/lib/pages/drive_detail/components/fs_entry_preview_widget.dart index dd952f22ca..d7e3985607 100644 --- a/lib/pages/drive_detail/components/fs_entry_preview_widget.dart +++ b/lib/pages/drive_detail/components/fs_entry_preview_widget.dart @@ -273,13 +273,14 @@ class _VideoPlayerWidgetState extends State const SizedBox(height: 8), Row( children: [ - ScreenTypeLayout.builder( - desktop: (context) => Row(children: [ - Text(currentTime), - const SizedBox(width: 8), - ]), - mobile: (context) => const SizedBox.shrink(), - ), + if (widget.isSharePage) + ScreenTypeLayout.builder( + desktop: (context) => Row(children: [ + Text(currentTime), + const SizedBox(width: 8), + ]), + mobile: (context) => const SizedBox.shrink(), + ), Expanded( child: SliderTheme( data: SliderThemeData( @@ -351,13 +352,14 @@ class _VideoPlayerWidgetState extends State ), ), ), - ScreenTypeLayout.builder( - desktop: (context) => Row(children: [ - const SizedBox(width: 8), - Text(duration), - ]), - mobile: (context) => const SizedBox.shrink(), - ), + if (widget.isSharePage) + ScreenTypeLayout.builder( + desktop: (context) => Row(children: [ + const SizedBox(width: 8), + Text(duration), + ]), + mobile: (context) => const SizedBox.shrink(), + ), ], ), const SizedBox(height: 4), From d547745a9b8f2a44231708ea4dc1a64d53150b98 Mon Sep 17 00:00:00 2001 From: Mati Date: Thu, 2 Nov 2023 12:38:06 -0300 Subject: [PATCH 5/7] feat(preview cubit): emit preview unavailable for non-file entities PE-4930 --- lib/blocs/fs_entry_preview/fs_entry_preview_cubit.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/blocs/fs_entry_preview/fs_entry_preview_cubit.dart b/lib/blocs/fs_entry_preview/fs_entry_preview_cubit.dart index e614a8bc10..b81c3556dd 100644 --- a/lib/blocs/fs_entry_preview/fs_entry_preview_cubit.dart +++ b/lib/blocs/fs_entry_preview/fs_entry_preview_cubit.dart @@ -206,6 +206,8 @@ class FsEntryPreviewCubit extends Cubit { } } }); + } else { + emit(FsEntryPreviewUnavailable()); } } else { emit(FsEntryPreviewUnavailable()); From a52dda05e9d8f9cdb7dece9e63d5d0d8d16277f2 Mon Sep 17 00:00:00 2001 From: Mati Date: Thu, 2 Nov 2023 15:37:27 -0300 Subject: [PATCH 6/7] feat(pubspec): before-release version bump PE-4934 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index cb54c1b090..3a537df30c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: Secure, permanent storage publish_to: 'none' -version: 2.23.0 +version: 2.24.0 environment: sdk: '>=3.0.2 <4.0.0' From 38d266366e755b647f7c1d4729f88d04a8ba2b40 Mon Sep 17 00:00:00 2001 From: Mati Date: Thu, 2 Nov 2023 15:58:47 -0300 Subject: [PATCH 7/7] feat(android release notes): before-release android release notes PE-4934 --- android/fastlane/metadata/android/en-US/changelogs/75.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 android/fastlane/metadata/android/en-US/changelogs/75.txt diff --git a/android/fastlane/metadata/android/en-US/changelogs/75.txt b/android/fastlane/metadata/android/en-US/changelogs/75.txt new file mode 100644 index 0000000000..f50f91450e --- /dev/null +++ b/android/fastlane/metadata/android/en-US/changelogs/75.txt @@ -0,0 +1,3 @@ +- Updates the design of video file previews in the share page. +- Updates the design of image file previews in the share page. +- Fixes the issue of attempting to show a preview for a folder.