diff --git a/mobile/apps/photos/lib/ui/viewer/gallery/gallery.dart b/mobile/apps/photos/lib/ui/viewer/gallery/gallery.dart index 18dcdbe681..84c2bce479 100644 --- a/mobile/apps/photos/lib/ui/viewer/gallery/gallery.dart +++ b/mobile/apps/photos/lib/ui/viewer/gallery/gallery.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import "package:flutter/services.dart"; import 'package:logging/logging.dart'; import 'package:photos/core/constants.dart'; import 'package:photos/core/event_bus.dart'; @@ -136,6 +137,7 @@ class GalleryState extends State { } final miscUtil = MiscUtil(); + final scrollBarInUseNotifier = ValueNotifier(false); @override void initState() { @@ -429,6 +431,7 @@ class GalleryState extends State { } _debouncer.cancelDebounceTimer(); _scrollController.dispose(); + scrollBarInUseNotifier.dispose(); super.dispose(); } @@ -481,6 +484,7 @@ class GalleryState extends State { child: CustomScrollBar2( scrollController: _scrollController, galleryGroups: galleryGroups, + inUseNotifier: scrollBarInUseNotifier, child: Stack( key: _stackKey, clipBehavior: Clip.none, @@ -512,6 +516,7 @@ class GalleryState extends State { _sectionedListSliverRenderBoxYOffsetRelativeToStackRenderBox, selectedFiles: widget.selectedFiles, showSelectAllByDefault: widget.showSelectAllByDefault, + scrollbarInUseNotifier: scrollBarInUseNotifier, ), ], ), @@ -588,6 +593,7 @@ class PinnedGroupHeader extends StatefulWidget { getSectionedListSliverRenderBoxYOffsetRelativeToStackRenderBox; final SelectedFiles? selectedFiles; final bool showSelectAllByDefault; + final ValueNotifier scrollbarInUseNotifier; const PinnedGroupHeader({ required this.scrollController, @@ -595,6 +601,7 @@ class PinnedGroupHeader extends StatefulWidget { required this.getSectionedListSliverRenderBoxYOffsetRelativeToStackRenderBox, required this.selectedFiles, required this.showSelectAllByDefault, + required this.scrollbarInUseNotifier, super.key, }); @@ -672,6 +679,9 @@ class _PinnedGroupHeaderState extends State { } setState(() {}); + if (widget.scrollbarInUseNotifier.value) { + HapticFeedback.selectionClick(); + } } @override diff --git a/mobile/apps/photos/lib/ui/viewer/gallery/scrollbar/custom_scroll_bar_2.dart b/mobile/apps/photos/lib/ui/viewer/gallery/scrollbar/custom_scroll_bar_2.dart index 666c61b8a8..d4649ab870 100644 --- a/mobile/apps/photos/lib/ui/viewer/gallery/scrollbar/custom_scroll_bar_2.dart +++ b/mobile/apps/photos/lib/ui/viewer/gallery/scrollbar/custom_scroll_bar_2.dart @@ -10,11 +10,13 @@ class CustomScrollBar2 extends StatefulWidget { final Widget child; final ScrollController scrollController; final GalleryGroups galleryGroups; + final ValueNotifier inUseNotifier; const CustomScrollBar2({ super.key, required this.child, required this.scrollController, required this.galleryGroups, + required this.inUseNotifier, }); @override @@ -38,7 +40,6 @@ division and populate position to title mapping. class _CustomScrollBar2State extends State { final _logger = Logger("CustomScrollBar2"); final _key = GlobalKey(); - final inUseNotifier = ValueNotifier(false); List<({double position, String title})>? positionToTitleMap; static const _bottomPadding = 92.0; @@ -58,7 +59,6 @@ class _CustomScrollBar2State extends State { @override void dispose() { - inUseNotifier.dispose(); super.dispose(); } @@ -133,14 +133,14 @@ class _CustomScrollBar2State extends State { key: _key, controller: widget.scrollController, interactive: true, - inUseNotifier: inUseNotifier, + inUseNotifier: widget.inUseNotifier, child: widget.child, ), ), positionToTitleMap == null ? const SizedBox.shrink() : ValueListenableBuilder( - valueListenable: inUseNotifier, + valueListenable: widget.inUseNotifier, builder: (context, inUse, _) { return AnimatedSwitcher( duration: const Duration(milliseconds: 250),