Skip to content

Commit

Permalink
deps: Migrate to @react-native-clipboard/clipboard
Browse files Browse the repository at this point in the history
`Clipboard` in RN core is deprecated; see warning at
  https://reactnative.dev/docs/clipboard

We've reportedly been getting console warnings that we should use
@react-native-community/clipboard instead of the RN-core module. Do
basically that, except we use its new name,
@react-native-clipboard/clipboard; see
  react-native-clipboard/clipboard#87

Put the types in a .js.flow file, rather than a libdef in
`flow-typed/`, inspired by Greg's commit 007dea3.

Supersedes: #4502
Co-authored-by: rajprakash00 <rajprakash1999@gmail.com>
  • Loading branch information
chrisbobbe and rajprakash00 committed Mar 29, 2022
1 parent dc5ab4c commit 3d9cd20
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 5 deletions.
6 changes: 5 additions & 1 deletion .eslintrc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,11 @@ rules:
- devDependencies: ['**/__tests__/**/*.js', tools/**]
no-restricted-imports:
- error
- patterns:
- paths:
- name: 'react-native'
importNames: ['Clipboard']
message: 'Use Clipboard from @react-native-clipboard/clipboard instead.'
patterns:
- group: ['**/__tests__/**']
- group: ['/react-redux']
message: 'Use our own src/react-redux.js instead.'
Expand Down
2 changes: 1 addition & 1 deletion .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ module.name_mapper='^react-native/\(.*\)$' -> '<PROJECT_ROOT>/node_modules/react
module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '<PROJECT_ROOT>/node_modules/react-native/Libraries/Image/RelativeImageStub'
# This lets us write .js.flow files instead of libdefs.
# Add more libraries as needed to this pattern with `\|`: `foo\|bar\|…`.
module.name_mapper='^\(sqlite3\|@react-navigation/bottom-tabs\|@react-navigation/drawer\|@react-navigation/material-top-tabs\|@react-navigation/native\|@react-navigation/stack\)$' -> '<PROJECT_ROOT>/types/\0'
module.name_mapper='^\(sqlite3\|@react-navigation/bottom-tabs\|@react-navigation/drawer\|@react-navigation/material-top-tabs\|@react-navigation/native\|@react-navigation/stack\|@react-native-clipboard/clipboard\)$' -> '<PROJECT_ROOT>/types/\0'

suppress_type=$FlowIssue
suppress_type=$FlowFixMe
Expand Down
6 changes: 6 additions & 0 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,8 @@ PODS:
- React-Core
- RNCAsyncStorage (1.16.1):
- React-Core
- RNCClipboard (1.8.5):
- React-Core
- RNCMaskedView (0.1.11):
- React
- RNCPushNotificationIOS (1.10.1):
Expand Down Expand Up @@ -480,6 +482,7 @@ DEPENDENCIES:
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- rn-fetch-blob (from `../node_modules/rn-fetch-blob`)
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
- "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)"
- "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)"
- "RNCPushNotificationIOS (from `../node_modules/@react-native-community/push-notification-ios`)"
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
Expand Down Expand Up @@ -603,6 +606,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/rn-fetch-blob"
RNCAsyncStorage:
:path: "../node_modules/@react-native-async-storage/async-storage"
RNCClipboard:
:path: "../node_modules/@react-native-clipboard/clipboard"
RNCMaskedView:
:path: "../node_modules/@react-native-community/masked-view"
RNCPushNotificationIOS:
Expand Down Expand Up @@ -680,6 +685,7 @@ SPEC CHECKSUMS:
ReactCommon: 8fea6422328e2fc093e25c9fac67adbcf0f04fb4
rn-fetch-blob: f525a73a78df9ed5d35e67ea65e79d53c15255bc
RNCAsyncStorage: b49b4e38a1548d03b74b30e558a1d18465b94be7
RNCClipboard: cc054ad1e8a33d2a74cd13e565588b4ca928d8fd
RNCMaskedView: 0e1bc4bfa8365eba5fbbb71e07fbdc0555249489
RNCPushNotificationIOS: 87b8d16d3ede4532745e05b03c42cff33a36cc45
RNDeviceInfo: 4944cf8787b9c5bffaf301fda68cc1a2ec003341
Expand Down
6 changes: 6 additions & 0 deletions jest/jestSetup.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { polyfillGlobal } from 'react-native/Libraries/Utilities/PolyfillFunctio
import { URL, URLSearchParams } from 'react-native-url-polyfill';
// $FlowIgnore[untyped-import] - this is not anywhere near critical
import mockAsyncStorage from '@react-native-async-storage/async-storage/jest/async-storage-mock';
// $FlowIgnore[untyped-import] - this is not anywhere near critical
import mockClipboard from '@react-native-clipboard/clipboard/jest/clipboard-mock';

import { assertUsingModernFakeTimers } from '../src/__tests__/lib/fakeTimers';

Expand Down Expand Up @@ -102,6 +104,10 @@ jest.mock('react-native-reanimated', () => {

jest.mock('@react-native-async-storage/async-storage', () => mockAsyncStorage);

// As instructed at
// https://github.com/react-native-clipboard/clipboard/tree/v1.9.0#mocking-clipboard
jest.mock('@react-native-clipboard/clipboard', () => mockClipboard);

// Without this, we get lots of these errors on importing the module:
// `Invariant Violation: Native module cannot be null.`
jest.mock('@react-native-community/push-notification-ios', () => ({
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"dependencies": {
"@expo/react-native-action-sheet": "^3.8.0",
"@react-native-async-storage/async-storage": "^1.13.0",
"@react-native-clipboard/clipboard": "^1.8.5",
"@react-native-community/cameraroll": "chrisbobbe/react-native-cameraroll#17fa5d8d2",
"@react-native-community/masked-view": "^0.1.10",
"@react-native-community/netinfo": "6.0.0",
Expand Down
3 changes: 2 additions & 1 deletion src/RootErrorBoundary.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/* @flow strict-local */
import React from 'react';
import type { Node } from 'react';
import { View, Text, Clipboard, TextInput, ScrollView, Button, Platform } from 'react-native';
import { View, Text, TextInput, ScrollView, Button, Platform } from 'react-native';
import Clipboard from '@react-native-clipboard/clipboard';
import Toast from 'react-native-simple-toast';
// $FlowFixMe[untyped-import]
import isEqual from 'lodash.isequal';
Expand Down
3 changes: 2 additions & 1 deletion src/action-sheets/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* @flow strict-local */
import { Clipboard, Share, Alert } from 'react-native';
import { Share, Alert } from 'react-native';
import Clipboard from '@react-native-clipboard/clipboard';
import invariant from 'invariant';
import * as resolved_topic from '@zulip/shared/js/resolved_topic';

Expand Down
3 changes: 2 additions & 1 deletion src/webview/handleOutboundEvents.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* @flow strict-local */
import { Clipboard, Alert } from 'react-native';
import { Alert } from 'react-native';
import Clipboard from '@react-native-clipboard/clipboard';

import * as NavigationService from '../nav/NavigationService';
import * as api from '../api';
Expand Down
154 changes: 154 additions & 0 deletions types/@react-native-clipboard/clipboard.js.flow
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/**
* Flowtype definitions for Clipboard
* Generated by Flowgen from a Typescript Definition
* Flowgen v1.11.0
*
* @flow strict-local
*/

import type EmitterSubscription from 'react-native/Libraries/vendor/emitter/_EmitterSubscription';

/**
* `Clipboard` gives you an interface for setting and getting content from Clipboard on both iOS and Android
*/
declare var Clipboard: {
/**
* Get content of string type, this method returns a `Promise`, so you can use following code to get clipboard content
* ```javascript
* async _getContent() {
* var content = await Clipboard.getString();
* }
* ```
*/
getString(): Promise<string>,

/**
* Get clipboard image as PNG in base64, this method returns a `Promise`, so you can use following code to get clipboard content
* ```javascript
* async _getContent() {
* var content = await Clipboard.getImagePNG();
* }
* ```
*/
getImagePNG(): Promise<string>,

/**
* Get clipboard image as JPG in base64, this method returns a `Promise`, so you can use following code to get clipboard content
* ```javascript
* async _getContent() {
* var content = await Clipboard.getImageJPG();
* }
* ```
*/
getImageJPG(): Promise<string>,

/**
* Set content of base64 image type. You can use following code to set clipboard content
* ```javascript
* _setContent() {
* Clipboard.setImage(...);
* }
*
* iOS only
* ```
* @param the content to be stored in the clipboard.
*/
setImage(content: string): void,
getImage(): Promise<string>,

/**
* Set content of string type. You can use following code to set clipboard content
* ```javascript
* _setContent() {
* Clipboard.setString('hello world');
* }
* ```
* @param the content to be stored in the clipboard.
*/
setString(content: string): void,

/**
* Returns whether the clipboard has content or is empty.
* This method returns a `Promise`, so you can use following code to get clipboard content
* ```javascript
* async _hasContent() {
* var hasContent = await Clipboard.hasString();
* }
* ```
*/
hasString(): $FlowFixMe, // `any` in TypeScript upstream :(

/**
* Returns whether the clipboard has an image or is empty.
* This method returns a `Promise`, so you can use following code to check clipboard content
* ```javascript
* async _hasContent() {
* var hasContent = await Clipboard.hasImage();
* }
* ```
*/
hasImage(): $FlowFixMe, // `any` in TypeScript upstream :(

/**
* (IOS Only)
* Returns whether the clipboard has a URL content. Can check
* if there is a URL content in clipboard without triggering PasteBoard notification for iOS 14+
* This method returns a `Promise`, so you can use following code to check for url content in clipboard.
* ```javascript
* async _hasURL() {
* var hasURL = await Clipboard.hasURL();
* }
* ```
*/
hasURL(): $FlowFixMe, // `any` in TypeScript upstream :(

/**
* (IOS 14+ Only)
* Returns whether the clipboard has a Number(UIPasteboardDetectionPatternNumber) content. Can check
* if there is a Number content in clipboard without triggering PasteBoard notification for iOS 14+
* This method returns a `Promise`, so you can use following code to check for Number content in clipboard.
* ```javascript
* async _hasNumber() {
* var hasNumber = await Clipboard.hasNumber();
* }
* ```
*/
hasNumber(): $FlowFixMe, // `any` in TypeScript upstream :(

/**
* (IOS 14+ Only)
* Returns whether the clipboard has a WebURL(UIPasteboardDetectionPatternProbableWebURL) content. Can check
* if there is a WebURL content in clipboard without triggering PasteBoard notification for iOS 14+
* This method returns a `Promise`, so you can use following code to check for WebURL content in clipboard.
* ```javascript
* async _hasWebURL() {
* var hasWebURL = await Clipboard.hasWebURL();
* }
* ```
*/
hasWebURL(): $FlowFixMe, // `any` in TypeScript upstream :(

/**
* (iOS and Android Only)
* Adds a listener to get notifications when the clipboard has changed.
* If this is the first listener, turns on clipboard notifications on the native side.
* It returns EmitterSubscription where you can call "remove" to remove listener
* ```javascript
* const listener = () => console.log("changed!");
* Clipboard.addListener(listener);
* ```
*/
addListener(callback: () => void): EmitterSubscription,

/**
* (iOS and Android Only)
* Removes all previously registered listeners and turns off notifications on the native side.
* ```javascript
* Clipboard.removeAllListeners();
* ```
*/
removeAllListeners(): void,
...
};

export default Clipboard;
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1795,6 +1795,11 @@
dependencies:
merge-options "^3.0.4"

"@react-native-clipboard/clipboard@^1.8.5":
version "1.8.5"
resolved "https://registry.yarnpkg.com/@react-native-clipboard/clipboard/-/clipboard-1.8.5.tgz#b11276e38ef288b0fd70c0a38506e2deecc5fa5a"
integrity sha512-o2RPDwP9JMnLece1Qq6a3Fsz/VxfA9auLckkGOor7WcI82DWaWiJ6Uiyu7H1xpaUyqWc+ypVKRX680GYS36HjA==

"@react-native-community/cameraroll@chrisbobbe/react-native-cameraroll#17fa5d8d2":
version "4.0.4"
resolved "https://codeload.github.com/chrisbobbe/react-native-cameraroll/tar.gz/17fa5d8d2f4e00ec78304070a0b91292e884b7f5"
Expand Down

0 comments on commit 3d9cd20

Please sign in to comment.