diff --git a/app/containers/Avatar/Avatar.tsx b/app/containers/Avatar/Avatar.tsx index 4f2da1806..5457f6f50 100644 --- a/app/containers/Avatar/Avatar.tsx +++ b/app/containers/Avatar/Avatar.tsx @@ -8,7 +8,6 @@ import { getAvatarURL } from '../../lib/methods/helpers/getAvatarUrl'; import { SubscriptionType } from '../../definitions'; import Emoji from '../markdown/Emoji'; import { IAvatar } from './interfaces'; -import { useTheme } from '../../theme'; const Avatar = React.memo( ({ @@ -16,7 +15,8 @@ const Avatar = React.memo( style, avatar, children, - user, + userId, + token, onPress, emoji, getCustomEmoji, @@ -31,8 +31,6 @@ const Avatar = React.memo( type = SubscriptionType.DIRECT, externalProviderUrl }: IAvatar) => { - const { theme } = useTheme(); - if ((!text && !avatar && !emoji && !rid) || !server) { return null; } @@ -46,14 +44,7 @@ const Avatar = React.memo( let image; if (emoji) { image = ( - + ); } else { let uri = avatar; @@ -62,7 +53,8 @@ const Avatar = React.memo( type, text, size, - user, + userId, + token, avatar, server, avatarETag, diff --git a/app/containers/Avatar/index.tsx b/app/containers/Avatar/index.tsx index 404e3e4c9..9f762308d 100644 --- a/app/containers/Avatar/index.tsx +++ b/app/containers/Avatar/index.tsx @@ -1,84 +1,65 @@ -import React from 'react'; -import { connect } from 'react-redux'; import { Q } from '@nozbe/watermelondb'; +import React, { useEffect, useRef, useState } from 'react'; +import { shallowEqual, useSelector } from 'react-redux'; import { Observable, Subscription } from 'rxjs'; +import { IApplicationState, TSubscriptionModel, TUserModel } from '../../definitions'; import database from '../../lib/database'; import { getUserSelector } from '../../selectors/login'; -import { IApplicationState, TSubscriptionModel, TUserModel } from '../../definitions'; import Avatar from './Avatar'; import { IAvatar } from './interfaces'; -class AvatarContainer extends React.Component { - private subscription?: Subscription; +const AvatarContainer = ({ + style, + text = '', + avatar, + emoji, + size, + borderRadius, + type, + children, + onPress, + getCustomEmoji, + isStatic, + rid +}: IAvatar): React.ReactElement => { + const subscription = useRef(); + const [avatarETag, setAvatarETag] = useState(''); - static defaultProps = { - text: '', - type: 'd' - }; + const isDirect = () => type === 'd'; - constructor(props: IAvatar) { - super(props); - this.state = { avatarETag: '' }; - this.init(); - } + const server = useSelector((state: IApplicationState) => state.share.server.server || state.server.server); + const serverVersion = useSelector((state: IApplicationState) => state.share.server.version || state.server.version); + const { id, token } = useSelector( + (state: IApplicationState) => ({ + id: getUserSelector(state).id, + token: getUserSelector(state).token + }), + shallowEqual + ); - componentDidUpdate(prevProps: IAvatar) { - const { text, type } = this.props; - if (prevProps.text !== text || prevProps.type !== type) { - this.init(); - } - } + const externalProviderUrl = useSelector( + (state: IApplicationState) => state.settings.Accounts_AvatarExternalProviderUrl as string + ); + const blockUnauthenticatedAccess = useSelector( + (state: IApplicationState) => + (state.share.settings?.Accounts_AvatarBlockUnauthenticatedAccess as boolean) ?? + state.settings.Accounts_AvatarBlockUnauthenticatedAccess ?? + true + ); - shouldComponentUpdate(nextProps: IAvatar, nextState: { avatarETag: string }) { - const { avatarETag } = this.state; - const { text, type, size, externalProviderUrl } = this.props; - if (nextProps.externalProviderUrl !== externalProviderUrl) { - return true; - } - if (nextState.avatarETag !== avatarETag) { - return true; - } - if (nextProps.text !== text) { - return true; - } - if (nextProps.type !== type) { - return true; - } - if (nextProps.size !== size) { - return true; - } - - return false; - } - - componentWillUnmount() { - if (this.subscription?.unsubscribe) { - this.subscription.unsubscribe(); - } - } - - get isDirect() { - const { type } = this.props; - return type === 'd'; - } - - init = async () => { + const init = async () => { const db = database.active; const usersCollection = db.get('users'); const subsCollection = db.get('subscriptions'); let record; try { - if (this.isDirect) { - const { text } = this.props; + if (isDirect()) { const [user] = await usersCollection.query(Q.where('username', text)).fetch(); record = user; - } else { - const { rid } = this.props; - if (rid) { - record = await subsCollection.find(rid); - } + } else if (rid) { + record = await subsCollection.find(rid); } } catch { // Record not found @@ -86,28 +67,46 @@ class AvatarContainer extends React.Component { if (record) { const observable = record.observe() as Observable; - this.subscription = observable.subscribe(r => { - const { avatarETag } = r; - this.setState({ avatarETag }); + subscription.current = observable.subscribe(r => { + setAvatarETag(r.avatarETag); }); } }; - render() { - const { avatarETag } = this.state; - const { serverVersion } = this.props; - return ; - } -} + useEffect(() => { + if (!avatarETag) { + init(); + } + return () => { + if (subscription?.current?.unsubscribe) { + subscription.current.unsubscribe(); + } + }; + }, [text, type, size, avatarETag, externalProviderUrl]); -const mapStateToProps = (state: IApplicationState) => ({ - user: getUserSelector(state), - server: state.share.server.server || state.server.server, - serverVersion: state.share.server.version || state.server.version, - blockUnauthenticatedAccess: - (state.share.settings?.Accounts_AvatarBlockUnauthenticatedAccess as boolean) ?? - state.settings.Accounts_AvatarBlockUnauthenticatedAccess ?? - true, - externalProviderUrl: state.settings.Accounts_AvatarExternalProviderUrl as string -}); -export default connect(mapStateToProps)(AvatarContainer); + return ( + + ); +}; + +export default AvatarContainer; diff --git a/app/containers/Avatar/interfaces.ts b/app/containers/Avatar/interfaces.ts index c4be26f7b..8124f4e65 100644 --- a/app/containers/Avatar/interfaces.ts +++ b/app/containers/Avatar/interfaces.ts @@ -5,23 +5,21 @@ import { TGetCustomEmoji } from '../../definitions/IEmoji'; export interface IAvatar { server?: string; style?: any; - text: string; + text?: string; avatar?: string; emoji?: string; size?: number; borderRadius?: number; type?: string; children?: React.ReactElement | null; - user?: { - id?: string; - token?: string; - }; + userId?: string; + token?: string; onPress?: () => void; getCustomEmoji?: TGetCustomEmoji; avatarETag?: string; isStatic?: boolean | string; rid?: string; blockUnauthenticatedAccess?: boolean; - serverVersion: string | null; + serverVersion?: string | null; externalProviderUrl?: string; } diff --git a/app/containers/markdown/Emoji.tsx b/app/containers/markdown/Emoji.tsx index 8abfd8161..130d1cda0 100644 --- a/app/containers/markdown/Emoji.tsx +++ b/app/containers/markdown/Emoji.tsx @@ -3,9 +3,8 @@ import { Text } from 'react-native'; import shortnameToUnicode from '../../lib/methods/helpers/shortnameToUnicode'; import CustomEmoji from '../EmojiPicker/CustomEmoji'; -import { themes } from '../../lib/constants'; import styles from './styles'; -import { TSupportedThemes } from '../../theme'; +import { useTheme } from '../../theme'; interface IEmoji { literal: string; @@ -14,13 +13,13 @@ interface IEmoji { baseUrl: string; customEmojis?: any; style?: object; - theme: TSupportedThemes; onEmojiSelected?: Function; tabEmojiStyle?: object; } const Emoji = React.memo( - ({ literal, isMessageContainsOnlyEmoji, getCustomEmoji, baseUrl, customEmojis = true, style = {}, theme }: IEmoji) => { + ({ literal, isMessageContainsOnlyEmoji, getCustomEmoji, baseUrl, customEmojis = true, style = {} }: IEmoji) => { + const { colors } = useTheme(); const emojiUnicode = shortnameToUnicode(literal); const emoji: any = getCustomEmoji && getCustomEmoji(literal.replace(/:/g, '')); if (emoji && customEmojis) { @@ -33,7 +32,7 @@ const Emoji = React.memo( ); } return ( - + {emojiUnicode} ); diff --git a/app/containers/markdown/index.tsx b/app/containers/markdown/index.tsx index 16c86d1d0..7b7c3f92b 100644 --- a/app/containers/markdown/index.tsx +++ b/app/containers/markdown/index.tsx @@ -233,7 +233,7 @@ class Markdown extends PureComponent { }; renderEmoji = ({ literal }: TLiteral) => { - const { getCustomEmoji, baseUrl = '', customEmojis, style, theme } = this.props; + const { getCustomEmoji, baseUrl = '', customEmojis, style } = this.props; return ( { baseUrl={baseUrl} customEmojis={customEmojis} style={style} - theme={theme} /> ); }; diff --git a/app/lib/methods/helpers/getAvatarUrl.ts b/app/lib/methods/helpers/getAvatarUrl.ts index 1c4c18dd3..bf5c732fc 100644 --- a/app/lib/methods/helpers/getAvatarUrl.ts +++ b/app/lib/methods/helpers/getAvatarUrl.ts @@ -6,9 +6,10 @@ const formatUrl = (url: string, size: number, query?: string) => `${url}?format= export const getAvatarURL = ({ type, - text, + text = '', size = 25, - user = {}, + userId, + token, avatar, server, avatarETag, @@ -30,10 +31,9 @@ export const getAvatarURL = ({ room = `@${text}`; } - const { id, token } = user; let query = ''; - if (id && token && blockUnauthenticatedAccess) { - query += `&rc_token=${token}&rc_uid=${id}`; + if (userId && token && blockUnauthenticatedAccess) { + query += `&rc_token=${token}&rc_uid=${userId}`; } if (avatarETag) { query += `&etag=${avatarETag}`; diff --git a/app/views/CreateDiscussionView/SelectChannel.tsx b/app/views/CreateDiscussionView/SelectChannel.tsx index f96562fa7..5e09af9a6 100644 --- a/app/views/CreateDiscussionView/SelectChannel.tsx +++ b/app/views/CreateDiscussionView/SelectChannel.tsx @@ -36,7 +36,8 @@ const SelectChannel = ({ getAvatarURL({ text: getRoomAvatar(item), type: item.t, - user: { id: userId, token }, + userId, + token, server, avatarETag: item.avatarETag, rid: item.rid, diff --git a/app/views/CreateDiscussionView/SelectUsers.tsx b/app/views/CreateDiscussionView/SelectUsers.tsx index a58410f76..7cb3a98cb 100644 --- a/app/views/CreateDiscussionView/SelectUsers.tsx +++ b/app/views/CreateDiscussionView/SelectUsers.tsx @@ -40,7 +40,8 @@ const SelectUsers = ({ getAvatarURL({ text: getRoomAvatar(item), type: SubscriptionType.DIRECT, - user: { id: userId, token }, + userId, + token, server, avatarETag: item.avatarETag, blockUnauthenticatedAccess,