diff --git a/__tests__/Storyshots.test.js b/__tests__/Storyshots.test.js index 9b14d0d5..0395eef2 100644 --- a/__tests__/Storyshots.test.js +++ b/__tests__/Storyshots.test.js @@ -1,3 +1,6 @@ import initStoryshots from '@storybook/addon-storyshots'; +jest.mock('../app/lib/database', () => jest.fn(() => null)); +global.Date.now = jest.fn(() => new Date('2019-10-10').getTime()); + initStoryshots(); diff --git a/app/containers/Avatar/Avatar.js b/app/containers/Avatar/Avatar.js index 97871115..0b898a3c 100644 --- a/app/containers/Avatar/Avatar.js +++ b/app/containers/Avatar/Avatar.js @@ -25,7 +25,8 @@ const Avatar = React.memo(({ avatarETag, isStatic, rid, - blockUnauthenticatedAccess + blockUnauthenticatedAccess, + serverVersion }) => { if ((!text && !avatar && !emoji && !rid) || !server) { return null; @@ -60,6 +61,7 @@ const Avatar = React.memo(({ avatar, server, avatarETag, + serverVersion, rid, blockUnauthenticatedAccess }); @@ -114,7 +116,8 @@ Avatar.propTypes = { avatarETag: PropTypes.string, isStatic: PropTypes.bool, rid: PropTypes.string, - blockUnauthenticatedAccess: PropTypes.bool + blockUnauthenticatedAccess: PropTypes.bool, + serverVersion: PropTypes.string }; Avatar.defaultProps = { diff --git a/app/containers/Avatar/index.js b/app/containers/Avatar/index.js index 3218ec7a..73314a17 100644 --- a/app/containers/Avatar/index.js +++ b/app/containers/Avatar/index.js @@ -13,7 +13,8 @@ class AvatarContainer extends React.Component { rid: PropTypes.string, text: PropTypes.string, type: PropTypes.string, - blockUnauthenticatedAccess: PropTypes.bool + blockUnauthenticatedAccess: PropTypes.bool, + serverVersion: PropTypes.string }; static defaultProps = { @@ -83,9 +84,11 @@ class AvatarContainer extends React.Component { render() { const { avatarETag } = this.state; + const { serverVersion } = this.props; return ( ); @@ -94,7 +97,8 @@ class AvatarContainer extends React.Component { const mapStateToProps = state => ({ user: getUserSelector(state), - server: state.share.server || state.server.server, + server: state.share.server.server || state.server.server, + serverVersion: state.share.server.version || state.server.version, blockUnauthenticatedAccess: state.share.settings?.Accounts_AvatarBlockUnauthenticatedAccess ?? state.settings.Accounts_AvatarBlockUnauthenticatedAccess diff --git a/app/containers/MessageBox/EmojiKeyboard.js b/app/containers/MessageBox/EmojiKeyboard.js index 8d552509..3cd183e5 100644 --- a/app/containers/MessageBox/EmojiKeyboard.js +++ b/app/containers/MessageBox/EmojiKeyboard.js @@ -17,7 +17,7 @@ export default class EmojiKeyboard extends React.PureComponent { constructor(props) { super(props); const state = store.getState(); - this.baseUrl = state.share.server || state.server.server; + this.baseUrl = state.share.server.server || state.server.server; } onEmojiSelected = (emoji) => { diff --git a/app/containers/message/MessageAvatar.js b/app/containers/message/MessageAvatar.js index 4c0f5468..7fcdffb5 100644 --- a/app/containers/message/MessageAvatar.js +++ b/app/containers/message/MessageAvatar.js @@ -1,14 +1,14 @@ import React, { useContext } from 'react'; import PropTypes from 'prop-types'; -import Avatar from '../Avatar/Avatar'; +import Avatar from '../Avatar'; import styles from './styles'; import MessageContext from './Context'; const MessageAvatar = React.memo(({ isHeader, avatar, author, small, navToRoomInfo, emoji, getCustomEmoji, theme }) => { - const { baseUrl, user } = useContext(MessageContext); + const { user } = useContext(MessageContext); if (isHeader && author) { const navParam = { t: 'd', @@ -22,9 +22,6 @@ const MessageAvatar = React.memo(({ borderRadius={small ? 2 : 4} onPress={author._id === user.id ? undefined : () => navToRoomInfo(navParam)} getCustomEmoji={getCustomEmoji} - user={user} - server={baseUrl} - avatarETag={author.avatarETag} avatar={avatar} emoji={emoji} theme={theme} diff --git a/app/containers/message/index.js b/app/containers/message/index.js index 269a8e85..4dfe0162 100644 --- a/app/containers/message/index.js +++ b/app/containers/message/index.js @@ -9,7 +9,6 @@ import { SYSTEM_MESSAGES, getMessageTranslation } from './utils'; import { E2E_MESSAGE_TYPE, E2E_STATUS } from '../../lib/encryption/constants'; import messagesStatus from '../../constants/messagesStatus'; import { withTheme } from '../../theme'; -import database from '../../lib/database'; class MessageContainer extends React.Component { static propTypes = { @@ -74,11 +73,7 @@ class MessageContainer extends React.Component { theme: 'light' } - state = { - author: null - } - - async componentDidMount() { + componentDidMount() { const { item } = this.props; if (item && item.observe) { const observable = item.observe(); @@ -86,19 +81,6 @@ class MessageContainer extends React.Component { this.forceUpdate(); }); } - - const db = database.active; - const usersCollection = db.collections.get('users'); - try { - const user = await usersCollection.find(item.u?._id); - const observable = user.observe(); - this.userSubscription = observable.subscribe((author) => { - this.setState({ author }); - this.forceUpdate(); - }); - } catch { - // Do nothing - } } shouldComponentUpdate(nextProps) { @@ -113,9 +95,6 @@ class MessageContainer extends React.Component { if (this.subscription && this.subscription.unsubscribe) { this.subscription.unsubscribe(); } - if (this.userSubscription && this.userSubscription.unsubscribe) { - this.userSubscription.unsubscribe(); - } } onPress = debounce(() => { @@ -264,7 +243,6 @@ class MessageContainer extends React.Component { } render() { - const { author } = this.state; const { item, user, style, archived, baseUrl, useRealName, broadcast, fetchThreadName, showAttachment, timeFormat, isReadReceiptEnabled, autoTranslateRoom, autoTranslateLanguage, navToRoomInfo, getCustomEmoji, isThreadRoom, callJitsi, blockAction, rid, theme, getBadgeColor, toggleFollowThread } = this.props; @@ -302,7 +280,7 @@ class MessageContainer extends React.Component { id={id} msg={message} rid={rid} - author={author || u} + author={u} ts={ts} type={t} attachments={attachments} diff --git a/app/i18n/locales/ru.js b/app/i18n/locales/ru.js index 8f33924a..7da47108 100644 --- a/app/i18n/locales/ru.js +++ b/app/i18n/locales/ru.js @@ -662,7 +662,7 @@ export default { Logout_failed: 'Выход не успешен!', Log_analytics_events: 'Журнал событий аналитики', E2E_encryption_change_password_title: 'Изменить пароль шифрования', - E2E_encryption_change_password_description: 'Теперь вы можете создавать зашифрованные прватные чаты и личные беседы. Вы так же можете сделать существующие приватные чаты и личные беседы шифрованными. \nЭто сквозное шифрование, поэтому ключь для шифрования\дешифрования ваших сообщений не будет сохранен на сервере. Именно поэтому вам необходимо сохранить ваш пароль в надежном и безопасном месте. Вам необходимо вводить этот пароль на всех устройствах, где вы хотите использовать E2E шифрование.', + E2E_encryption_change_password_description: 'Теперь вы можете создавать зашифрованные прватные чаты и личные беседы. Вы так же можете сделать существующие приватные чаты и личные беседы шифрованными. \nЭто сквозное шифрование, поэтому ключь для шифрования\nдешифрования ваших сообщений не будет сохранен на сервере. Именно поэтому вам необходимо сохранить ваш пароль в надежном и безопасном месте. Вам необходимо вводить этот пароль на всех устройствах, где вы хотите использовать E2E шифрование.', E2E_encryption_change_password_error: 'Ошибка при смене пароля E2E ключа!', E2E_encryption_change_password_success: 'Пароль ключа E2E изменен успешно!', E2E_encryption_change_password_message: 'Убедитесь, что вы сохранили пароль в надежном мпсте.', diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index 92995852..9e246cb8 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -320,8 +320,16 @@ const RocketChat = { this.shareSDK = new RocketchatClient({ host: server, protocol: 'ddp', useSsl: useSsl(server) }); // set Server + const currentServer = { server }; const serversDB = database.servers; - reduxStore.dispatch(shareSelectServer(server)); + const serversCollection = serversDB.collections.get('servers'); + try { + const serverRecord = await serversCollection.find(server); + currentServer.version = serverRecord.version; + } catch { + // Record not found + } + reduxStore.dispatch(shareSelectServer(currentServer)); RocketChat.setCustomEmojis(); @@ -368,6 +376,7 @@ const RocketChat = { } database.share = null; + reduxStore.dispatch(shareSelectServer({})); reduxStore.dispatch(shareSetUser({})); reduxStore.dispatch(shareSetSettings({})); }, diff --git a/app/presentation/RoomItem/RoomItem.js b/app/presentation/RoomItem/RoomItem.js index b5133fd0..8d9d0eba 100644 --- a/app/presentation/RoomItem/RoomItem.js +++ b/app/presentation/RoomItem/RoomItem.js @@ -19,10 +19,7 @@ const RoomItem = ({ avatar, width, avatarSize, - baseUrl, - userId, username, - token, showLastMessage, status, useRealName, @@ -48,8 +45,7 @@ const RoomItem = ({ onPress, toggleFav, toggleRead, - hideChannel, - avatarETag + hideChannel }) => ( @@ -160,11 +152,8 @@ RoomItem.propTypes = { prid: PropTypes.string, name: PropTypes.string.isRequired, avatar: PropTypes.string.isRequired, - baseUrl: PropTypes.string.isRequired, showLastMessage: PropTypes.bool, - userId: PropTypes.string, username: PropTypes.string, - token: PropTypes.string, avatarSize: PropTypes.number, testID: PropTypes.string, width: PropTypes.number, @@ -191,8 +180,7 @@ RoomItem.propTypes = { toggleFav: PropTypes.func, toggleRead: PropTypes.func, onPress: PropTypes.func, - hideChannel: PropTypes.func, - avatarETag: PropTypes.string + hideChannel: PropTypes.func }; RoomItem.defaultProps = { diff --git a/app/presentation/RoomItem/Wrapper.js b/app/presentation/RoomItem/Wrapper.js index 2a0d17bc..52aa0f8a 100644 --- a/app/presentation/RoomItem/Wrapper.js +++ b/app/presentation/RoomItem/Wrapper.js @@ -4,17 +4,13 @@ import PropTypes from 'prop-types'; import styles from './styles'; import { themes } from '../../constants/colors'; -import Avatar from '../../containers/Avatar/Avatar'; +import Avatar from '../../containers/Avatar'; const Wrapper = ({ accessibilityLabel, avatar, avatarSize, - avatarETag, type, - baseUrl, - userId, - token, theme, rid, children @@ -28,9 +24,6 @@ const Wrapper = ({ size={avatarSize} type={type} style={styles.avatar} - server={baseUrl} - user={{ id: userId, token }} - avatarETag={avatarETag} rid={rid} /> props[key] === nextProps[key]); } @@ -88,9 +79,6 @@ class RoomItemContainer extends React.Component { } componentWillUnmount() { - if (this.avatarSubscription?.unsubscribe) { - this.avatarSubscription.unsubscribe(); - } if (this.roomSubscription?.unsubscribe) { this.roomSubscription.unsubscribe(); } @@ -106,7 +94,7 @@ class RoomItemContainer extends React.Component { return t === 'd' && id && !this.isGroupChat; } - init = async() => { + init = () => { const { item } = this.props; if (item?.observe) { const observable = item.observe(); @@ -114,35 +102,6 @@ class RoomItemContainer extends React.Component { this.forceUpdate(); }); } - - const db = database.active; - const usersCollection = db.collections.get('users'); - const subsCollection = db.collections.get('subscriptions'); - try { - const { id } = this.props; - const { rid } = item; - - let record; - if (this.isDirect) { - record = await usersCollection.find(id); - } else { - record = await subsCollection.find(rid); - } - - if (record) { - const observable = record.observe(); - this.avatarSubscription = observable.subscribe((u) => { - const { avatarETag } = u; - if (this.mounted) { - this.setState({ avatarETag }); - } else { - this.state.avatarETag = avatarETag; - } - }); - } - } catch { - // Record not found - } } onPress = () => { @@ -151,7 +110,6 @@ class RoomItemContainer extends React.Component { } render() { - const { avatarETag } = this.state; const { item, getRoomTitle, @@ -165,9 +123,6 @@ class RoomItemContainer extends React.Component { theme, isFocused, avatarSize, - baseUrl, - userId, - token, status, showLastMessage, username, @@ -215,9 +170,6 @@ class RoomItemContainer extends React.Component { theme={theme} isFocused={isFocused} size={avatarSize} - baseUrl={baseUrl} - userId={userId} - token={token} prid={item.prid} status={status} hideUnreadStatus={item.hideUnreadStatus} @@ -233,7 +185,6 @@ class RoomItemContainer extends React.Component { tunread={item.tunread} tunreadUser={item.tunreadUser} tunreadGroup={item.tunreadGroup} - avatarETag={avatarETag || item.avatarETag} swipeEnabled={swipeEnabled} /> ); diff --git a/app/reducers/share.js b/app/reducers/share.js index 069d36d7..4f2a22a1 100644 --- a/app/reducers/share.js +++ b/app/reducers/share.js @@ -2,7 +2,7 @@ import { SHARE } from '../actions/actionsTypes'; const initialState = { user: {}, - server: '', + server: {}, settings: {} }; diff --git a/app/sagas/encryption.js b/app/sagas/encryption.js index 8c74ede2..3aaed531 100644 --- a/app/sagas/encryption.js +++ b/app/sagas/encryption.js @@ -19,7 +19,7 @@ import { showErrorAlert } from '../utils/info'; import I18n from '../i18n'; import log from '../utils/log'; -const getServer = state => state.share.server || state.server.server; +const getServer = state => state.share.server.server || state.server.server; const getE2eEnable = state => state.settings.E2E_Enable; const handleEncryptionInit = function* handleEncryptionInit() { diff --git a/app/utils/avatar.js b/app/utils/avatar.js index 54ad2238..9e76ceaa 100644 --- a/app/utils/avatar.js +++ b/app/utils/avatar.js @@ -1,19 +1,14 @@ import semver from 'semver'; -import reduxStore from '../lib/createStore'; - const formatUrl = (url, size, query) => `${ url }?format=png&size=${ size }${ query }`; export const avatarURL = ({ - type, text, size, user = {}, avatar, server, avatarETag, rid, blockUnauthenticatedAccess + type, text, size, user = {}, avatar, server, avatarETag, rid, blockUnauthenticatedAccess, serverVersion }) => { - const { version: serverVersion } = reduxStore.getState().server; - const isLegacy = serverVersion && semver.lt(semver.coerce(serverVersion), '3.6.0'); - let room; if (type === 'd') { room = text; - } else if (rid && !isLegacy) { + } else if (rid && !(serverVersion && semver.lt(semver.coerce(serverVersion), '3.6.0'))) { room = `room/${ rid }`; } else { room = `@${ text }`; diff --git a/app/views/CreateDiscussionView/SelectChannel.js b/app/views/CreateDiscussionView/SelectChannel.js index 806e9009..fff60982 100644 --- a/app/views/CreateDiscussionView/SelectChannel.js +++ b/app/views/CreateDiscussionView/SelectChannel.js @@ -12,7 +12,7 @@ import { themes } from '../../constants/colors'; import styles from './styles'; const SelectChannel = ({ - server, token, userId, onChannelSelect, initial, blockUnauthenticatedAccess, theme + server, token, userId, onChannelSelect, initial, blockUnauthenticatedAccess, serverVersion, theme }) => { const [channels, setChannels] = useState([]); @@ -32,7 +32,8 @@ const SelectChannel = ({ server, avatarETag: item.avatarETag, rid: item.rid, - blockUnauthenticatedAccess + blockUnauthenticatedAccess, + serverVersion }); return ( @@ -63,6 +64,7 @@ SelectChannel.propTypes = { initial: PropTypes.object, onChannelSelect: PropTypes.func, blockUnauthenticatedAccess: PropTypes.bool, + serverVersion: PropTypes.string, theme: PropTypes.string }; diff --git a/app/views/CreateDiscussionView/SelectUsers.js b/app/views/CreateDiscussionView/SelectUsers.js index e3a40436..a88773ab 100644 --- a/app/views/CreateDiscussionView/SelectUsers.js +++ b/app/views/CreateDiscussionView/SelectUsers.js @@ -15,7 +15,7 @@ import styles from './styles'; import { themes } from '../../constants/colors'; const SelectUsers = ({ - server, token, userId, selected, onUserSelect, blockUnauthenticatedAccess, theme + server, token, userId, selected, onUserSelect, blockUnauthenticatedAccess, serverVersion, theme }) => { const [users, setUsers] = useState([]); @@ -53,7 +53,8 @@ const SelectUsers = ({ user: { id: userId, token }, server, avatarETag: item.avatarETag, - blockUnauthenticatedAccess + blockUnauthenticatedAccess, + serverVersion }); return ( @@ -84,6 +85,7 @@ SelectUsers.propTypes = { selected: PropTypes.array, onUserSelect: PropTypes.func, blockUnauthenticatedAccess: PropTypes.bool, + serverVersion: PropTypes.string, theme: PropTypes.string }; diff --git a/app/views/CreateDiscussionView/index.js b/app/views/CreateDiscussionView/index.js index ebad1fa6..afadb5e6 100644 --- a/app/views/CreateDiscussionView/index.js +++ b/app/views/CreateDiscussionView/index.js @@ -40,7 +40,8 @@ class CreateChannelView extends React.Component { error: PropTypes.object, theme: PropTypes.string, isMasterDetail: PropTypes.bool, - blockUnauthenticatedAccess: PropTypes.bool + blockUnauthenticatedAccess: PropTypes.bool, + serverVersion: PropTypes.string } constructor(props) { @@ -144,7 +145,7 @@ class CreateChannelView extends React.Component { render() { const { name, users } = this.state; const { - server, user, loading, blockUnauthenticatedAccess, theme + server, user, loading, blockUnauthenticatedAccess, theme, serverVersion } = this.props; return ( ({ loading: state.createDiscussion.isFetching, result: state.createDiscussion.result, blockUnauthenticatedAccess: state.settings.Accounts_AvatarBlockUnauthenticatedAccess ?? true, + serverVersion: state.share.server.version || state.server.version, isMasterDetail: state.app.isMasterDetail }); diff --git a/app/views/RoomInfoEditView/index.js b/app/views/RoomInfoEditView/index.js index 2d295223..b42c83ec 100644 --- a/app/views/RoomInfoEditView/index.js +++ b/app/views/RoomInfoEditView/index.js @@ -405,6 +405,11 @@ class RoomInfoEditView extends React.Component { this.setState({ encrypted: value }); } + isServerVersionLowerThan = (version) => { + const { serverVersion } = this.props; + return serverVersion && semver.lt(semver.coerce(serverVersion), version); + } + render() { const { name, nameError, description, topic, announcement, t, ro, reactWhenReadOnly, room, joinCode, saving, permissions, archived, enableSysMes, encrypted, avatar @@ -428,7 +433,11 @@ class RoomInfoEditView extends React.Component { testID='room-info-edit-view-list' {...scrollPersistTaps} > - + - - - + {this.isServerVersionLowerThan('3.6.0') + ? null + : ( + + + + ) + } ({ - serverVersion: state.server.version, + serverVersion: state.share.server.version || state.server.version, e2eEnabled: state.settings.E2E_Enable || false }); diff --git a/app/views/RoomsListView/index.js b/app/views/RoomsListView/index.js index 8c1d78c3..cfd88a8e 100644 --- a/app/views/RoomsListView/index.js +++ b/app/views/RoomsListView/index.js @@ -896,12 +896,7 @@ class RoomsListView extends React.Component { const { item: currentItem } = this.state; const { - user: { - id: userId, - username, - token - }, - server, + user: { username }, StoreLastMessage, useRealName, theme, @@ -916,10 +911,7 @@ class RoomsListView extends React.Component { theme={theme} id={id} type={item.t} - userId={userId} username={username} - token={token} - baseUrl={server} showLastMessage={StoreLastMessage} onPress={this.onPressItem} testID={`rooms-list-view-item-${ item.name }`} diff --git a/app/views/SelectServerView.js b/app/views/SelectServerView.js index 8213a236..f956feba 100644 --- a/app/views/SelectServerView.js +++ b/app/views/SelectServerView.js @@ -106,7 +106,7 @@ class SelectServerView extends React.Component { } const mapStateToProps = (({ share }) => ({ - server: share.server + server: share.server.server })); export default connect(mapStateToProps)(withTheme(SelectServerView)); diff --git a/app/views/ShareListView/index.js b/app/views/ShareListView/index.js index 2544d43b..6bcf295d 100644 --- a/app/views/ShareListView/index.js +++ b/app/views/ShareListView/index.js @@ -473,7 +473,7 @@ class ShareListView extends React.Component { const mapStateToProps = (({ share }) => ({ userId: share.user && share.user.id, token: share.user && share.user.token, - server: share.server + server: share.server.server })); export default connect(mapStateToProps)(withTheme(ShareListView)); diff --git a/app/views/ShareView/index.js b/app/views/ShareView/index.js index 9e8c710e..6909f447 100644 --- a/app/views/ShareView/index.js +++ b/app/views/ShareView/index.js @@ -345,7 +345,7 @@ ShareView.propTypes = { const mapStateToProps = state => ({ user: getUserSelector(state), - server: state.share.server || state.server.server, + server: state.share.server.server || state.server.server, FileUpload_MediaTypeWhiteList: state.settings.FileUpload_MediaTypeWhiteList, FileUpload_MaxFileSize: state.settings.FileUpload_MaxFileSize }); diff --git a/app/views/ThreadMessagesView/Item.stories.js b/app/views/ThreadMessagesView/Item.stories.js index 81181e98..191583a6 100644 --- a/app/views/ThreadMessagesView/Item.stories.js +++ b/app/views/ThreadMessagesView/Item.stories.js @@ -56,8 +56,13 @@ const reducers = combineReducers({ name: 'Rocket Cat' } }), + server: () => ({ + server: 'https://open.rocket.chat', + version: '3.7.0' + }), share: () => ({ - server: 'https://open.rocket.chat' + server: 'https://open.rocket.chat', + version: '3.7.0' }), settings: () => ({ blockUnauthenticatedAccess: false diff --git a/storybook/index.js b/storybook/index.js index 99b30178..aac761a4 100644 --- a/storybook/index.js +++ b/storybook/index.js @@ -4,11 +4,6 @@ import { getStorybookUI, configure } from '@storybook/react-native'; // eslint-d import RNBootSplash from 'react-native-bootsplash'; import 'react-native-gesture-handler'; -// eslint-disable-next-line no-undef -jest.mock('../app/lib/database', () => jest.fn(() => null)); // comment this line to make storybook work -// eslint-disable-next-line no-undef -jest.mock('../app/lib/createStore', () => ({ getState: () => ({ server: {} }) })); // comment this line to make storybook work - RNBootSplash.hide(); // import stories diff --git a/storybook/stories/index.js b/storybook/stories/index.js index 4be88875..2865f5b5 100644 --- a/storybook/stories/index.js +++ b/storybook/stories/index.js @@ -37,7 +37,15 @@ const reducers = combineReducers({ username: 'diego.mello' } }), - share: () => ({ settings: {} }), + server: () => ({ + server: 'https://open.rocket.chat', + version: '3.7.0' + }), + share: () => ({ + server: 'https://open.rocket.chat', + version: '3.7.0', + settings: {} + }), meteor: () => ({ connected: true }), activeUsers: () => ({ abc: { status: 'online', statusText: 'dog' } }) }); diff --git a/yarn.lock b/yarn.lock index 3d17db72..9cb69950 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6162,16 +6162,16 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.2.tgz#ac74db0bba8d33808bbf36809c3a5c3683531436" integrity sha512-dmD3AvJQBUjKpcNkoqr+x+IF0SdRtPz9Vk0uTy4yWqga9ibB6s4v++QFWNohjiUGoMlF552ZvNyXDxz5iW0qmw== -envinfo@^7.1.0: - version "7.5.1" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.5.1.tgz#93c26897225a00457c75e734d354ea9106a72236" - integrity sha512-hQBkDf2iO4Nv0CNHpCuSBeaSrveU6nThVxFGTrq/eDlV716UQk09zChaJae4mZRsos1x4YLY2TaH3LHUae3ZmQ== - envinfo@^7.5.0: version "7.7.0" resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.7.0.tgz#fbfa46d739dec0554ef40220cd91fb20f64c9698" integrity sha512-XX0+kACx7HcIFhar/JjsDtDIVcC8hnzQO1Asehq+abs+v9MtzpUuujFb6eBTT4lF9j2Bh6d2XFngbFRryjUAeQ== +envinfo@^7.7.2: + version "7.7.3" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.7.3.tgz#4b2d8622e3e7366afb8091b23ed95569ea0208cc" + integrity sha512-46+j5QxbPWza0PB1i15nZx0xQ4I/EfQxg9J8Had3b408SV63nEtor2e+oiY63amTo9KTuh2a3XLObNwduxYwwA== + errno@^0.1.3, errno@~0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" @@ -7829,6 +7829,13 @@ hermes-engine@~0.5.0: resolved "https://registry.yarnpkg.com/hermes-engine/-/hermes-engine-0.5.0.tgz#d914acce72e9657b3c98875ad3f9094d8643f327" integrity sha512-jSuHiOhdh2+IF3bH2gLpQ37eMkdUrEb9GK6PoG3rLRaUDK3Zn2Y9fXM+wyDfoUTA3gz9EET0/IIWk5k21qp4kw== +hermes-profile-transformer@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz#bd0f5ecceda80dd0ddaae443469ab26fb38fc27b" + integrity sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ== + dependencies: + source-map "^0.7.3" + hex-lite@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/hex-lite/-/hex-lite-1.5.0.tgz#482db64f673dcacdb8be93c629a799ce5a76b24d"