未验证 提交 08d1f2af 编写于 作者: N Nurhan Turgut 提交者: GitHub

[web] Calling platform message callback after copy (#15950)

* Calling platform message callback after copy

* addressing pr comments

* adding unit tests to clipbpard.dart
上级 bd8c9555
......@@ -7,26 +7,51 @@ part of engine;
/// Handles clipboard related platform messages.
class ClipboardMessageHandler {
/// Helper to handle copy to clipboard functionality.
final CopyToClipboardStrategy _copyToClipboardStrategy =
CopyToClipboardStrategy();
CopyToClipboardStrategy _copyToClipboardStrategy = CopyToClipboardStrategy();
/// Helper to handle copy to clipboard functionality.
final PasteFromClipboardStrategy _pasteFromClipboardStrategy =
PasteFromClipboardStrategy _pasteFromClipboardStrategy =
PasteFromClipboardStrategy();
/// Handles the platform message which stores the given text to the clipboard.
void setDataMethodCall(MethodCall methodCall) {
_copyToClipboardStrategy.setData(methodCall.arguments['text']);
void setDataMethodCall(
MethodCall methodCall, ui.PlatformMessageResponseCallback callback) {
const MethodCodec codec = JSONMethodCodec();
_copyToClipboardStrategy
.setData(methodCall.arguments['text'])
.then((bool success) {
if (success) {
callback(codec.encodeSuccessEnvelope(true));
} else {
callback(codec.encodeErrorEnvelope(
code: 'copy_fail', message: 'Clipboard.setData failed'));
}
}).catchError((_) {
callback(codec.encodeErrorEnvelope(
code: 'copy_fail', message: 'Clipboard.setData failed'));
});
}
/// Handles the platform message which retrieves text data from the clipboard.
void getDataMethodCall(ui.PlatformMessageResponseCallback callback) {
const MethodCodec codec = JSONMethodCodec();
_pasteFromClipboardStrategy.getData().then((String data) {
const MethodCodec codec = JSONMethodCodec();
final Map<String, dynamic> map = {'text': data};
callback(codec.encodeSuccessEnvelope(map));
}).catchError(
(error) => print('Could not get text from clipboard: $error'));
}).catchError((error) {
print('Could not get text from clipboard: $error');
callback(codec.encodeErrorEnvelope(
code: 'paste_fail', message: 'Clipboard.getData failed'));
});
}
/// Methods used by tests.
set pasteFromClipboardStrategy(PasteFromClipboardStrategy strategy) {
_pasteFromClipboardStrategy = strategy;
}
set copyToClipboardStrategy(CopyToClipboardStrategy strategy) {
_copyToClipboardStrategy = strategy;
}
}
......@@ -42,7 +67,11 @@ abstract class CopyToClipboardStrategy {
}
/// Places the text onto the browser Clipboard.
void setData(String text);
///
/// Returns `true` for a successful action.
///
/// Returns `false` for an uncessful action or when there is an excaption.
Future<bool> setData(String text);
}
/// Provides functionality for reading text from clipboard.
......@@ -67,10 +96,14 @@ abstract class PasteFromClipboardStrategy {
/// See: https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API
class ClipboardAPICopyStrategy implements CopyToClipboardStrategy {
@override
void setData(String text) {
html.window.navigator.clipboard
.writeText(text)
.catchError((error) => print('Could not copy text: $error'));
Future<bool> setData(String text) async {
try {
await html.window.navigator.clipboard.writeText(text);
} catch (e) {
print('copy is not successful ${e.message}');
return Future.value(false);
}
return Future.value(true);
}
}
......@@ -90,15 +123,20 @@ class ClipboardAPIPasteStrategy implements PasteFromClipboardStrategy {
/// Provides a fallback strategy for browsers which does not support ClipboardAPI.
class ExecCommandCopyStrategy implements CopyToClipboardStrategy {
@override
void setData(String text) {
Future<bool> setData(String text) {
return Future.value(_setDataSync(text));
}
bool _setDataSync(String text) {
// Copy content to clipboard with execCommand.
// See: https://developers.google.com/web/updates/2015/04/cut-and-copy-commands
final html.TextAreaElement tempTextArea = _appendTemporaryTextArea();
tempTextArea.value = text;
tempTextArea.focus();
tempTextArea.select();
bool result = false;
try {
final bool result = html.document.execCommand('copy');
result = html.document.execCommand('copy');
if (!result) {
print('copy is not successful');
}
......@@ -107,6 +145,7 @@ class ExecCommandCopyStrategy implements CopyToClipboardStrategy {
} finally {
_removeTemporaryTextArea(tempTextArea);
}
return result;
}
html.TextAreaElement _appendTemporaryTextArea() {
......
......@@ -170,7 +170,7 @@ class EngineWindow extends ui.Window {
// There are no default system sounds on web.
return;
case 'Clipboard.setData':
ClipboardMessageHandler().setDataMethodCall(decoded);
ClipboardMessageHandler().setDataMethodCall(decoded, callback);
return;
case 'Clipboard.getData':
ClipboardMessageHandler().getDataMethodCall(callback);
......
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'dart:typed_data';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
import 'package:ui/ui.dart' as ui;
import 'package:ui/src/engine.dart';
Future<void> main() async {
await ui.webOnlyInitializeTestDomRenderer();
group('message handler', () {
const String testText = 'test text';
final Future<bool> success = Future.value(true);
final Future<bool> failure = Future.value(false);
final Future<String> pasteTest = Future.value(testText);
ClipboardMessageHandler clipboardMessageHandler;
ClipboardAPICopyStrategy clipboardAPICopyStrategy =
MockClipboardAPICopyStrategy();
ClipboardAPIPasteStrategy clipboardAPIPasteStrategy =
MockClipboardAPIPasteStrategy();
setUp(() {
clipboardMessageHandler = new ClipboardMessageHandler();
clipboardAPICopyStrategy = MockClipboardAPICopyStrategy();
clipboardAPIPasteStrategy = MockClipboardAPIPasteStrategy();
clipboardMessageHandler.copyToClipboardStrategy =
clipboardAPICopyStrategy;
clipboardMessageHandler.pasteFromClipboardStrategy =
clipboardAPIPasteStrategy;
});
test('set data successful', () async {
when(clipboardAPICopyStrategy.setData(testText))
.thenAnswer((_) => success);
const MethodCodec codec = JSONMethodCodec();
bool result = false;
ui.PlatformMessageResponseCallback callback = (ByteData data) {
result = codec.decodeEnvelope(data);
};
await clipboardMessageHandler.setDataMethodCall(
const MethodCall('Clipboard.setData', <String, dynamic>{
'text': testText,
}),
callback);
await expectLater(result, true);
});
test('set data error', () async {
when(clipboardAPICopyStrategy.setData(testText))
.thenAnswer((_) => failure);
const MethodCodec codec = JSONMethodCodec();
ByteData result;
ui.PlatformMessageResponseCallback callback = (ByteData data) {
result = data;
};
await clipboardMessageHandler.setDataMethodCall(
const MethodCall('Clipboard.setData', <String, dynamic>{
'text': testText,
}),
callback);
expect(() async {
codec.decodeEnvelope(result);
}, throwsA(TypeMatcher<PlatformException>()
.having((e) => e.code, 'code', equals('copy_fail'))));
});
test('get data successful', () async {
when(clipboardAPIPasteStrategy.getData())
.thenAnswer((_) => pasteTest);
const MethodCodec codec = JSONMethodCodec();
Map<String, dynamic> result;
ui.PlatformMessageResponseCallback callback = (ByteData data) {
result = codec.decodeEnvelope(data);
};
await clipboardMessageHandler.getDataMethodCall(callback);
await expectLater(result['text'], testText);
});
});
}
class MockClipboardAPICopyStrategy extends Mock
implements ClipboardAPICopyStrategy {}
class MockClipboardAPIPasteStrategy extends Mock
implements ClipboardAPIPasteStrategy {}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册