From c10eb9751144e33c01a1d4fe2127b6031cd4c023 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Tue, 13 Aug 2024 17:48:36 +0530 Subject: [PATCH] [mob][photos] Fix screen snapping when toggling to full screen when viewing items + imporve full screen UX on the new native video player --- mobile/lib/ui/viewer/file/detail_page.dart | 34 ++- .../lib/ui/viewer/file/file_bottom_bar.dart | 88 ++++---- .../ui/viewer/file/video_widget_native.dart | 209 +++++++++--------- 3 files changed, 171 insertions(+), 160 deletions(-) diff --git a/mobile/lib/ui/viewer/file/detail_page.dart b/mobile/lib/ui/viewer/file/detail_page.dart index 387ccd7de3..96d56f3a58 100644 --- a/mobile/lib/ui/viewer/file/detail_page.dart +++ b/mobile/lib/ui/viewer/file/detail_page.dart @@ -117,11 +117,19 @@ class _DetailPageState extends State { _pageController.dispose(); _enableFullScreenNotifier.dispose(); _selectedIndexNotifier.dispose(); - SystemChrome.setEnabledSystemUIMode( - SystemUiMode.manual, - overlays: SystemUiOverlay.values, - ); super.dispose(); + + SystemChrome.setSystemUIOverlayStyle( + const SystemUiOverlayStyle( + systemNavigationBarColor: Color(0x00010000), + ), + ); + + unawaited( + SystemChrome.setEnabledSystemUIMode( + SystemUiMode.edgeToEdge, + ), + ); } @override @@ -324,14 +332,20 @@ class _DetailPageState extends State { if (_enableFullScreenNotifier.value == shouldEnable) return; } _enableFullScreenNotifier.value = !_enableFullScreenNotifier.value; - - Future.delayed(const Duration(milliseconds: 125), () { + if (_enableFullScreenNotifier.value) { + Future.delayed(const Duration(milliseconds: 200), () { + SystemChrome.setEnabledSystemUIMode( + SystemUiMode.manual, + overlays: [], + ); + }); + } else { SystemChrome.setEnabledSystemUIMode( - //to hide status bar? - SystemUiMode.manual, - overlays: _enableFullScreenNotifier.value ? [] : SystemUiOverlay.values, + SystemUiMode.edgeToEdge, + overlays: SystemUiOverlay.values, ); - }); + } + // }); } Future _preloadEntries() async { diff --git a/mobile/lib/ui/viewer/file/file_bottom_bar.dart b/mobile/lib/ui/viewer/file/file_bottom_bar.dart index 3d04fee809..e7b6d0654b 100644 --- a/mobile/lib/ui/viewer/file/file_bottom_bar.dart +++ b/mobile/lib/ui/viewer/file/file_bottom_bar.dart @@ -76,7 +76,7 @@ class FileBottomBarState extends State { } } } - return _getBottomBar(); + return SafeArea(child: _getBottomBar()); } void safeRefresh() { @@ -95,7 +95,7 @@ class FileBottomBarState extends State { Tooltip( message: "Info", child: Padding( - padding: const EdgeInsets.only(top: 12, bottom: 12), + padding: const EdgeInsets.only(top: 12), child: IconButton( icon: Icon( Platform.isAndroid ? Icons.info_outline : CupertinoIcons.info, @@ -125,7 +125,7 @@ class FileBottomBarState extends State { Tooltip( message: "Edit", child: Padding( - padding: const EdgeInsets.only(top: 12, bottom: 12), + padding: const EdgeInsets.only(top: 12), child: IconButton( icon: const Icon( Icons.tune_outlined, @@ -144,7 +144,7 @@ class FileBottomBarState extends State { Tooltip( message: S.of(context).delete, child: Padding( - padding: const EdgeInsets.only(top: 12, bottom: 12), + padding: const EdgeInsets.only(top: 12), child: IconButton( icon: Icon( Platform.isAndroid @@ -165,7 +165,7 @@ class FileBottomBarState extends State { Tooltip( message: S.of(context).share, child: Padding( - padding: const EdgeInsets.only(top: 12, bottom: 12), + padding: const EdgeInsets.only(top: 12), child: IconButton( key: shareButtonKey, icon: Icon( @@ -182,7 +182,6 @@ class FileBottomBarState extends State { ), ); } - final safeAreaBottomPadding = MediaQuery.of(context).padding.bottom * .5; return ValueListenableBuilder( valueListenable: widget.enableFullScreenNotifier, builder: (BuildContext context, bool isFullScreen, _) { @@ -207,45 +206,42 @@ class FileBottomBarState extends State { stops: const [0, 0.8, 1], ), ), - child: Padding( - padding: EdgeInsets.only(bottom: safeAreaBottomPadding), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - widget.file.caption?.isNotEmpty ?? false - ? Padding( - padding: const EdgeInsets.fromLTRB( - 16, - 12, - 16, - 0, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + widget.file.caption?.isNotEmpty ?? false + ? Padding( + padding: const EdgeInsets.fromLTRB( + 16, + 12, + 16, + 0, + ), + child: GestureDetector( + onTap: () async { + await _displayDetails(widget.file); + await Future.delayed( + const Duration(milliseconds: 500), + ); //Waiting for some time till the caption gets updated in db if the user closes the bottom sheet without pressing 'done' + safeRefresh(); + }, + child: Text( + widget.file.caption!, + overflow: TextOverflow.ellipsis, + maxLines: 1, + style: getEnteTextTheme(context) + .mini + .copyWith(color: textBaseDark), + textAlign: TextAlign.center, ), - child: GestureDetector( - onTap: () async { - await _displayDetails(widget.file); - await Future.delayed( - const Duration(milliseconds: 500), - ); //Waiting for some time till the caption gets updated in db if the user closes the bottom sheet without pressing 'done' - safeRefresh(); - }, - child: Text( - widget.file.caption!, - overflow: TextOverflow.ellipsis, - maxLines: 1, - style: getEnteTextTheme(context) - .mini - .copyWith(color: textBaseDark), - textAlign: TextAlign.center, - ), - ), - ) - : const SizedBox.shrink(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: children, - ), - ], - ), + ), + ) + : const SizedBox.shrink(), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: children, + ), + ], ), ), ), @@ -268,7 +264,7 @@ class FileBottomBarState extends State { Tooltip( message: S.of(context).restore, child: Padding( - padding: const EdgeInsets.only(top: 12, bottom: 12), + padding: const EdgeInsets.only(top: 12), child: IconButton( icon: const Icon( Icons.restore_outlined, @@ -292,7 +288,7 @@ class FileBottomBarState extends State { Tooltip( message: S.of(context).delete, child: Padding( - padding: const EdgeInsets.only(top: 12, bottom: 12), + padding: const EdgeInsets.only(top: 12), child: IconButton( icon: const Icon( Icons.delete_forever_outlined, diff --git a/mobile/lib/ui/viewer/file/video_widget_native.dart b/mobile/lib/ui/viewer/file/video_widget_native.dart index 8a6d024dac..4a95465bc9 100644 --- a/mobile/lib/ui/viewer/file/video_widget_native.dart +++ b/mobile/lib/ui/viewer/file/video_widget_native.dart @@ -48,7 +48,7 @@ class VideoWidgetNative extends StatefulWidget { class _VideoWidgetNativeState extends State with WidgetsBindingObserver { final Logger _logger = Logger("VideoWidgetNative"); - static const verticalMargin = 72.0; + static const verticalMargin = 64.0; final _progressNotifier = ValueNotifier(null); late StreamSubscription pauseVideoSubscription; bool _isGuestView = false; @@ -192,9 +192,7 @@ class _VideoWidgetNativeState extends State behavior: HitTestBehavior.opaque, onTap: () { _showControls.value = !_showControls.value; - if (Platform.isIOS) { - widget.playbackCallback!(!_showControls.value); - } + widget.playbackCallback!(!_showControls.value); }, child: Container( constraints: const BoxConstraints.expand(), @@ -230,113 +228,118 @@ class _VideoWidgetNativeState extends State bottom: verticalMargin, right: 0, left: 0, - child: Padding( - padding: EdgeInsets.only( - bottom: widget.isFromMemories ? 32 : 0, - ), - child: ValueListenableBuilder( - builder: (BuildContext context, bool value, _) { - return value - ? ValueListenableBuilder( - valueListenable: _showControls, - builder: ( - BuildContext context, - bool value, - _, - ) { - return AnimatedOpacity( - duration: const Duration( - milliseconds: 200, - ), - curve: Curves.easeInQuad, - opacity: value ? 1 : 0, - child: IgnorePointer( - ignoring: !value, - child: Padding( - padding: - const EdgeInsets.symmetric( - horizontal: 8, - ), - child: Container( + child: SafeArea( + child: Padding( + padding: EdgeInsets.only( + bottom: widget.isFromMemories ? 32 : 0, + ), + child: ValueListenableBuilder( + builder: (BuildContext context, bool value, _) { + return value + ? ValueListenableBuilder( + valueListenable: _showControls, + builder: ( + BuildContext context, + bool value, + _, + ) { + return AnimatedOpacity( + duration: const Duration( + milliseconds: 200, + ), + curve: Curves.easeInQuad, + opacity: value ? 1 : 0, + child: IgnorePointer( + ignoring: !value, + child: Padding( padding: - const EdgeInsets.fromLTRB( - 16, - 4, - 16, - 4, + const EdgeInsets.symmetric( + horizontal: 8, ), - decoration: BoxDecoration( - color: Colors.black - .withOpacity(0.3), - borderRadius: - const BorderRadius.all( - Radius.circular(8), + child: Container( + padding: + const EdgeInsets.fromLTRB( + 16, + 4, + 16, + 4, ), - border: Border.all( - color: strokeFaintDark, - width: 1, - ), - ), - child: Row( - children: [ - AnimatedSize( - duration: const Duration( - seconds: 5, - ), - curve: Curves.easeInOut, - child: - ValueListenableBuilder( - valueListenable: - _controller! - .onPlaybackPositionChanged, - builder: ( - BuildContext context, - int value, - _, - ) { - return Text( - secondsToDuration( - value, - ), - style: - getEnteTextTheme( - context, - ).mini.copyWith( - color: - textBaseDark, - ), - ); - }, - ), + decoration: BoxDecoration( + color: Colors.black + .withOpacity(0.3), + borderRadius: + const BorderRadius.all( + Radius.circular(8), ), - Expanded( - child: SeekBar( - _controller!, - _durationToSeconds( - duration, + border: Border.all( + color: strokeFaintDark, + width: 1, + ), + ), + child: Row( + children: [ + AnimatedSize( + duration: + const Duration( + seconds: 5, + ), + curve: Curves.easeInOut, + child: + ValueListenableBuilder( + valueListenable: + _controller! + .onPlaybackPositionChanged, + builder: ( + BuildContext + context, + int value, + _, + ) { + return Text( + secondsToDuration( + value, + ), + style: + getEnteTextTheme( + context, + ).mini.copyWith( + color: + textBaseDark, + ), + ); + }, ), - _isSeeking, ), - ), - Text( - duration ?? "0:00", - style: getEnteTextTheme( - context, - ).mini.copyWith( - color: textBaseDark, + Expanded( + child: SeekBar( + _controller!, + _durationToSeconds( + duration, ), - ), - ], + _isSeeking, + ), + ), + Text( + duration ?? "0:00", + style: getEnteTextTheme( + context, + ).mini.copyWith( + color: + textBaseDark, + ), + ), + ], + ), ), ), ), - ), - ); - }, - ) - : const SizedBox(); - }, - valueListenable: _isPlaybackReady, + ); + }, + ) + : const SizedBox(); + }, + valueListenable: _isPlaybackReady, + ), ), ), ), @@ -417,9 +420,7 @@ class _VideoWidgetNativeState extends State return; } _showControls.value = false; - if (Platform.isIOS) { - widget.playbackCallback!(true); - } + widget.playbackCallback!(true); } }); }