Merge pull request #594 from ente-io/scroll_to_top
Scroll to top on doubleTap on homescreen
This commit is contained in:
commit
ceac771f67
|
@ -16,3 +16,9 @@ enum TabChangedEventSource {
|
|||
collectionsPage,
|
||||
backButton,
|
||||
}
|
||||
|
||||
class TabDoubleTapEvent extends Event {
|
||||
final int selectedIndex;
|
||||
|
||||
TabDoubleTapEvent(this.selectedIndex);
|
||||
}
|
||||
|
|
|
@ -66,6 +66,15 @@ class _HomeBottomNavigationBarState extends State<HomeBottomNavigationBar> {
|
|||
);
|
||||
}
|
||||
|
||||
void _onDoubleTap(int index) {
|
||||
debugPrint("doubleTap on tab $index");
|
||||
Bus.instance.fire(
|
||||
TabDoubleTapEvent(
|
||||
index,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final bool filesAreSelected = widget.selectedFiles.files.isNotEmpty;
|
||||
|
@ -132,6 +141,9 @@ class _HomeBottomNavigationBarState extends State<HomeBottomNavigationBar> {
|
|||
0,
|
||||
); // To take care of occasional missing events
|
||||
},
|
||||
onDoubleTap: () {
|
||||
_onDoubleTap(0);
|
||||
},
|
||||
),
|
||||
GButton(
|
||||
margin: const EdgeInsets.fromLTRB(10, 6, 10, 6),
|
||||
|
@ -142,7 +154,11 @@ class _HomeBottomNavigationBarState extends State<HomeBottomNavigationBar> {
|
|||
onPressed: () {
|
||||
_onTabChange(
|
||||
1,
|
||||
); // To take care of occasional missing events
|
||||
); // To take care of occasional missing
|
||||
// events
|
||||
},
|
||||
onDoubleTap: () {
|
||||
_onDoubleTap(1);
|
||||
},
|
||||
),
|
||||
GButton(
|
||||
|
@ -154,12 +170,17 @@ class _HomeBottomNavigationBarState extends State<HomeBottomNavigationBar> {
|
|||
onPressed: () {
|
||||
_onTabChange(
|
||||
2,
|
||||
); // To take care of occasional missing events
|
||||
); // To take care
|
||||
// of occasional missing events
|
||||
},
|
||||
onDoubleTap: () {
|
||||
_onDoubleTap(2);
|
||||
},
|
||||
),
|
||||
],
|
||||
selectedIndex: currentTabIndex,
|
||||
onTabChange: _onTabChange,
|
||||
onDoubleTap: _onDoubleTap,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -13,6 +13,7 @@ class GNav extends StatefulWidget {
|
|||
this.tabs,
|
||||
this.selectedIndex = 0,
|
||||
this.onTabChange,
|
||||
this.onDoubleTap,
|
||||
this.gap,
|
||||
this.padding,
|
||||
this.activeColor,
|
||||
|
@ -39,6 +40,7 @@ class GNav extends StatefulWidget {
|
|||
final List<GButton> tabs;
|
||||
final int selectedIndex;
|
||||
final Function onTabChange;
|
||||
final Function onDoubleTap;
|
||||
final double gap;
|
||||
final double tabBorderRadius;
|
||||
final double iconSize;
|
||||
|
@ -119,6 +121,9 @@ class _GNavState extends State<GNav> {
|
|||
widget.tabBackgroundColor ??
|
||||
Colors.transparent,
|
||||
duration: widget.duration ?? const Duration(milliseconds: 500),
|
||||
onDoubleTap: () {
|
||||
widget.onDoubleTap(widget.tabs.indexOf(t));
|
||||
},
|
||||
onPressed: () {
|
||||
if (!clickable) return;
|
||||
setState(() {
|
||||
|
@ -157,6 +162,7 @@ class GButton extends StatefulWidget {
|
|||
final TextStyle textStyle;
|
||||
final double iconSize;
|
||||
final Function onPressed;
|
||||
final Function onDoubleTap;
|
||||
final String text;
|
||||
final IconData icon;
|
||||
final Color backgroundColor;
|
||||
|
@ -192,6 +198,7 @@ class GButton extends StatefulWidget {
|
|||
this.iconSize,
|
||||
this.leading,
|
||||
this.onPressed,
|
||||
this.onDoubleTap,
|
||||
this.backgroundGradient,
|
||||
this.borderRadius,
|
||||
this.border,
|
||||
|
@ -222,6 +229,11 @@ class _GButtonState extends State<GButton> {
|
|||
if (widget.haptic) HapticFeedback.selectionClick();
|
||||
widget.onPressed();
|
||||
},
|
||||
onDoubleTap: () {
|
||||
if (widget.onDoubleTap != null) {
|
||||
widget.onDoubleTap();
|
||||
}
|
||||
},
|
||||
padding: widget.padding,
|
||||
margin: widget.margin,
|
||||
gap: widget.gap,
|
||||
|
@ -253,6 +265,7 @@ class Button extends StatefulWidget {
|
|||
this.rippleColor,
|
||||
this.hoverColor,
|
||||
this.onPressed,
|
||||
this.onDoubleTap,
|
||||
this.duration,
|
||||
this.curve,
|
||||
this.padding = const EdgeInsets.all(25),
|
||||
|
@ -279,6 +292,7 @@ class Button extends StatefulWidget {
|
|||
final bool active;
|
||||
final bool debug;
|
||||
final VoidCallback onPressed;
|
||||
final VoidCallback onDoubleTap;
|
||||
final EdgeInsetsGeometry padding;
|
||||
final EdgeInsetsGeometry margin;
|
||||
final Duration duration;
|
||||
|
@ -339,6 +353,11 @@ class _ButtonState extends State<Button> with TickerProviderStateMixin {
|
|||
onTap: () {
|
||||
widget.onPressed();
|
||||
},
|
||||
onDoubleTap: () {
|
||||
if (widget.onDoubleTap != null) {
|
||||
widget.onDoubleTap();
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
padding: widget.margin,
|
||||
child: AnimatedContainer(
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'package:photos/core/event_bus.dart';
|
|||
import 'package:photos/ente_theme_data.dart';
|
||||
import 'package:photos/events/event.dart';
|
||||
import 'package:photos/events/files_updated_event.dart';
|
||||
import 'package:photos/events/tab_changed_event.dart';
|
||||
import 'package:photos/models/file.dart';
|
||||
import 'package:photos/models/file_load_result.dart';
|
||||
import 'package:photos/models/selected_files.dart';
|
||||
|
@ -68,12 +69,16 @@ class _GalleryState extends State<Gallery> {
|
|||
Logger _logger;
|
||||
List<List<File>> _collatedFiles = [];
|
||||
bool _hasLoadedFiles = false;
|
||||
ItemScrollController _itemScroller;
|
||||
StreamSubscription<FilesUpdatedEvent> _reloadEventSubscription;
|
||||
StreamSubscription<TabDoubleTapEvent> _tabDoubleTapEvent;
|
||||
final _forceReloadEventSubscriptions = <StreamSubscription<Event>>[];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_logger = Logger("Gallery_" + widget.tagPrefix);
|
||||
_itemScroller = ItemScrollController();
|
||||
|
||||
_logger.info("initState");
|
||||
if (widget.reloadEvent != null) {
|
||||
_reloadEventSubscription = widget.reloadEvent.listen((event) async {
|
||||
|
@ -82,6 +87,14 @@ class _GalleryState extends State<Gallery> {
|
|||
_onFilesLoaded(result.files);
|
||||
});
|
||||
}
|
||||
_tabDoubleTapEvent =
|
||||
Bus.instance.on<TabDoubleTapEvent>().listen((event) async {
|
||||
// todo: Assign ID to Gallery and fire generic event with ID &
|
||||
// target index/date
|
||||
if (mounted && event.selectedIndex == 0) {
|
||||
_itemScroller.jumpTo(index: 0);
|
||||
}
|
||||
});
|
||||
if (widget.forceReloadEvents != null) {
|
||||
for (final event in widget.forceReloadEvents) {
|
||||
_forceReloadEventSubscriptions.add(
|
||||
|
@ -159,6 +172,7 @@ class _GalleryState extends State<Gallery> {
|
|||
@override
|
||||
void dispose() {
|
||||
_reloadEventSubscription?.cancel();
|
||||
_tabDoubleTapEvent?.cancel();
|
||||
for (final subscription in _forceReloadEventSubscriptions) {
|
||||
subscription.cancel();
|
||||
}
|
||||
|
@ -177,7 +191,7 @@ class _GalleryState extends State<Gallery> {
|
|||
Widget _getListView() {
|
||||
return HugeListView<List<File>>(
|
||||
key: _hugeListViewKey,
|
||||
controller: ItemScrollController(),
|
||||
controller: _itemScroller,
|
||||
startIndex: 0,
|
||||
totalCount: _collatedFiles.length,
|
||||
isDraggableScrollbarEnabled: _collatedFiles.length > 30,
|
||||
|
|
|
@ -1004,7 +1004,7 @@ packages:
|
|||
name: scrollable_positioned_list
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.3"
|
||||
version: "0.3.5"
|
||||
sentry:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -97,7 +97,7 @@ dependencies:
|
|||
provider: ^6.0.0
|
||||
quiver: ^3.0.1
|
||||
receive_sharing_intent: ^1.4.5
|
||||
scrollable_positioned_list: ^0.2.2
|
||||
scrollable_positioned_list: ^0.3.5
|
||||
sentry: ^6.12.1
|
||||
sentry_flutter: ^6.12.1
|
||||
share_plus: ^4.0.10
|
||||
|
|
Loading…
Reference in a new issue