singerdmx / flutter-quill

Rich text editor for Flutter
https://pub.dev/packages/flutter_quill
MIT License
2.6k stars 839 forks source link

Add paste options (bool plainTextOnly and a callback to view/modify a delta prior to pasting) #2350

Open mtallenca opened 2 weeks ago

mtallenca commented 2 weeks ago

Is there an existing issue for this?

Use case

Problem: On iOS when pasting HTML, it is converted into a quill delta object and then performs a controller replaceText(). The conversion assumes the full functionality of the editor and keeps all converted attributes. If the QuillEditor implementation isn't using some of the Quill features, it can be inserted into the document and not be editable. i.e. fonts, colors, images, etc.

I propose adding two changes to the controller.

1) Whenever HTML is pasted, pass the converted delta object to a callback that would allow the delta to be edited. The callback would return the edited delta object and that would be used with the replaceText controller method.

2) Provide a bool that would convert any pasted HTML into plain text prior to calling replaceText().

Alternative solutions: Currently in the onReplaceText controller callback, I'm examining the delta, removing any unsupported attributes, and then calling a 2nd replace text with the modified delta.

Proposal

quill_controller_rich_paste.dart

final htmlText = await getHTML();
    if (htmlText != null) {
      final htmlBody = html_parser.parse(htmlText).body?.outerHtml;
      // ignore: deprecated_member_use_from_same_package
      var deltaFromClipboard = DeltaX.fromHtml(htmlBody ?? htmlText);

      //Add an optional callback...
      if (verifyPasteDelta != null) {
          deltaFromClipboard = verifyPasteDelta!(deltaFromClipboard);
       }
       // end of add

      _pasteUsingDelta(deltaFromClipboard);

      return true;
    }
EchoEllet commented 2 weeks ago

This was originally discussed at flutter_quill_delta_from_html #12.

This issue will be addressed in #2338 (release/v11) as there are related changes in there (see migration guide for list of breaking changes).

I'm thinking about moving the QuillControllerConfig.onClipboardPaste to a separate config class related to the clipboard (QuillClipboardConfig) before addressing this issue.

What to address:

Any suggestions?

mtallenca commented 2 weeks ago
EchoEllet commented 2 weeks ago
  • In the 1st example add a comment // Do something with the clipboardData before the return true

The ClipboardData is a Flutter API that only supports plain text, in this example, it was used to check if the clipboard has plain text and then remove the plain text from the system clipboard to disable plain text pasting. Not a very useful example though.

The enabling of rich text paste while not a breaking change, probably should have been classified as one

I agree, even though I introduced it in 9.0.0 it was buggy at the time, and didn't mention this as a breaking change in CHANGELOG.md.

Maybe change onPasteDelta to onPaste(Object? deltaOrString) so any type of paste can be intercepted / modified. If this was the case

How about adding both onPasteDelta and onPastePlainText for type safety (this name suggestion is not final), it's also a bit more clear.

Object? deltaOrString

It can be an image.

I'm thinking about moving onImagePaste and onGifPaste from the editor's config to the QuillClipboardConfig since v11 is still published as pre-release (dev).

Since the clipboardPaste method is in the controller and pasteText (in QuillRawEditorState) still uses those callbacks.

EchoEllet commented 2 weeks ago

This might be a good feature (#2354) to add or at least provide a way to customize the copy/cut behavior.

EchoEllet commented 1 week ago

Whenever HTML is pasted, pass the converted delta object to a callback that would allow the delta to be edited. The callback would return the edited delta object and that would be used

Added the onDeltaPaste callback.

To try the latest pre-release version (#2338):

dependencies:
  flutter_quill: ^11.0.0-dev.6

See the migration guide.

Use the QuillClipboardConfig:

QuillController.basic(
  config: QuillControllerConfig(
    clipboardConfig: QuillClipboardConfig(
      onDeltaPaste: (delta) async {
        // TODO: Your custom implementation or return the Delta directly
        return delta;
      },
      onPlainTextPaste: (plainText) async {
        // TODO: Your custom implementation or return the plain text directly
        return plainText;
      },
     enableExternalRichPaste: false, // Currently default to true
    ),
  ),
);
EchoEllet commented 1 week ago

@mtallenca Do the parameters onDeltaPaste, onPlainTextPaste, and enableExternalRichPaste fix the issue?

What is missing is Paste as plain text (for the end-user) in the context menu which is supported by default on native Android, we can add it on all platforms or Android only, it's similar to native Android though not the same.

mtallenca commented 1 week ago

Yes, having these will fix the issue

On Mon, Nov 11, 2024, 1:22 AM Ellet @.***> wrote:

@mtallenca https://github.com/mtallenca Do the parameters onDeltaPaste, onPlainTextPaste, and enableExternalRichPaste fix the issue?

What is missing is Paste as plain text (for the end-user) in the context menu which is supported by default on native Android, we can add it on all platforms or Android only, it's similar to native Android though not the same.

— Reply to this email directly, view it on GitHub https://github.com/singerdmx/flutter-quill/issues/2350#issuecomment-2467636108, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAXMGLNDN5OVAD7MXNZXQFL2ABZNTAVCNFSM6AAAAABRHUH7DSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDINRXGYZTMMJQHA . You are receiving this because you were mentioned.Message ID: @.***>