Kate Lovett 9d96df2364
Modernize framework lints (#179089)
WIP

Commits separated as follows:
- Update lints in analysis_options files
- Run `dart fix --apply`
- Clean up leftover analysis issues 
- Run `dart format .` in the right places.

Local analysis and testing passes. Checking CI now.

Part of https://github.com/flutter/flutter/issues/178827
- Adoption of flutter_lints in examples/api coming in a separate change
(cc @loic-sharma)

## Pre-launch Checklist

- [ ] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [ ] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [ ] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [ ] I signed the [CLA].
- [ ] I listed at least one issue that this PR fixes in the description
above.
- [ ] I updated/added relevant documentation (doc comments with `///`).
- [ ] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [ ] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [ ] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
2025-11-26 01:10:39 +00:00

588 lines
21 KiB
Dart

// 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 'package:flutter/material.dart';
import '../demo/all.dart';
import 'icons.dart';
@immutable
class GalleryDemoCategory {
const GalleryDemoCategory._({required this.name, required this.icon});
final String name;
final IconData icon;
@override
bool operator ==(Object other) {
if (identical(this, other)) {
return true;
}
if (other.runtimeType != runtimeType) {
return false;
}
return other is GalleryDemoCategory && other.name == name && other.icon == icon;
}
@override
int get hashCode => Object.hash(name, icon);
@override
String toString() {
return '$runtimeType($name)';
}
}
const GalleryDemoCategory _kDemos = GalleryDemoCategory._(
name: 'Studies',
icon: GalleryIcons.animation,
);
const GalleryDemoCategory _kStyle = GalleryDemoCategory._(
name: 'Style',
icon: GalleryIcons.custom_typography,
);
const GalleryDemoCategory _kMaterialComponents = GalleryDemoCategory._(
name: 'Material',
icon: GalleryIcons.category_mdc,
);
const GalleryDemoCategory _kCupertinoComponents = GalleryDemoCategory._(
name: 'Cupertino',
icon: GalleryIcons.phone_iphone,
);
const GalleryDemoCategory _kMedia = GalleryDemoCategory._(
name: 'Media',
icon: GalleryIcons.drive_video,
);
class GalleryDemo {
const GalleryDemo({
required this.title,
required this.icon,
this.subtitle,
required this.category,
required this.routeName,
this.documentationUrl,
required this.buildRoute,
});
final String title;
final IconData icon;
final String? subtitle;
final GalleryDemoCategory category;
final String routeName;
final WidgetBuilder buildRoute;
final String? documentationUrl;
@override
String toString() {
return '$runtimeType($title $routeName)';
}
}
List<GalleryDemo> _buildGalleryDemos() {
final galleryDemos = <GalleryDemo>[
// Demos
GalleryDemo(
title: 'Shrine',
subtitle: 'Basic shopping app',
icon: GalleryIcons.shrine,
category: _kDemos,
routeName: ShrineDemo.routeName,
buildRoute: (BuildContext context) => const ShrineDemo(),
),
GalleryDemo(
title: 'Fortnightly',
subtitle: 'Newspaper typography app',
icon: GalleryIcons.custom_typography,
category: _kDemos,
routeName: FortnightlyDemo.routeName,
buildRoute: (BuildContext context) => const FortnightlyDemo(),
),
GalleryDemo(
title: 'Contact profile',
subtitle: 'Address book entry with a flexible appbar',
icon: GalleryIcons.account_box,
category: _kDemos,
routeName: ContactsDemo.routeName,
buildRoute: (BuildContext context) => const ContactsDemo(),
),
GalleryDemo(
title: 'Animation',
subtitle: 'Section organizer',
icon: GalleryIcons.animation,
category: _kDemos,
routeName: AnimationDemo.routeName,
buildRoute: (BuildContext context) => const AnimationDemo(),
),
GalleryDemo(
title: '2D Transformations',
subtitle: 'Pan, Zoom, Rotate',
icon: GalleryIcons.grid_on,
category: _kDemos,
routeName: TransformationsDemo.routeName,
buildRoute: (BuildContext context) => const TransformationsDemo(),
),
GalleryDemo(
title: 'Pesto',
subtitle: 'Simple recipe browser',
icon: Icons.adjust,
category: _kDemos,
routeName: PestoDemo.routeName,
buildRoute: (BuildContext context) => const PestoDemo(),
),
// Style
GalleryDemo(
title: 'Colors',
subtitle: 'All of the predefined colors',
icon: GalleryIcons.colors,
category: _kStyle,
routeName: ColorsDemo.routeName,
buildRoute: (BuildContext context) => const ColorsDemo(),
),
GalleryDemo(
title: 'Typography',
subtitle: 'All of the predefined text styles',
icon: GalleryIcons.custom_typography,
category: _kStyle,
routeName: TypographyDemo.routeName,
buildRoute: (BuildContext context) => const TypographyDemo(),
),
// Material Components
GalleryDemo(
title: 'Backdrop',
subtitle: 'Select a front layer from back layer',
icon: GalleryIcons.backdrop,
category: _kMaterialComponents,
routeName: BackdropDemo.routeName,
buildRoute: (BuildContext context) => const BackdropDemo(),
),
GalleryDemo(
title: 'Banner',
subtitle: 'Displaying a banner within a list',
icon: GalleryIcons.lists_leave_behind,
category: _kMaterialComponents,
routeName: BannerDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/MaterialBanner-class.html',
buildRoute: (BuildContext context) => const BannerDemo(),
),
GalleryDemo(
title: 'Bottom app bar',
subtitle: 'Optional floating action button notch',
icon: GalleryIcons.bottom_app_bar,
category: _kMaterialComponents,
routeName: BottomAppBarDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/BottomAppBar-class.html',
buildRoute: (BuildContext context) => const BottomAppBarDemo(),
),
GalleryDemo(
title: 'Bottom navigation',
subtitle: 'Bottom navigation with cross-fading views',
icon: GalleryIcons.bottom_navigation,
category: _kMaterialComponents,
routeName: BottomNavigationDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/BottomNavigationBar-class.html',
buildRoute: (BuildContext context) => const BottomNavigationDemo(),
),
GalleryDemo(
title: 'Bottom sheet: Modal',
subtitle: 'A dismissible bottom sheet',
icon: GalleryIcons.bottom_sheets,
category: _kMaterialComponents,
routeName: ModalBottomSheetDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/showModalBottomSheet.html',
buildRoute: (BuildContext context) => const ModalBottomSheetDemo(),
),
GalleryDemo(
title: 'Bottom sheet: Persistent',
subtitle: 'A bottom sheet that sticks around',
icon: GalleryIcons.bottom_sheet_persistent,
category: _kMaterialComponents,
routeName: PersistentBottomSheetDemo.routeName,
documentationUrl:
'https://api.flutter.dev/flutter/material/ScaffoldState/showBottomSheet.html',
buildRoute: (BuildContext context) => const PersistentBottomSheetDemo(),
),
GalleryDemo(
title: 'Buttons',
subtitle: 'Flat, raised, dropdown, and more',
icon: GalleryIcons.generic_buttons,
category: _kMaterialComponents,
routeName: ButtonsDemo.routeName,
buildRoute: (BuildContext context) => const ButtonsDemo(),
),
GalleryDemo(
title: 'Buttons: Floating Action Button',
subtitle: 'FAB with transitions',
icon: GalleryIcons.buttons,
category: _kMaterialComponents,
routeName: TabsFabDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/FloatingActionButton-class.html',
buildRoute: (BuildContext context) => const TabsFabDemo(),
),
GalleryDemo(
title: 'Cards',
subtitle: 'Baseline cards with rounded corners',
icon: GalleryIcons.cards,
category: _kMaterialComponents,
routeName: CardsDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/Card-class.html',
buildRoute: (BuildContext context) => const CardsDemo(),
),
GalleryDemo(
title: 'Chips',
subtitle: 'Labeled with delete buttons and avatars',
icon: GalleryIcons.chips,
category: _kMaterialComponents,
routeName: ChipDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/Chip-class.html',
buildRoute: (BuildContext context) => const ChipDemo(),
),
GalleryDemo(
title: 'Data tables',
subtitle: 'Rows and columns',
icon: GalleryIcons.data_table,
category: _kMaterialComponents,
routeName: DataTableDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/PaginatedDataTable-class.html',
buildRoute: (BuildContext context) => const DataTableDemo(),
),
GalleryDemo(
title: 'Dialogs',
subtitle: 'Simple, alert, and fullscreen',
icon: GalleryIcons.dialogs,
category: _kMaterialComponents,
routeName: DialogDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/showDialog.html',
buildRoute: (BuildContext context) => const DialogDemo(),
),
GalleryDemo(
title: 'Elevations',
subtitle: 'Shadow values on cards',
// TODO(larche): Change to custom icon for elevations when one exists.
icon: GalleryIcons.cupertino_progress,
category: _kMaterialComponents,
routeName: ElevationDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/Material/elevation.html',
buildRoute: (BuildContext context) => const ElevationDemo(),
),
GalleryDemo(
title: 'Expand/collapse list control',
subtitle: 'A list with one sub-list level',
icon: GalleryIcons.expand_all,
category: _kMaterialComponents,
routeName: ExpansionTileListDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/ExpansionTile-class.html',
buildRoute: (BuildContext context) => const ExpansionTileListDemo(),
),
GalleryDemo(
title: 'Expansion panels',
subtitle: 'List of expanding panels',
icon: GalleryIcons.expand_all,
category: _kMaterialComponents,
routeName: ExpansionPanelsDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/ExpansionPanel-class.html',
buildRoute: (BuildContext context) => const ExpansionPanelsDemo(),
),
GalleryDemo(
title: 'Grid',
subtitle: 'Row and column layout',
icon: GalleryIcons.grid_on,
category: _kMaterialComponents,
routeName: GridListDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/widgets/GridView-class.html',
buildRoute: (BuildContext context) => const GridListDemo(),
),
GalleryDemo(
title: 'Icons',
subtitle: 'Enabled and disabled icons with opacity',
icon: GalleryIcons.sentiment_very_satisfied,
category: _kMaterialComponents,
routeName: IconsDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/IconButton-class.html',
buildRoute: (BuildContext context) => const IconsDemo(),
),
GalleryDemo(
title: 'Lists',
subtitle: 'Scrolling list layouts',
icon: GalleryIcons.list_alt,
category: _kMaterialComponents,
routeName: ListDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/ListTile-class.html',
buildRoute: (BuildContext context) => const ListDemo(),
),
GalleryDemo(
title: 'Lists: leave-behind list items',
subtitle: 'List items with hidden actions',
icon: GalleryIcons.lists_leave_behind,
category: _kMaterialComponents,
routeName: LeaveBehindDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/widgets/Dismissible-class.html',
buildRoute: (BuildContext context) => const LeaveBehindDemo(),
),
GalleryDemo(
title: 'Lists: reorderable',
subtitle: 'Reorderable lists',
icon: GalleryIcons.list_alt,
category: _kMaterialComponents,
routeName: ReorderableListDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/ReorderableListView-class.html',
buildRoute: (BuildContext context) => const ReorderableListDemo(),
),
GalleryDemo(
title: 'Menus',
subtitle: 'Menu buttons and simple menus',
icon: GalleryIcons.more_vert,
category: _kMaterialComponents,
routeName: MenuDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/PopupMenuButton-class.html',
buildRoute: (BuildContext context) => const MenuDemo(),
),
GalleryDemo(
title: 'Navigation drawer',
subtitle: 'Navigation drawer with standard header',
icon: GalleryIcons.menu,
category: _kMaterialComponents,
routeName: DrawerDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/Drawer-class.html',
buildRoute: (BuildContext context) => const DrawerDemo(),
),
GalleryDemo(
title: 'Pagination',
subtitle: 'PageView with indicator',
icon: GalleryIcons.page_control,
category: _kMaterialComponents,
routeName: PageSelectorDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/TabBarView-class.html',
buildRoute: (BuildContext context) => const PageSelectorDemo(),
),
GalleryDemo(
title: 'Pickers',
subtitle: 'Date and time selection widgets',
icon: GalleryIcons.event,
category: _kMaterialComponents,
routeName: DateAndTimePickerDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/showDatePicker.html',
buildRoute: (BuildContext context) => const DateAndTimePickerDemo(),
),
GalleryDemo(
title: 'Progress indicators',
subtitle: 'Linear, circular, indeterminate',
icon: GalleryIcons.progress_activity,
category: _kMaterialComponents,
routeName: ProgressIndicatorDemo.routeName,
documentationUrl:
'https://api.flutter.dev/flutter/material/LinearProgressIndicator-class.html',
buildRoute: (BuildContext context) => const ProgressIndicatorDemo(),
),
GalleryDemo(
title: 'Pull to refresh',
subtitle: 'Refresh indicators',
icon: GalleryIcons.refresh,
category: _kMaterialComponents,
routeName: OverscrollDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/RefreshIndicator-class.html',
buildRoute: (BuildContext context) => const OverscrollDemo(),
),
GalleryDemo(
title: 'Search',
subtitle: 'Expandable search',
icon: Icons.search,
category: _kMaterialComponents,
routeName: SearchDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/showSearch.html',
buildRoute: (BuildContext context) => const SearchDemo(),
),
GalleryDemo(
title: 'Selection controls',
subtitle: 'Checkboxes, radio buttons, and switches',
icon: GalleryIcons.check_box,
category: _kMaterialComponents,
routeName: SelectionControlsDemo.routeName,
buildRoute: (BuildContext context) => const SelectionControlsDemo(),
),
GalleryDemo(
title: 'Sliders',
subtitle: 'Widgets for selecting a value by swiping',
icon: GalleryIcons.sliders,
category: _kMaterialComponents,
routeName: SliderDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/Slider-class.html',
buildRoute: (BuildContext context) => const SliderDemo(),
),
GalleryDemo(
title: 'Snackbar',
subtitle: 'Temporary messaging',
icon: GalleryIcons.snackbar,
category: _kMaterialComponents,
routeName: SnackBarDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/ScaffoldState/showSnackBar.html',
buildRoute: (BuildContext context) => const SnackBarDemo(),
),
GalleryDemo(
title: 'Tabs',
subtitle: 'Tabs with independently scrollable views',
icon: GalleryIcons.tabs,
category: _kMaterialComponents,
routeName: TabsDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/TabBarView-class.html',
buildRoute: (BuildContext context) => const TabsDemo(),
),
GalleryDemo(
title: 'Tabs: Scrolling',
subtitle: 'Tab bar that scrolls',
category: _kMaterialComponents,
icon: GalleryIcons.tabs,
routeName: ScrollableTabsDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/TabBar-class.html',
buildRoute: (BuildContext context) => const ScrollableTabsDemo(),
),
GalleryDemo(
title: 'Text fields',
subtitle: 'Single line of editable text and numbers',
icon: GalleryIcons.text_fields_alt,
category: _kMaterialComponents,
routeName: TextFormFieldDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/TextFormField-class.html',
buildRoute: (BuildContext context) => const TextFormFieldDemo(),
),
GalleryDemo(
title: 'Tooltips',
subtitle: 'Short message displayed on long-press',
icon: GalleryIcons.tooltip,
category: _kMaterialComponents,
routeName: TooltipDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/material/Tooltip-class.html',
buildRoute: (BuildContext context) => const TooltipDemo(),
),
// Cupertino Components
GalleryDemo(
title: 'Activity Indicator',
icon: GalleryIcons.cupertino_progress,
category: _kCupertinoComponents,
routeName: CupertinoProgressIndicatorDemo.routeName,
documentationUrl:
'https://api.flutter.dev/flutter/cupertino/CupertinoActivityIndicator-class.html',
buildRoute: (BuildContext context) => const CupertinoProgressIndicatorDemo(),
),
GalleryDemo(
title: 'Alerts',
icon: GalleryIcons.dialogs,
category: _kCupertinoComponents,
routeName: CupertinoAlertDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/cupertino/showCupertinoDialog.html',
buildRoute: (BuildContext context) => const CupertinoAlertDemo(),
),
GalleryDemo(
title: 'Buttons',
icon: GalleryIcons.generic_buttons,
category: _kCupertinoComponents,
routeName: CupertinoButtonsDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/cupertino/CupertinoButton-class.html',
buildRoute: (BuildContext context) => const CupertinoButtonsDemo(),
),
GalleryDemo(
title: 'Navigation',
icon: GalleryIcons.bottom_navigation,
category: _kCupertinoComponents,
routeName: CupertinoNavigationDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/cupertino/CupertinoTabScaffold-class.html',
buildRoute: (BuildContext context) => CupertinoNavigationDemo(),
),
GalleryDemo(
title: 'Pickers',
icon: GalleryIcons.event,
category: _kCupertinoComponents,
routeName: CupertinoPickerDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/cupertino/CupertinoPicker-class.html',
buildRoute: (BuildContext context) => const CupertinoPickerDemo(),
),
GalleryDemo(
title: 'Pull to refresh',
icon: GalleryIcons.cupertino_pull_to_refresh,
category: _kCupertinoComponents,
routeName: CupertinoRefreshControlDemo.routeName,
documentationUrl:
'https://api.flutter.dev/flutter/cupertino/CupertinoSliverRefreshControl-class.html',
buildRoute: (BuildContext context) => const CupertinoRefreshControlDemo(),
),
GalleryDemo(
title: 'Segmented Control',
icon: GalleryIcons.tabs,
category: _kCupertinoComponents,
routeName: CupertinoSegmentedControlDemo.routeName,
documentationUrl:
'https://api.flutter.dev/flutter/cupertino/CupertinoSegmentedControl-class.html',
buildRoute: (BuildContext context) => const CupertinoSegmentedControlDemo(),
),
GalleryDemo(
title: 'Sliders',
icon: GalleryIcons.sliders,
category: _kCupertinoComponents,
routeName: CupertinoSliderDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/cupertino/CupertinoSlider-class.html',
buildRoute: (BuildContext context) => const CupertinoSliderDemo(),
),
GalleryDemo(
title: 'Switches',
icon: GalleryIcons.cupertino_switch,
category: _kCupertinoComponents,
routeName: CupertinoSwitchDemo.routeName,
documentationUrl: 'https://api.flutter.dev/flutter/cupertino/CupertinoSwitch-class.html',
buildRoute: (BuildContext context) => const CupertinoSwitchDemo(),
),
GalleryDemo(
title: 'Text Fields',
icon: GalleryIcons.text_fields_alt,
category: _kCupertinoComponents,
routeName: CupertinoTextFieldDemo.routeName,
buildRoute: (BuildContext context) => const CupertinoTextFieldDemo(),
),
// Media
GalleryDemo(
title: 'Animated images',
subtitle: 'GIF and WebP animations',
icon: GalleryIcons.animation,
category: _kMedia,
routeName: ImagesDemo.routeName,
buildRoute: (BuildContext context) => const ImagesDemo(),
),
GalleryDemo(
title: 'Video',
subtitle: 'Video playback',
icon: GalleryIcons.drive_video,
category: _kMedia,
routeName: VideoDemo.routeName,
buildRoute: (BuildContext context) => const VideoDemo(),
),
];
return galleryDemos;
}
final List<GalleryDemo> kAllGalleryDemos = _buildGalleryDemos();
final Set<GalleryDemoCategory> kAllGalleryDemoCategories = kAllGalleryDemos
.map<GalleryDemoCategory>((GalleryDemo demo) => demo.category)
.toSet();
final Map<GalleryDemoCategory, List<GalleryDemo>> kGalleryCategoryToDemos =
Map<GalleryDemoCategory, List<GalleryDemo>>.fromIterable(
kAllGalleryDemoCategories,
value: (dynamic category) {
return kAllGalleryDemos.where((GalleryDemo demo) => demo.category == category).toList();
},
);
final Map<String, String?> kDemoDocumentationUrl = <String, String?>{
for (final GalleryDemo demo in kAllGalleryDemos)
if (demo.documentationUrl != null) demo.routeName: demo.documentationUrl,
};