diff --git a/lib/src/utils/platform.dart b/lib/src/utils/platform.dart index d248b369..e2ccc1bc 100644 --- a/lib/src/utils/platform.dart +++ b/lib/src/utils/platform.dart @@ -4,14 +4,6 @@ import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/foundation.dart' show TargetPlatform, defaultTargetPlatform, kIsWeb, visibleForTesting; -/// If you want to override the [kIsWeb] use [overrideIsWeb] but it's only -/// for testing -bool isWeb({ - @visibleForTesting bool? overrideIsWeb, -}) { - return overrideIsWeb ?? kIsWeb; -} - /// [supportWeb] is a parameter that ask you if we should care about web support /// if the value is true then we will return the result no matter if we are /// on web or using a native app to run the flutter app @@ -128,6 +120,16 @@ Future isIOSSimulator({ return false; } +// TODO: This is only used for tests, we might remove it or keep it + +/// If you want to override the [kIsWeb] use [overrideIsWeb] but it's only +/// for testing +bool isWeb({ + @visibleForTesting bool? overrideIsWeb, +}) { + return overrideIsWeb ?? kIsWeb; +} + bool isFlutterTest({ bool? overrideIsWeb, }) { diff --git a/lib/src/widgets/quill/quill_controller.dart b/lib/src/widgets/quill/quill_controller.dart index bf21c8f4..97cf303e 100644 --- a/lib/src/widgets/quill/quill_controller.dart +++ b/lib/src/widgets/quill/quill_controller.dart @@ -1,9 +1,12 @@ +import 'dart:async' show StreamSubscription; import 'dart:math' as math; +import 'package:flutter/foundation.dart' show kIsWeb; import 'package:flutter/services.dart' show ClipboardData, Clipboard; import 'package:flutter/widgets.dart'; import 'package:html/parser.dart' as html_parser; import 'package:meta/meta.dart'; +import 'package:web/web.dart' as web; import '../../../flutter_quill.dart'; import '../../../quill_delta.dart'; @@ -27,7 +30,20 @@ class QuillController extends ChangeNotifier { this.readOnly = false, this.editorFocusNode, }) : _document = document, - _selection = selection; + _selection = selection { + if (kIsWeb) { + _webPasteEventSubscription = web.EventStreamProviders.pasteEvent + .forTarget(web.window.document) + .listen((e) { + // TODO: See if we can support markdown as well + final html = e.clipboardData?.getData('text/html'); + if (html == null) { + return; + } + _pasteHTML(html: html); + }); + } + } factory QuillController.basic( {QuillControllerConfigurations configurations = @@ -97,8 +113,8 @@ class QuillController extends ChangeNotifier { bool ignoreFocusOnTextChange = false; - /// Skip requestKeyboard being called in - /// RawEditorState#_didChangeTextEditingValue + /// Skip requestKeyboard being called + /// in [QuillRawEditorState._didChangeTextEditingValue] bool skipRequestKeyboard = false; /// True when this [QuillController] instance has been disposed. @@ -114,6 +130,13 @@ class QuillController extends ChangeNotifier { selection: selection, ); + /// Paste event for the web. + /// + /// Will be `null` for non-web platforms. + /// + /// See: https://developer.mozilla.org/en-US/docs/Web/API/Element/paste_event + StreamSubscription? _webPasteEventSubscription; + /// Only attributes applied to all characters within this range are /// included in the result. Style getSelectionStyle() { @@ -431,6 +454,8 @@ class QuillController extends ChangeNotifier { } _isDisposed = true; + + _webPasteEventSubscription?.cancel(); super.dispose(); } @@ -566,11 +591,21 @@ class QuillController extends ChangeNotifier { ); } - /// Return true if can paste using HTML - Future _pasteHTML() async { + /// Paste the HTML into the document from [html] if not null, otherwise + /// will read it from the Clipboard in case the [ClipboardServiceProvider.instance] + /// support it on the current platform. + /// + /// The argument [html] allow to override the HTML that's being pasted, + /// mainly to support pasting HTML on the web in [_webPasteEventSubscription]. + /// + /// Return `true` if can paste or have pasted using HTML. + Future _pasteHTML({String? html}) async { final clipboardService = ClipboardServiceProvider.instance; Future getHTML() async { + if (html != null) { + return html; + } if (await clipboardService.canProvideHtmlTextFromFile()) { return await clipboardService.getHtmlTextFromFile(); } @@ -593,7 +628,7 @@ class QuillController extends ChangeNotifier { return false; } - /// Return true if can paste using Markdown + /// Return `true` if can paste or have pasted using HTML. Future _pasteMarkdown() async { final clipboardService = ClipboardServiceProvider.instance; diff --git a/test/widgets/controller_test.dart b/test/widgets/controller_test.dart index 7c04b274..88679290 100644 --- a/test/widgets/controller_test.dart +++ b/test/widgets/controller_test.dart @@ -412,5 +412,8 @@ void main() { reason: 'line 1 extends into line3 which is not block'); } }); + + // TODO: Implement this, check of kIsWeb is not testable in QuillController + test('the paste event should be not null on web', () {}); }); }