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

Commit 845075b

Browse files
authored
hasStrings for web (#43360)
Support hasStrings on web, so that developers can check for clipboard content before showing the paste button, for example, if desired.
1 parent 46c1191 commit 845075b

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed

lib/web_ui/lib/src/engine/clipboard.dart

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,31 @@ class ClipboardMessageHandler {
6565
});
6666
}
6767

68+
/// Handles the platform message which asks if the clipboard contains
69+
/// pasteable strings.
70+
void hasStringsMethodCall(ui.PlatformMessageResponseCallback? callback) {
71+
const MethodCodec codec = JSONMethodCodec();
72+
_pasteFromClipboardStrategy.getData().then((String data) {
73+
final Map<String, dynamic> map = <String, dynamic>{'value': data.isNotEmpty};
74+
callback!(codec.encodeSuccessEnvelope(map));
75+
}).catchError((dynamic error) {
76+
if (error is UnimplementedError) {
77+
// Clipboard.hasStrings not supported.
78+
// Passing [null] to [callback] indicates that the platform message isn't
79+
// implemented. Look at [MethodChannel.invokeMethod] to see how [null] is
80+
// handled.
81+
Future<void>.delayed(Duration.zero).then((_) {
82+
if (callback != null) {
83+
callback(null);
84+
}
85+
});
86+
return;
87+
}
88+
final Map<String, dynamic> map = <String, dynamic>{'value': false};
89+
callback!(codec.encodeSuccessEnvelope(map));
90+
});
91+
}
92+
6893
void _reportGetDataFailure(ui.PlatformMessageResponseCallback? callback,
6994
MethodCodec codec, dynamic error) {
7095
print('Could not get text from clipboard: $error');

lib/web_ui/lib/src/engine/platform_dispatcher.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,9 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
580580
case 'Clipboard.getData':
581581
ClipboardMessageHandler().getDataMethodCall(callback);
582582
return;
583+
case 'Clipboard.hasStrings':
584+
ClipboardMessageHandler().hasStringsMethodCall(callback);
585+
return;
583586
}
584587

585588
// Dispatched by the bindings to delay service worker initialization.

lib/web_ui/test/engine/clipboard_test.dart

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,48 @@ Future<void> testMain() async {
8787
final Map<String, dynamic> result = await completer.future;
8888
expect(result['text'], testText);
8989
});
90+
91+
test('has strings true', () async {
92+
clipboardAPIPasteStrategy.testResult = testText;
93+
const MethodCodec codec = JSONMethodCodec();
94+
final Completer<Map<String, dynamic>> completer = Completer<Map<String, dynamic>>();
95+
void callback(ByteData? data) {
96+
completer.complete(codec.decodeEnvelope(data!) as Map<String, dynamic>);
97+
}
98+
99+
clipboardMessageHandler.hasStringsMethodCall(callback);
100+
101+
final Map<String, dynamic> result = await completer.future;
102+
expect(result['value'], isTrue);
103+
});
104+
105+
test('has strings false', () async {
106+
clipboardAPIPasteStrategy.testResult = '';
107+
const MethodCodec codec = JSONMethodCodec();
108+
final Completer<Map<String, dynamic>> completer = Completer<Map<String, dynamic>>();
109+
void callback(ByteData? data) {
110+
completer.complete(codec.decodeEnvelope(data!) as Map<String, dynamic>);
111+
}
112+
113+
clipboardMessageHandler.hasStringsMethodCall(callback);
114+
115+
final Map<String, dynamic> result = await completer.future;
116+
expect(result['value'], isFalse);
117+
});
118+
119+
test('has strings error', () async {
120+
clipboardAPIPasteStrategy.errors = true;
121+
const MethodCodec codec = JSONMethodCodec();
122+
final Completer<Map<String, dynamic>> completer = Completer<Map<String, dynamic>>();
123+
void callback(ByteData? data) {
124+
completer.complete(codec.decodeEnvelope(data!) as Map<String, dynamic>);
125+
}
126+
127+
clipboardMessageHandler.hasStringsMethodCall(callback);
128+
129+
final Map<String, dynamic> result = await completer.future;
130+
expect(result['value'], isFalse);
131+
});
90132
});
91133
}
92134

@@ -102,8 +144,14 @@ class MockClipboardAPICopyStrategy implements ClipboardAPICopyStrategy {
102144
class MockClipboardAPIPasteStrategy implements ClipboardAPIPasteStrategy {
103145
String testResult = '';
104146

147+
// Whether getData's Future will resolve with an error.
148+
bool errors = false;
149+
105150
@override
106151
Future<String> getData() {
152+
if (errors) {
153+
return Future<String>.error(Error());
154+
}
107155
return Future<String>.value(testResult);
108156
}
109157
}

0 commit comments

Comments
 (0)