-
Notifications
You must be signed in to change notification settings - Fork 814
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(web): rich text paste from Clipboard using HTML (#2009)
* feat(web): support rich text paste from Clipboard using HTML * chore: moving the comment of internal usage only in quill_controller_rich_paste.dart to the start of the file
- Loading branch information
Showing
5 changed files
with
165 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
// This file should not be exported as the APIs in it are meant for internal usage only | ||
|
||
import 'package:flutter/widgets.dart' show TextSelection; | ||
import 'package:html/parser.dart' as html_parser; | ||
|
||
import '../../quill_delta.dart'; | ||
import '../delta/delta_x.dart'; | ||
import '../editor_toolbar_controller_shared/clipboard/clipboard_service_provider.dart'; | ||
import 'quill_controller.dart'; | ||
|
||
extension QuillControllerRichPaste on QuillController { | ||
/// 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<bool> pasteHTML({String? html}) async { | ||
final clipboardService = ClipboardServiceProvider.instance; | ||
|
||
Future<String?> getHTML() async { | ||
if (html != null) { | ||
return html; | ||
} | ||
if (await clipboardService.canProvideHtmlTextFromFile()) { | ||
return await clipboardService.getHtmlTextFromFile(); | ||
} | ||
if (await clipboardService.canProvideHtmlText()) { | ||
return await clipboardService.getHtmlText(); | ||
} | ||
return null; | ||
} | ||
|
||
final htmlText = await getHTML(); | ||
if (htmlText != null) { | ||
final htmlBody = html_parser.parse(htmlText).body?.outerHtml; | ||
// ignore: deprecated_member_use_from_same_package | ||
final deltaFromClipboard = DeltaX.fromHtml(htmlBody ?? htmlText); | ||
|
||
_pasteUsingDelta(deltaFromClipboard); | ||
|
||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
// Paste the Markdown into the document from [markdown] if not null, otherwise | ||
/// will read it from the Clipboard in case the [ClipboardServiceProvider.instance] | ||
/// support it on the current platform. | ||
/// | ||
/// The argument [markdown] allow to override the Markdown that's being pasted, | ||
/// mainly to support pasting Markdown on the web in [_webPasteEventSubscription]. | ||
/// | ||
/// Return `true` if can paste or have pasted using Markdown. | ||
Future<bool> pasteMarkdown({String? markdown}) async { | ||
final clipboardService = ClipboardServiceProvider.instance; | ||
|
||
Future<String?> getMarkdown() async { | ||
if (markdown != null) { | ||
return markdown; | ||
} | ||
if (await clipboardService.canProvideMarkdownTextFromFile()) { | ||
return await clipboardService.getMarkdownTextFromFile(); | ||
} | ||
if (await clipboardService.canProvideMarkdownText()) { | ||
return await clipboardService.getMarkdownText(); | ||
} | ||
return null; | ||
} | ||
|
||
final markdownText = await getMarkdown(); | ||
if (markdownText != null) { | ||
// ignore: deprecated_member_use_from_same_package | ||
final deltaFromClipboard = DeltaX.fromMarkdown(markdownText); | ||
|
||
_pasteUsingDelta(deltaFromClipboard); | ||
|
||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
void _pasteUsingDelta(Delta deltaFromClipboard) { | ||
replaceText( | ||
selection.start, | ||
selection.end - selection.start, | ||
deltaFromClipboard, | ||
TextSelection.collapsed(offset: selection.end), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// This file should not be exported as the APIs in it are meant for internal usage only | ||
|
||
import 'dart:async' show StreamSubscription; | ||
|
||
import 'package:web/web.dart'; | ||
|
||
import '../quill_controller.dart'; | ||
import '../quill_controller_rich_paste.dart'; | ||
|
||
/// 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; | ||
|
||
extension QuillControllerWeb on QuillController { | ||
void initializeWebPasteEvent() { | ||
_webPasteEventSubscription = | ||
EventStreamProviders.pasteEvent.forTarget(window.document).listen((e) { | ||
// TODO: See if we can support markdown paste | ||
final html = e.clipboardData?.getData('text/html'); | ||
if (html == null) { | ||
return; | ||
} | ||
pasteHTML(html: html); | ||
}); | ||
} | ||
|
||
void closeWebPasteEvent() { | ||
_webPasteEventSubscription?.cancel(); | ||
_webPasteEventSubscription = null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// This file should not be exported as the APIs in it are meant for internal usage only | ||
|
||
import '../quill_controller.dart'; | ||
|
||
// This is a mock implementation to compile the app on non-web platforms. | ||
// The real implementation is quill_controller_web_real.dart | ||
|
||
extension QuillControllerWeb on QuillController { | ||
void initializeWebPasteEvent() { | ||
throw UnsupportedError( | ||
'The initializeWebPasteEvent() method should be called only on web.', | ||
); | ||
} | ||
|
||
void closeWebPasteEvent() { | ||
throw UnsupportedError( | ||
'The closeWebPasteEvent() method should be called only on web.', | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,6 +50,7 @@ dependencies: | |
equatable: ^2.0.5 | ||
meta: ^1.10.0 | ||
html: ^0.15.4 | ||
web: ^1.0.0 | ||
|
||
flutter_colorpicker: ^1.1.0 | ||
|
||
|