diff --git a/app/lib/features/geckoview/domain/providers/tab_session.dart b/app/lib/features/geckoview/domain/providers/tab_session.dart index 95a71bfc..88fea07a 100644 --- a/app/lib/features/geckoview/domain/providers/tab_session.dart +++ b/app/lib/features/geckoview/domain/providers/tab_session.dart @@ -106,6 +106,16 @@ class TabSession extends _$TabSession { return _sessionService.dispatchKeyEvent(keyCode: 93); } + Future scrollToTop() { + // Android KeyEvent.KEYCODE_MOVE_HOME = 122 + return _sessionService.dispatchKeyEvent(keyCode: 122); + } + + Future scrollToBottom() { + // Android KeyEvent.KEYCODE_MOVE_END = 123 + return _sessionService.dispatchKeyEvent(keyCode: 123); + } + @override void build({required String? tabId}) { _sessionService = (tabId != null) diff --git a/app/lib/features/geckoview/features/browser/features/contextual_toolbar/presentation/toolbar_button_registry.dart b/app/lib/features/geckoview/features/browser/features/contextual_toolbar/presentation/toolbar_button_registry.dart index d4f02d12..340785eb 100644 --- a/app/lib/features/geckoview/features/browser/features/contextual_toolbar/presentation/toolbar_button_registry.dart +++ b/app/lib/features/geckoview/features/browser/features/contextual_toolbar/presentation/toolbar_button_registry.dart @@ -353,6 +353,16 @@ final List toolbarButtonRegistry = [ .pageUp(); } }, + onLongPress: scope.isPreview + ? () {} + : () async { + final tabId = scope.selectedTabId; + if (tabId != null) { + await ref + .read(tabSessionProvider(tabId: tabId).notifier) + .scrollToTop(); + } + }, icon: const Icon(MdiIcons.chevronDoubleUp), ); }, @@ -373,6 +383,16 @@ final List toolbarButtonRegistry = [ .pageDown(); } }, + onLongPress: scope.isPreview + ? () {} + : () async { + final tabId = scope.selectedTabId; + if (tabId != null) { + await ref + .read(tabSessionProvider(tabId: tabId).notifier) + .scrollToBottom(); + } + }, icon: const Icon(MdiIcons.chevronDoubleDown), ); },