mirror of
				https://github.com/immich-app/immich.git
				synced 2025-10-31 10:37:11 -04:00 
			
		
		
		
	* fix: incorrect archive action shown in asset viewer' * Refactor * use enums syntax and add tests
		
			
				
	
	
		
			142 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import 'package:flutter/material.dart';
 | |
| import 'package:hooks_riverpod/hooks_riverpod.dart';
 | |
| import 'package:immich_mobile/extensions/build_context_extensions.dart';
 | |
| import 'package:immich_mobile/extensions/theme_extensions.dart';
 | |
| import 'package:immich_mobile/presentation/widgets/timeline/timeline.state.dart';
 | |
| 
 | |
| class BaseBottomSheet extends ConsumerStatefulWidget {
 | |
|   final List<Widget> actions;
 | |
|   final DraggableScrollableController? controller;
 | |
|   final List<Widget>? slivers;
 | |
|   final double initialChildSize;
 | |
|   final double minChildSize;
 | |
|   final double maxChildSize;
 | |
|   final bool expand;
 | |
|   final bool shouldCloseOnMinExtent;
 | |
|   final bool resizeOnScroll;
 | |
|   final Color? backgroundColor;
 | |
| 
 | |
|   const BaseBottomSheet({
 | |
|     super.key,
 | |
|     required this.actions,
 | |
|     this.slivers,
 | |
|     this.controller,
 | |
|     this.initialChildSize = 0.35,
 | |
|     double? minChildSize,
 | |
|     this.maxChildSize = 0.65,
 | |
|     this.expand = true,
 | |
|     this.shouldCloseOnMinExtent = true,
 | |
|     this.resizeOnScroll = true,
 | |
|     this.backgroundColor,
 | |
|   }) : minChildSize = minChildSize ?? 0.15;
 | |
| 
 | |
|   @override
 | |
|   ConsumerState<BaseBottomSheet> createState() => _BaseDraggableScrollableSheetState();
 | |
| }
 | |
| 
 | |
| class _BaseDraggableScrollableSheetState extends ConsumerState<BaseBottomSheet> {
 | |
|   late DraggableScrollableController _controller;
 | |
| 
 | |
|   @override
 | |
|   void initState() {
 | |
|     super.initState();
 | |
|     _controller = widget.controller ?? DraggableScrollableController();
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   Widget build(BuildContext context) {
 | |
|     ref.listen(timelineStateProvider, (previous, next) {
 | |
|       if (!widget.resizeOnScroll) {
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|       if (previous?.isInteracting != true && next.isInteracting) {
 | |
|         _controller.animateTo(
 | |
|           widget.minChildSize,
 | |
|           duration: const Duration(milliseconds: 200),
 | |
|           curve: Curves.easeInOut,
 | |
|         );
 | |
|       }
 | |
|     });
 | |
| 
 | |
|     return DraggableScrollableSheet(
 | |
|       controller: _controller,
 | |
|       initialChildSize: widget.initialChildSize,
 | |
|       minChildSize: widget.minChildSize,
 | |
|       maxChildSize: widget.maxChildSize,
 | |
|       snap: false,
 | |
|       expand: widget.expand,
 | |
|       shouldCloseOnMinExtent: widget.shouldCloseOnMinExtent,
 | |
|       builder: (BuildContext context, ScrollController scrollController) {
 | |
|         return Card(
 | |
|           color: widget.backgroundColor ?? context.colorScheme.surfaceContainer,
 | |
|           elevation: 3.0,
 | |
|           shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(18))),
 | |
|           margin: const EdgeInsets.symmetric(horizontal: 0),
 | |
|           child: CustomScrollView(
 | |
|             controller: scrollController,
 | |
|             slivers: [
 | |
|               const SliverPersistentHeader(delegate: _DragHandleDelegate(), pinned: true),
 | |
|               if (widget.actions.isNotEmpty)
 | |
|                 SliverToBoxAdapter(
 | |
|                   child: Column(
 | |
|                     children: [
 | |
|                       SizedBox(
 | |
|                         height: 115,
 | |
|                         child: ListView(shrinkWrap: true, scrollDirection: Axis.horizontal, children: widget.actions),
 | |
|                       ),
 | |
|                       const Divider(indent: 16, endIndent: 16),
 | |
|                       const SizedBox(height: 16),
 | |
|                     ],
 | |
|                   ),
 | |
|                 ),
 | |
|               if (widget.slivers != null) ...widget.slivers!,
 | |
|             ],
 | |
|           ),
 | |
|         );
 | |
|       },
 | |
|     );
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _DragHandleDelegate extends SliverPersistentHeaderDelegate {
 | |
|   const _DragHandleDelegate();
 | |
| 
 | |
|   @override
 | |
|   Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
 | |
|     return const _DragHandle();
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   bool shouldRebuild(_DragHandleDelegate oldDelegate) => false;
 | |
| 
 | |
|   @override
 | |
|   double get minExtent => 50.0;
 | |
| 
 | |
|   @override
 | |
|   double get maxExtent => 50.0;
 | |
| }
 | |
| 
 | |
| class _DragHandle extends StatelessWidget {
 | |
|   const _DragHandle();
 | |
| 
 | |
|   @override
 | |
|   Widget build(BuildContext context) {
 | |
|     return SizedBox(
 | |
|       height: 50,
 | |
|       child: Center(
 | |
|         child: SizedBox(
 | |
|           width: 32,
 | |
|           height: 6,
 | |
|           child: DecoratedBox(
 | |
|             decoration: BoxDecoration(
 | |
|               borderRadius: const BorderRadius.all(Radius.circular(20)),
 | |
|               color: context.themeData.dividerColor.lighten(amount: 0.6),
 | |
|             ),
 | |
|           ),
 | |
|         ),
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| }
 |