mirror of
https://github.com/flutter/samples.git
synced 2025-11-08 13:58:47 +00:00
Dart 3.9 / Flutter 3.35 [first LLM release] (#2714)
I got carried away with Gemini and basically rewrote CI and the release process for the new LLM reality. This work was largely completed by Gemini. - Bump all SDK versions to the current beta (3.9.0-0) - Run `flutter channel beta` - Wrote `ci_script.dart` to replace the bash scripts - Converted repository to pub workspace #2499 - Added llm.md and release.md - Added redirect for deprecated Samples Index ## Pre-launch Checklist - [x] I read the [Flutter Style Guide] _recently_, and have followed its advice. - [x] I signed the [CLA]. - [x] I read the [Contributors Guide]. - [x] I have added sample code updates to the [changelog]. - [x] I updated/added relevant documentation (doc comments with `///`).
This commit is contained in:
@@ -228,20 +228,22 @@ class _MyCascadingContextMenuState extends State<_MyCascadingContextMenu> {
|
||||
);
|
||||
widget.onToggleMessageVisibility();
|
||||
},
|
||||
shortcut: const SingleActivator(LogicalKeyboardKey.keyS, control: true),
|
||||
shortcut: const SingleActivator(
|
||||
LogicalKeyboardKey.keyS,
|
||||
control: true,
|
||||
),
|
||||
),
|
||||
// Hides the message, but is only enabled if the message isn't
|
||||
// already hidden.
|
||||
MenuEntry(
|
||||
label: 'Reset',
|
||||
onPressed:
|
||||
widget.showingMessage
|
||||
? () {
|
||||
ContextMenuController.removeAny();
|
||||
widget.onChangeSelection('Reset');
|
||||
widget.onToggleMessageVisibility();
|
||||
}
|
||||
: null,
|
||||
onPressed: widget.showingMessage
|
||||
? () {
|
||||
ContextMenuController.removeAny();
|
||||
widget.onChangeSelection('Reset');
|
||||
widget.onToggleMessageVisibility();
|
||||
}
|
||||
: null,
|
||||
shortcut: const SingleActivator(LogicalKeyboardKey.escape),
|
||||
),
|
||||
MenuEntry(
|
||||
|
||||
@@ -52,26 +52,27 @@ class CustomButtonsPage extends StatelessWidget {
|
||||
// Build the default buttons, but make them look custom.
|
||||
// Note that in a real project you may want to build
|
||||
// different buttons depending on the platform.
|
||||
children:
|
||||
editableTextState.contextMenuButtonItems.map((buttonItem) {
|
||||
return CupertinoButton(
|
||||
borderRadius: null,
|
||||
color: const Color(0xffaaaa00),
|
||||
disabledColor: const Color(0xffaaaaff),
|
||||
onPressed: buttonItem.onPressed,
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
pressedOpacity: 0.7,
|
||||
child: SizedBox(
|
||||
width: 200.0,
|
||||
child: Text(
|
||||
CupertinoTextSelectionToolbarButton.getButtonLabel(
|
||||
context,
|
||||
buttonItem,
|
||||
),
|
||||
),
|
||||
children: editableTextState.contextMenuButtonItems.map((
|
||||
buttonItem,
|
||||
) {
|
||||
return CupertinoButton(
|
||||
borderRadius: null,
|
||||
color: const Color(0xffaaaa00),
|
||||
disabledColor: const Color(0xffaaaaff),
|
||||
onPressed: buttonItem.onPressed,
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
pressedOpacity: 0.7,
|
||||
child: SizedBox(
|
||||
width: 200.0,
|
||||
child: Text(
|
||||
CupertinoTextSelectionToolbarButton.getButtonLabel(
|
||||
context,
|
||||
buttonItem,
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -47,11 +47,10 @@ class CustomMenuPage extends StatelessWidget {
|
||||
contextMenuBuilder: (context, editableTextState) {
|
||||
return _MyContextMenu(
|
||||
anchor: editableTextState.contextMenuAnchors.primaryAnchor,
|
||||
children:
|
||||
AdaptiveTextSelectionToolbar.getAdaptiveButtons(
|
||||
context,
|
||||
editableTextState.contextMenuButtonItems,
|
||||
).toList(),
|
||||
children: AdaptiveTextSelectionToolbar.getAdaptiveButtons(
|
||||
context,
|
||||
editableTextState.contextMenuButtonItems,
|
||||
).toList(),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -62,7 +62,11 @@ class DefaultValuesPage extends StatelessWidget {
|
||||
'This example simply shows what happens when contextMenuBuilder is given null, a custom value, or omitted altogether.',
|
||||
),
|
||||
const SizedBox(height: 40.0),
|
||||
TextField(maxLines: 2, minLines: 2, controller: _controllerNone),
|
||||
TextField(
|
||||
maxLines: 2,
|
||||
minLines: 2,
|
||||
controller: _controllerNone,
|
||||
),
|
||||
TextField(
|
||||
maxLines: 2,
|
||||
minLines: 2,
|
||||
|
||||
@@ -22,9 +22,8 @@ class EmailButtonPage extends StatelessWidget {
|
||||
DialogRoute _showDialog(BuildContext context) {
|
||||
return DialogRoute<void>(
|
||||
context: context,
|
||||
builder:
|
||||
(context) =>
|
||||
const AlertDialog(title: Text('You clicked send email!')),
|
||||
builder: (context) =>
|
||||
const AlertDialog(title: Text('You clicked send email!')),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -64,7 +63,9 @@ class EmailButtonPage extends StatelessWidget {
|
||||
editableTextState.textEditingValue;
|
||||
final List<ContextMenuButtonItem> buttonItems =
|
||||
editableTextState.contextMenuButtonItems;
|
||||
if (isValidEmail(value.selection.textInside(value.text))) {
|
||||
if (isValidEmail(
|
||||
value.selection.textInside(value.text),
|
||||
)) {
|
||||
buttonItems.insert(
|
||||
0,
|
||||
ContextMenuButtonItem(
|
||||
|
||||
@@ -26,16 +26,16 @@ class FieldTypesPage extends StatelessWidget {
|
||||
"CupertinoTextField can't show Material menus by default. On non-Apple platforms, you'll still see a Cupertino menu here.",
|
||||
);
|
||||
|
||||
final TextEditingController _cupertinoControllerFixed = TextEditingController(
|
||||
final TextEditingController
|
||||
_cupertinoControllerFixed = TextEditingController(
|
||||
text:
|
||||
"But CupertinoTextField can be made to adaptively show any menu. You'll see the correct menu for your platform here.",
|
||||
);
|
||||
|
||||
final TextEditingController _cupertinoControllerForced =
|
||||
TextEditingController(
|
||||
text:
|
||||
'Or forced to always show a specific menu (Material desktop menu).',
|
||||
);
|
||||
final TextEditingController
|
||||
_cupertinoControllerForced = TextEditingController(
|
||||
text: 'Or forced to always show a specific menu (Material desktop menu).',
|
||||
);
|
||||
|
||||
final TextEditingController _editableController = TextEditingController(
|
||||
text:
|
||||
@@ -67,7 +67,10 @@ class FieldTypesPage extends StatelessWidget {
|
||||
const SizedBox(height: 20.0),
|
||||
TextField(maxLines: 3, controller: _controller),
|
||||
const SizedBox(height: 60.0),
|
||||
CupertinoTextField(maxLines: 3, controller: _cupertinoController),
|
||||
CupertinoTextField(
|
||||
maxLines: 3,
|
||||
controller: _cupertinoController,
|
||||
),
|
||||
const SizedBox(height: 20.0),
|
||||
CupertinoTextField(
|
||||
maxLines: 3,
|
||||
@@ -85,11 +88,10 @@ class FieldTypesPage extends StatelessWidget {
|
||||
contextMenuBuilder: (context, editableTextState) {
|
||||
return DesktopTextSelectionToolbar(
|
||||
anchor: editableTextState.contextMenuAnchors.primaryAnchor,
|
||||
children:
|
||||
AdaptiveTextSelectionToolbar.getAdaptiveButtons(
|
||||
context,
|
||||
editableTextState.contextMenuButtonItems,
|
||||
).toList(),
|
||||
children: AdaptiveTextSelectionToolbar.getAdaptiveButtons(
|
||||
context,
|
||||
editableTextState.contextMenuButtonItems,
|
||||
).toList(),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -107,7 +107,9 @@ class FullPage extends StatelessWidget {
|
||||
editableTextState.textEditingValue;
|
||||
final List<ContextMenuButtonItem> buttonItems =
|
||||
editableTextState.contextMenuButtonItems;
|
||||
if (isValidEmail(value.selection.textInside(value.text))) {
|
||||
if (isValidEmail(
|
||||
value.selection.textInside(value.text),
|
||||
)) {
|
||||
buttonItems.insert(
|
||||
0,
|
||||
ContextMenuButtonItem(
|
||||
@@ -115,7 +117,10 @@ class FullPage extends StatelessWidget {
|
||||
onPressed: () {
|
||||
ContextMenuController.removeAny();
|
||||
Navigator.of(context).push(
|
||||
_showDialog(context, 'You clicked send email'),
|
||||
_showDialog(
|
||||
context,
|
||||
'You clicked send email',
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -126,26 +131,25 @@ class FullPage extends StatelessWidget {
|
||||
// Build the default buttons, but make them look crazy.
|
||||
// Note that in a real project you may want to build
|
||||
// different buttons depending on the platform.
|
||||
children:
|
||||
buttonItems.map((buttonItem) {
|
||||
return CupertinoButton(
|
||||
borderRadius: null,
|
||||
color: const Color(0xffaaaa00),
|
||||
disabledColor: const Color(0xffaaaaff),
|
||||
onPressed: buttonItem.onPressed,
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
pressedOpacity: 0.7,
|
||||
child: SizedBox(
|
||||
width: 200.0,
|
||||
child: Text(
|
||||
CupertinoTextSelectionToolbarButton.getButtonLabel(
|
||||
context,
|
||||
buttonItem,
|
||||
),
|
||||
),
|
||||
children: buttonItems.map((buttonItem) {
|
||||
return CupertinoButton(
|
||||
borderRadius: null,
|
||||
color: const Color(0xffaaaa00),
|
||||
disabledColor: const Color(0xffaaaaff),
|
||||
onPressed: buttonItem.onPressed,
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
pressedOpacity: 0.7,
|
||||
child: SizedBox(
|
||||
width: 200.0,
|
||||
child: Text(
|
||||
CupertinoTextSelectionToolbarButton.getButtonLabel(
|
||||
context,
|
||||
buttonItem,
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -9,7 +9,8 @@ class GlobalSelectionPage extends StatelessWidget {
|
||||
|
||||
static const String route = 'global-selection';
|
||||
static const String title = 'Global Selection Example';
|
||||
static const String subtitle = 'Context menus in and out of global selection';
|
||||
static const String subtitle =
|
||||
'Context menus in and out of global selection';
|
||||
static const String url = '$kCodeUrl/global_selection_page.dart';
|
||||
|
||||
final PlatformCallback onChangedPlatform;
|
||||
|
||||
@@ -19,10 +19,9 @@ class ImagePage extends StatelessWidget {
|
||||
DialogRoute _showDialog(BuildContext context) {
|
||||
return DialogRoute<void>(
|
||||
context: context,
|
||||
builder:
|
||||
(context) => const AlertDialog(
|
||||
title: Text('Image saved! (not really though)'),
|
||||
),
|
||||
builder: (context) => const AlertDialog(
|
||||
title: Text('Image saved! (not really though)'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -49,7 +48,9 @@ class ImagePage extends StatelessWidget {
|
||||
ContextMenuRegion(
|
||||
contextMenuBuilder: (context, offset) {
|
||||
return AdaptiveTextSelectionToolbar.buttonItems(
|
||||
anchors: TextSelectionToolbarAnchors(primaryAnchor: offset),
|
||||
anchors: TextSelectionToolbarAnchors(
|
||||
primaryAnchor: offset,
|
||||
),
|
||||
buttonItems: <ContextMenuButtonItem>[
|
||||
ContextMenuButtonItem(
|
||||
onPressed: () {
|
||||
|
||||
@@ -64,36 +64,30 @@ class _MyAppState extends State<MyApp> {
|
||||
initialRoute: '/',
|
||||
routes: <String, Widget Function(BuildContext)>{
|
||||
'/': (context) => MyHomePage(onChangedPlatform: onChangedPlatform),
|
||||
AnywherePage.route:
|
||||
(context) => AnywherePage(onChangedPlatform: onChangedPlatform),
|
||||
CustomButtonsPage.route:
|
||||
(context) =>
|
||||
CustomButtonsPage(onChangedPlatform: onChangedPlatform),
|
||||
CustomMenuPage.route:
|
||||
(context) => CustomMenuPage(onChangedPlatform: onChangedPlatform),
|
||||
ReorderedButtonsPage.route:
|
||||
(context) =>
|
||||
ReorderedButtonsPage(onChangedPlatform: onChangedPlatform),
|
||||
EmailButtonPage.route:
|
||||
(context) => EmailButtonPage(onChangedPlatform: onChangedPlatform),
|
||||
ImagePage.route:
|
||||
(context) => ImagePage(onChangedPlatform: onChangedPlatform),
|
||||
FieldTypesPage.route:
|
||||
(context) => FieldTypesPage(onChangedPlatform: onChangedPlatform),
|
||||
FullPage.route:
|
||||
(context) => FullPage(onChangedPlatform: onChangedPlatform),
|
||||
ModifiedActionPage.route:
|
||||
(context) =>
|
||||
ModifiedActionPage(onChangedPlatform: onChangedPlatform),
|
||||
GlobalSelectionPage.route:
|
||||
(context) =>
|
||||
GlobalSelectionPage(onChangedPlatform: onChangedPlatform),
|
||||
DefaultValuesPage.route:
|
||||
(context) =>
|
||||
DefaultValuesPage(onChangedPlatform: onChangedPlatform),
|
||||
CascadingMenuPage.route:
|
||||
(context) =>
|
||||
CascadingMenuPage(onChangedPlatform: onChangedPlatform),
|
||||
AnywherePage.route: (context) =>
|
||||
AnywherePage(onChangedPlatform: onChangedPlatform),
|
||||
CustomButtonsPage.route: (context) =>
|
||||
CustomButtonsPage(onChangedPlatform: onChangedPlatform),
|
||||
CustomMenuPage.route: (context) =>
|
||||
CustomMenuPage(onChangedPlatform: onChangedPlatform),
|
||||
ReorderedButtonsPage.route: (context) =>
|
||||
ReorderedButtonsPage(onChangedPlatform: onChangedPlatform),
|
||||
EmailButtonPage.route: (context) =>
|
||||
EmailButtonPage(onChangedPlatform: onChangedPlatform),
|
||||
ImagePage.route: (context) =>
|
||||
ImagePage(onChangedPlatform: onChangedPlatform),
|
||||
FieldTypesPage.route: (context) =>
|
||||
FieldTypesPage(onChangedPlatform: onChangedPlatform),
|
||||
FullPage.route: (context) =>
|
||||
FullPage(onChangedPlatform: onChangedPlatform),
|
||||
ModifiedActionPage.route: (context) =>
|
||||
ModifiedActionPage(onChangedPlatform: onChangedPlatform),
|
||||
GlobalSelectionPage.route: (context) =>
|
||||
GlobalSelectionPage(onChangedPlatform: onChangedPlatform),
|
||||
DefaultValuesPage.route: (context) =>
|
||||
DefaultValuesPage(onChangedPlatform: onChangedPlatform),
|
||||
CascadingMenuPage.route: (context) =>
|
||||
CascadingMenuPage(onChangedPlatform: onChangedPlatform),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -22,10 +22,9 @@ class ModifiedActionPage extends StatelessWidget {
|
||||
DialogRoute _showDialog(BuildContext context) {
|
||||
return DialogRoute<void>(
|
||||
context: context,
|
||||
builder:
|
||||
(context) => const AlertDialog(
|
||||
title: Text('Copied, but also showed this dialog.'),
|
||||
),
|
||||
builder: (context) => const AlertDialog(
|
||||
title: Text('Copied, but also showed this dialog.'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,19 +37,18 @@ class _PlatformSelectorState extends State<PlatformSelector> {
|
||||
widget.onChangedPlatform(value);
|
||||
setState(() {});
|
||||
},
|
||||
items:
|
||||
TargetPlatform.values.map((platform) {
|
||||
return DropdownMenuItem<TargetPlatform>(
|
||||
value: platform,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
if (platform == originaPlatform)
|
||||
const Icon(Icons.home, color: Color(0xff616161)),
|
||||
Text(_platformToString(platform)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
items: TargetPlatform.values.map((platform) {
|
||||
return DropdownMenuItem<TargetPlatform>(
|
||||
value: platform,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
if (platform == originaPlatform)
|
||||
const Icon(Icons.home, color: Color(0xff616161)),
|
||||
Text(_platformToString(platform)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ class ReorderedButtonsPage extends StatelessWidget {
|
||||
|
||||
static const String route = 'reordered-buttons';
|
||||
static const String title = 'Reordered Buttons';
|
||||
static const String subtitle = 'The usual buttons, but in a different order.';
|
||||
static const String subtitle =
|
||||
'The usual buttons, but in a different order.';
|
||||
static const String url = '$kCodeUrl/reordered_buttons_page.dart';
|
||||
|
||||
final PlatformCallback onChangedPlatform;
|
||||
@@ -61,19 +62,25 @@ class ReorderedButtonsPage extends StatelessWidget {
|
||||
in editableTextState.contextMenuButtonItems) {
|
||||
buttonItemsMap[buttonItem.type] = buttonItem;
|
||||
}
|
||||
final List<ContextMenuButtonItem>
|
||||
reorderedButtonItems = <ContextMenuButtonItem>[
|
||||
if (buttonItemsMap.containsKey(
|
||||
ContextMenuButtonType.selectAll,
|
||||
))
|
||||
buttonItemsMap[ContextMenuButtonType.selectAll]!,
|
||||
if (buttonItemsMap.containsKey(ContextMenuButtonType.paste))
|
||||
buttonItemsMap[ContextMenuButtonType.paste]!,
|
||||
if (buttonItemsMap.containsKey(ContextMenuButtonType.copy))
|
||||
buttonItemsMap[ContextMenuButtonType.copy]!,
|
||||
if (buttonItemsMap.containsKey(ContextMenuButtonType.cut))
|
||||
buttonItemsMap[ContextMenuButtonType.cut]!,
|
||||
];
|
||||
final List<ContextMenuButtonItem> reorderedButtonItems =
|
||||
<ContextMenuButtonItem>[
|
||||
if (buttonItemsMap.containsKey(
|
||||
ContextMenuButtonType.selectAll,
|
||||
))
|
||||
buttonItemsMap[ContextMenuButtonType.selectAll]!,
|
||||
if (buttonItemsMap.containsKey(
|
||||
ContextMenuButtonType.paste,
|
||||
))
|
||||
buttonItemsMap[ContextMenuButtonType.paste]!,
|
||||
if (buttonItemsMap.containsKey(
|
||||
ContextMenuButtonType.copy,
|
||||
))
|
||||
buttonItemsMap[ContextMenuButtonType.copy]!,
|
||||
if (buttonItemsMap.containsKey(
|
||||
ContextMenuButtonType.cut,
|
||||
))
|
||||
buttonItemsMap[ContextMenuButtonType.cut]!,
|
||||
];
|
||||
return AdaptiveTextSelectionToolbar.buttonItems(
|
||||
anchors: editableTextState.contextMenuAnchors,
|
||||
buttonItems: reorderedButtonItems,
|
||||
|
||||
Reference in New Issue
Block a user