Don't access clipboard passively on iOS (#60316)

This commit is contained in:
Justin McCandless
2020-06-29 09:43:03 -07:00
committed by GitHub
parent d55251cbab
commit f6cd2d4b35
3 changed files with 77 additions and 5 deletions

View File

@@ -1522,6 +1522,25 @@ class ClipboardStatusNotifier extends ValueNotifier<ClipboardStatus> with Widget
/// Check the [Clipboard] and update [value] if needed.
void update() {
// iOS 14 added a notification that appears when an app accesses the
// clipboard. To avoid the notification, don't access the clipboard on iOS,
// and instead always shown the paste button, even when the clipboard is
// empty.
// TODO(justinmc): Use the new iOS 14 clipboard API method hasStrings that
// won't trigger the notification.
// https://github.com/flutter/flutter/issues/60145
switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
value = ClipboardStatus.pasteable;
return;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.macOS:
case TargetPlatform.windows:
break;
}
Clipboard.getData(Clipboard.kTextPlain).then((ClipboardData data) {
final ClipboardStatus clipboardStatus = data != null && data.text != null && data.text.isNotEmpty
? ClipboardStatus.pasteable

View File

@@ -176,7 +176,8 @@ void main() {
});
});
testWidgets('Paste only appears when clipboard has contents', (WidgetTester tester) async {
// TODO(justinmc): https://github.com/flutter/flutter/issues/60145
testWidgets('Paste always appears regardless of clipboard content on iOS', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure',
);
@@ -202,8 +203,8 @@ void main() {
await tester.tapAt(textOffsetToPosition(tester, index));
await tester.pumpAndSettle();
// No Paste yet, because nothing has been copied.
expect(find.text('Paste'), findsNothing);
// Paste is showing even though clipboard is empty.
expect(find.text('Paste'), findsOneWidget);
expect(find.text('Copy'), findsOneWidget);
expect(find.text('Cut'), findsOneWidget);
@@ -219,7 +220,7 @@ void main() {
await tester.tapAt(textOffsetToPosition(tester, index));
await tester.pumpAndSettle();
// Paste now shows.
// Paste still shows.
expect(find.text('Paste'), findsOneWidget);
expect(find.text('Copy'), findsOneWidget);
expect(find.text('Cut'), findsOneWidget);

View File

@@ -636,5 +636,57 @@ void main() {
expect(find.text('Cut'), findsOneWidget);
expect(find.text('Paste'), findsOneWidget);
expect(find.text('Select all'), findsOneWidget);
}, skip: isBrowser);
}, skip: isBrowser, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }));
// TODO(justinmc): https://github.com/flutter/flutter/issues/60145
testWidgets('Paste always appears regardless of clipboard content on iOS', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure',
);
await tester.pumpWidget(
MaterialApp(
home: Material(
child: Column(
children: <Widget>[
TextField(
controller: controller,
),
],
),
),
),
);
// Make sure the clipboard is empty.
await Clipboard.setData(const ClipboardData(text: ''));
// Double tap to select the first word.
const int index = 4;
await tester.tapAt(textOffsetToPosition(tester, index));
await tester.pump(const Duration(milliseconds: 50));
await tester.tapAt(textOffsetToPosition(tester, index));
await tester.pumpAndSettle();
// Paste is showing even though clipboard is empty.
expect(find.text('Paste'), findsOneWidget);
expect(find.text('Copy'), findsOneWidget);
expect(find.text('Cut'), findsOneWidget);
// Tap copy to add something to the clipboard and close the menu.
await tester.tapAt(tester.getCenter(find.text('Copy')));
await tester.pumpAndSettle();
expect(find.text('Copy'), findsNothing);
expect(find.text('Cut'), findsNothing);
// Double tap to show the menu again.
await tester.tapAt(textOffsetToPosition(tester, index));
await tester.pump(const Duration(milliseconds: 50));
await tester.tapAt(textOffsetToPosition(tester, index));
await tester.pumpAndSettle();
// Paste still shows.
expect(find.text('Copy'), findsOneWidget);
expect(find.text('Cut'), findsOneWidget);
expect(find.text('Paste'), findsOneWidget);
}, skip: isBrowser, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }));
}