1
0
mirror of https://github.com/immich-app/immich.git synced 2025-08-10 23:22:22 +02:00
Files
immich/mobile/lib/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart

130 lines
3.9 KiB
Dart
Raw Permalink Normal View History

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;
const BaseBottomSheet({
super.key,
required this.actions,
this.slivers,
this.controller,
this.initialChildSize = 0.35,
this.minChildSize = 0.15,
this.maxChildSize = 0.65,
this.expand = true,
this.shouldCloseOnMinExtent = true,
this.resizeOnScroll = true,
});
@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: context.colorScheme.surfaceContainerHigh,
surfaceTintColor: context.colorScheme.surfaceContainerHigh,
borderOnForeground: false,
clipBehavior: Clip.antiAlias,
elevation: 6.0,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(18)),
),
margin: const EdgeInsets.symmetric(horizontal: 0),
child: CustomScrollView(
controller: scrollController,
slivers: [
SliverToBoxAdapter(
child: Column(
children: [
const SizedBox(height: 10),
const _DragHandle(),
const SizedBox(height: 14),
if (widget.actions.isNotEmpty)
SizedBox(
height: 115,
child: ListView(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
children: widget.actions,
),
),
if (widget.actions.isNotEmpty) ...[
const Divider(indent: 16, endIndent: 16),
const SizedBox(height: 16),
],
],
),
),
...(widget.slivers ?? []),
],
),
);
},
);
}
}
class _DragHandle extends StatelessWidget {
const _DragHandle();
@override
Widget build(BuildContext context) {
return Container(
height: 6,
width: 32,
decoration: BoxDecoration(
color: context.themeData.dividerColor.lighten(amount: 0.6),
borderRadius: const BorderRadius.all(Radius.circular(20)),
),
);
}
}