_CastError on Semantics copy in release mode (#91827)
This commit is contained in:
parent
76f17185fc
commit
3ece170c40
@ -2712,7 +2712,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
if (hideHandles) {
|
if (hideHandles) {
|
||||||
// Hide the handles and the toolbar.
|
// Hide the handles and the toolbar.
|
||||||
_selectionOverlay?.hide();
|
_selectionOverlay?.hide();
|
||||||
} else {
|
} else if (_selectionOverlay?.toolbarIsVisible ?? false) {
|
||||||
// Hide only the toolbar but not the handles.
|
// Hide only the toolbar but not the handles.
|
||||||
_selectionOverlay?.hideToolbar();
|
_selectionOverlay?.hideToolbar();
|
||||||
}
|
}
|
||||||
|
@ -357,7 +357,7 @@ class TextSelectionOverlay {
|
|||||||
/// Controls the fade-in and fade-out animations for the toolbar and handles.
|
/// Controls the fade-in and fade-out animations for the toolbar and handles.
|
||||||
static const Duration fadeDuration = Duration(milliseconds: 150);
|
static const Duration fadeDuration = Duration(milliseconds: 150);
|
||||||
|
|
||||||
late AnimationController _toolbarController;
|
late final AnimationController _toolbarController;
|
||||||
Animation<double> get _toolbarOpacity => _toolbarController.view;
|
Animation<double> get _toolbarOpacity => _toolbarController.view;
|
||||||
|
|
||||||
/// Retrieve current value.
|
/// Retrieve current value.
|
||||||
@ -496,7 +496,7 @@ class TextSelectionOverlay {
|
|||||||
void hideToolbar() {
|
void hideToolbar() {
|
||||||
assert(_toolbar != null);
|
assert(_toolbar != null);
|
||||||
_toolbarController.stop();
|
_toolbarController.stop();
|
||||||
_toolbar!.remove();
|
_toolbar?.remove();
|
||||||
_toolbar = null;
|
_toolbar = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3323,6 +3323,51 @@ void main() {
|
|||||||
|
|
||||||
semantics.dispose();
|
semantics.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Regression test for b/201218542.
|
||||||
|
testWidgets('copying with a11y works even when toolbar is hidden', (WidgetTester tester) async {
|
||||||
|
Future<void> testByControls(TextSelectionControls controls) async {
|
||||||
|
final SemanticsTester semantics = SemanticsTester(tester);
|
||||||
|
final TextEditingController controller = TextEditingController(text: 'ABCDEFG');
|
||||||
|
|
||||||
|
await tester.pumpWidget(MaterialApp(
|
||||||
|
home: EditableText(
|
||||||
|
backgroundCursorColor: Colors.grey,
|
||||||
|
controller: controller,
|
||||||
|
focusNode: focusNode,
|
||||||
|
style: textStyle,
|
||||||
|
cursorColor: cursorColor,
|
||||||
|
selectionControls: controls,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
await tester.tap(find.byType(EditableText));
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
final SemanticsOwner owner = tester.binding.pipelineOwner.semanticsOwner!;
|
||||||
|
const int expectedNodeId = 5;
|
||||||
|
|
||||||
|
expect(controller.value.selection.isCollapsed, isTrue);
|
||||||
|
|
||||||
|
controller.selection = TextSelection(
|
||||||
|
baseOffset: 0,
|
||||||
|
extentOffset: controller.value.text.length,
|
||||||
|
);
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
expect(find.text('Copy'), findsNothing);
|
||||||
|
|
||||||
|
owner.performAction(expectedNodeId, SemanticsAction.copy);
|
||||||
|
expect(tester.takeException(), isNull);
|
||||||
|
expect(
|
||||||
|
(await Clipboard.getData(Clipboard.kTextPlain))!.text,
|
||||||
|
equals('ABCDEFG'),
|
||||||
|
);
|
||||||
|
|
||||||
|
semantics.dispose();
|
||||||
|
}
|
||||||
|
await testByControls(materialTextSelectionControls);
|
||||||
|
await testByControls(cupertinoTextSelectionControls);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('can set text with a11y', (WidgetTester tester) async {
|
testWidgets('can set text with a11y', (WidgetTester tester) async {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user