From 67e4cce4c02d261572e6afd8ae81738384f4ec01 Mon Sep 17 00:00:00 2001 From: Pratik-canopas Date: Mon, 8 Apr 2024 10:26:24 +0530 Subject: [PATCH] Implement dismissible page --- .../components/download_require_view.dart | 14 +-- .../media_preview/media_preview_screen.dart | 85 +++---------------- style/lib/animations/dismissible_page.dart | 76 +++++++++++++++++ 3 files changed, 97 insertions(+), 78 deletions(-) create mode 100644 style/lib/animations/dismissible_page.dart diff --git a/app/lib/ui/flow/media_preview/components/download_require_view.dart b/app/lib/ui/flow/media_preview/components/download_require_view.dart index 61aafe8..13156c2 100644 --- a/app/lib/ui/flow/media_preview/components/download_require_view.dart +++ b/app/lib/ui/flow/media_preview/components/download_require_view.dart @@ -1,6 +1,7 @@ import 'package:data/models/media/media.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; import 'package:style/extensions/context_extensions.dart'; import '../../../../components/error_view.dart'; @@ -14,11 +15,14 @@ class DownloadRequireView extends StatelessWidget { child: Stack( alignment: Alignment.center, children: [ - Image.network( - height: double.infinity, - width: double.infinity, - media.thumbnailLink!, - fit: BoxFit.cover, + Hero( + tag: media, + child: Image.network( + height: double.infinity, + width: double.infinity, + media.thumbnailLink!, + fit: BoxFit.cover, + ), ), Container( color: Colors.black38, diff --git a/app/lib/ui/flow/media_preview/media_preview_screen.dart b/app/lib/ui/flow/media_preview/media_preview_screen.dart index a0ab6a5..a69fcfe 100644 --- a/app/lib/ui/flow/media_preview/media_preview_screen.dart +++ b/app/lib/ui/flow/media_preview/media_preview_screen.dart @@ -17,6 +17,7 @@ import 'package:style/extensions/context_extensions.dart'; import 'package:style/indicators/circular_progress_indicator.dart'; import 'package:video_player/video_player.dart'; import 'components/video_player_components/video_duration_slider.dart'; +import 'package:style/animations/dismissible_page.dart'; class MediaPreview extends ConsumerStatefulWidget { final List medias; @@ -124,6 +125,7 @@ class _MediaPreviewState extends ConsumerState { ref.watch(_provider.select((state) => state.showActions)); return DismissiblePage( + backgroundColor: context.colorScheme.surface, onProgress: (progress) { if (progress > 0 && showActions) { notifier.toggleActionVisibility(); @@ -132,7 +134,10 @@ class _MediaPreviewState extends ConsumerState { onDismiss: () { context.pop(); }, - child: AppPage( + child: (progress) => AppPage( + backgroundColor: progress == 0 + ? context.colorScheme.surface + : Colors.transparent, body: Stack( children: [ GestureDetector( @@ -170,9 +175,12 @@ class _MediaPreviewState extends ConsumerState { color: context.colorScheme.onPrimary, ); } else { - return AspectRatio( - aspectRatio: _videoPlayerController!.value.aspectRatio, - child: VideoPlayer(_videoPlayerController!), + return Hero( + tag: media, + child: AspectRatio( + aspectRatio: _videoPlayerController!.value.aspectRatio, + child: VideoPlayer(_videoPlayerController!), + ), ); } }), @@ -256,72 +264,3 @@ class _MediaPreviewState extends ConsumerState { }); } -class DismissiblePage extends StatefulWidget { - final Widget child; - final double threshold; - final void Function(double progress)? onProgress; - final void Function()? onDismiss; - final double scaleDownPercentage; - - const DismissiblePage({ - Key? key, - required this.child, - this.threshold = 200, - this.onProgress, - this.onDismiss, - this.scaleDownPercentage = 0.25, - }) : super(key: key); - - @override - State createState() => _DismissiblePageState(); -} - -class _DismissiblePageState extends State { - double _startY = 0.0; - double displacement = 0.0; - double percentage = 0.0; - - @override - Widget build(BuildContext context) { - return GestureDetector( - onVerticalDragStart: (DragStartDetails details) { - _startY = details.globalPosition.dy; - }, - onVerticalDragUpdate: (DragUpdateDetails details) { - if ((details.globalPosition.dy - _startY) > 0) { - setState(() { - displacement = details.globalPosition.dy - _startY; - percentage = (displacement / widget.threshold).clamp(0, 1); - }); - } - widget.onProgress?.call(percentage); - }, - onVerticalDragEnd: (DragEndDetails details) { - if (displacement > widget.threshold) { - widget.onDismiss?.call(); - } else { - setState(() { - displacement = 0.0; - percentage = 0.0; - }); - } - }, - child: Stack( - children: [ - Container( - color: Colors.black.withOpacity(1 - percentage), - height: double.infinity, - width: double.infinity, - ), - Transform.translate( - offset: Offset(0, displacement), - child: Transform.scale( - scale: 1 - (percentage * widget.scaleDownPercentage), - child: widget.child, - ), - ), - ], - ), - ); - } -} diff --git a/style/lib/animations/dismissible_page.dart b/style/lib/animations/dismissible_page.dart new file mode 100644 index 0000000..cc77bc6 --- /dev/null +++ b/style/lib/animations/dismissible_page.dart @@ -0,0 +1,76 @@ +import 'package:flutter/cupertino.dart'; + +class DismissiblePage extends StatefulWidget { + final Widget Function(double progress) child; + final double threshold; + final Color backgroundColor; + final bool enable; + final void Function(double progress)? onProgress; + final void Function()? onDismiss; + final double scaleDownPercentage; + + const DismissiblePage({ + Key? key, + required this.child, + this.threshold = 100, + this.onProgress, + this.enable = true, + this.onDismiss, + this.scaleDownPercentage = 0.25, + this.backgroundColor = const Color(0xff000000), + }) : super(key: key); + + @override + State createState() => _DismissiblePageState(); +} + +class _DismissiblePageState extends State { + double _startY = 0.0; + double displacement = 0.0; + double percentage = 0.0; + + @override + Widget build(BuildContext context) { + return GestureDetector( + behavior: HitTestBehavior.opaque, + onVerticalDragStart: (DragStartDetails details) { + _startY = details.globalPosition.dy; + }, + onVerticalDragUpdate: (DragUpdateDetails details) { + if ((details.globalPosition.dy - _startY) > 0 && widget.enable) { + setState(() { + displacement = details.globalPosition.dy - _startY; + percentage = (displacement / widget.threshold).clamp(0, 1); + }); + widget.onProgress?.call(percentage); + } + }, + onVerticalDragEnd: (DragEndDetails details) { + if (displacement > widget.threshold) { + widget.onDismiss?.call(); + } else { + setState(() { + displacement = 0.0; + percentage = 0.0; + }); + } + }, + child: Stack( + children: [ + Container( + color: widget.backgroundColor.withOpacity(1 - percentage), + height: double.infinity, + width: double.infinity, + ), + Transform.translate( + offset: Offset(0, displacement), + child: Transform.scale( + scale: 1 - (percentage * widget.scaleDownPercentage), + child: widget.child(percentage), + ), + ), + ], + ), + ); + } +}