Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

hasStrings for web #43360

Merged
merged 5 commits into from
Aug 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions lib/web_ui/lib/src/engine/clipboard.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down
3 changes: 3 additions & 0 deletions lib/web_ui/lib/src/engine/platform_dispatcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
48 changes: 48 additions & 0 deletions lib/web_ui/test/engine/clipboard_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});
}

Expand All @@ -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);
}
}