diff --git a/dev/integration_tests/new_gallery/lib/data/demos.dart b/dev/integration_tests/new_gallery/lib/data/demos.dart index 3f63904662..c5fcabdbb0 100644 --- a/dev/integration_tests/new_gallery/lib/data/demos.dart +++ b/dev/integration_tests/new_gallery/lib/data/demos.dart @@ -26,8 +26,6 @@ import '../demos/reference/motion_demo_shared_y_axis_transition.dart'; import '../demos/reference/motion_demo_shared_z_axis_transition.dart'; import '../demos/reference/transformations_demo.dart' deferred as transformations_demo; -import '../demos/reference/two_pane_demo.dart' - deferred as twopane_demo; import '../demos/reference/typography_demo.dart' deferred as typography; import '../gallery_localizations.dart'; @@ -1158,54 +1156,6 @@ class Demos { static List otherDemos(GalleryLocalizations localizations) { return [ - GalleryDemo( - title: localizations.demoTwoPaneTitle, - icon: GalleryIcons.bottomSheetPersistent, - slug: 'two-pane', - subtitle: localizations.demoTwoPaneSubtitle, - configurations: [ - GalleryDemoConfiguration( - title: localizations.demoTwoPaneFoldableLabel, - description: localizations.demoTwoPaneFoldableDescription, - documentationUrl: - 'https://pub.dev/documentation/dual_screen/latest/dual_screen/TwoPane-class.html', - buildRoute: (_) => DeferredWidget( - twopane_demo.loadLibrary, - () => twopane_demo.TwoPaneDemo( - type: twopane_demo.TwoPaneDemoType.foldable, - restorationId: 'two_pane_foldable', - ), - ), - ), - GalleryDemoConfiguration( - title: localizations.demoTwoPaneTabletLabel, - description: localizations.demoTwoPaneTabletDescription, - documentationUrl: - 'https://pub.dev/documentation/dual_screen/latest/dual_screen/TwoPane-class.html', - buildRoute: (_) => DeferredWidget( - twopane_demo.loadLibrary, - () => twopane_demo.TwoPaneDemo( - type: twopane_demo.TwoPaneDemoType.tablet, - restorationId: 'two_pane_tablet', - ), - ), - ), - GalleryDemoConfiguration( - title: localizations.demoTwoPaneSmallScreenLabel, - description: localizations.demoTwoPaneSmallScreenDescription, - documentationUrl: - 'https://pub.dev/documentation/dual_screen/latest/dual_screen/TwoPane-class.html', - buildRoute: (_) => DeferredWidget( - twopane_demo.loadLibrary, - () => twopane_demo.TwoPaneDemo( - type: twopane_demo.TwoPaneDemoType.smallScreen, - restorationId: 'two_pane_single', - ), - ), - ), - ], - category: GalleryDemoCategory.other, - ), GalleryDemo( title: localizations.demoMotionTitle, icon: GalleryIcons.animation, diff --git a/dev/integration_tests/new_gallery/lib/demos/reference/two_pane_demo.dart b/dev/integration_tests/new_gallery/lib/demos/reference/two_pane_demo.dart deleted file mode 100644 index 894479b2c5..0000000000 --- a/dev/integration_tests/new_gallery/lib/demos/reference/two_pane_demo.dart +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright 2014 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:ui'; -import 'package:dual_screen/dual_screen.dart'; -import 'package:flutter/material.dart'; -import '../../gallery_localizations.dart'; - -// BEGIN twoPaneDemo - -enum TwoPaneDemoType { - foldable, - tablet, - smallScreen, -} - -class TwoPaneDemo extends StatefulWidget { - const TwoPaneDemo({ - super.key, - required this.restorationId, - required this.type, - }); - - final String restorationId; - final TwoPaneDemoType type; - - @override - TwoPaneDemoState createState() => TwoPaneDemoState(); -} - -class TwoPaneDemoState extends State with RestorationMixin { - final RestorableInt _currentIndex = RestorableInt(-1); - - @override - String get restorationId => widget.restorationId; - - @override - void restoreState(RestorationBucket? oldBucket, bool initialRestore) { - registerForRestoration(_currentIndex, 'two_pane_selected_item'); - } - - @override - void dispose() { - _currentIndex.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - TwoPanePriority panePriority = TwoPanePriority.both; - if (widget.type == TwoPaneDemoType.smallScreen) { - panePriority = _currentIndex.value == -1 - ? TwoPanePriority.start - : TwoPanePriority.end; - } - return SimulateScreen( - type: widget.type, - child: TwoPane( - paneProportion: 0.3, - panePriority: panePriority, - startPane: ListPane( - selectedIndex: _currentIndex.value, - onSelect: (int index) { - setState(() { - _currentIndex.value = index; - }); - }, - ), - endPane: DetailsPane( - selectedIndex: _currentIndex.value, - onClose: switch (widget.type) { - TwoPaneDemoType.smallScreen => () => setState(() { _currentIndex.value = -1; }), - TwoPaneDemoType.foldable || TwoPaneDemoType.tablet => null, - }, - ), - ), - ); - } -} - -class ListPane extends StatelessWidget { - - const ListPane({ - super.key, - required this.onSelect, - required this.selectedIndex, - }); - final ValueChanged onSelect; - final int selectedIndex; - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - automaticallyImplyLeading: false, - title: Text(GalleryLocalizations.of(context)!.demoTwoPaneList), - ), - body: Scrollbar( - child: ListView( - restorationId: 'list_demo_list_view', - padding: const EdgeInsets.symmetric(vertical: 8), - children: [ - for (int index = 1; index < 21; index++) - ListTile( - onTap: () { - onSelect(index); - }, - selected: selectedIndex == index, - leading: ExcludeSemantics( - child: CircleAvatar(child: Text('$index')), - ), - title: Text( - GalleryLocalizations.of(context)!.demoTwoPaneItem(index), - ), - ), - ], - ), - ), - ); - } -} - -class DetailsPane extends StatelessWidget { - - const DetailsPane({ - super.key, - required this.selectedIndex, - this.onClose, - }); - final VoidCallback? onClose; - final int selectedIndex; - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - automaticallyImplyLeading: false, - leading: onClose == null - ? null - : IconButton(icon: const Icon(Icons.close), onPressed: onClose), - title: Text( - GalleryLocalizations.of(context)!.demoTwoPaneDetails, - ), - ), - body: ColoredBox( - color: const Color(0xfffafafa), - child: Center( - child: Text( - selectedIndex == -1 - ? GalleryLocalizations.of(context)!.demoTwoPaneSelectItem - : GalleryLocalizations.of(context)! - .demoTwoPaneItemDetails(selectedIndex), - ), - ), - ), - ); - } -} - -class SimulateScreen extends StatelessWidget { - const SimulateScreen({ - super.key, - required this.type, - required this.child, - }); - - final TwoPaneDemoType type; - final TwoPane child; - - // An approximation of a real foldable - static const double foldableAspectRatio = 20 / 18; - // 16x9 candy bar phone - static const double singleScreenAspectRatio = 9 / 16; - // Taller desktop / tablet - static const double tabletAspectRatio = 4 / 3; - // How wide should the hinge be, as a proportion of total width - static const double hingeProportion = 1 / 35; - - @override - Widget build(BuildContext context) { - return Center( - child: Container( - decoration: BoxDecoration( - color: Colors.black, - borderRadius: BorderRadius.circular(16), - ), - padding: const EdgeInsets.all(14), - child: AspectRatio( - aspectRatio: switch (type) { - TwoPaneDemoType.foldable => foldableAspectRatio, - TwoPaneDemoType.tablet => tabletAspectRatio, - TwoPaneDemoType.smallScreen => singleScreenAspectRatio, - }, - child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) { - final Size size = Size(constraints.maxWidth, constraints.maxHeight); - final Size hingeSize = Size(size.width * hingeProportion, size.height); - // Position the hinge in the middle of the display - final Rect hingeBounds = Rect.fromLTWH( - (size.width - hingeSize.width) / 2, - 0, - hingeSize.width, - hingeSize.height, - ); - return MediaQuery( - data: MediaQueryData( - size: size, - displayFeatures: [ - if (type == TwoPaneDemoType.foldable) - DisplayFeature( - bounds: hingeBounds, - type: DisplayFeatureType.hinge, - state: DisplayFeatureState.postureFlat, - ), - ], - ), - child: child, - ); - }), - ), - ), - ); - } -} - -// END diff --git a/dev/integration_tests/new_gallery/lib/layout/adaptive.dart b/dev/integration_tests/new_gallery/lib/layout/adaptive.dart index 4e198508d8..283c018f35 100644 --- a/dev/integration_tests/new_gallery/lib/layout/adaptive.dart +++ b/dev/integration_tests/new_gallery/lib/layout/adaptive.dart @@ -2,10 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui'; - import 'package:adaptive_breakpoints/adaptive_breakpoints.dart'; -import 'package:dual_screen/dual_screen.dart'; import 'package:flutter/material.dart'; /// The maximum width taken up by each item on the home screen. @@ -13,14 +10,12 @@ const double maxHomeItemWidth = 1400.0; /// Returns a boolean value whether the window is considered medium or large size. /// -/// When running on a desktop device that is also foldable, the display is not -/// considered desktop. Widgets using this method might consider the display is +/// Widgets using this method might consider the display is /// large enough for certain layouts, which is not the case on foldable devices, /// where only part of the display is available to said widgets. /// /// Used to build adaptive and responsive layouts. bool isDisplayDesktop(BuildContext context) => - !isDisplayFoldable(context) && getWindowType(context) >= AdaptiveWindowType.medium; /// Returns boolean value whether the window is considered medium size. @@ -29,16 +24,3 @@ bool isDisplayDesktop(BuildContext context) => bool isDisplaySmallDesktop(BuildContext context) { return getWindowType(context) == AdaptiveWindowType.medium; } - -/// Returns a boolean value whether the display has a hinge that splits the -/// screen into two, left and right sub-screens. Horizontal splits (top and -/// bottom sub-screens) are ignored for this application. -bool isDisplayFoldable(BuildContext context) { - final DisplayFeature? hinge = MediaQuery.of(context).hinge; - if (hinge == null) { - return false; - } else { - // Vertical - return hinge.bounds.size.aspectRatio < 1; - } -} diff --git a/dev/integration_tests/new_gallery/lib/main.dart b/dev/integration_tests/new_gallery/lib/main.dart index 223135962c..315fe00b8f 100644 --- a/dev/integration_tests/new_gallery/lib/main.dart +++ b/dev/integration_tests/new_gallery/lib/main.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:dual_screen/dual_screen.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart' show timeDilation; @@ -50,7 +49,6 @@ class GalleryApp extends StatelessWidget { child: Builder( builder: (BuildContext context) { final GalleryOptions options = GalleryOptions.of(context); - final bool hasHinge = MediaQuery.of(context).hinge?.bounds != null; return MaterialApp( restorationScopeId: 'rootGallery', title: 'Flutter Gallery', @@ -74,7 +72,7 @@ class GalleryApp extends StatelessWidget { return basicLocaleListResolution(locales, supportedLocales); }, onGenerateRoute: (RouteSettings settings) => - RouteConfiguration.onGenerateRoute(settings, hasHinge), + RouteConfiguration.onGenerateRoute(settings), ); }, ), diff --git a/dev/integration_tests/new_gallery/lib/pages/demo.dart b/dev/integration_tests/new_gallery/lib/pages/demo.dart index 46ad1ecc25..937a1cb7be 100644 --- a/dev/integration_tests/new_gallery/lib/pages/demo.dart +++ b/dev/integration_tests/new_gallery/lib/pages/demo.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:dual_screen/dual_screen.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -188,13 +187,12 @@ class _GalleryDemoPageState extends State void _resolveState(BuildContext context) { final bool isDesktop = isDisplayDesktop(context); - final bool isFoldable = isDisplayFoldable(context); if (_DemoState.values[_demoStateIndex.value] == _DemoState.fullscreen && !isDesktop) { // Do not allow fullscreen state for mobile. _demoStateIndex.value = _DemoState.normal.index; } else if (_DemoState.values[_demoStateIndex.value] == _DemoState.normal && - (isDesktop || isFoldable)) { + isDesktop) { // Do not allow normal state for desktop. _demoStateIndex.value = _hasOptions ? _DemoState.options.index : _DemoState.info.index; @@ -209,7 +207,6 @@ class _GalleryDemoPageState extends State @override Widget build(BuildContext context) { - final bool isFoldable = isDisplayFoldable(context); final bool isDesktop = isDisplayDesktop(context); _resolveState(context); @@ -372,14 +369,6 @@ class _GalleryDemoPageState extends State child: sectionAndDemo, ), ); - } else if (isFoldable) { - body = Padding( - padding: const EdgeInsets.only(top: 12.0), - child: TwoPane( - startPane: demoContent, - endPane: section, - ), - ); } else { section = AnimatedSize( duration: const Duration(milliseconds: 200), @@ -429,7 +418,7 @@ class _GalleryDemoPageState extends State Widget page; - if (isDesktop || isFoldable) { + if (isDesktop) { page = AnimatedBuilder( animation: _codeBackgroundColorController, builder: (BuildContext context, Widget? child) { diff --git a/dev/integration_tests/new_gallery/lib/pages/home.dart b/dev/integration_tests/new_gallery/lib/pages/home.dart index 3f160ae6e5..0394acb2ff 100644 --- a/dev/integration_tests/new_gallery/lib/pages/home.dart +++ b/dev/integration_tests/new_gallery/lib/pages/home.dart @@ -1154,8 +1154,6 @@ class StudyWrapper extends StatefulWidget { class _StudyWrapperState extends State { @override Widget build(BuildContext context) { - final ColorScheme colorScheme = Theme.of(context).colorScheme; - final TextTheme textTheme = Theme.of(context).textTheme; return ApplyTextOptions( child: Stack( children: [ @@ -1166,47 +1164,8 @@ class _StudyWrapperState extends State { child: widget.study, ), ), - if (!isDisplayFoldable(context)) - SafeArea( - child: Align( - alignment: widget.alignment, - child: Padding( - padding: EdgeInsets.symmetric( - horizontal: 16.0, - vertical: widget.hasBottomNavBar - ? kBottomNavigationBarHeight + 16.0 - : 16.0), - child: Semantics( - sortKey: const OrdinalSortKey(0), - label: GalleryLocalizations.of(context)!.backToGallery, - button: true, - enabled: true, - excludeSemantics: true, - child: FloatingActionButton.extended( - heroTag: _BackButtonHeroTag(), - key: const ValueKey('Back'), - onPressed: () { - Navigator.of(context) - .popUntil((Route route) => route.settings.name == '/'); - }, - icon: IconTheme( - data: IconThemeData(color: colorScheme.onPrimary), - child: const BackButtonIcon(), - ), - label: Text( - MaterialLocalizations.of(context).backButtonTooltip, - style: textTheme.labelLarge! - .apply(color: colorScheme.onPrimary), - ), - ), - ), - ), - ), - ), ], ), ); } } - -class _BackButtonHeroTag {} diff --git a/dev/integration_tests/new_gallery/lib/pages/splash.dart b/dev/integration_tests/new_gallery/lib/pages/splash.dart index 898903503a..d7914048fa 100644 --- a/dev/integration_tests/new_gallery/lib/pages/splash.dart +++ b/dev/integration_tests/new_gallery/lib/pages/splash.dart @@ -4,11 +4,9 @@ import 'dart:math'; -import 'package:dual_screen/dual_screen.dart'; import 'package:flutter/material.dart'; import '../constants.dart'; -import '../gallery_localizations.dart'; import '../layout/adaptive.dart'; import 'home.dart'; @@ -145,36 +143,19 @@ class _SplashPageState extends State ); } - if (isDisplayFoldable(context)) { - return TwoPane( - startPane: frontLayer, - endPane: GestureDetector( - onTap: () { - if (_isSplashVisible) { - _controller.reverse(); - } else { - _controller.forward(); - } - }, - child: _SplashBackLayer( - isSplashCollapsed: !_isSplashVisible, effect: _effect), + return Stack( + children: [ + _SplashBackLayer( + isSplashCollapsed: !_isSplashVisible, + effect: _effect, + onTap: _controller.forward, ), - ); - } else { - return Stack( - children: [ - _SplashBackLayer( - isSplashCollapsed: !_isSplashVisible, - effect: _effect, - onTap: _controller.forward, - ), - PositionedTransition( - rect: animation, - child: frontLayer, - ), - ], - ); - } + PositionedTransition( + rect: animation, + child: frontLayer, + ), + ], + ); }, ), ), @@ -218,26 +199,6 @@ class _SplashBackLayer extends StatelessWidget { ), ); } - if (isDisplayFoldable(context)) { - child = ColoredBox( - color: Theme.of(context).colorScheme.background, - child: Stack( - children: [ - Center( - child: flutterLogo, - ), - Padding( - padding: const EdgeInsets.only(top: 100.0), - child: Center( - child: Text( - GalleryLocalizations.of(context)!.splashSelectDemo, - ), - ), - ) - ], - ), - ); - } } else { child = Stack( children: [ @@ -260,9 +221,7 @@ class _SplashBackLayer extends StatelessWidget { padding: EdgeInsets.only( bottom: isDisplayDesktop(context) ? homePeekDesktop - : isDisplayFoldable(context) - ? 0 - : homePeekMobile, + : homePeekMobile, ), child: child, ), diff --git a/dev/integration_tests/new_gallery/lib/routes.dart b/dev/integration_tests/new_gallery/lib/routes.dart index 06f5eb3672..d5cc07f1f0 100644 --- a/dev/integration_tests/new_gallery/lib/routes.dart +++ b/dev/integration_tests/new_gallery/lib/routes.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:dual_screen/dual_screen.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'deferred_widget.dart'; @@ -25,7 +24,7 @@ import 'studies/starter/routes.dart' as starter_app_routes; typedef PathWidgetBuilder = Widget Function(BuildContext, String?); class Path { - const Path(this.pattern, this.builder, {this.openInSecondScreen = false}); + const Path(this.pattern, this.builder); /// A RegEx string for route matching. final String pattern; @@ -41,9 +40,6 @@ class Path { /// ) /// ``` final PathWidgetBuilder builder; - - /// If the route should open on the second screen on foldables. - final bool openInSecondScreen; } class RouteConfiguration { @@ -63,7 +59,6 @@ class RouteConfiguration { study: DeferredWidget(rally.loadLibrary, () => rally.RallyApp()), // ignore: prefer_const_constructors ), - openInSecondScreen: true, ), Path( r'^' + shrine_routes.homeRoute, @@ -71,7 +66,6 @@ class RouteConfiguration { study: DeferredWidget(shrine.loadLibrary, () => shrine.ShrineApp()), // ignore: prefer_const_constructors ), - openInSecondScreen: true, ), Path( r'^' + crane_routes.defaultRoute, @@ -80,7 +74,6 @@ class RouteConfiguration { () => crane.CraneApp(), // ignore: prefer_const_constructors placeholder: const DeferredLoadingPlaceholder(name: 'Crane')), ), - openInSecondScreen: true, ), Path( r'^' + fortnightly_routes.defaultRoute, @@ -90,21 +83,18 @@ class RouteConfiguration { // ignore: prefer_const_constructors () => fortnightly.FortnightlyApp()), ), - openInSecondScreen: true, ), Path( r'^' + reply_routes.homeRoute, // ignore: prefer_const_constructors (BuildContext context, String? match) => const StudyWrapper(study: reply.ReplyApp(), hasBottomNavBar: true), - openInSecondScreen: true, ), Path( r'^' + starter_app_routes.defaultRoute, (BuildContext context, String? match) => const StudyWrapper( study: starter_app.StarterApp(), ), - openInSecondScreen: true, ), Path( r'^/', @@ -118,7 +108,6 @@ class RouteConfiguration { /// matching. static Route? onGenerateRoute( RouteSettings settings, - bool hasHinge, ) { for (final Path path in paths) { final RegExp regExpPattern = RegExp(path.pattern); @@ -131,17 +120,10 @@ class RouteConfiguration { settings: settings, ); } - if (path.openInSecondScreen && hasHinge) { - return TwoPanePageRoute( - builder: (BuildContext context) => path.builder(context, match), - settings: settings, - ); - } else { - return MaterialPageRoute( - builder: (BuildContext context) => path.builder(context, match), - settings: settings, - ); - } + return MaterialPageRoute( + builder: (BuildContext context) => path.builder(context, match), + settings: settings, + ); } } @@ -178,17 +160,7 @@ class TwoPanePageRoute extends OverlayRoute { @override Iterable createOverlayEntries() sync* { yield OverlayEntry(builder: (BuildContext context) { - final Rect? hinge = MediaQuery.of(context).hinge?.bounds; - if (hinge == null) { - return builder.call(context); - } else { - return Positioned( - top: 0, - left: hinge.right, - right: 0, - bottom: 0, - child: builder.call(context)); - } + return builder.call(context); }); } } diff --git a/dev/integration_tests/new_gallery/pubspec.yaml b/dev/integration_tests/new_gallery/pubspec.yaml index 99bb107ba8..a931c48101 100644 --- a/dev/integration_tests/new_gallery/pubspec.yaml +++ b/dev/integration_tests/new_gallery/pubspec.yaml @@ -16,7 +16,6 @@ dependencies: animations: 2.0.11 collection: 1.18.0 cupertino_icons: 1.0.8 - dual_screen: 1.0.4 flutter_gallery_assets: 1.0.2 flutter_localized_locales: 2.0.5 flutter_staggered_grid_view: 0.7.0 @@ -312,4 +311,4 @@ flutter: fonts: - asset: packages/flutter_gallery_assets/fonts/GalleryIcons.ttf -# PUBSPEC CHECKSUM: f270 +# PUBSPEC CHECKSUM: 579a