Don't access clipboard passively on iOS (#60316)
This commit is contained in:
committed by
GitHub
parent
d55251cbab
commit
f6cd2d4b35
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 }));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user