diff --git a/src/api/gramjs/apiBuilders/chats.ts b/src/api/gramjs/apiBuilders/chats.ts index f86feeca8..d39e81d66 100644 --- a/src/api/gramjs/apiBuilders/chats.ts +++ b/src/api/gramjs/apiBuilders/chats.ts @@ -34,6 +34,8 @@ function buildApiChatFieldsFromPeerEntity( const avatarHash = ('photo' in peerEntity) && peerEntity.photo && buildAvatarHash(peerEntity.photo); const isSignaturesShown = Boolean('signatures' in peerEntity && peerEntity.signatures); const hasPrivateLink = Boolean('hasLink' in peerEntity && peerEntity.hasLink); + const isScam = Boolean('scam' in peerEntity && peerEntity.scam); + const isFake = Boolean('fake' in peerEntity && peerEntity.fake); return { isMin, @@ -60,6 +62,7 @@ function buildApiChatFieldsFromPeerEntity( ...(('creator' in peerEntity) && { isCreator: peerEntity.creator }), ...buildApiChatRestrictions(peerEntity), ...buildApiChatMigrationInfo(peerEntity), + fakeType: isScam ? 'scam' : (isFake ? 'fake' : undefined), }; } diff --git a/src/api/gramjs/apiBuilders/users.ts b/src/api/gramjs/apiBuilders/users.ts index 04a58eb51..5a181634d 100644 --- a/src/api/gramjs/apiBuilders/users.ts +++ b/src/api/gramjs/apiBuilders/users.ts @@ -32,7 +32,9 @@ export function buildApiUser(mtpUser: GramJs.TypeUser): ApiUser | undefined { return undefined; } - const { id, firstName, lastName } = mtpUser; + const { + id, firstName, lastName, fake, scam, + } = mtpUser; const avatarHash = mtpUser.photo instanceof GramJs.UserProfilePhoto ? String(mtpUser.photo.photoId) : undefined; @@ -41,6 +43,7 @@ export function buildApiUser(mtpUser: GramJs.TypeUser): ApiUser | undefined { return { id: buildApiPeerId(id, 'user'), isMin: Boolean(mtpUser.min), + fakeType: scam ? 'scam' : (fake ? 'fake' : undefined), ...(mtpUser.self && { isSelf: true }), ...(mtpUser.verified && { isVerified: true }), ...((mtpUser.contact || mtpUser.mutualContact) && { isContact: true }), diff --git a/src/api/types/chats.ts b/src/api/types/chats.ts index 110b4a29a..4ae0c6d59 100644 --- a/src/api/types/chats.ts +++ b/src/api/types/chats.ts @@ -1,6 +1,7 @@ import { ApiMessage, ApiPhoto } from './messages'; import { ApiBotCommand } from './bots'; import { ApiChatInviteImporter } from './misc'; +import { ApiFakeType } from './users'; type ApiChatType = ( 'chatTypePrivate' | 'chatTypeSecret' | @@ -33,6 +34,7 @@ export interface ApiChat { photos?: ApiPhoto[]; draftDate?: number; isProtected?: boolean; + fakeType?: ApiFakeType; // Calls isCallActive?: boolean; diff --git a/src/api/types/users.ts b/src/api/types/users.ts index c723bef7b..6a15616af 100644 --- a/src/api/types/users.ts +++ b/src/api/types/users.ts @@ -23,6 +23,7 @@ export interface ApiUser { maxId: string; isFullyLoaded: boolean; }; + fakeType?: ApiFakeType; // Obtained from GetFullUser / UserFullInfo fullInfo?: ApiUserFullInfo; @@ -37,6 +38,8 @@ export interface ApiUserFullInfo { botCommands?: ApiBotCommand[]; } +export type ApiFakeType = 'fake' | 'scam'; + export type ApiUserType = 'userTypeBot' | 'userTypeRegular' | 'userTypeDeleted' | 'userTypeUnknown'; export interface ApiUserStatus { diff --git a/src/components/common/FakeIcon.scss b/src/components/common/FakeIcon.scss new file mode 100644 index 000000000..d92a12503 --- /dev/null +++ b/src/components/common/FakeIcon.scss @@ -0,0 +1,11 @@ +.FakeIcon { + border: 1px solid var(--color-error); + border-radius: 0.375rem; + color: var(--color-error); + font-size: 0.625rem; + padding: 0.125rem 0.25rem; + line-height: initial; + margin-inline: 0.25rem; + font-weight: 500; + text-transform: capitalize; +} diff --git a/src/components/common/FakeIcon.tsx b/src/components/common/FakeIcon.tsx new file mode 100644 index 000000000..9ff249a83 --- /dev/null +++ b/src/components/common/FakeIcon.tsx @@ -0,0 +1,21 @@ +import React, { FC, memo } from '../../lib/teact/teact'; + +import { ApiFakeType } from '../../api/types'; + +import useLang from '../../hooks/useLang'; + +import './FakeIcon.scss'; + +type OwnProps = { + fakeType: ApiFakeType; +}; + +const FakeIcon: FC = ({ + fakeType, +}) => { + const lang = useLang(); + + return {lang(fakeType === 'fake' ? 'FakeMessage' : 'ScamMessage')}; +}; + +export default memo(FakeIcon); diff --git a/src/components/common/GroupChatInfo.tsx b/src/components/common/GroupChatInfo.tsx index 6043dd454..c83df5751 100644 --- a/src/components/common/GroupChatInfo.tsx +++ b/src/components/common/GroupChatInfo.tsx @@ -21,6 +21,7 @@ import Avatar from './Avatar'; import VerifiedIcon from './VerifiedIcon'; import TypingStatus from './TypingStatus'; import DotAnimation from './DotAnimation'; +import FakeIcon from './FakeIcon'; type OwnProps = { chatId: string; @@ -144,6 +145,7 @@ const GroupChatInfo: FC = ({

{renderText(getChatTitle(lang, chat))}

{chat.isVerified && } + {chat.fakeType && }
{renderStatusOrTyping()} diff --git a/src/components/common/PrivateChatInfo.tsx b/src/components/common/PrivateChatInfo.tsx index 69b1dcab2..62d37148f 100644 --- a/src/components/common/PrivateChatInfo.tsx +++ b/src/components/common/PrivateChatInfo.tsx @@ -17,6 +17,7 @@ import Avatar from './Avatar'; import VerifiedIcon from './VerifiedIcon'; import TypingStatus from './TypingStatus'; import DotAnimation from './DotAnimation'; +import FakeIcon from './FakeIcon'; type OwnProps = { userId: string; @@ -140,6 +141,7 @@ const PrivateChatInfo: FC = ({

{fullName && renderText(fullName)}

{user?.isVerified && } + {user.fakeType && }
)} {(status || (!isSavedMessages && !noStatusOrTyping)) && renderStatusOrTyping()} diff --git a/src/components/common/ProfileInfo.tsx b/src/components/common/ProfileInfo.tsx index 669f45782..7673d8fba 100644 --- a/src/components/common/ProfileInfo.tsx +++ b/src/components/common/ProfileInfo.tsx @@ -21,6 +21,7 @@ import useLang from '../../hooks/useLang'; import VerifiedIcon from './VerifiedIcon'; import ProfilePhoto from './ProfilePhoto'; import Transition from '../ui/Transition'; +import FakeIcon from './FakeIcon'; import './ProfileInfo.scss'; @@ -185,6 +186,7 @@ const ProfileInfo: FC = ({ } const isVerifiedIconShown = (user || chat)?.isVerified; + const fakeType = (user || chat)?.fakeType; return (
@@ -221,6 +223,7 @@ const ProfileInfo: FC = ({

{fullName && renderText(fullName)}

{isVerifiedIconShown && } + {fakeType && }
)} {!isSavedMessages && renderStatus()} diff --git a/src/components/left/main/Chat.tsx b/src/components/left/main/Chat.tsx index d411c8cc0..1df4294bc 100644 --- a/src/components/left/main/Chat.tsx +++ b/src/components/left/main/Chat.tsx @@ -50,6 +50,7 @@ import ListItem from '../../ui/ListItem'; import Badge from './Badge'; import ChatFolderModal from '../ChatFolderModal.async'; import ChatCallStatus from './ChatCallStatus'; +import FakeIcon from '../../common/FakeIcon'; import './Chat.scss'; @@ -299,6 +300,7 @@ const Chat: FC = ({

{renderText(getChatTitle(lang, chat, user))}

{chat.isVerified && } + {chat.fakeType && } {isMuted && } {chat.lastMessage && ( = ({

{renderText(getChatTitle(lang, chat, privateChatUser))}

{chat.isVerified && } + {chat.fakeType && }