Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
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
1 change: 1 addition & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/bitmap_canvas.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/browser_detection.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/browser_location.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvas_pool.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/clipboard.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/color_filter.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/canvas.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/canvas_kit_canvas.dart
Expand Down
1 change: 1 addition & 0 deletions lib/web_ui/lib/src/engine.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ part 'engine/bitmap_canvas.dart';
part 'engine/browser_detection.dart';
part 'engine/browser_location.dart';
part 'engine/canvas_pool.dart';
part 'engine/clipboard.dart';
part 'engine/color_filter.dart';
part 'engine/compositor/canvas.dart';
part 'engine/compositor/canvas_kit_canvas.dart';
Expand Down
109 changes: 109 additions & 0 deletions lib/web_ui/lib/src/engine/clipboard.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// 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.

part of engine;

/// Handles clipboard related platform messages.
class ClipboardMessageHandler {
/// Helper to handle copy to clipboard functionality.
final CopyToClipboardStrategy _copyToClipboardStrategy =
CopyToClipboardStrategy();

/// Helper to handle copy to clipboard functionality.
final PasteFromClipboardStrategy _pasteFromClipboardStrategy =
PasteFromClipboardStrategy();

/// Handles the platform message which stores the given text to the clipboard.
void setDataMethodCall(MethodCall methodCall) {
_copyToClipboardStrategy.setData(methodCall.arguments['text']);
}

/// Handles the platform message which retrieves text data from the clipboard.
void getDataMethodCall(ui.PlatformMessageResponseCallback callback) {
_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'));
}
}

/// Provides functionality for writing text to clipboard.
///
/// A concrete implementation is picked at runtime based on the available
/// APIs and the browser.
abstract class CopyToClipboardStrategy {
factory CopyToClipboardStrategy() {
return (html.window.navigator.clipboard.writeText != null)
? ClipboardAPICopyStrategy()
: ExecCommandCopyStrategy();
}

/// Places the text onto the browser Clipboard.
void setData(String text);
}

/// Provides functionality for reading text from clipboard.
///
/// A concrete implementation is picked at runtime based on the available
/// APIs and the browser.
abstract class PasteFromClipboardStrategy {
factory PasteFromClipboardStrategy() {
return (browserEngine == BrowserEngine.firefox ||
html.window.navigator.clipboard.readText == null)
? ExecCommandPasteStrategy()
: ClipboardAPIPasteStrategy();
}

/// Returns text from the system Clipboard.
Future<String> getData();
}

/// Provides copy functionality for browsers which supports ClipboardAPI.
///
/// Works on Chrome and Firefox browsers.
/// 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'));
}
}

/// Provides paste functionality for browsers which supports `clipboard.readText`.
///
/// Works on Chrome. Firefox only supports `readText` if the target element is
/// in content editable mode.
/// See: https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Editable_content
/// See: https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API
class ClipboardAPIPasteStrategy implements PasteFromClipboardStrategy {
@override
Future<String> getData() async {
return html.window.navigator.clipboard.readText();
}
}

/// Provides a fallback strategy for browsers which does not support ClipboardAPI.
class ExecCommandCopyStrategy implements CopyToClipboardStrategy {
@override
void setData(String text) {
// TODO(nurhan): https://github.com/flutter/flutter/issues/48578
print('Clipboard is only implemented for browsers '
'supporting Clipboard API. Use context menu for text editing.');
}
}

/// Provides a fallback strategy for browsers which does not support ClipboardAPI.
class ExecCommandPasteStrategy implements PasteFromClipboardStrategy {
@override
Future<String> getData() {
// TODO(nurhan): https://github.com/flutter/flutter/issues/48581
// TODO(nurhan): https://github.com/flutter/flutter/issues/48580
print('Paste is not implemented for this browser.');
throw UnimplementedError();
}
}
6 changes: 3 additions & 3 deletions lib/web_ui/lib/src/engine/window.dart
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,10 @@ class EngineWindow extends ui.Window {
// There are no default system sounds on web.
return;
case 'Clipboard.setData':
ClipboardMessageHandler().setDataMethodCall(decoded);
return;
case 'Clipboard.getData':
// TODO(nurhan): https://github.com/flutter/flutter/issues/46020
print('WARNING: Clipboard API unimplemented for Flutter for Web. '
'Use context menu for text editing.');
ClipboardMessageHandler().getDataMethodCall(callback);
return;
}
break;
Expand Down