mirror of
https://github.com/immich-app/immich.git
synced 2025-09-29 15:31:13 -04:00
* feat(mobile): drift map page * refactor: map query * perf: do not filter markers * fix: refresh timeline by key * chore: rename * remove ref listen and global key * clean code * remove locked and favorite * temporary change for stress test * optimizations * fix bottom sheet * cleaner bounds check * cleanup * feat: back button --------- Co-authored-by: wuzihao051119 <wuzihao051119@outlook.com> Co-authored-by: Alex <alex.tran1502@gmail.com>
144 lines
4.3 KiB
Dart
144 lines
4.3 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.surface,
|
|
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: [
|
|
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),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|