Support hasStrings on web, so that developers can check for clipboard content before showing the paste button, for example, if desired.
This commit is contained in:
Justin McCandless 2023-08-14 10:08:50 -07:00 committed by GitHub
parent 6af9ea88ce
commit 90d79a902b
3 changed files with 76 additions and 0 deletions

View File

@ -65,6 +65,31 @@ class ClipboardMessageHandler {
});
}
/// Handles the platform message which asks if the clipboard contains
/// pasteable strings.
void hasStringsMethodCall(ui.PlatformMessageResponseCallback? callback) {
const MethodCodec codec = JSONMethodCodec();
_pasteFromClipboardStrategy.getData().then((String data) {
final Map<String, dynamic> map = <String, dynamic>{'value': data.isNotEmpty};
callback!(codec.encodeSuccessEnvelope(map));
}).catchError((dynamic error) {
if (error is UnimplementedError) {
// Clipboard.hasStrings not supported.
// Passing [null] to [callback] indicates that the platform message isn't
// implemented. Look at [MethodChannel.invokeMethod] to see how [null] is
// handled.
Future<void>.delayed(Duration.zero).then((_) {
if (callback != null) {
callback(null);
}
});
return;
}
final Map<String, dynamic> map = <String, dynamic>{'value': false};
callback!(codec.encodeSuccessEnvelope(map));
});
}
void _reportGetDataFailure(ui.PlatformMessageResponseCallback? callback,
MethodCodec codec, dynamic error) {
print('Could not get text from clipboard: $error');

View File

@ -580,6 +580,9 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
case 'Clipboard.getData':
ClipboardMessageHandler().getDataMethodCall(callback);
return;
case 'Clipboard.hasStrings':
ClipboardMessageHandler().hasStringsMethodCall(callback);
return;
}
// Dispatched by the bindings to delay service worker initialization.

View File

@ -87,6 +87,48 @@ Future<void> testMain() async {
final Map<String, dynamic> result = await completer.future;
expect(result['text'], testText);
});
test('has strings true', () async {
clipboardAPIPasteStrategy.testResult = testText;
const MethodCodec codec = JSONMethodCodec();
final Completer<Map<String, dynamic>> completer = Completer<Map<String, dynamic>>();
void callback(ByteData? data) {
completer.complete(codec.decodeEnvelope(data!) as Map<String, dynamic>);
}
clipboardMessageHandler.hasStringsMethodCall(callback);
final Map<String, dynamic> result = await completer.future;
expect(result['value'], isTrue);
});
test('has strings false', () async {
clipboardAPIPasteStrategy.testResult = '';
const MethodCodec codec = JSONMethodCodec();
final Completer<Map<String, dynamic>> completer = Completer<Map<String, dynamic>>();
void callback(ByteData? data) {
completer.complete(codec.decodeEnvelope(data!) as Map<String, dynamic>);
}
clipboardMessageHandler.hasStringsMethodCall(callback);
final Map<String, dynamic> result = await completer.future;
expect(result['value'], isFalse);
});
test('has strings error', () async {
clipboardAPIPasteStrategy.errors = true;
const MethodCodec codec = JSONMethodCodec();
final Completer<Map<String, dynamic>> completer = Completer<Map<String, dynamic>>();
void callback(ByteData? data) {
completer.complete(codec.decodeEnvelope(data!) as Map<String, dynamic>);
}
clipboardMessageHandler.hasStringsMethodCall(callback);
final Map<String, dynamic> result = await completer.future;
expect(result['value'], isFalse);
});
});
}
@ -102,8 +144,14 @@ class MockClipboardAPICopyStrategy implements ClipboardAPICopyStrategy {
class MockClipboardAPIPasteStrategy implements ClipboardAPIPasteStrategy {
String testResult = '';
// Whether getData's Future will resolve with an error.
bool errors = false;
@override
Future<String> getData() {
if (errors) {
return Future<String>.error(Error());
}
return Future<String>.value(testResult);
}
}