Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add onPaste to TextInput #804

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Changes from 2 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
58 changes: 58 additions & 0 deletions proposals/0000-textinput-onpaste.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
title: Add onPaste to TextInput
author:
- Abdelhafidh Belalia
date: 2024-07-18
---

# RFC0000: Add onPaste to TextInput

## Summary

Add `onPaste` prop to `TextInput` component

## Basic example

```js
<TextInput onPaste={() => console.log("User pressed Paste")} />
```

## Motivation

Detect `Paste` event on TextInput. In our use case detecting paste event can be used to support image pasting.

## Detailed design

iOS:

1. In `RCTUITextField`/`RCTUITextView` override the `paste:` method to call the delegate adapater `[didPaste]`
2. Implement the `didPaste` method on the delegate adapater and call the delegate input `[textInputDidPaste]`
3. Implement the `textInputDidPaste` method on the delegate input to disptach the `onPaste` event

Android:

1. In `ReactEditText` override the `onTextContextMenuItem` method to call the `PasteWatcher` insatnce
2. In `ReactTextInputManager` create and set the `PasteWatcher` instance for the view (`ReactEditText`)
3. Implement the `PasteWatcher` class to to disptach the `onPaste` event

There is a PR for that change already https://github.com/facebook/react-native/pull/45425

## Drawbacks

None

## Alternatives

None

## Adoption strategy

This is not a breaking change. Developers can adopt the feature by simply adding `onPaste` prop to their components

## How we teach this

Update the docs https://github.com/facebook/react-native-website/pull/4161

## Unresolved questions

- onPaste event does not expose any clipboard data. How can we add such data?
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@NickGerleman Can we handle this as a follow up?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. The event without data would require accessing clipboard afterward, and since that happens asynchronously, the data may have changed or be incorrect. A concrete example of this, is if you paste a password, a password manager might immediately clear it from the clipboard.

I.e. the current approach without the data is impossible to make reliable, and would encourage users to add code which falls into the anti-pattern.

I don't know how much time @cipolleschi has dedicated to this change, but did want to share the context I had on this, and some of the baselines of what these events should look like.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The data can be as follow:

{
    target: viewTag,
    items: [
        {
            type: "image/jpeg", // MIME type
            data: "data:image/jpeg;base64,..." // data: plaintext for text/plain and base64 encoded data for the rest
        }
    ],
}

items is an array that holds different items present in the clipboard, but for the current implementation only the first item is added.

Android implementation facebook/react-native@af06d9e

Screen.Recording.2024-07-24.at.3.22.50.AM-2.mov

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding pasting files, using base64 string is not looking very performant (dealing with long strings can be slow). I'm looking into passing the URI instead, for Android we can directly use clipData.getItemAt(0).getUri()

(still investigating the same for iOS)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On iOS the clipboard items do not expose any URI. When a file is pasted, we copy its data into a temporarily file and provide that file's URI instead. Proposal updated.