From d6da8665c6752f2819346c5ade1b66bb1701f206 Mon Sep 17 00:00:00 2001 From: Gerzon Z Date: Fri, 26 Feb 2021 12:01:45 -0400 Subject: [PATCH] [IMPROVEMENT] Remove lodash.isEqual (#2893) * Added dequal and react-fast-compare as substitutes to lodash.isEqual * Update ReplyPreview.js * Remove react-fast-compare * Removed deep-equal and upgrade babel-eslint dev dependency * Fix avatar * Fix Messagebox * Fix CreateDiscussionView * ModalBlockView * NewMessageView * ProfileView * RoomInfoEditView * ServerDropdown * Return local search as object instead of observable * SelectedUsersView Co-authored-by: Diego Mello --- .eslintrc.js | 8 +- app/containers/Avatar/index.js | 4 +- app/containers/EmojiPicker/index.js | 4 +- app/containers/InAppNotification/index.js | 4 +- .../MessageBox/CommandsPreview/index.js | 4 +- app/containers/MessageBox/Mentions/index.js | 4 +- app/containers/MessageBox/ReplyPreview.js | 3 +- app/containers/MessageBox/index.js | 13 +- app/containers/message/Attachments.js | 4 +- app/containers/message/Audio.js | 4 +- app/containers/message/Content.js | 6 +- app/containers/message/Image.js | 4 +- app/containers/message/Reply.js | 6 +- app/containers/message/Urls.js | 6 +- app/containers/message/Video.js | 4 +- app/ee/omnichannel/views/QueueListView.js | 4 +- app/lib/rocketchat.js | 22 +-- app/presentation/RoomItem/LastMessage.js | 4 +- app/views/CreateChannelView.js | 4 +- app/views/CreateDiscussionView/index.js | 4 +- app/views/LoginView.js | 4 +- app/views/MessagesView/index.js | 4 +- app/views/ModalBlockView.js | 12 -- app/views/NewMessageView.js | 16 -- app/views/ProfileView/index.js | 14 +- app/views/ReadReceiptView/index.js | 4 +- app/views/RoomInfoEditView/index.js | 18 +- app/views/RoomView/Header/RightButtons.js | 8 +- app/views/RoomView/Header/index.js | 4 +- app/views/RoomView/List.js | 10 +- app/views/RoomView/index.js | 8 +- app/views/RoomsListView/ServerDropdown.js | 19 -- app/views/RoomsListView/index.js | 12 +- app/views/SearchMessagesView/index.js | 4 +- app/views/SelectedUsersView.js | 22 --- app/views/ShareListView/index.js | 4 +- app/views/ShareView/Thumbs.js | 1 + app/views/ShareView/index.js | 4 +- app/views/SidebarView/index.js | 12 +- package.json | 6 +- yarn.lock | 169 ++++-------------- 41 files changed, 143 insertions(+), 328 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 44e4eaf4c..add372a0b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -6,7 +6,7 @@ module.exports = { } } }, - "parser": "babel-eslint", + "parser": "@babel/eslint-parser", "extends": "airbnb", "parserOptions": { "sourceType": "module", @@ -21,7 +21,8 @@ module.exports = { "react", "jsx-a11y", "import", - "react-native" + "react-native", + "@babel" ], "env": { "browser": true, @@ -148,7 +149,8 @@ module.exports = { "react/jsx-curly-newline": [0], "react/state-in-constructor": [0], "no-async-promise-executor": [0], - "max-classes-per-file": [0] + "max-classes-per-file": [0], + "no-multiple-empty-lines": [0] }, "globals": { "__DEV__": true diff --git a/app/containers/Avatar/index.js b/app/containers/Avatar/index.js index 73314a17d..8c4ca0ad4 100644 --- a/app/containers/Avatar/index.js +++ b/app/containers/Avatar/index.js @@ -2,7 +2,6 @@ import React from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { Q } from '@nozbe/watermelondb'; -import isEqual from 'react-fast-compare'; import database from '../../lib/database'; import { getUserSelector } from '../../selectors/login'; @@ -34,7 +33,8 @@ class AvatarContainer extends React.Component { } componentDidUpdate(prevProps) { - if (!isEqual(prevProps, this.props)) { + const { text, type } = this.props; + if (prevProps.text !== text || prevProps.type !== type) { this.init(); } } diff --git a/app/containers/EmojiPicker/index.js b/app/containers/EmojiPicker/index.js index 65a973715..64d941c6f 100644 --- a/app/containers/EmojiPicker/index.js +++ b/app/containers/EmojiPicker/index.js @@ -2,7 +2,7 @@ import React, { Component } from 'react'; import { View } from 'react-native'; import PropTypes from 'prop-types'; import ScrollableTabView from 'react-native-scrollable-tab-view'; -import equal from 'deep-equal'; +import { dequal } from 'dequal'; import { connect } from 'react-redux'; import orderBy from 'lodash/orderBy'; import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord'; @@ -67,7 +67,7 @@ class EmojiPicker extends Component { if (nextState.width !== width) { return true; } - if (!equal(nextState.frequentlyUsed, frequentlyUsed)) { + if (!dequal(nextState.frequentlyUsed, frequentlyUsed)) { return true; } return false; diff --git a/app/containers/InAppNotification/index.js b/app/containers/InAppNotification/index.js index 2083b8f1b..53e4bb264 100644 --- a/app/containers/InAppNotification/index.js +++ b/app/containers/InAppNotification/index.js @@ -2,7 +2,7 @@ import React, { memo, useEffect } from 'react'; import PropTypes from 'prop-types'; import { NotifierRoot, Notifier, Easing } from 'react-native-notifier'; import { connect } from 'react-redux'; -import isEqual from 'deep-equal'; +import { dequal } from 'dequal'; import NotifierComponent from './NotifierComponent'; import EventEmitter from '../../utils/events'; @@ -38,7 +38,7 @@ const InAppNotification = memo(({ rooms }) => { }, [rooms]); return ; -}, (prevProps, nextProps) => isEqual(prevProps.rooms, nextProps.rooms)); +}, (prevProps, nextProps) => dequal(prevProps.rooms, nextProps.rooms)); const mapStateToProps = state => ({ rooms: state.room.rooms diff --git a/app/containers/MessageBox/CommandsPreview/index.js b/app/containers/MessageBox/CommandsPreview/index.js index 1b6a27acd..1bb03ca8b 100644 --- a/app/containers/MessageBox/CommandsPreview/index.js +++ b/app/containers/MessageBox/CommandsPreview/index.js @@ -1,7 +1,7 @@ import React from 'react'; import { FlatList } from 'react-native'; import PropTypes from 'prop-types'; -import equal from 'deep-equal'; +import { dequal } from 'dequal'; import Item from './Item'; import styles from '../styles'; @@ -31,7 +31,7 @@ const CommandsPreview = React.memo(({ theme, commandPreview, showCommandPreview if (prevProps.showCommandPreview !== nextProps.showCommandPreview) { return false; } - if (!equal(prevProps.commandPreview, nextProps.commandPreview)) { + if (!dequal(prevProps.commandPreview, nextProps.commandPreview)) { return false; } return true; diff --git a/app/containers/MessageBox/Mentions/index.js b/app/containers/MessageBox/Mentions/index.js index 37c30c30b..fb845b2ad 100644 --- a/app/containers/MessageBox/Mentions/index.js +++ b/app/containers/MessageBox/Mentions/index.js @@ -1,7 +1,7 @@ import React from 'react'; import { FlatList, View } from 'react-native'; import PropTypes from 'prop-types'; -import equal from 'deep-equal'; +import { dequal } from 'dequal'; import styles from '../styles'; import MentionItem from './MentionItem'; @@ -30,7 +30,7 @@ const Mentions = React.memo(({ mentions, trackingType, theme }) => { if (prevProps.trackingType !== nextProps.trackingType) { return false; } - if (!equal(prevProps.mentions, nextProps.mentions)) { + if (!dequal(prevProps.mentions, nextProps.mentions)) { return false; } return true; diff --git a/app/containers/MessageBox/ReplyPreview.js b/app/containers/MessageBox/ReplyPreview.js index 1a77a2540..eee81236d 100644 --- a/app/containers/MessageBox/ReplyPreview.js +++ b/app/containers/MessageBox/ReplyPreview.js @@ -3,7 +3,6 @@ import { View, Text, StyleSheet } from 'react-native'; import PropTypes from 'prop-types'; import moment from 'moment'; import { connect } from 'react-redux'; -import isEqual from 'lodash/isEqual'; import Markdown from '../markdown'; import { CustomIcon } from '../../lib/Icons'; @@ -75,7 +74,7 @@ const ReplyPreview = React.memo(({ ); -}, (prevProps, nextProps) => prevProps.replying === nextProps.replying && prevProps.theme === nextProps.theme && isEqual(prevProps.message, nextProps.message)); +}, (prevProps, nextProps) => prevProps.replying === nextProps.replying && prevProps.theme === nextProps.theme && prevProps.message.id === nextProps.message.id); ReplyPreview.propTypes = { replying: PropTypes.bool, diff --git a/app/containers/MessageBox/index.js b/app/containers/MessageBox/index.js index 0f9696b17..d509004bc 100644 --- a/app/containers/MessageBox/index.js +++ b/app/containers/MessageBox/index.js @@ -6,7 +6,7 @@ import { import { connect } from 'react-redux'; import { KeyboardAccessoryView } from 'react-native-ui-lib/keyboard'; import ImagePicker from 'react-native-image-crop-picker'; -import equal from 'deep-equal'; +import { dequal } from 'dequal'; import DocumentPicker from 'react-native-document-picker'; import { Q } from '@nozbe/watermelondb'; import { TouchableWithoutFeedback } from 'react-native-gesture-handler'; @@ -271,7 +271,7 @@ class MessageBox extends Component { } = this.state; const { - roomType, replying, editing, isFocused, message, theme, children + roomType, replying, editing, isFocused, message, theme } = this.props; if (nextProps.theme !== theme) { return true; @@ -300,16 +300,13 @@ class MessageBox extends Component { if (nextState.tshow !== tshow) { return true; } - if (!equal(nextState.mentions, mentions)) { + if (!dequal(nextState.mentions, mentions)) { return true; } - if (!equal(nextState.commandPreview, commandPreview)) { + if (!dequal(nextState.commandPreview, commandPreview)) { return true; } - if (!equal(nextProps.message, message)) { - return true; - } - if (!equal(nextProps.children, children)) { + if (!dequal(nextProps.message?.id, message?.id)) { return true; } return false; diff --git a/app/containers/message/Attachments.js b/app/containers/message/Attachments.js index 3d4ff48b4..0d068e9fd 100644 --- a/app/containers/message/Attachments.js +++ b/app/containers/message/Attachments.js @@ -1,5 +1,5 @@ import React from 'react'; -import isEqual from 'lodash/isEqual'; +import { dequal } from 'dequal'; import PropTypes from 'prop-types'; import Image from './Image'; @@ -28,7 +28,7 @@ const Attachments = React.memo(({ // eslint-disable-next-line react/no-array-index-key return ; }); -}, (prevProps, nextProps) => isEqual(prevProps.attachments, nextProps.attachments) && prevProps.theme === nextProps.theme); +}, (prevProps, nextProps) => dequal(prevProps.attachments, nextProps.attachments) && prevProps.theme === nextProps.theme); Attachments.propTypes = { attachments: PropTypes.array, diff --git a/app/containers/message/Audio.js b/app/containers/message/Audio.js index fad195890..e22dff408 100644 --- a/app/containers/message/Audio.js +++ b/app/containers/message/Audio.js @@ -6,7 +6,7 @@ import { import { Audio } from 'expo-av'; import Slider from '@react-native-community/slider'; import moment from 'moment'; -import equal from 'deep-equal'; +import { dequal } from 'dequal'; import { activateKeepAwake, deactivateKeepAwake } from 'expo-keep-awake'; import Touchable from './Touchable'; @@ -150,7 +150,7 @@ class MessageAudio extends React.Component { if (nextState.paused !== paused) { return true; } - if (!equal(nextProps.file, file)) { + if (!dequal(nextProps.file, file)) { return true; } if (nextState.loading !== loading) { diff --git a/app/containers/message/Content.js b/app/containers/message/Content.js index c963fed5c..2f29bf4ac 100644 --- a/app/containers/message/Content.js +++ b/app/containers/message/Content.js @@ -1,7 +1,7 @@ import React, { useContext } from 'react'; import { Text, View } from 'react-native'; import PropTypes from 'prop-types'; -import equal from 'deep-equal'; +import { dequal } from 'dequal'; import I18n from '../../i18n'; import styles from './styles'; @@ -108,10 +108,10 @@ const Content = React.memo((props) => { if (prevProps.isIgnored !== nextProps.isIgnored) { return false; } - if (!equal(prevProps.mentions, nextProps.mentions)) { + if (!dequal(prevProps.mentions, nextProps.mentions)) { return false; } - if (!equal(prevProps.channels, nextProps.channels)) { + if (!dequal(prevProps.channels, nextProps.channels)) { return false; } return true; diff --git a/app/containers/message/Image.js b/app/containers/message/Image.js index 1471b449e..6f466b3b3 100644 --- a/app/containers/message/Image.js +++ b/app/containers/message/Image.js @@ -2,7 +2,7 @@ import React, { useContext } from 'react'; import { View } from 'react-native'; import PropTypes from 'prop-types'; import FastImage from '@rocket.chat/react-native-fast-image'; -import equal from 'deep-equal'; +import { dequal } from 'dequal'; import { createImageProgress } from 'react-native-image-progress'; import * as Progress from 'react-native-progress'; @@ -66,7 +66,7 @@ const ImageContainer = React.memo(({ ); -}, (prevProps, nextProps) => equal(prevProps.file, nextProps.file) && prevProps.theme === nextProps.theme); +}, (prevProps, nextProps) => dequal(prevProps.file, nextProps.file) && prevProps.theme === nextProps.theme); ImageContainer.propTypes = { file: PropTypes.object, diff --git a/app/containers/message/Reply.js b/app/containers/message/Reply.js index 2502cb42c..88c748baa 100644 --- a/app/containers/message/Reply.js +++ b/app/containers/message/Reply.js @@ -2,7 +2,7 @@ import React, { useContext } from 'react'; import { View, Text, StyleSheet } from 'react-native'; import PropTypes from 'prop-types'; import moment from 'moment'; -import isEqual from 'deep-equal'; +import { dequal } from 'dequal'; import Touchable from './Touchable'; import Markdown from '../markdown'; @@ -125,7 +125,7 @@ const Fields = React.memo(({ attachment, theme }) => { ))} ); -}, (prevProps, nextProps) => isEqual(prevProps.attachment.fields, nextProps.attachment.fields) && prevProps.theme === nextProps.theme); +}, (prevProps, nextProps) => dequal(prevProps.attachment.fields, nextProps.attachment.fields) && prevProps.theme === nextProps.theme); const Reply = React.memo(({ attachment, timeFormat, index, getCustomEmoji, theme @@ -187,7 +187,7 @@ const Reply = React.memo(({ /> ); -}, (prevProps, nextProps) => isEqual(prevProps.attachment, nextProps.attachment) && prevProps.theme === nextProps.theme); +}, (prevProps, nextProps) => dequal(prevProps.attachment, nextProps.attachment) && prevProps.theme === nextProps.theme); Reply.propTypes = { attachment: PropTypes.object, diff --git a/app/containers/message/Urls.js b/app/containers/message/Urls.js index 946433d43..742b2f478 100644 --- a/app/containers/message/Urls.js +++ b/app/containers/message/Urls.js @@ -4,7 +4,7 @@ import { } from 'react-native'; import PropTypes from 'prop-types'; import FastImage from '@rocket.chat/react-native-fast-image'; -import isEqual from 'lodash/isEqual'; +import { dequal } from 'dequal'; import Touchable from './Touchable'; import openLink from '../../utils/openLink'; @@ -112,7 +112,7 @@ const Url = React.memo(({ url, index, theme }) => { ); -}, (oldProps, newProps) => isEqual(oldProps.url, newProps.url) && oldProps.theme === newProps.theme); +}, (oldProps, newProps) => dequal(oldProps.url, newProps.url) && oldProps.theme === newProps.theme); const Urls = React.memo(({ urls, theme }) => { if (!urls || urls.length === 0) { @@ -122,7 +122,7 @@ const Urls = React.memo(({ urls, theme }) => { return urls.map((url, index) => ( )); -}, (oldProps, newProps) => isEqual(oldProps.urls, newProps.urls) && oldProps.theme === newProps.theme); +}, (oldProps, newProps) => dequal(oldProps.urls, newProps.urls) && oldProps.theme === newProps.theme); UrlImage.propTypes = { image: PropTypes.string diff --git a/app/containers/message/Video.js b/app/containers/message/Video.js index 2e9ef6c2a..fed0c67f2 100644 --- a/app/containers/message/Video.js +++ b/app/containers/message/Video.js @@ -1,7 +1,7 @@ import React, { useContext } from 'react'; import PropTypes from 'prop-types'; import { StyleSheet } from 'react-native'; -import isEqual from 'deep-equal'; +import { dequal } from 'dequal'; import Touchable from './Touchable'; import Markdown from '../markdown'; @@ -57,7 +57,7 @@ const Video = React.memo(({ ); -}, (prevProps, nextProps) => isEqual(prevProps.file, nextProps.file) && prevProps.theme === nextProps.theme); +}, (prevProps, nextProps) => dequal(prevProps.file, nextProps.file) && prevProps.theme === nextProps.theme); Video.propTypes = { file: PropTypes.object, diff --git a/app/ee/omnichannel/views/QueueListView.js b/app/ee/omnichannel/views/QueueListView.js index 34a307699..a261d481e 100644 --- a/app/ee/omnichannel/views/QueueListView.js +++ b/app/ee/omnichannel/views/QueueListView.js @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { FlatList } from 'react-native'; import { connect } from 'react-redux'; -import isEqual from 'react-fast-compare'; +import { dequal } from 'dequal'; import I18n from '../../../i18n'; import RoomItem, { ROW_HEIGHT } from '../../../presentation/RoomItem'; @@ -56,7 +56,7 @@ class QueueListView extends React.Component { shouldComponentUpdate(nextProps) { const { queued } = this.props; - if (!isEqual(nextProps.queued, queued)) { + if (!dequal(nextProps.queued, queued)) { return true; } diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index 5c768cfab..b9f49ab20 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -620,19 +620,15 @@ const RocketChat = { data = data.slice(0, 7); - data = data.map((sub) => { - if (sub.t !== 'd') { - return { - rid: sub.rid, - name: sub.name, - fname: sub.fname, - avatarETag: sub.avatarETag, - t: sub.t, - encrypted: sub.encrypted - }; - } - return sub; - }); + data = data.map(sub => ({ + rid: sub.rid, + name: sub.name, + fname: sub.fname, + avatarETag: sub.avatarETag, + t: sub.t, + encrypted: sub.encrypted, + lastMessage: sub.lastMessage + })); return data; }, diff --git a/app/presentation/RoomItem/LastMessage.js b/app/presentation/RoomItem/LastMessage.js index b29cb6cd1..25fc2c08d 100644 --- a/app/presentation/RoomItem/LastMessage.js +++ b/app/presentation/RoomItem/LastMessage.js @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import isEqual from 'lodash/isEqual'; +import { dequal } from 'dequal'; import I18n from '../../i18n'; import styles from './styles'; @@ -45,7 +45,7 @@ const formatMsg = ({ return `${ prefix }${ lastMessage.msg }`; }; -const arePropsEqual = (oldProps, newProps) => isEqual(oldProps, newProps); +const arePropsEqual = (oldProps, newProps) => dequal(oldProps, newProps); const LastMessage = React.memo(({ lastMessage, type, showLastMessage, username, alert, useRealName, theme diff --git a/app/views/CreateChannelView.js b/app/views/CreateChannelView.js index 475996f4f..937a48ef2 100644 --- a/app/views/CreateChannelView.js +++ b/app/views/CreateChannelView.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; import { View, Text, Switch, ScrollView, StyleSheet, FlatList } from 'react-native'; -import equal from 'deep-equal'; +import { dequal } from 'dequal'; import TextInput from '../presentation/TextInput'; import Loading from '../containers/Loading'; @@ -133,7 +133,7 @@ class CreateChannelView extends React.Component { if (nextProps.encryptionEnabled !== encryptionEnabled) { return true; } - if (!equal(nextProps.users, users)) { + if (!dequal(nextProps.users, users)) { return true; } return false; diff --git a/app/views/CreateDiscussionView/index.js b/app/views/CreateDiscussionView/index.js index f03c36328..2970ba016 100644 --- a/app/views/CreateDiscussionView/index.js +++ b/app/views/CreateDiscussionView/index.js @@ -2,7 +2,6 @@ import React from 'react'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import { ScrollView, Text, Switch } from 'react-native'; -import isEqual from 'lodash/isEqual'; import Loading from '../../containers/Loading'; import KeyboardView from '../../presentation/KeyboardView'; @@ -63,11 +62,12 @@ class CreateChannelView extends React.Component { } componentDidUpdate(prevProps, prevState) { + const { channel, name } = this.state; const { loading, failure, error, result, isMasterDetail } = this.props; - if (!isEqual(this.state, prevState)) { + if (channel?.rid !== prevState.channel?.rid || name !== prevState.name) { this.setHeader(); } diff --git a/app/views/LoginView.js b/app/views/LoginView.js index bdffd103b..8e9791d36 100644 --- a/app/views/LoginView.js +++ b/app/views/LoginView.js @@ -4,7 +4,7 @@ import { Text, View, StyleSheet, Keyboard, Alert } from 'react-native'; import { connect } from 'react-redux'; -import equal from 'deep-equal'; +import { dequal } from 'dequal'; import sharedStyles from './Styles'; import Button from '../containers/Button'; @@ -82,7 +82,7 @@ class LoginView extends React.Component { UNSAFE_componentWillReceiveProps(nextProps) { const { error } = this.props; - if (nextProps.failure && !equal(error, nextProps.error)) { + if (nextProps.failure && !dequal(error, nextProps.error)) { Alert.alert(I18n.t('Oops'), I18n.t('Login_error')); } } diff --git a/app/views/MessagesView/index.js b/app/views/MessagesView/index.js index 678d28f29..fc840b2d6 100644 --- a/app/views/MessagesView/index.js +++ b/app/views/MessagesView/index.js @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { FlatList, View, Text } from 'react-native'; import { connect } from 'react-redux'; -import equal from 'deep-equal'; +import { dequal } from 'dequal'; import styles from './styles'; import Message from '../../containers/message'; @@ -57,7 +57,7 @@ class MessagesView extends React.Component { if (nextState.loading !== loading) { return true; } - if (!equal(nextState.messages, messages)) { + if (!dequal(nextState.messages, messages)) { return true; } if (fileLoading !== nextState.fileLoading) { diff --git a/app/views/ModalBlockView.js b/app/views/ModalBlockView.js index 2d72fa339..85eee8492 100644 --- a/app/views/ModalBlockView.js +++ b/app/views/ModalBlockView.js @@ -1,7 +1,6 @@ import React from 'react'; import { StyleSheet, View } from 'react-native'; import PropTypes from 'prop-types'; -import isEqual from 'lodash/isEqual'; import { connect } from 'react-redux'; import { KeyboardAwareScrollView } from '@codler/react-native-keyboard-aware-scroll-view'; @@ -94,17 +93,6 @@ class ModalBlockView extends React.Component { EventEmitter.addEventListener(viewId, this.handleUpdate); } - shouldComponentUpdate(nextProps, nextState) { - if (!isEqual(nextProps, this.props)) { - return true; - } - if (!isEqual(nextState, this.state)) { - return true; - } - - return false; - } - componentDidUpdate(prevProps) { const { navigation, route } = this.props; const oldData = prevProps.route.params?.data ?? {}; diff --git a/app/views/NewMessageView.js b/app/views/NewMessageView.js index be47513bc..fb5890ab7 100644 --- a/app/views/NewMessageView.js +++ b/app/views/NewMessageView.js @@ -4,7 +4,6 @@ import { View, StyleSheet, FlatList, Text } from 'react-native'; import { connect } from 'react-redux'; -import equal from 'deep-equal'; import orderBy from 'lodash/orderBy'; import { Q } from '@nozbe/watermelondb'; @@ -77,21 +76,6 @@ class NewMessageView extends React.Component { }; } - shouldComponentUpdate(nextProps, nextState) { - const { search, chats } = this.state; - const { theme } = this.props; - if (nextProps.theme !== theme) { - return true; - } - if (!equal(nextState.search, search)) { - return true; - } - if (!equal(nextState.chats, chats)) { - return true; - } - return false; - } - componentWillUnmount() { if (this.querySubscription && this.querySubscription.unsubscribe) { this.querySubscription.unsubscribe(); diff --git a/app/views/ProfileView/index.js b/app/views/ProfileView/index.js index 053790bf1..7e97422df 100644 --- a/app/views/ProfileView/index.js +++ b/app/views/ProfileView/index.js @@ -6,7 +6,7 @@ import prompt from 'react-native-prompt-android'; import SHA256 from 'js-sha256'; import ImagePicker from 'react-native-image-crop-picker'; import RNPickerSelect from 'react-native-picker-select'; -import isEqual from 'lodash/isEqual'; +import { dequal } from 'dequal'; import omit from 'lodash/omit'; import Touch from '../../utils/touch'; @@ -91,21 +91,11 @@ class ProfileView extends React.Component { * it's resetting the avatar right after * select some image from gallery. */ - if (!isEqual(omit(user, ['status']), omit(nextProps.user, ['status']))) { + if (!dequal(omit(user, ['status']), omit(nextProps.user, ['status']))) { this.init(nextProps.user); } } - shouldComponentUpdate(nextProps, nextState) { - if (!isEqual(nextState, this.state)) { - return true; - } - if (!isEqual(nextProps, this.props)) { - return true; - } - return false; - } - setAvatar = (avatar) => { const { Accounts_AllowUserAvatarChange } = this.props; diff --git a/app/views/ReadReceiptView/index.js b/app/views/ReadReceiptView/index.js index b7456c77a..113e8936a 100644 --- a/app/views/ReadReceiptView/index.js +++ b/app/views/ReadReceiptView/index.js @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { FlatList, View, Text } from 'react-native'; -import equal from 'deep-equal'; +import { dequal } from 'dequal'; import moment from 'moment'; import { connect } from 'react-redux'; @@ -55,7 +55,7 @@ class ReadReceiptView extends React.Component { if (nextState.loading !== loading) { return true; } - if (!equal(nextState.receipts, receipts)) { + if (!dequal(nextState.receipts, receipts)) { return true; } return false; diff --git a/app/views/RoomInfoEditView/index.js b/app/views/RoomInfoEditView/index.js index bf4527e4a..6b0cf68e9 100644 --- a/app/views/RoomInfoEditView/index.js +++ b/app/views/RoomInfoEditView/index.js @@ -4,15 +4,13 @@ import { Text, View, ScrollView, TouchableOpacity, Keyboard, Alert } from 'react-native'; import { connect } from 'react-redux'; -import equal from 'deep-equal'; import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit'; import ImagePicker from 'react-native-image-crop-picker'; -import isEqual from 'lodash/isEqual'; +import { dequal } from 'dequal'; import isEmpty from 'lodash/isEmpty'; import lt from 'semver/functions/lt'; import coerce from 'semver/functions/coerce'; - import database from '../../lib/database'; import { deleteRoom as deleteRoomAction } from '../../actions/room'; import KeyboardView from '../../presentation/KeyboardView'; @@ -88,16 +86,6 @@ class RoomInfoEditView extends React.Component { this.loadRoom(); } - shouldComponentUpdate(nextProps, nextState) { - if (!equal(nextState, this.state)) { - return true; - } - if (!equal(nextProps, this.props)) { - return true; - } - return false; - } - componentWillUnmount() { if (this.querySubscription && this.querySubscription.unsubscribe) { this.querySubscription.unsubscribe(); @@ -202,7 +190,7 @@ class RoomInfoEditView extends React.Component { && room.t === 'p' === t && room.ro === ro && room.reactWhenReadOnly === reactWhenReadOnly - && isEqual(room.sysMes, systemMessages) + && dequal(room.sysMes, systemMessages) && enableSysMes === (room.sysMes && room.sysMes.length > 0) && room.encrypted === encrypted && isEmpty(avatar) @@ -262,7 +250,7 @@ class RoomInfoEditView extends React.Component { params.reactWhenReadOnly = reactWhenReadOnly; } - if (!isEqual(room.sysMes, systemMessages)) { + if (!dequal(room.sysMes, systemMessages)) { params.systemMessages = systemMessages; } diff --git a/app/views/RoomView/Header/RightButtons.js b/app/views/RoomView/Header/RightButtons.js index 42ac86b1b..0c5e6db9b 100644 --- a/app/views/RoomView/Header/RightButtons.js +++ b/app/views/RoomView/Header/RightButtons.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; -import isEqual from 'react-fast-compare'; +import { dequal } from 'dequal'; import * as HeaderButton from '../../../containers/HeaderButton'; import database from '../../../lib/database'; @@ -59,13 +59,13 @@ class RightButtonsContainer extends Component { if (nextState.isFollowingThread !== isFollowingThread) { return true; } - if (!isEqual(nextState.tunread, tunread)) { + if (!dequal(nextState.tunread, tunread)) { return true; } - if (!isEqual(nextState.tunreadUser, tunreadUser)) { + if (!dequal(nextState.tunreadUser, tunreadUser)) { return true; } - if (!isEqual(nextState.tunreadGroup, tunreadGroup)) { + if (!dequal(nextState.tunreadGroup, tunreadGroup)) { return true; } return false; diff --git a/app/views/RoomView/Header/index.js b/app/views/RoomView/Header/index.js index 33663bbe4..05a5f2e12 100644 --- a/app/views/RoomView/Header/index.js +++ b/app/views/RoomView/Header/index.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; -import equal from 'deep-equal'; +import { dequal } from 'dequal'; import Header from './Header'; import LeftButtons from './LeftButtons'; @@ -65,7 +65,7 @@ class RoomHeaderView extends Component { if (nextProps.height !== height) { return true; } - if (!equal(nextProps.usersTyping, usersTyping)) { + if (!dequal(nextProps.usersTyping, usersTyping)) { return true; } if (nextProps.goRoomActionsView !== goRoomActionsView) { diff --git a/app/views/RoomView/List.js b/app/views/RoomView/List.js index 4db965d97..41d424fa3 100644 --- a/app/views/RoomView/List.js +++ b/app/views/RoomView/List.js @@ -3,7 +3,7 @@ import { FlatList, RefreshControl } from 'react-native'; import PropTypes from 'prop-types'; import { Q } from '@nozbe/watermelondb'; import moment from 'moment'; -import isEqual from 'lodash/isEqual'; +import { dequal } from 'dequal'; import styles from './styles'; import database from '../../lib/database'; @@ -89,13 +89,13 @@ class List extends React.Component { if (refreshing !== nextState.refreshing) { return true; } - if (!isEqual(hideSystemMessages, nextProps.hideSystemMessages)) { + if (!dequal(hideSystemMessages, nextProps.hideSystemMessages)) { return true; } - if (!isEqual(tunread, nextProps.tunread)) { + if (!dequal(tunread, nextProps.tunread)) { return true; } - if (!isEqual(ignored, nextProps.ignored)) { + if (!dequal(ignored, nextProps.ignored)) { return true; } return false; @@ -103,7 +103,7 @@ class List extends React.Component { componentDidUpdate(prevProps) { const { hideSystemMessages } = this.props; - if (!isEqual(hideSystemMessages, prevProps.hideSystemMessages)) { + if (!dequal(hideSystemMessages, prevProps.hideSystemMessages)) { this.reload(); } } diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js index cd8ebf9a8..2119fb4a0 100644 --- a/app/views/RoomView/index.js +++ b/app/views/RoomView/index.js @@ -7,7 +7,7 @@ import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord'; import moment from 'moment'; import * as Haptics from 'expo-haptics'; import { Q } from '@nozbe/watermelondb'; -import isEqual from 'lodash/isEqual'; +import { dequal } from 'dequal'; import { withSafeAreaInsets } from 'react-native-safe-area-context'; import Touch from '../../utils/touch'; @@ -205,10 +205,10 @@ class RoomView extends React.Component { if (stateUpdated) { return true; } - if (!isEqual(nextProps.insets, insets)) { + if (!dequal(nextProps.insets, insets)) { return true; } - return roomAttrsUpdate.some(key => !isEqual(nextState.roomUpdate[key], roomUpdate[key])); + return roomAttrsUpdate.some(key => !dequal(nextState.roomUpdate[key], roomUpdate[key])); } componentDidUpdate(prevProps, prevState) { @@ -229,7 +229,7 @@ class RoomView extends React.Component { } // If it's a livechat room if (this.t === 'l') { - if (!isEqual(prevState.roomUpdate.visitor, roomUpdate.visitor)) { + if (!dequal(prevState.roomUpdate.visitor, roomUpdate.visitor)) { this.setHeader(); } } diff --git a/app/views/RoomsListView/ServerDropdown.js b/app/views/RoomsListView/ServerDropdown.js index 77e281afc..aeef8d337 100644 --- a/app/views/RoomsListView/ServerDropdown.js +++ b/app/views/RoomsListView/ServerDropdown.js @@ -4,7 +4,6 @@ import { } from 'react-native'; import PropTypes from 'prop-types'; import { connect, batch } from 'react-redux'; -import equal from 'deep-equal'; import { withSafeAreaInsets } from 'react-native-safe-area-context'; import { toggleServerDropdown as toggleServerDropdownAction } from '../../actions/rooms'; @@ -75,24 +74,6 @@ class ServerDropdown extends Component { } } - shouldComponentUpdate(nextProps, nextState) { - const { servers } = this.state; - const { closeServerDropdown, server, theme } = this.props; - if (nextProps.theme !== theme) { - return true; - } - if (nextProps.closeServerDropdown !== closeServerDropdown) { - return true; - } - if (nextProps.server !== server) { - return true; - } - if (!equal(nextState.servers, servers)) { - return true; - } - return false; - } - componentDidUpdate(prevProps) { const { closeServerDropdown } = this.props; if (prevProps.closeServerDropdown !== closeServerDropdown) { diff --git a/app/views/RoomsListView/index.js b/app/views/RoomsListView/index.js index 6ec23f29c..b71af2968 100644 --- a/app/views/RoomsListView/index.js +++ b/app/views/RoomsListView/index.js @@ -9,7 +9,7 @@ import { RefreshControl } from 'react-native'; import { connect } from 'react-redux'; -import isEqual from 'react-fast-compare'; +import { dequal } from 'dequal'; import Orientation from 'react-native-orientation-locker'; import { Q } from '@nozbe/watermelondb'; import { withSafeAreaInsets } from 'react-native-safe-area-context'; @@ -222,7 +222,7 @@ class RoomsListView extends React.Component { } // Compare changes only once - const chatsNotEqual = !isEqual(nextState.chatsUpdate, chatsUpdate); + const chatsNotEqual = !dequal(nextState.chatsUpdate, chatsUpdate); // If they aren't equal, set to update if focused if (chatsNotEqual) { @@ -253,13 +253,13 @@ class RoomsListView extends React.Component { if (nextProps.width !== width) { return true; } - if (!isEqual(nextState.search, search)) { + if (!dequal(nextState.search, search)) { return true; } - if (!isEqual(nextProps.rooms, rooms)) { + if (!dequal(nextProps.rooms, rooms)) { return true; } - if (!isEqual(nextProps.insets, insets)) { + if (!dequal(nextProps.insets, insets)) { return true; } // If it's focused and there are changes, update @@ -302,7 +302,7 @@ class RoomsListView extends React.Component { roomsRequest(); } // Update current item in case of another action triggers an update on rooms reducer - if (isMasterDetail && item?.rid !== rooms[0] && !isEqual(rooms, prevProps.rooms)) { + if (isMasterDetail && item?.rid !== rooms[0] && !dequal(rooms, prevProps.rooms)) { // eslint-disable-next-line react/no-did-update-set-state this.setState({ item: { rid: rooms[0] } }); } diff --git a/app/views/SearchMessagesView/index.js b/app/views/SearchMessagesView/index.js index ece0c4ecb..7fb585165 100644 --- a/app/views/SearchMessagesView/index.js +++ b/app/views/SearchMessagesView/index.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import { View, FlatList, Text } from 'react-native'; import { Q } from '@nozbe/watermelondb'; import { connect } from 'react-redux'; -import equal from 'deep-equal'; +import { dequal } from 'dequal'; import RCTextInput from '../../containers/TextInput'; import ActivityIndicator from '../../containers/ActivityIndicator'; @@ -69,7 +69,7 @@ class SearchMessagesView extends React.Component { if (nextState.searchText !== searchText) { return true; } - if (!equal(nextState.messages, messages)) { + if (!dequal(nextState.messages, messages)) { return true; } return false; diff --git a/app/views/SelectedUsersView.js b/app/views/SelectedUsersView.js index 666cee3d1..94d2f6b2d 100644 --- a/app/views/SelectedUsersView.js +++ b/app/views/SelectedUsersView.js @@ -2,7 +2,6 @@ import React from 'react'; import PropTypes from 'prop-types'; import { View, StyleSheet, FlatList } from 'react-native'; import { connect } from 'react-redux'; -import equal from 'deep-equal'; import orderBy from 'lodash/orderBy'; import { Q } from '@nozbe/watermelondb'; @@ -70,27 +69,6 @@ class SelectedUsersView extends React.Component { this.setHeader(props.route.params?.showButton); } - shouldComponentUpdate(nextProps, nextState) { - const { search, chats } = this.state; - const { users, loading, theme } = this.props; - if (nextProps.theme !== theme) { - return true; - } - if (nextProps.loading !== loading) { - return true; - } - if (!equal(nextProps.users, users)) { - return true; - } - if (!equal(nextState.search, search)) { - return true; - } - if (!equal(nextState.chats, chats)) { - return true; - } - return false; - } - componentDidUpdate(prevProps) { if (this.isGroupChat()) { const { users } = this.props; diff --git a/app/views/ShareListView/index.js b/app/views/ShareListView/index.js index aa8cf7f6d..b6730876b 100644 --- a/app/views/ShareListView/index.js +++ b/app/views/ShareListView/index.js @@ -7,7 +7,7 @@ import ShareExtension from 'rn-extensions-share'; import * as FileSystem from 'expo-file-system'; import { connect } from 'react-redux'; import * as mime from 'react-native-mime-types'; -import isEqual from 'react-fast-compare'; +import { dequal } from 'dequal'; import { Q } from '@nozbe/watermelondb'; import database from '../../lib/database'; @@ -118,7 +118,7 @@ class ShareListView extends React.Component { const { searchResults } = this.state; if (nextState.searching) { - if (!isEqual(nextState.searchResults, searchResults)) { + if (!dequal(nextState.searchResults, searchResults)) { return true; } } diff --git a/app/views/ShareView/Thumbs.js b/app/views/ShareView/Thumbs.js index 0ce0d7373..26bc54fb4 100644 --- a/app/views/ShareView/Thumbs.js +++ b/app/views/ShareView/Thumbs.js @@ -179,6 +179,7 @@ const Thumbs = React.memo(({ /> ); } + return null; }); Thumbs.propTypes = { attachments: PropTypes.array, diff --git a/app/views/ShareView/index.js b/app/views/ShareView/index.js index 03ea45724..36648a791 100644 --- a/app/views/ShareView/index.js +++ b/app/views/ShareView/index.js @@ -235,7 +235,9 @@ class ShareView extends Component { newSelected = attachments[selectedIndex - 1] || {}; } } - this.setState({ attachments: attachments.filter(att => att.path !== item.path), selected: newSelected ?? selected }); + this.setState({ attachments: attachments.filter(att => att.path !== item.path), selected: newSelected ?? selected }, () => { + this.messagebox?.current?.forceUpdate?.(); + }); } onChangeText = (text) => { diff --git a/app/views/SidebarView/index.js b/app/views/SidebarView/index.js index 6f3ed6023..a14b178cd 100644 --- a/app/views/SidebarView/index.js +++ b/app/views/SidebarView/index.js @@ -4,7 +4,7 @@ import { ScrollView, Text, View, TouchableWithoutFeedback } from 'react-native'; import { connect } from 'react-redux'; -import isEqual from 'react-fast-compare'; +import { dequal } from 'dequal'; import Avatar from '../../containers/Avatar'; import Status from '../../containers/Status/Status'; import { logEvent, events } from '../../utils/log'; @@ -73,7 +73,7 @@ class Sidebar extends Component { if (nextProps.theme !== theme) { return true; } - if (!isEqual(nextProps.user, user)) { + if (!dequal(nextProps.user, user)) { return true; } if (nextProps.isMasterDetail !== isMasterDetail) { @@ -85,16 +85,16 @@ class Sidebar extends Component { if (nextState.isAdmin !== isAdmin) { return true; } - if (!isEqual(nextProps.viewStatisticsPermission, viewStatisticsPermission)) { + if (!dequal(nextProps.viewStatisticsPermission, viewStatisticsPermission)) { return true; } - if (!isEqual(nextProps.viewRoomAdministrationPermission, viewRoomAdministrationPermission)) { + if (!dequal(nextProps.viewRoomAdministrationPermission, viewRoomAdministrationPermission)) { return true; } - if (!isEqual(nextProps.viewUserAdministrationPermission, viewUserAdministrationPermission)) { + if (!dequal(nextProps.viewUserAdministrationPermission, viewUserAdministrationPermission)) { return true; } - if (!isEqual(nextProps.viewPrivilegedSettingPermission, viewPrivilegedSettingPermission)) { + if (!dequal(nextProps.viewPrivilegedSettingPermission, viewPrivilegedSettingPermission)) { return true; } return false; diff --git a/package.json b/package.json index 71bfdbc1e..727a0e8bb 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "bytebuffer": "^5.0.1", "commonmark": "git+https://github.com/RocketChat/commonmark.js.git", "commonmark-react-renderer": "git+https://github.com/RocketChat/commonmark-react-renderer.git", - "deep-equal": "2.0.3", + "dequal": "^2.0.2", "ejson": "2.2.0", "eslint-config-airbnb": "^18.1.0", "expo-apple-authentication": "^2.2.1", @@ -70,7 +70,6 @@ "pretty-bytes": "^5.3.0", "prop-types": "15.7.2", "react": "16.13.1", - "react-fast-compare": "^3.2.0", "react-native": "RocketChat/react-native#0.63.4", "react-native-animatable": "^1.3.3", "react-native-appearance": "0.3.4", @@ -130,6 +129,8 @@ }, "devDependencies": { "@babel/core": "^7.8.4", + "@babel/eslint-parser": "^7.13.4", + "@babel/eslint-plugin": "^7.13.0", "@babel/plugin-proposal-decorators": "^7.8.3", "@babel/runtime": "^7.8.4", "@storybook/addon-storyshots": "5.3.19", @@ -137,7 +138,6 @@ "@types/react-native": "^0.62.7", "axios": "^0.19.2", "babel-core": "^6.26.3", - "babel-eslint": "^9.0.0", "babel-jest": "^25.1.0", "babel-plugin-transform-remove-console": "^6.9.4", "babel-runtime": "^6.26.0", diff --git a/yarn.lock b/yarn.lock index c16c63185..bc0d65951 100644 --- a/yarn.lock +++ b/yarn.lock @@ -76,6 +76,22 @@ semver "^5.4.1" source-map "^0.5.0" +"@babel/eslint-parser@^7.13.4": + version "7.13.4" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.13.4.tgz#dd9df3c70f44d2fb5a6519e8e10ca06c67dca43a" + integrity sha512-WfFEd89SzqmtYox8crTLJuEXyJolZY6Uu6iJpJmw4aMu50zHbYnxzxwuVkCt2cWygw+gLkUPTtAuox7eSnrL8g== + dependencies: + eslint-scope "5.1.0" + eslint-visitor-keys "^1.3.0" + semver "7.0.0" + +"@babel/eslint-plugin@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/eslint-plugin/-/eslint-plugin-7.13.0.tgz#e6d99efcd6b8551adf479e382a47218726179b1b" + integrity sha512-YGwCLc/u/uc3bU+q/fvgRQ62+TkxuyVvdmybK6ElzE49vODp+RnRe16eJzMM7EwvcRPQfQvcOSuGmzfcbZE2+w== + dependencies: + eslint-rule-composer "^0.3.0" + "@babel/generator@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.4.tgz#e49eeed9fe114b62fa5b181856a43a5e32f5f243" @@ -3457,11 +3473,6 @@ array-equal@^1.0.0: resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= -array-filter@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83" - integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM= - array-filter@~0.0.0: version "0.0.1" resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" @@ -3649,13 +3660,6 @@ autoprefixer@^9.7.2: postcss "^7.0.30" postcss-value-parser "^4.1.0" -available-typed-arrays@^1.0.0, available-typed-arrays@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz#6b098ca9d8039079ee3f77f7b783c4480ba513f5" - integrity sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ== - dependencies: - array-filter "^1.0.0" - aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -3717,18 +3721,6 @@ babel-core@^6.0.0, babel-core@^6.26.0, babel-core@^6.26.3: slash "^1.0.0" source-map "^0.5.7" -babel-eslint@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-9.0.0.tgz#7d9445f81ed9f60aff38115f838970df9f2b6220" - integrity sha512-itv1MwE3TMbY0QtNfeL7wzak1mV47Uy+n6HtSOO4Xd7rvmO+tsGQSgyOEEgo6Y2vHZKZphaoelNeSVj4vkLA1g== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.0.0" - "@babel/traverse" "^7.0.0" - "@babel/types" "^7.0.0" - eslint-scope "3.7.1" - eslint-visitor-keys "^1.0.0" - babel-generator@^6.18.0, babel-generator@^6.26.0: version "6.26.1" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" @@ -5741,26 +5733,6 @@ deep-assign@^3.0.0: dependencies: is-obj "^1.0.0" -deep-equal@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.0.3.tgz#cad1c15277ad78a5c01c49c2dee0f54de8a6a7b0" - integrity sha512-Spqdl4H+ky45I9ByyJtXteOm9CaIrPmnIPmOhrkKGNYWeDgCvJ8jNYVCTjChxW4FqGuZnLHADc8EKRMX6+CgvA== - dependencies: - es-abstract "^1.17.5" - es-get-iterator "^1.1.0" - is-arguments "^1.0.4" - is-date-object "^1.0.2" - is-regex "^1.0.5" - isarray "^2.0.5" - object-is "^1.1.2" - object-keys "^1.1.1" - object.assign "^4.1.0" - regexp.prototype.flags "^1.3.0" - side-channel "^1.0.2" - which-boxed-primitive "^1.0.1" - which-collection "^1.0.1" - which-typed-array "^1.1.2" - deep-equal@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" @@ -5871,6 +5843,11 @@ dequal@^1.0.0: resolved "https://registry.yarnpkg.com/dequal/-/dequal-1.0.0.tgz#41c6065e70de738541c82cdbedea5292277a017e" integrity sha512-/Nd1EQbQbI9UbSHrMiKZjFLrXSnU328iQdZKPQf78XQI6C+gutkFUeoHpG5J08Ioa6HeRbRNFpSIclh1xyG0mw== +dequal@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.2.tgz#85ca22025e3a87e65ef75a7a437b35284a7e319d" + integrity sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug== + des.js@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" @@ -6309,7 +6286,7 @@ es-array-method-boxes-properly@^1.0.0: resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== -es-get-iterator@^1.0.2, es-get-iterator@^1.1.0: +es-get-iterator@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.0.tgz#bb98ad9d6d63b31aacdc8f89d5d0ee57bcb5b4c8" integrity sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ== @@ -6484,10 +6461,15 @@ eslint-plugin-react@7.20.3: resolve "^1.17.0" string.prototype.matchall "^4.0.2" -eslint-scope@3.7.1: - version "3.7.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" - integrity sha1-PWPD7f2gLgbgGkUq2IyqzHzctug= +eslint-rule-composer@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" + integrity sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg== + +eslint-scope@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5" + integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" @@ -6515,11 +6497,16 @@ eslint-utils@^1.4.3: dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: +eslint-visitor-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== +eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + eslint@6.8.0: version "6.8.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" @@ -7344,11 +7331,6 @@ for-own@^1.0.0: dependencies: for-in "^1.0.1" -foreach@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" - integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -8458,11 +8440,6 @@ is-arrayish@^0.3.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== -is-bigint@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.0.tgz#73da8c33208d00f130e9b5e15d23eac9215601c4" - integrity sha512-t5mGUXC/xRheCK431ylNiSkGGpBp8bHENBcENTkDT6ppwPzEVxNGZRvgvmOEfbWkFhA7D2GEuE2mmQTr78sl2g== - is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" @@ -8477,11 +8454,6 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-boolean-object@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.1.tgz#10edc0900dd127697a92f6f9807c7617d68ac48e" - integrity sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ== - is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -8525,7 +8497,7 @@ is-data-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" -is-date-object@^1.0.1, is-date-object@^1.0.2: +is-date-object@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== @@ -8665,11 +8637,6 @@ is-map@^2.0.1: resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.1.tgz#520dafc4307bb8ebc33b813de5ce7c9400d644a1" integrity sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw== -is-number-object@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197" - integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw== - is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" @@ -8767,16 +8734,6 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.1" -is-typed-array@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.3.tgz#a4ff5a5e672e1a55f99c7f54e59597af5c1df04d" - integrity sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ== - dependencies: - available-typed-arrays "^1.0.0" - es-abstract "^1.17.4" - foreach "^2.0.5" - has-symbols "^1.0.1" - is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -8787,16 +8744,6 @@ is-utf8@^0.2.0: resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= -is-weakmap@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" - integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA== - -is-weakset@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.1.tgz#e9a0af88dbd751589f5e50d80f4c98b780884f83" - integrity sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw== - is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -11522,7 +11469,7 @@ object-inspect@^1.7.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== -object-is@^1.0.1, object-is@^1.1.2: +object-is@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6" integrity sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ== @@ -12786,11 +12733,6 @@ react-fast-compare@^3.0.1: resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.1.1.tgz#0becf31e3812fa70dc231e259f40d892d4767900" integrity sha512-SCsAORWK59BvauR2L1BTdjQbJcSGJJz03U0awektk2hshLKrITDDFTlgGCqIZpTDlPC/NFlZee6xTMzXPVLiHw== -react-fast-compare@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" - integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== - react-focus-lock@^2.1.0: version "2.3.1" resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.3.1.tgz#9d5d85899773609c7eefa4fc54fff6a0f5f2fc47" @@ -15993,44 +15935,11 @@ whatwg-url@^7.0.0: tr46 "^1.0.1" webidl-conversions "^4.0.2" -which-boxed-primitive@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz#cbe8f838ebe91ba2471bb69e9edbda67ab5a5ec1" - integrity sha512-7BT4TwISdDGBgaemWU0N0OU7FeAEJ9Oo2P1PHRm/FCWoEi2VLWC9b6xvxAA3C/NMpxg3HXVgi0sMmGbNUbNepQ== - dependencies: - is-bigint "^1.0.0" - is-boolean-object "^1.0.0" - is-number-object "^1.0.3" - is-string "^1.0.4" - is-symbol "^1.0.2" - -which-collection@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906" - integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A== - dependencies: - is-map "^2.0.1" - is-set "^2.0.1" - is-weakmap "^2.0.1" - is-weakset "^2.0.1" - which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which-typed-array@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.2.tgz#e5f98e56bda93e3dac196b01d47c1156679c00b2" - integrity sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ== - dependencies: - available-typed-arrays "^1.0.2" - es-abstract "^1.17.5" - foreach "^2.0.5" - function-bind "^1.1.1" - has-symbols "^1.0.1" - is-typed-array "^1.1.3" - which@1.3.1, which@^1.2.12, which@^1.2.9, which@^1.3.0, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"