From 3fce16c32944fdc57ae3e54d8c9f1483515596e1 Mon Sep 17 00:00:00 2001 From: Zachary Anderson Date: Thu, 12 Nov 2020 09:49:12 -0800 Subject: [PATCH] Revert "Default Keyboard ScrollActions with PrimaryScrollController (#69795)" (#70391) This reverts commit 1f0df54553bab852026a2801ce3921a2ba493fab. --- .../lib/src/cupertino/page_scaffold.dart | 15 ++- .../flutter/lib/src/material/scaffold.dart | 53 +++++----- .../widgets/primary_scroll_controller.dart | 13 --- packages/flutter/lib/src/widgets/routes.dart | 76 +++++++-------- .../flutter/lib/src/widgets/scroll_view.dart | 5 - .../flutter/lib/src/widgets/scrollable.dart | 27 +----- .../flutter/lib/src/widgets/shortcuts.dart | 2 +- .../src/widgets/single_child_scroll_view.dart | 5 - .../flutter/test/material/app_bar_test.dart | 61 +++++++----- .../flutter/test/material/debug_test.dart | 1 - .../flutter/test/material/scaffold_test.dart | 3 +- .../test/widgets/scroll_view_test.dart | 45 --------- .../flutter/test/widgets/scrollable_test.dart | 96 ++++++------------- 13 files changed, 141 insertions(+), 261 deletions(-) diff --git a/packages/flutter/lib/src/cupertino/page_scaffold.dart b/packages/flutter/lib/src/cupertino/page_scaffold.dart index 032b82c5e4..19e96de1d8 100644 --- a/packages/flutter/lib/src/cupertino/page_scaffold.dart +++ b/packages/flutter/lib/src/cupertino/page_scaffold.dart @@ -12,12 +12,6 @@ import 'theme.dart'; /// The scaffold lays out the navigation bar on top and the content between or /// behind the navigation bar. /// -/// When tapping a status bar at the top of the CupertinoPageScaffold, an -/// animation will complete for the current primary [ScrollView], scrolling to -/// the beginning. This is done using the [PrimaryScrollController] that -/// encloses the [ScrollView]. The [ScrollView.primary] flag is used to connect -/// a [ScrollView] to the enclosing [PrimaryScrollController]. -/// /// See also: /// /// * [CupertinoTabScaffold], a similar widget for tabbed applications. @@ -81,11 +75,11 @@ class CupertinoPageScaffold extends StatefulWidget { } class _CupertinoPageScaffoldState extends State { + final ScrollController _primaryScrollController = ScrollController(); void _handleStatusBarTap() { - final ScrollController? _primaryScrollController = PrimaryScrollController.of(context); // Only act on the scroll controller if it has any attached scroll positions. - if (_primaryScrollController != null && _primaryScrollController.hasClients) { + if (_primaryScrollController.hasClients) { _primaryScrollController.animateTo( 0.0, // Eyeballed from iOS. @@ -169,7 +163,10 @@ class _CupertinoPageScaffoldState extends State { child: Stack( children: [ // The main content being at the bottom is added to the stack first. - paddedContent, + PrimaryScrollController( + controller: _primaryScrollController, + child: paddedContent, + ), if (widget.navigationBar != null) Positioned( top: 0.0, diff --git a/packages/flutter/lib/src/material/scaffold.dart b/packages/flutter/lib/src/material/scaffold.dart index e2ec6a8914..33b17643c0 100644 --- a/packages/flutter/lib/src/material/scaffold.dart +++ b/packages/flutter/lib/src/material/scaffold.dart @@ -2670,11 +2670,13 @@ class ScaffoldState extends State with TickerProviderStateMixin { // iOS FEATURES - status bar tap, back gesture // On iOS, tapping the status bar scrolls the app's primary scrollable to the - // top. We implement this by looking up the primary scroll controller and + // top. We implement this by providing a primary scroll controller and // scrolling it to the top when tapped. + + final ScrollController _primaryScrollController = ScrollController(); + void _handleStatusBarTap() { - final ScrollController? _primaryScrollController = PrimaryScrollController.of(context); - if (_primaryScrollController != null && _primaryScrollController.hasClients) { + if (_primaryScrollController.hasClients) { _primaryScrollController.animateTo( 0.0, duration: const Duration(milliseconds: 300), @@ -3158,27 +3160,30 @@ class ScaffoldState extends State with TickerProviderStateMixin { return _ScaffoldScope( hasDrawer: hasDrawer, geometryNotifier: _geometryNotifier, - child: Material( - color: widget.backgroundColor ?? themeData.scaffoldBackgroundColor, - child: AnimatedBuilder(animation: _floatingActionButtonMoveController, builder: (BuildContext context, Widget? child) { - return CustomMultiChildLayout( - children: children, - delegate: _ScaffoldLayout( - extendBody: _extendBody, - extendBodyBehindAppBar: widget.extendBodyBehindAppBar, - minInsets: minInsets, - minViewPadding: minViewPadding, - currentFloatingActionButtonLocation: _floatingActionButtonLocation!, - floatingActionButtonMoveAnimationProgress: _floatingActionButtonMoveController.value, - floatingActionButtonMotionAnimator: _floatingActionButtonAnimator, - geometryNotifier: _geometryNotifier, - previousFloatingActionButtonLocation: _previousFloatingActionButtonLocation!, - textDirection: textDirection, - isSnackBarFloating: isSnackBarFloating, - snackBarWidth: snackBarWidth, - ), - ); - }), + child: PrimaryScrollController( + controller: _primaryScrollController, + child: Material( + color: widget.backgroundColor ?? themeData.scaffoldBackgroundColor, + child: AnimatedBuilder(animation: _floatingActionButtonMoveController, builder: (BuildContext context, Widget? child) { + return CustomMultiChildLayout( + children: children, + delegate: _ScaffoldLayout( + extendBody: _extendBody, + extendBodyBehindAppBar: widget.extendBodyBehindAppBar, + minInsets: minInsets, + minViewPadding: minViewPadding, + currentFloatingActionButtonLocation: _floatingActionButtonLocation!, + floatingActionButtonMoveAnimationProgress: _floatingActionButtonMoveController.value, + floatingActionButtonMotionAnimator: _floatingActionButtonAnimator, + geometryNotifier: _geometryNotifier, + previousFloatingActionButtonLocation: _previousFloatingActionButtonLocation!, + textDirection: textDirection, + isSnackBarFloating: isSnackBarFloating, + snackBarWidth: snackBarWidth, + ), + ); + }), + ), ), ); } diff --git a/packages/flutter/lib/src/widgets/primary_scroll_controller.dart b/packages/flutter/lib/src/widgets/primary_scroll_controller.dart index e42f37ef51..cb71d9eb9f 100644 --- a/packages/flutter/lib/src/widgets/primary_scroll_controller.dart +++ b/packages/flutter/lib/src/widgets/primary_scroll_controller.dart @@ -16,19 +16,6 @@ import 'scroll_controller.dart'; /// This mechanism can be used to provide default behavior for scroll views in a /// subtree. For example, the [Scaffold] uses this mechanism to implement the /// scroll-to-top gesture on iOS. -/// -/// Another default behavior handled by the PrimaryScrollController is default -/// [ScrollAction]s. If a ScrollAction is not handled by an otherwise focused -/// part of the application, the ScrollAction will be evaluated using the scroll -/// view associated with a PrimaryScrollController, for example, when executing -/// [Shortcuts] key events like page up and down. -/// -/// See also: -/// * [ScrollAction], an [Action] that scrolls the [Scrollable] that encloses -/// the current [primaryFocus] or is attached to the PrimaryScrollController. -/// * [Shortcuts], a widget that establishes a [ShortcutManager] to be used -/// by its descendants when invoking an [Action] via a keyboard key -/// combination that maps to an [Intent]. class PrimaryScrollController extends InheritedWidget { /// Creates a widget that associates a [ScrollController] with a subtree. const PrimaryScrollController({ diff --git a/packages/flutter/lib/src/widgets/routes.dart b/packages/flutter/lib/src/widgets/routes.dart index eb0bc278ad..b9a1591f05 100644 --- a/packages/flutter/lib/src/widgets/routes.dart +++ b/packages/flutter/lib/src/widgets/routes.dart @@ -18,9 +18,7 @@ import 'modal_barrier.dart'; import 'navigator.dart'; import 'overlay.dart'; import 'page_storage.dart'; -import 'primary_scroll_controller.dart'; import 'restoration.dart'; -import 'scroll_controller.dart'; import 'transitions.dart'; // Examples can assume: @@ -714,7 +712,6 @@ class _ModalScopeState extends State<_ModalScope> { /// The node this scope will use for its root [FocusScope] widget. final FocusScopeNode focusScopeNode = FocusScopeNode(debugLabel: '$_ModalScopeState Focus Scope'); - final ScrollController primaryScrollController = ScrollController(); @override void initState() { @@ -795,47 +792,44 @@ class _ModalScopeState extends State<_ModalScope> { bucket: widget.route._storageBucket, // immutable child: Actions( actions: _actionMap, - child: PrimaryScrollController( - controller: primaryScrollController, - child: FocusScope( - node: focusScopeNode, // immutable - child: RepaintBoundary( - child: AnimatedBuilder( - animation: _listenable, // immutable - builder: (BuildContext context, Widget? child) { - return widget.route.buildTransitions( - context, - widget.route.animation!, - widget.route.secondaryAnimation!, - // This additional AnimatedBuilder is include because if the - // value of the userGestureInProgressNotifier changes, it's - // only necessary to rebuild the IgnorePointer widget and set - // the focus node's ability to focus. - AnimatedBuilder( - animation: widget.route.navigator?.userGestureInProgressNotifier ?? ValueNotifier(false), - builder: (BuildContext context, Widget? child) { - final bool ignoreEvents = _shouldIgnoreFocusRequest; - focusScopeNode.canRequestFocus = !ignoreEvents; - return IgnorePointer( - ignoring: ignoreEvents, - child: child, - ); - }, - child: child, - ), - ); - }, - child: _page ??= RepaintBoundary( - key: widget.route._subtreeKey, // immutable - child: Builder( - builder: (BuildContext context) { - return widget.route.buildPage( - context, - widget.route.animation!, - widget.route.secondaryAnimation!, + child: FocusScope( + node: focusScopeNode, // immutable + child: RepaintBoundary( + child: AnimatedBuilder( + animation: _listenable, // immutable + builder: (BuildContext context, Widget? child) { + return widget.route.buildTransitions( + context, + widget.route.animation!, + widget.route.secondaryAnimation!, + // This additional AnimatedBuilder is include because if the + // value of the userGestureInProgressNotifier changes, it's + // only necessary to rebuild the IgnorePointer widget and set + // the focus node's ability to focus. + AnimatedBuilder( + animation: widget.route.navigator?.userGestureInProgressNotifier ?? ValueNotifier(false), + builder: (BuildContext context, Widget? child) { + final bool ignoreEvents = _shouldIgnoreFocusRequest; + focusScopeNode.canRequestFocus = !ignoreEvents; + return IgnorePointer( + ignoring: ignoreEvents, + child: child, ); }, + child: child, ), + ); + }, + child: _page ??= RepaintBoundary( + key: widget.route._subtreeKey, // immutable + child: Builder( + builder: (BuildContext context) { + return widget.route.buildPage( + context, + widget.route.animation!, + widget.route.secondaryAnimation!, + ); + }, ), ), ), diff --git a/packages/flutter/lib/src/widgets/scroll_view.dart b/packages/flutter/lib/src/widgets/scroll_view.dart index 0f9592e610..ee6f3123ae 100644 --- a/packages/flutter/lib/src/widgets/scroll_view.dart +++ b/packages/flutter/lib/src/widgets/scroll_view.dart @@ -149,11 +149,6 @@ abstract class ScrollView extends StatelessWidget { /// sufficient content to actually scroll. Otherwise, by default the user can /// only scroll the view if it has sufficient content. See [physics]. /// - /// Also when true, the scroll view is used for default [ScrollAction]s. If a - /// ScrollAction is not handled by an otherwise focused part of the application, - /// the ScrollAction will be evaluated using this scroll view, for example, - /// when executing [Shortcuts] key events like page up and down. - /// /// On iOS, this also identifies the scroll view that will scroll to top in /// response to a tap in the status bar. /// diff --git a/packages/flutter/lib/src/widgets/scrollable.dart b/packages/flutter/lib/src/widgets/scrollable.dart index 3b288f9a48..b8ec576df4 100644 --- a/packages/flutter/lib/src/widgets/scrollable.dart +++ b/packages/flutter/lib/src/widgets/scrollable.dart @@ -17,7 +17,6 @@ import 'focus_manager.dart'; import 'framework.dart'; import 'gesture_detector.dart'; import 'notification_listener.dart'; -import 'primary_scroll_controller.dart'; import 'restoration.dart'; import 'restoration_properties.dart'; import 'scroll_configuration.dart'; @@ -960,10 +959,6 @@ class ScrollIntent extends Intent { /// An [Action] that scrolls the [Scrollable] that encloses the current /// [primaryFocus] by the amount configured in the [ScrollIntent] given to it. /// -/// If a Scrollable cannot be found above the current [primaryFocus], the -/// [PrimaryScrollController] will be considered for default handling of -/// [ScrollAction]s. -/// /// If [Scrollable.incrementCalculator] is null for the scrollable, the default /// for a [ScrollIntent.type] set to [ScrollIncrementType.page] is 80% of the /// size of the scroll window, and for [ScrollIncrementType.line], 50 logical @@ -972,21 +967,7 @@ class ScrollAction extends Action { @override bool isEnabled(ScrollIntent intent) { final FocusNode? focus = primaryFocus; - final bool contextIsValid = focus != null && focus.context != null; - if (contextIsValid) { - // Check for primary scrollable within the current context - if (Scrollable.of(focus!.context!) != null) - return true; - // Check for fallback scrollable with context from PrimaryScrollController - if (PrimaryScrollController.of(focus.context!) != null) { - final ScrollController? primaryScrollController = PrimaryScrollController.of(focus.context!); - return primaryScrollController != null - && primaryScrollController.hasClients - && primaryScrollController.position.context.notificationContext != null - && Scrollable.of(primaryScrollController.position.context.notificationContext!) != null; - } - } - return false; + return focus != null && focus.context != null && Scrollable.of(focus.context!) != null; } // Returns the scroll increment for a single scroll request, for use when @@ -1070,11 +1051,7 @@ class ScrollAction extends Action { @override void invoke(ScrollIntent intent) { - ScrollableState? state = Scrollable.of(primaryFocus!.context!); - if (state == null) { - final ScrollController? primaryScrollController = PrimaryScrollController.of(primaryFocus!.context!); - state = Scrollable.of(primaryScrollController!.position.context.notificationContext!); - } + final ScrollableState? state = Scrollable.of(primaryFocus!.context!); assert(state != null, '$ScrollAction was invoked on a context that has no scrollable parent'); assert(state!.position.hasPixels, 'Scrollable must be laid out before it can be scrolled via a ScrollAction'); assert(state!.position.viewportDimension != null); diff --git a/packages/flutter/lib/src/widgets/shortcuts.dart b/packages/flutter/lib/src/widgets/shortcuts.dart index a56755e641..1ce5ae3918 100644 --- a/packages/flutter/lib/src/widgets/shortcuts.dart +++ b/packages/flutter/lib/src/widgets/shortcuts.dart @@ -382,7 +382,7 @@ class ShortcutManager extends ChangeNotifier with Diagnosticable { } } -/// A widget that establishes a [ShortcutManager] to be used by its descendants +/// A widget that establishes an [ShortcutManager] to be used by its descendants /// when invoking an [Action] via a keyboard key combination that maps to an /// [Intent]. /// diff --git a/packages/flutter/lib/src/widgets/single_child_scroll_view.dart b/packages/flutter/lib/src/widgets/single_child_scroll_view.dart index e72a91cb2d..b5d9617225 100644 --- a/packages/flutter/lib/src/widgets/single_child_scroll_view.dart +++ b/packages/flutter/lib/src/widgets/single_child_scroll_view.dart @@ -270,11 +270,6 @@ class SingleChildScrollView extends StatelessWidget { /// Whether this is the primary scroll view associated with the parent /// [PrimaryScrollController]. /// - /// When true, the scroll view is used for default [ScrollAction]s. If a - /// ScrollAction is not handled by an otherwise focused part of the application, - /// the ScrollAction will be evaluated using this scroll view, for example, - /// when executing [Shortcuts] key events like page up and down. - /// /// On iOS, this identifies the scroll view that will scroll to top in /// response to a tap in the status bar. /// diff --git a/packages/flutter/test/material/app_bar_test.dart b/packages/flutter/test/material/app_bar_test.dart index 73ec45dbe4..5af0cf6ce1 100644 --- a/packages/flutter/test/material/app_bar_test.dart +++ b/packages/flutter/test/material/app_bar_test.dart @@ -19,32 +19,43 @@ Widget buildSliverAppBarApp({ bool snap = false, double toolbarHeight = kToolbarHeight, }) { - return MaterialApp( - home: Scaffold( - body: DefaultTabController( - length: 3, - child: CustomScrollView( - primary: true, - slivers: [ - SliverAppBar( - title: const Text('AppBar Title'), - floating: floating, - pinned: pinned, - collapsedHeight: collapsedHeight, - expandedHeight: expandedHeight, - toolbarHeight: toolbarHeight, - snap: snap, - bottom: TabBar( - tabs: ['A','B','C'].map((String t) => Tab(text: 'TAB $t')).toList(), - ), + return Localizations( + locale: const Locale('en', 'US'), + delegates: const >[ + DefaultMaterialLocalizations.delegate, + DefaultWidgetsLocalizations.delegate, + ], + child: Directionality( + textDirection: TextDirection.ltr, + child: MediaQuery( + data: const MediaQueryData(), + child: Scaffold( + body: DefaultTabController( + length: 3, + child: CustomScrollView( + primary: true, + slivers: [ + SliverAppBar( + title: const Text('AppBar Title'), + floating: floating, + pinned: pinned, + collapsedHeight: collapsedHeight, + expandedHeight: expandedHeight, + toolbarHeight: toolbarHeight, + snap: snap, + bottom: TabBar( + tabs: ['A','B','C'].map((String t) => Tab(text: 'TAB $t')).toList(), + ), + ), + SliverToBoxAdapter( + child: Container( + height: 1200.0, + color: Colors.orange[400], + ), + ), + ], ), - SliverToBoxAdapter( - child: Container( - height: 1200.0, - color: Colors.orange[400], - ), - ), - ], + ), ), ), ), diff --git a/packages/flutter/test/material/debug_test.dart b/packages/flutter/test/material/debug_test.dart index 3eed0e81e1..5647ba9f86 100644 --- a/packages/flutter/test/material/debug_test.dart +++ b/packages/flutter/test/material/debug_test.dart @@ -135,7 +135,6 @@ void main() { ' _FocusMarker\n' ' Semantics\n' ' FocusScope\n' - ' PrimaryScrollController\n' ' _ActionsMarker\n' ' Actions\n' ' PageStorage\n' diff --git a/packages/flutter/test/material/scaffold_test.dart b/packages/flutter/test/material/scaffold_test.dart index 8675a63d1b..3abdd6f87e 100644 --- a/packages/flutter/test/material/scaffold_test.dart +++ b/packages/flutter/test/material/scaffold_test.dart @@ -2128,11 +2128,12 @@ void main() { ' AnimatedBuilder\n' ' DefaultTextStyle\n' ' AnimatedDefaultTextStyle\n' - ' _InkFeatures-[GlobalKey#00000 ink renderer]\n' + ' _InkFeatures-[GlobalKey#342d0 ink renderer]\n' ' NotificationListener\n' ' PhysicalModel\n' ' AnimatedPhysicalModel\n' ' Material\n' + ' PrimaryScrollController\n' ' _ScaffoldScope\n' ' Scaffold\n' ' MediaQuery\n' diff --git a/packages/flutter/test/widgets/scroll_view_test.dart b/packages/flutter/test/widgets/scroll_view_test.dart index 0fe2875203..5f89f3f3b6 100644 --- a/packages/flutter/test/widgets/scroll_view_test.dart +++ b/packages/flutter/test/widgets/scroll_view_test.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:flutter/services.dart' show LogicalKeyboardKey; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter/gestures.dart' show DragStartBehavior; @@ -1260,48 +1259,4 @@ void main() { semanticChildCount: 4, ), throwsAssertionError); }); - - testWidgets('PrimaryScrollController provides fallback ScrollActions', (WidgetTester tester) async { - await tester.pumpWidget( - MaterialApp( - home: CustomScrollView( - primary: true, - slivers: List.generate( - 20, - (int index) { - return SliverToBoxAdapter( - child: Focus( - autofocus: index == 0, - child: SizedBox(key: ValueKey('Box $index'), height: 50.0), - ), - ); - }, - ), - ), - ), - ); - final ScrollController controller = PrimaryScrollController.of( - tester.element(find.byType(CustomScrollView)) - )!; - await tester.pumpAndSettle(); - expect(controller.position.pixels, equals(0.0)); - expect( - tester.getRect(find.byKey(const ValueKey('Box 0'), skipOffstage: false)), - equals(const Rect.fromLTRB(0.0, 0.0, 800.0, 50.0)), - ); - await tester.sendKeyEvent(LogicalKeyboardKey.pageDown); - await tester.pumpAndSettle(); - expect(controller.position.pixels, equals(400.0)); - expect( - tester.getRect(find.byKey(const ValueKey('Box 0'), skipOffstage: false)), - equals(const Rect.fromLTRB(0.0, -400.0, 800.0, -350.0)), - ); - await tester.sendKeyEvent(LogicalKeyboardKey.pageUp); - await tester.pumpAndSettle(); - expect(controller.position.pixels, equals(0.0)); - expect( - tester.getRect(find.byKey(const ValueKey('Box 0'), skipOffstage: false)), - equals(const Rect.fromLTRB(0.0, 0.0, 800.0, 50.0)), - ); - }); } diff --git a/packages/flutter/test/widgets/scrollable_test.dart b/packages/flutter/test/widgets/scrollable_test.dart index 0fe718e777..a474e9a1dd 100644 --- a/packages/flutter/test/widgets/scrollable_test.dart +++ b/packages/flutter/test/widgets/scrollable_test.dart @@ -521,20 +521,14 @@ void main() { await tester.pumpAndSettle(); expect(controller.position.pixels, equals(0.0)); expect(tester.getRect(find.byKey(const ValueKey('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 0.0, 800.0, 50.0))); - // We exclude the modifier keys here for web testing since default web shortcuts - // do not use a modifier key with arrow keys for ScrollActions. - if (!kIsWeb) - await tester.sendKeyDownEvent(modifierKey); + await tester.sendKeyDownEvent(modifierKey); await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown); - if (!kIsWeb) - await tester.sendKeyUpEvent(modifierKey); + await tester.sendKeyUpEvent(modifierKey); await tester.pumpAndSettle(); expect(tester.getRect(find.byKey(const ValueKey('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, -50.0, 800.0, 0.0))); - if (!kIsWeb) - await tester.sendKeyDownEvent(modifierKey); + await tester.sendKeyDownEvent(modifierKey); await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp); - if (!kIsWeb) - await tester.sendKeyUpEvent(modifierKey); + await tester.sendKeyUpEvent(modifierKey); await tester.pumpAndSettle(); expect(tester.getRect(find.byKey(const ValueKey('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 0.0, 800.0, 50.0))); await tester.sendKeyEvent(LogicalKeyboardKey.pageDown); @@ -543,7 +537,7 @@ void main() { await tester.sendKeyEvent(LogicalKeyboardKey.pageUp); await tester.pumpAndSettle(); expect(tester.getRect(find.byKey(const ValueKey('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 0.0, 800.0, 50.0))); - }); + }, skip: isBrowser); // https://github.com/flutter/flutter/issues/43694 testWidgets('Horizontal scrollables are scrolled when activated via keyboard.', (WidgetTester tester) async { final ScrollController controller = ScrollController(); @@ -573,23 +567,17 @@ void main() { await tester.pumpAndSettle(); expect(controller.position.pixels, equals(0.0)); expect(tester.getRect(find.byKey(const ValueKey('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 0.0, 50.0, 600.0))); - // We exclude the modifier keys here for web testing since default web shortcuts - // do not use a modifier key with arrow keys for ScrollActions. - if (!kIsWeb) - await tester.sendKeyDownEvent(modifierKey); + await tester.sendKeyDownEvent(modifierKey); await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight); - if (!kIsWeb) - await tester.sendKeyUpEvent(modifierKey); + await tester.sendKeyUpEvent(modifierKey); await tester.pumpAndSettle(); expect(tester.getRect(find.byKey(const ValueKey('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(-50.0, 0.0, 0.0, 600.0))); - if (!kIsWeb) - await tester.sendKeyDownEvent(modifierKey); + await tester.sendKeyDownEvent(modifierKey); await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft); - if (!kIsWeb) - await tester.sendKeyUpEvent(modifierKey); + await tester.sendKeyUpEvent(modifierKey); await tester.pumpAndSettle(); expect(tester.getRect(find.byKey(const ValueKey('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 0.0, 50.0, 600.0))); - }); + }, skip: isBrowser); // https://github.com/flutter/flutter/issues/43694 testWidgets('Horizontal scrollables are scrolled the correct direction in RTL locales.', (WidgetTester tester) async { final ScrollController controller = ScrollController(); @@ -622,23 +610,17 @@ void main() { await tester.pumpAndSettle(); expect(controller.position.pixels, equals(0.0)); expect(tester.getRect(find.byKey(const ValueKey('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(750.0, 0.0, 800.0, 600.0))); - // We exclude the modifier keys here for web testing since default web shortcuts - // do not use a modifier key with arrow keys for ScrollActions. - if (!kIsWeb) - await tester.sendKeyDownEvent(modifierKey); + await tester.sendKeyDownEvent(modifierKey); await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft); - if (!kIsWeb) - await tester.sendKeyUpEvent(modifierKey); + await tester.sendKeyUpEvent(modifierKey); await tester.pumpAndSettle(); expect(tester.getRect(find.byKey(const ValueKey('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(800.0, 0.0, 850.0, 600.0))); - if (!kIsWeb) - await tester.sendKeyDownEvent(modifierKey); + await tester.sendKeyDownEvent(modifierKey); await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight); - if (!kIsWeb) - await tester.sendKeyUpEvent(modifierKey); + await tester.sendKeyUpEvent(modifierKey); await tester.pumpAndSettle(); expect(tester.getRect(find.byKey(const ValueKey('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(750.0, 0.0, 800.0, 600.0))); - }); + }, skip: isBrowser); // https://github.com/flutter/flutter/issues/43694 testWidgets('Reversed vertical scrollables are scrolled when activated via keyboard.', (WidgetTester tester) async { final ScrollController controller = ScrollController(); @@ -670,20 +652,14 @@ void main() { await tester.pumpAndSettle(); expect(controller.position.pixels, equals(0.0)); expect(tester.getRect(find.byKey(const ValueKey('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 550.0, 800.0, 600.0))); - // We exclude the modifier keys here for web testing since default web shortcuts - // do not use a modifier key with arrow keys for ScrollActions. - if (!kIsWeb) - await tester.sendKeyDownEvent(modifierKey); + await tester.sendKeyDownEvent(modifierKey); await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp); - if (!kIsWeb) - await tester.sendKeyUpEvent(modifierKey); + await tester.sendKeyUpEvent(modifierKey); await tester.pumpAndSettle(); expect(tester.getRect(find.byKey(const ValueKey('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 600.0, 800.0, 650.0))); - if (!kIsWeb) - await tester.sendKeyDownEvent(modifierKey); + await tester.sendKeyDownEvent(modifierKey); await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown); - if (!kIsWeb) - await tester.sendKeyUpEvent(modifierKey); + await tester.sendKeyUpEvent(modifierKey); await tester.pumpAndSettle(); expect(tester.getRect(find.byKey(const ValueKey('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 550.0, 800.0, 600.0))); await tester.sendKeyEvent(LogicalKeyboardKey.pageUp); @@ -692,7 +668,7 @@ void main() { await tester.sendKeyEvent(LogicalKeyboardKey.pageDown); await tester.pumpAndSettle(); expect(tester.getRect(find.byKey(const ValueKey('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 550.0, 800.0, 600.0))); - }); + }, skip: isBrowser); // https://github.com/flutter/flutter/issues/43694 testWidgets('Reversed horizontal scrollables are scrolled when activated via keyboard.', (WidgetTester tester) async { final ScrollController controller = ScrollController(); @@ -725,22 +701,16 @@ void main() { await tester.pumpAndSettle(); expect(controller.position.pixels, equals(0.0)); expect(tester.getRect(find.byKey(const ValueKey('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(750.0, 0.0, 800.0, 600.00))); - // We exclude the modifier keys here for web testing since default web shortcuts - // do not use a modifier key with arrow keys for ScrollActions. - if (!kIsWeb) - await tester.sendKeyDownEvent(modifierKey); + await tester.sendKeyDownEvent(modifierKey); await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft); - if (!kIsWeb) - await tester.sendKeyUpEvent(modifierKey); + await tester.sendKeyUpEvent(modifierKey); await tester.pumpAndSettle(); expect(tester.getRect(find.byKey(const ValueKey('Box 0'), skipOffstage: false)), equals(const Rect.fromLTRB(800.0, 0.0, 850.0, 600.0))); - if (!kIsWeb) - await tester.sendKeyDownEvent(modifierKey); + await tester.sendKeyDownEvent(modifierKey); await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight); - if (!kIsWeb) - await tester.sendKeyUpEvent(modifierKey); + await tester.sendKeyUpEvent(modifierKey); await tester.pumpAndSettle(); - }); + }, skip: isBrowser); // https://github.com/flutter/flutter/issues/43694 testWidgets('Custom scrollables with a center sliver are scrolled when activated via keyboard.', (WidgetTester tester) async { final ScrollController controller = ScrollController(); @@ -777,30 +747,24 @@ void main() { expect(controller.position.pixels, equals(0.0)); expect(tester.getRect(find.byKey(const ValueKey('Item 10'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 0.0, 800.0, 100.0))); for (int i = 0; i < 10; ++i) { - // We exclude the modifier keys here for web testing since default web shortcuts - // do not use a modifier key with arrow keys for ScrollActions. - if (!kIsWeb) - await tester.sendKeyDownEvent(modifierKey); + await tester.sendKeyDownEvent(modifierKey); await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown); - if (!kIsWeb) - await tester.sendKeyUpEvent(modifierKey); + await tester.sendKeyUpEvent(modifierKey); await tester.pumpAndSettle(); } // Starts at #10 already, so doesn't work out to 500.0 because it hits bottom. expect(controller.position.pixels, equals(400.0)); expect(tester.getRect(find.byKey(const ValueKey('Item 10'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, -400.0, 800.0, -300.0))); for (int i = 0; i < 10; ++i) { - if (!kIsWeb) - await tester.sendKeyDownEvent(modifierKey); + await tester.sendKeyDownEvent(modifierKey); await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp); - if (!kIsWeb) - await tester.sendKeyUpEvent(modifierKey); + await tester.sendKeyUpEvent(modifierKey); await tester.pumpAndSettle(); } // Goes up two past "center" where it started, so negative. expect(controller.position.pixels, equals(-100.0)); expect(tester.getRect(find.byKey(const ValueKey('Item 10'), skipOffstage: false)), equals(const Rect.fromLTRB(0.0, 100.0, 800.0, 200.0))); - }); + }, skip: isBrowser); // https://github.com/flutter/flutter/issues/43694 testWidgets('Can recommendDeferredLoadingForContext - animation', (WidgetTester tester) async { final List widgetTracker = [];