Emoji Status: Support EmojiStatusCollectible (#5547)
Co-authored-by: Alexander Zinchuk <alx.zinchuk@gmail.com>
This commit is contained in:
parent
79c904fe17
commit
3491a3b63b
@ -1,9 +1,10 @@
|
|||||||
import type BigInt from 'big-integer';
|
import type BigInt from 'big-integer';
|
||||||
import { Api as GramJs } from '../../../lib/gramjs';
|
import { Api as GramJs } from '../../../lib/gramjs';
|
||||||
|
|
||||||
import type { ApiEmojiStatus, ApiPeerColor } from '../../types';
|
import type { ApiEmojiStatusType, ApiPeerColor } from '../../types';
|
||||||
|
|
||||||
import { CHANNEL_ID_LENGTH } from '../../../config';
|
import { CHANNEL_ID_LENGTH } from '../../../config';
|
||||||
|
import { numberToHexColor } from '../../../util/colors';
|
||||||
|
|
||||||
export function isPeerUser(peer: GramJs.TypePeer | GramJs.TypeInputPeer): peer is GramJs.PeerUser {
|
export function isPeerUser(peer: GramJs.TypePeer | GramJs.TypeInputPeer): peer is GramJs.PeerUser {
|
||||||
return peer.hasOwnProperty('userId');
|
return peer.hasOwnProperty('userId');
|
||||||
@ -50,14 +51,30 @@ export function buildApiPeerColor(peerColor: GramJs.TypePeerColor): ApiPeerColor
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildApiEmojiStatus(mtpEmojiStatus: GramJs.TypeEmojiStatus): ApiEmojiStatus | undefined {
|
export function buildApiEmojiStatus(mtpEmojiStatus: GramJs.TypeEmojiStatus):
|
||||||
|
ApiEmojiStatusType | undefined {
|
||||||
if (mtpEmojiStatus instanceof GramJs.EmojiStatus) {
|
if (mtpEmojiStatus instanceof GramJs.EmojiStatus) {
|
||||||
return { documentId: mtpEmojiStatus.documentId.toString(), until: mtpEmojiStatus.until };
|
return {
|
||||||
|
type: 'regular',
|
||||||
|
documentId: mtpEmojiStatus.documentId.toString(),
|
||||||
|
until: mtpEmojiStatus.until,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Support other parameters
|
|
||||||
if (mtpEmojiStatus instanceof GramJs.EmojiStatusCollectible) {
|
if (mtpEmojiStatus instanceof GramJs.EmojiStatusCollectible) {
|
||||||
return { documentId: mtpEmojiStatus.documentId.toString(), until: mtpEmojiStatus.until };
|
return {
|
||||||
|
type: 'collectible',
|
||||||
|
collectibleId: mtpEmojiStatus.collectibleId.toString(),
|
||||||
|
documentId: mtpEmojiStatus.documentId.toString(),
|
||||||
|
title: mtpEmojiStatus.title,
|
||||||
|
slug: mtpEmojiStatus.slug,
|
||||||
|
patternDocumentId: mtpEmojiStatus.patternDocumentId.toString(),
|
||||||
|
centerColor: numberToHexColor(mtpEmojiStatus.centerColor),
|
||||||
|
edgeColor: numberToHexColor(mtpEmojiStatus.edgeColor),
|
||||||
|
patternColor: numberToHexColor(mtpEmojiStatus.patternColor),
|
||||||
|
textColor: numberToHexColor(mtpEmojiStatus.textColor),
|
||||||
|
until: mtpEmojiStatus.until,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import type {
|
|||||||
ApiChatBannedRights,
|
ApiChatBannedRights,
|
||||||
ApiChatFolder,
|
ApiChatFolder,
|
||||||
ApiChatReactions,
|
ApiChatReactions,
|
||||||
|
ApiEmojiStatusType,
|
||||||
ApiFormattedText,
|
ApiFormattedText,
|
||||||
ApiGroupCall,
|
ApiGroupCall,
|
||||||
ApiInputPrivacyRules,
|
ApiInputPrivacyRules,
|
||||||
@ -735,14 +736,21 @@ export function buildInputChatReactions(chatReactions?: ApiChatReactions) {
|
|||||||
return new GramJs.ChatReactionsNone();
|
return new GramJs.ChatReactionsNone();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildInputEmojiStatus(emojiStatusId: string, expires?: number) {
|
export function buildInputEmojiStatus(emojiStatus: ApiEmojiStatusType) {
|
||||||
if (emojiStatusId === DEFAULT_STATUS_ICON_ID) {
|
if (emojiStatus.type === 'collectible') {
|
||||||
|
return new GramJs.InputEmojiStatusCollectible({
|
||||||
|
collectibleId: BigInt(emojiStatus.collectibleId),
|
||||||
|
until: emojiStatus.until,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emojiStatus.documentId === DEFAULT_STATUS_ICON_ID) {
|
||||||
return new GramJs.EmojiStatusEmpty();
|
return new GramJs.EmojiStatusEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new GramJs.EmojiStatus({
|
return new GramJs.EmojiStatus({
|
||||||
documentId: BigInt(emojiStatusId),
|
documentId: BigInt(emojiStatus.documentId),
|
||||||
until: expires,
|
until: emojiStatus.until,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -276,6 +276,23 @@ export async function fetchDefaultStatusEmojis() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function fetchCollectibleEmojiStatuses({ hash = '0' }: { hash?: string }) {
|
||||||
|
const result = await invokeRequest(new GramJs.account.GetCollectibleEmojiStatuses(
|
||||||
|
{ hash: BigInt(hash) },
|
||||||
|
));
|
||||||
|
|
||||||
|
if (!(result instanceof GramJs.account.EmojiStatuses)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const statuses = result.statuses.map(buildApiEmojiStatus).filter(Boolean);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statuses,
|
||||||
|
hash: String(result.hash),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export async function searchStickers({ query, hash = '0' }: { query: string; hash?: string }) {
|
export async function searchStickers({ query, hash = '0' }: { query: string; hash?: string }) {
|
||||||
const result = await invokeRequest(new GramJs.messages.SearchStickerSets({
|
const result = await invokeRequest(new GramJs.messages.SearchStickerSets({
|
||||||
q: query,
|
q: query,
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import BigInt from 'big-integer';
|
|||||||
import { Api as GramJs } from '../../../lib/gramjs';
|
import { Api as GramJs } from '../../../lib/gramjs';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ApiChat, ApiPeer, ApiUser,
|
ApiChat, ApiEmojiStatusType, ApiPeer, ApiUser,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
|
|
||||||
import { buildApiChatFromPreview } from '../apiBuilders/chats';
|
import { buildApiChatFromPreview } from '../apiBuilders/chats';
|
||||||
@ -304,9 +304,9 @@ export function reportSpam(userOrChat: ApiPeer) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateEmojiStatus(emojiStatusId: string, expires?: number) {
|
export function updateEmojiStatus(emojiStatus: ApiEmojiStatusType) {
|
||||||
return invokeRequest(new GramJs.account.UpdateEmojiStatus({
|
return invokeRequest(new GramJs.account.UpdateEmojiStatus({
|
||||||
emojiStatus: buildInputEmojiStatus(emojiStatusId, expires),
|
emojiStatus: buildInputEmojiStatus(emojiStatus),
|
||||||
}), {
|
}), {
|
||||||
shouldReturnTrue: true,
|
shouldReturnTrue: true,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import type {
|
|||||||
} from './messages';
|
} from './messages';
|
||||||
import type { ApiBotVerification, ApiChatInviteImporter } from './misc';
|
import type { ApiBotVerification, ApiChatInviteImporter } from './misc';
|
||||||
import type {
|
import type {
|
||||||
ApiEmojiStatus, ApiFakeType, ApiUser, ApiUsername,
|
ApiEmojiStatusType, ApiFakeType, ApiUser, ApiUsername,
|
||||||
} from './users';
|
} from './users';
|
||||||
|
|
||||||
type ApiChatType = (
|
type ApiChatType = (
|
||||||
@ -44,7 +44,7 @@ export interface ApiChat {
|
|||||||
isProtected?: boolean;
|
isProtected?: boolean;
|
||||||
fakeType?: ApiFakeType;
|
fakeType?: ApiFakeType;
|
||||||
color?: ApiPeerColor;
|
color?: ApiPeerColor;
|
||||||
emojiStatus?: ApiEmojiStatus;
|
emojiStatus?: ApiEmojiStatusType;
|
||||||
isForum?: boolean;
|
isForum?: boolean;
|
||||||
isForumAsMessages?: true;
|
isForumAsMessages?: true;
|
||||||
boostLevel?: number;
|
boostLevel?: number;
|
||||||
|
|||||||
@ -40,7 +40,7 @@ import type { ApiStarsAmount } from './payments';
|
|||||||
import type { ApiPrivacyKey, LangPackStringValue, PrivacyVisibility } from './settings';
|
import type { ApiPrivacyKey, LangPackStringValue, PrivacyVisibility } from './settings';
|
||||||
import type { ApiStealthMode, ApiStory, ApiStorySkipped } from './stories';
|
import type { ApiStealthMode, ApiStory, ApiStorySkipped } from './stories';
|
||||||
import type {
|
import type {
|
||||||
ApiEmojiStatus, ApiUser, ApiUserFullInfo, ApiUserStatus,
|
ApiEmojiStatusType, ApiUser, ApiUserFullInfo, ApiUserStatus,
|
||||||
} from './users';
|
} from './users';
|
||||||
|
|
||||||
export type ApiUpdateReady = {
|
export type ApiUpdateReady = {
|
||||||
@ -419,7 +419,7 @@ export type ApiUpdateUserStatus = {
|
|||||||
export type ApiUpdateUserEmojiStatus = {
|
export type ApiUpdateUserEmojiStatus = {
|
||||||
'@type': 'updateUserEmojiStatus';
|
'@type': 'updateUserEmojiStatus';
|
||||||
userId: string;
|
userId: string;
|
||||||
emojiStatus?: ApiEmojiStatus;
|
emojiStatus?: ApiEmojiStatusType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ApiUpdateRecentEmojiStatuses = {
|
export type ApiUpdateRecentEmojiStatuses = {
|
||||||
|
|||||||
@ -28,7 +28,7 @@ export interface ApiUser {
|
|||||||
canBeInvitedToGroup?: boolean;
|
canBeInvitedToGroup?: boolean;
|
||||||
fakeType?: ApiFakeType;
|
fakeType?: ApiFakeType;
|
||||||
isAttachBot?: boolean;
|
isAttachBot?: boolean;
|
||||||
emojiStatus?: ApiEmojiStatus;
|
emojiStatus?: ApiEmojiStatusType;
|
||||||
areStoriesHidden?: boolean;
|
areStoriesHidden?: boolean;
|
||||||
hasStories?: boolean;
|
hasStories?: boolean;
|
||||||
hasUnreadStories?: boolean;
|
hasUnreadStories?: boolean;
|
||||||
@ -132,11 +132,28 @@ export interface ApiPremiumGiftOption {
|
|||||||
botUrl: string;
|
botUrl: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ApiEmojiStatusType = ApiEmojiStatus | ApiEmojiStatusCollectible;
|
||||||
|
|
||||||
export interface ApiEmojiStatus {
|
export interface ApiEmojiStatus {
|
||||||
|
type: 'regular';
|
||||||
documentId: string;
|
documentId: string;
|
||||||
until?: number;
|
until?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ApiEmojiStatusCollectible {
|
||||||
|
type: 'collectible';
|
||||||
|
collectibleId: string;
|
||||||
|
documentId: string;
|
||||||
|
title: string;
|
||||||
|
slug: string;
|
||||||
|
patternDocumentId: string;
|
||||||
|
centerColor: string;
|
||||||
|
edgeColor: string;
|
||||||
|
patternColor: string;
|
||||||
|
textColor: string;
|
||||||
|
until?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ApiBirthday {
|
export interface ApiBirthday {
|
||||||
day: number;
|
day: number;
|
||||||
month: number;
|
month: number;
|
||||||
|
|||||||
1
src/assets/font-icons/crown-take-off.svg
Normal file
1
src/assets/font-icons/crown-take-off.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none"><path fill="#000" fill-rule="evenodd" d="M2.17 1.348a1.206 1.206 0 0 0-1.694 0 1.18 1.18 0 0 0 0 1.68L29.35 31.652a1.206 1.206 0 0 0 1.694 0 1.18 1.18 0 0 0 0-1.68l-4.523-4.484q.072-.228.12-.466l.23-1.146h-1.976l-2.529-2.508h5.012l2.04-10.11A3.03 3.03 0 0 0 32 8.27c0-1.669-1.364-3.022-3.047-3.022s-3.048 1.353-3.048 3.022c0 .812.324 1.55.85 2.093l-4.66 5.46-4.66-8.664a3.02 3.02 0 0 0 1.613-2.666c0-1.669-1.365-3.022-3.048-3.022s-3.048 1.353-3.048 3.022c0 1.154.654 2.158 1.614 2.666l-2.272 4.224zm7.818 14.321-1.4-1.387L.713 6.329c.07.163-.135-.133 0 0A3 3 0 0 0 0 8.27a3.03 3.03 0 0 0 2.583 2.986l2.04 10.112h11.113zm-4.859 8.207h13.137l4.75 4.71q-.42.079-.859.08H9.843c-2.18 0-4.055-1.526-4.483-3.644z" clip-rule="evenodd"/></svg>
|
||||||
|
After Width: | Height: | Size: 809 B |
1
src/assets/font-icons/crown-wear.svg
Normal file
1
src/assets/font-icons/crown-wear.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none"><path fill="#000" d="M5.452 25.987c.363 2.18 2.362 3.635 4.543 3.635h12.357c2.18 0 3.997-1.636 4.543-3.635l.181-1.09H5.27zM29.075 5.816c-1.635 0-3.089 1.454-3.089 3.09 0 .908.363 1.635.909 2.18l-4.725 5.452-4.543-8.723c.908-.545 1.635-1.454 1.635-2.726C19.262 3.454 17.81 2 16.173 2c-1.817 0-3.09 1.454-3.09 3.09 0 1.09.728 2.18 1.636 2.725l-4.724 8.723-4.725-5.452a3 3 0 0 0 .908-2.18c0-1.636-1.453-3.09-3.089-3.09S0 7.27 0 8.906c0 1.453 1.09 2.725 2.544 3.089l1.999 10.358H27.44l1.999-10.358c1.453-.182 2.544-1.454 2.544-3.09.181-1.635-1.09-3.089-2.908-3.089"/></svg>
|
||||||
|
After Width: | Height: | Size: 644 B |
1
src/assets/font-icons/proof-of-ownership.svg
Normal file
1
src/assets/font-icons/proof-of-ownership.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none"><path fill="#000" fill-rule="evenodd" d="M1.62 14.005a2.115 2.115 0 0 0 0 2.99l3.007 3.008v4.255c0 1.168.947 2.114 2.115 2.114h4.254l3.009 3.009a2.115 2.115 0 0 0 2.99 0l3.009-3.009h4.254a2.115 2.115 0 0 0 2.114-2.114v-4.254l3.009-3.009a2.114 2.114 0 0 0 0-2.99l-3.009-3.009V6.742a2.115 2.115 0 0 0-2.114-2.114h-4.254l-3.009-3.009a2.115 2.115 0 0 0-2.99 0l-3.008 3.009H6.742a2.115 2.115 0 0 0-2.115 2.114v4.255zm5.122 8.138v-3.016L4.61 16.995 3.115 15.5l1.495-1.495 2.132-2.132V6.742h5.131l2.132-2.132L15.5 3.115l1.495 1.495 2.133 2.132h5.13v5.13l2.132 2.133 1.495 1.495-1.495 1.495-2.132 2.133v5.13h-5.13l-2.133 2.132-1.495 1.495-1.495-1.495-2.133-2.132h-5.13zm14.522-8.682a1.058 1.058 0 0 0-1.496-1.495l-5.94 5.94-2.596-2.596a1.057 1.057 0 1 0-1.495 1.495l3.344 3.344a1.057 1.057 0 0 0 1.495 0z" clip-rule="evenodd"/></svg>
|
||||||
|
After Width: | Height: | Size: 900 B |
1
src/assets/font-icons/radial-badge.svg
Normal file
1
src/assets/font-icons/radial-badge.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none"><path fill="#000" d="m1.244 5.276 2.571.67a.24.24 0 0 1 .224.224l.67 2.571c.112.335.56.335.56 0l.67-2.571a.24.24 0 0 1 .224-.224l2.794-.67c.336-.112.336-.56 0-.56l-2.57-.67a.24.24 0 0 1-.224-.223L5.38 1.252c-.112-.336-.559-.336-.559 0l-.67 2.57a.24.24 0 0 1-.224.224l-2.683.67c-.335 0-.335.448 0 .56M14.658 25.397l-3.242-.895a.24.24 0 0 1-.223-.223l-.894-3.13c-.112-.335-.671-.335-.783 0l-.894 3.13a.24.24 0 0 1-.224.223l-3.241.895c-.336.111-.336.67 0 .782l3.241.894a.24.24 0 0 1 .224.224l.894 3.13c.112.335.67.335.783 0l.894-3.13a.24.24 0 0 1 .223-.224l3.242-.894c.447-.112.447-.67 0-.782M31.761 11.983l-2.683-.671h-.112c-.111 0-.111-.112-.111-.224l-.671-2.57c-.112-.336-.559-.336-.559 0l-.112.335-.67 2.235a.24.24 0 0 1-.224.224l-2.571.67c-.335.112-.335.56 0 .56l2.571.67c.112 0 .112.112.224.224l.67 2.57c.112.336.56.336.56 0l.558-1.788.224-.782a.24.24 0 0 1 .223-.224l2.571-.67c.447 0 .447-.448.112-.56"/><path fill="#000" d="m25.948 14.33-8.607 11.29 3.577-12.072c0-.112.112-.224.112-.336h2.012c-.224-.223-.335-.559-.335-.894 0-.559.335-1.006.894-1.23h-2.906l-2.124-5.03h3.688c.336 0 .671.224.895.447l2.794 3.913.56-2.124c0-.112.111-.336.223-.447l-1.9-2.683c-.56-.894-1.565-1.341-2.683-1.341H9.74c.335.223.559.67.559 1.117s-.224.783-.447 1.006h1.006l-2.236 5.142H2.92l1.118-1.565c-.112-.111-.224-.335-.335-.447l-.56-2.124-2.57 3.578c-.783 1.117-.783 2.682.111 3.912l7.043 9.166.782-2.57-5.924-7.714h5.812c0 .112 0 .224.112.335l1.789 6.26c.559.112.894.447 1.117 1.006l.783 2.795 1.677.447-3.13-10.843h8.16l-3.353 11.29c.447.224.67.783.67 1.23 0 .67-.447 1.341-1.118 1.453l-2.794.782-.447.895.223.335c1.342 1.677 3.913 1.677 5.142 0l9.502-12.52c-.112-.112-.224-.335-.224-.447zm-14.867-3.242 1.789-4.47q.335-.672 1.006-.672h1.453q.67 0 1.006.671l1.9 4.471z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.8 KiB |
1
src/assets/font-icons/unique-profile.svg
Normal file
1
src/assets/font-icons/unique-profile.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none"><path fill="#000" d="m4.925 1.225.6 2.3c0 .1.1.2.2.2l2.3.6c.3.1.3.5 0 .5l-2.3.6c-.1 0-.2.1-.2.2l-.6 2.3c-.1.3-.5.3-.5 0l-.7-2.3c0-.1-.1-.2-.2-.2l-2.3-.6c-.3-.1-.3-.5 0-.5l2.3-.6c.1 0 .2-.1.2-.2l.6-2.3c.2-.3.5-.3.6 0M28.325 8.125l.6 2.3c0 .1.1.2.2.2l2.3.6c.3.1.3.5 0 .5l-2.3.6c-.1 0-.2.1-.2.2l-.6 2.3c-.1.3-.5.3-.5 0l-.6-2.3c0-.1-.1-.2-.2-.2l-2.3-.6c-.3-.1-.3-.5 0-.5l2.3-.6c.1 0 .2-.1.2-.2l.6-2.3c0-.2.4-.2.5 0M15.625 9.425c1.9 0 3.5 1.5 3.5 3.5s-1.5 3.5-3.5 3.5-3.5-1.5-3.5-3.5 1.6-3.5 3.5-3.5m0-2c-3 0-5.5 2.4-5.5 5.5s2.4 5.5 5.5 5.5 5.5-2.4 5.5-5.5-2.5-5.5-5.5-5.5M20.525 23.325h-9.7c-.6 0-1-.4-1-1s.4-1 1-1h9.6c.6 0 1 .4 1 1s-.4 1-.9 1M5.925 21.825l.8 2.8c0 .1.1.2.2.2l2.9.8c.3.1.3.6 0 .7l-2.9.8c-.1 0-.2.1-.2.2l-.8 2.8c-.1.3-.6.3-.7 0l-.8-2.8c0-.1-.1-.2-.2-.2l-2.9-.8c-.3-.1-.3-.6 0-.7l2.9-.8c.1 0 .2-.1.2-.2l.8-2.8c.1-.3.6-.3.7 0M8.625 2.325c.8.3 1.4.9 1.6 1.7h14.6c1.2 0 2.2.9 2.4 2.1.2-.1.5-.2.8-.2q.6 0 1.2.3c-.1-2.4-2-4.2-4.4-4.2h-17.4z"/><path fill="#000" d="M28.025 17.025c-.3 0-.5-.1-.8-.1v8c0 1.3-1.1 2.4-2.4 2.4h-13.1c-.3.5-.8.8-1.3 1l-2 .5-.2.5h16.6c2.4 0 4.4-2 4.4-4.4v-8.3c-.3.3-.8.4-1.2.4M2.825 23.225l.5-1.9c.1-.4.3-.8.6-1.1v-10.2c-.7-.3-1.2-.8-1.4-1.6l-.4-1.3h-.1v16.3z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
@ -1437,6 +1437,9 @@
|
|||||||
"GiftInfoViewUpgraded" = "View Upgraded Gift";
|
"GiftInfoViewUpgraded" = "View Upgraded Gift";
|
||||||
"GiftInfoUpgradeBadge" = "upgrade";
|
"GiftInfoUpgradeBadge" = "upgrade";
|
||||||
"GiftInfoUpgradeForFree" = "Upgrade For Free";
|
"GiftInfoUpgradeForFree" = "Upgrade For Free";
|
||||||
|
"GiftInfoWithdraw" = "Withdraw";
|
||||||
|
"GiftInfoWear" = "Wear";
|
||||||
|
"GiftInfoTakeOff" = "Take Off";
|
||||||
"GiftInfoTransfer" = "Transfer";
|
"GiftInfoTransfer" = "Transfer";
|
||||||
"GiftTransferTitle" = "Transfer";
|
"GiftTransferTitle" = "Transfer";
|
||||||
"GiftTransferTON" = "Send via Blockchain";
|
"GiftTransferTON" = "Send via Blockchain";
|
||||||
@ -1620,3 +1623,13 @@
|
|||||||
"CheckPasswordTitle" = "Enter Password";
|
"CheckPasswordTitle" = "Enter Password";
|
||||||
"CheckPasswordPlaceholder" = "Password";
|
"CheckPasswordPlaceholder" = "Password";
|
||||||
"CheckPasswordDescription" = "Please enter your password to continue.";
|
"CheckPasswordDescription" = "Please enter your password to continue.";
|
||||||
|
"UniqueStatusWearTitle" = "Wear {gift}";
|
||||||
|
"UniqueStatusBenefitsDescription" = "and get these benefits:";
|
||||||
|
"UniqueStatusBadgeBenefitTitle" = "Radiant Badge";
|
||||||
|
"UniqueStatusBadgeDescription" = "The glittering icon of this item will be displayed next to your name.";
|
||||||
|
"UniqueStatusProfileDesignBenefitTitle" = "Unique Profile Design";
|
||||||
|
"UniqueStatusProfileDesignDescription" = "Your profile page will get the color and the symbol of this item.";
|
||||||
|
"UniqueStatusProofOfOwnershipBenefitTitle" = "Proof of Ownership";
|
||||||
|
"UniqueStatusProofOfOwnershipDescription" = "Tapping the icon of this item next to your name will show its info and owner.";
|
||||||
|
"UniqueStatusWearButton" = "Start Wearing";
|
||||||
|
"CollectibleStatusesCategory" = "Collectibles";
|
||||||
@ -9,5 +9,6 @@ export { default as GiftModal } from '../components/modals/gift/GiftModal';
|
|||||||
export { default as GiftRecipientPicker } from '../components/modals/gift/recipient/GiftRecipientPicker';
|
export { default as GiftRecipientPicker } from '../components/modals/gift/recipient/GiftRecipientPicker';
|
||||||
export { default as GiftInfoModal } from '../components/modals/gift/info/GiftInfoModal';
|
export { default as GiftInfoModal } from '../components/modals/gift/info/GiftInfoModal';
|
||||||
export { default as GiftUpgradeModal } from '../components/modals/gift/upgrade/GiftUpgradeModal';
|
export { default as GiftUpgradeModal } from '../components/modals/gift/upgrade/GiftUpgradeModal';
|
||||||
|
export { default as GiftStatusInfoModal } from '../components/modals/gift/status/GiftStatusInfoModal';
|
||||||
export { default as GiftWithdrawModal } from '../components/modals/gift/withdraw/GiftWithdrawModal';
|
export { default as GiftWithdrawModal } from '../components/modals/gift/withdraw/GiftWithdrawModal';
|
||||||
export { default as GiftTransferModal } from '../components/modals/gift/transfer/GiftTransferModal';
|
export { default as GiftTransferModal } from '../components/modals/gift/transfer/GiftTransferModal';
|
||||||
|
|||||||
@ -13,6 +13,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.withSparkles {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sparkles {
|
||||||
|
position: absolute;
|
||||||
|
inset: -0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
.placeholder {
|
.placeholder {
|
||||||
width: 85%;
|
width: 85%;
|
||||||
height: 85%;
|
height: 85%;
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import useDynamicColorListener from '../../hooks/stickers/useDynamicColorListene
|
|||||||
import useLastCallback from '../../hooks/useLastCallback';
|
import useLastCallback from '../../hooks/useLastCallback';
|
||||||
import useCustomEmoji from './hooks/useCustomEmoji';
|
import useCustomEmoji from './hooks/useCustomEmoji';
|
||||||
|
|
||||||
|
import Sparkles from './Sparkles';
|
||||||
import StickerView from './StickerView';
|
import StickerView from './StickerView';
|
||||||
|
|
||||||
import styles from './CustomEmoji.module.scss';
|
import styles from './CustomEmoji.module.scss';
|
||||||
@ -41,6 +42,9 @@ type OwnProps = {
|
|||||||
observeIntersectionForPlaying?: ObserveFn;
|
observeIntersectionForPlaying?: ObserveFn;
|
||||||
onClick?: NoneToVoidFunction;
|
onClick?: NoneToVoidFunction;
|
||||||
onAnimationEnd?: NoneToVoidFunction;
|
onAnimationEnd?: NoneToVoidFunction;
|
||||||
|
withSparkles?: boolean;
|
||||||
|
sparklesClassName?: string;
|
||||||
|
sparklesStyle?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const STICKER_SIZE = 20;
|
const STICKER_SIZE = 20;
|
||||||
@ -67,6 +71,9 @@ const CustomEmoji: FC<OwnProps> = ({
|
|||||||
observeIntersectionForPlaying,
|
observeIntersectionForPlaying,
|
||||||
onClick,
|
onClick,
|
||||||
onAnimationEnd,
|
onAnimationEnd,
|
||||||
|
withSparkles,
|
||||||
|
sparklesStyle,
|
||||||
|
sparklesClassName,
|
||||||
}) => {
|
}) => {
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
let containerRef = useRef<HTMLDivElement>(null);
|
let containerRef = useRef<HTMLDivElement>(null);
|
||||||
@ -114,6 +121,7 @@ const CustomEmoji: FC<OwnProps> = ({
|
|||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
className={buildClassName(
|
className={buildClassName(
|
||||||
styles.root,
|
styles.root,
|
||||||
|
withSparkles && styles.withSparkles,
|
||||||
className,
|
className,
|
||||||
'custom-emoji',
|
'custom-emoji',
|
||||||
'emoji',
|
'emoji',
|
||||||
@ -125,6 +133,16 @@ const CustomEmoji: FC<OwnProps> = ({
|
|||||||
data-alt={customEmoji?.emoji}
|
data-alt={customEmoji?.emoji}
|
||||||
style={style}
|
style={style}
|
||||||
>
|
>
|
||||||
|
{withSparkles && (
|
||||||
|
<Sparkles
|
||||||
|
className={buildClassName(
|
||||||
|
styles.sparkles,
|
||||||
|
sparklesClassName,
|
||||||
|
)}
|
||||||
|
style={sparklesStyle}
|
||||||
|
preset="button"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{isSelectable && (
|
{isSelectable && (
|
||||||
<img
|
<img
|
||||||
className={styles.highlightCatch}
|
className={styles.highlightCatch}
|
||||||
|
|||||||
@ -5,11 +5,14 @@ import React, {
|
|||||||
import { getGlobal, withGlobal } from '../../global';
|
import { getGlobal, withGlobal } from '../../global';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ApiAvailableReaction, ApiReaction, ApiReactionWithPaid, ApiSticker, ApiStickerSet,
|
ApiAvailableReaction,
|
||||||
|
ApiEmojiStatusType,
|
||||||
|
ApiReaction, ApiReactionWithPaid, ApiSticker, ApiStickerSet,
|
||||||
} from '../../api/types';
|
} from '../../api/types';
|
||||||
import type { StickerSetOrReactionsSetOrRecent } from '../../types';
|
import type { StickerSetOrReactionsSetOrRecent } from '../../types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
COLLECTIBLE_STATUS_SET_ID,
|
||||||
FAVORITE_SYMBOL_SET_ID,
|
FAVORITE_SYMBOL_SET_ID,
|
||||||
POPULAR_SYMBOL_SET_ID,
|
POPULAR_SYMBOL_SET_ID,
|
||||||
RECENT_SYMBOL_SET_ID,
|
RECENT_SYMBOL_SET_ID,
|
||||||
@ -28,12 +31,13 @@ import {
|
|||||||
} from '../../global/selectors';
|
} from '../../global/selectors';
|
||||||
import animateHorizontalScroll from '../../util/animateHorizontalScroll';
|
import animateHorizontalScroll from '../../util/animateHorizontalScroll';
|
||||||
import buildClassName from '../../util/buildClassName';
|
import buildClassName from '../../util/buildClassName';
|
||||||
import { pickTruthy, unique } from '../../util/iteratees';
|
import { pickTruthy, unique, uniqueByField } from '../../util/iteratees';
|
||||||
import { IS_TOUCH_ENV } from '../../util/windowEnvironment';
|
import { IS_TOUCH_ENV } from '../../util/windowEnvironment';
|
||||||
import { REM } from './helpers/mediaDimensions';
|
import { REM } from './helpers/mediaDimensions';
|
||||||
|
|
||||||
import useAppLayout from '../../hooks/useAppLayout';
|
import useAppLayout from '../../hooks/useAppLayout';
|
||||||
import useHorizontalScroll from '../../hooks/useHorizontalScroll';
|
import useHorizontalScroll from '../../hooks/useHorizontalScroll';
|
||||||
|
import useLang from '../../hooks/useLang';
|
||||||
import useLastCallback from '../../hooks/useLastCallback';
|
import useLastCallback from '../../hooks/useLastCallback';
|
||||||
import useOldLang from '../../hooks/useOldLang';
|
import useOldLang from '../../hooks/useOldLang';
|
||||||
import usePrevDuringAnimation from '../../hooks/usePrevDuringAnimation';
|
import usePrevDuringAnimation from '../../hooks/usePrevDuringAnimation';
|
||||||
@ -75,6 +79,7 @@ type StateProps = {
|
|||||||
customEmojisById?: Record<string, ApiSticker>;
|
customEmojisById?: Record<string, ApiSticker>;
|
||||||
recentCustomEmojiIds?: string[];
|
recentCustomEmojiIds?: string[];
|
||||||
recentStatusEmojis?: ApiSticker[];
|
recentStatusEmojis?: ApiSticker[];
|
||||||
|
collectibleStatuses?: ApiEmojiStatusType[];
|
||||||
chatEmojiSetId?: string;
|
chatEmojiSetId?: string;
|
||||||
topReactions?: ApiReaction[];
|
topReactions?: ApiReaction[];
|
||||||
recentReactions?: ApiReaction[];
|
recentReactions?: ApiReaction[];
|
||||||
@ -114,6 +119,7 @@ const CustomEmojiPicker: FC<OwnProps & StateProps> = ({
|
|||||||
recentCustomEmojiIds,
|
recentCustomEmojiIds,
|
||||||
selectedReactionIds,
|
selectedReactionIds,
|
||||||
recentStatusEmojis,
|
recentStatusEmojis,
|
||||||
|
collectibleStatuses,
|
||||||
stickerSetsById,
|
stickerSetsById,
|
||||||
chatEmojiSetId,
|
chatEmojiSetId,
|
||||||
topReactions,
|
topReactions,
|
||||||
@ -160,6 +166,11 @@ const CustomEmojiPicker: FC<OwnProps & StateProps> = ({
|
|||||||
: Object.values(pickTruthy(customEmojisById!, recentCustomEmojiIds!));
|
: Object.values(pickTruthy(customEmojisById!, recentCustomEmojiIds!));
|
||||||
}, [customEmojisById, isStatusPicker, recentCustomEmojiIds, recentStatusEmojis]);
|
}, [customEmojisById, isStatusPicker, recentCustomEmojiIds, recentStatusEmojis]);
|
||||||
|
|
||||||
|
const collectibleStatusEmojis = useMemo(() => {
|
||||||
|
const collectibleStatusEmojiIds = collectibleStatuses?.map((status) => status.documentId);
|
||||||
|
return customEmojisById && collectibleStatusEmojiIds?.map((id) => customEmojisById[id]).filter(Boolean);
|
||||||
|
}, [customEmojisById, collectibleStatuses]);
|
||||||
|
|
||||||
const prefix = `${idPrefix}-custom-emoji`;
|
const prefix = `${idPrefix}-custom-emoji`;
|
||||||
const {
|
const {
|
||||||
activeSetIndex,
|
activeSetIndex,
|
||||||
@ -172,7 +183,8 @@ const CustomEmojiPicker: FC<OwnProps & StateProps> = ({
|
|||||||
|
|
||||||
const canLoadAndPlay = usePrevDuringAnimation(loadAndPlay || undefined, SLIDE_TRANSITION_DURATION);
|
const canLoadAndPlay = usePrevDuringAnimation(loadAndPlay || undefined, SLIDE_TRANSITION_DURATION);
|
||||||
|
|
||||||
const lang = useOldLang();
|
const oldLang = useOldLang();
|
||||||
|
const lang = useLang();
|
||||||
|
|
||||||
const areAddedLoaded = Boolean(addedCustomEmojiIds);
|
const areAddedLoaded = Boolean(addedCustomEmojiIds);
|
||||||
|
|
||||||
@ -184,7 +196,7 @@ const CustomEmojiPicker: FC<OwnProps & StateProps> = ({
|
|||||||
defaultSets.push({
|
defaultSets.push({
|
||||||
id: TOP_SYMBOL_SET_ID,
|
id: TOP_SYMBOL_SET_ID,
|
||||||
accessHash: '',
|
accessHash: '',
|
||||||
title: lang('PremiumPreviewTags'),
|
title: oldLang('PremiumPreviewTags'),
|
||||||
reactions: defaultTagReactions,
|
reactions: defaultTagReactions,
|
||||||
count: defaultTagReactions.length,
|
count: defaultTagReactions.length,
|
||||||
isEmoji: true,
|
isEmoji: true,
|
||||||
@ -201,7 +213,7 @@ const CustomEmojiPicker: FC<OwnProps & StateProps> = ({
|
|||||||
defaultSets.push({
|
defaultSets.push({
|
||||||
id: TOP_SYMBOL_SET_ID,
|
id: TOP_SYMBOL_SET_ID,
|
||||||
accessHash: '',
|
accessHash: '',
|
||||||
title: lang('Reactions'),
|
title: oldLang('Reactions'),
|
||||||
reactions: topReactionsSlice,
|
reactions: topReactionsSlice,
|
||||||
count: topReactionsSlice.length,
|
count: topReactionsSlice.length,
|
||||||
isEmoji: true,
|
isEmoji: true,
|
||||||
@ -224,7 +236,7 @@ const CustomEmojiPicker: FC<OwnProps & StateProps> = ({
|
|||||||
defaultSets.push({
|
defaultSets.push({
|
||||||
id: isPopular ? POPULAR_SYMBOL_SET_ID : RECENT_SYMBOL_SET_ID,
|
id: isPopular ? POPULAR_SYMBOL_SET_ID : RECENT_SYMBOL_SET_ID,
|
||||||
accessHash: '',
|
accessHash: '',
|
||||||
title: lang(isPopular ? 'PopularReactions' : 'RecentStickers'),
|
title: oldLang(isPopular ? 'PopularReactions' : 'RecentStickers'),
|
||||||
reactions: allRecentReactions,
|
reactions: allRecentReactions,
|
||||||
count: allRecentReactions.length,
|
count: allRecentReactions.length,
|
||||||
isEmoji: true,
|
isEmoji: true,
|
||||||
@ -233,15 +245,26 @@ const CustomEmojiPicker: FC<OwnProps & StateProps> = ({
|
|||||||
} else if (isStatusPicker) {
|
} else if (isStatusPicker) {
|
||||||
const defaultStatusIconsPack = stickerSetsById[defaultStatusIconsId!];
|
const defaultStatusIconsPack = stickerSetsById[defaultStatusIconsId!];
|
||||||
if (defaultStatusIconsPack?.stickers?.length) {
|
if (defaultStatusIconsPack?.stickers?.length) {
|
||||||
const stickers = defaultStatusIconsPack.stickers
|
const stickers = uniqueByField(defaultStatusIconsPack.stickers
|
||||||
.slice(0, RECENT_DEFAULT_STATUS_COUNT)
|
.slice(0, RECENT_DEFAULT_STATUS_COUNT)
|
||||||
.concat(recentCustomEmojis || []);
|
.concat(recentCustomEmojis || []), 'id');
|
||||||
defaultSets.push({
|
defaultSets.push({
|
||||||
...defaultStatusIconsPack,
|
...defaultStatusIconsPack,
|
||||||
stickers,
|
stickers,
|
||||||
count: stickers.length,
|
count: stickers.length,
|
||||||
id: RECENT_SYMBOL_SET_ID,
|
id: RECENT_SYMBOL_SET_ID,
|
||||||
title: lang('RecentStickers'),
|
title: oldLang('RecentStickers'),
|
||||||
|
isEmoji: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (collectibleStatusEmojis?.length) {
|
||||||
|
defaultSets.push({
|
||||||
|
id: COLLECTIBLE_STATUS_SET_ID,
|
||||||
|
accessHash: '',
|
||||||
|
count: collectibleStatusEmojis.length,
|
||||||
|
stickers: collectibleStatusEmojis,
|
||||||
|
title: lang('CollectibleStatusesCategory'),
|
||||||
|
isEmoji: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (withDefaultTopicIcons) {
|
} else if (withDefaultTopicIcons) {
|
||||||
@ -250,14 +273,14 @@ const CustomEmojiPicker: FC<OwnProps & StateProps> = ({
|
|||||||
defaultSets.push({
|
defaultSets.push({
|
||||||
...defaultTopicIconsPack,
|
...defaultTopicIconsPack,
|
||||||
id: RECENT_SYMBOL_SET_ID,
|
id: RECENT_SYMBOL_SET_ID,
|
||||||
title: lang('RecentStickers'),
|
title: oldLang('RecentStickers'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (recentCustomEmojis?.length) {
|
} else if (recentCustomEmojis?.length) {
|
||||||
defaultSets.push({
|
defaultSets.push({
|
||||||
id: RECENT_SYMBOL_SET_ID,
|
id: RECENT_SYMBOL_SET_ID,
|
||||||
accessHash: '0',
|
accessHash: '0',
|
||||||
title: lang('RecentStickers'),
|
title: oldLang('RecentStickers'),
|
||||||
stickers: recentCustomEmojis,
|
stickers: recentCustomEmojis,
|
||||||
count: recentCustomEmojis.length,
|
count: recentCustomEmojis.length,
|
||||||
isEmoji: true,
|
isEmoji: true,
|
||||||
@ -279,9 +302,9 @@ const CustomEmojiPicker: FC<OwnProps & StateProps> = ({
|
|||||||
];
|
];
|
||||||
}, [
|
}, [
|
||||||
addedCustomEmojiIds, isReactionPicker, isStatusPicker, withDefaultTopicIcons, recentCustomEmojis,
|
addedCustomEmojiIds, isReactionPicker, isStatusPicker, withDefaultTopicIcons, recentCustomEmojis,
|
||||||
customEmojiFeaturedIds, stickerSetsById, topReactions, availableReactions, lang, recentReactions,
|
customEmojiFeaturedIds, stickerSetsById, topReactions, availableReactions, oldLang, recentReactions,
|
||||||
defaultStatusIconsId, defaultTopicIconsId, isSavedMessages, defaultTagReactions, chatEmojiSetId,
|
defaultStatusIconsId, defaultTopicIconsId, isSavedMessages, defaultTagReactions, chatEmojiSetId,
|
||||||
isWithPaidReaction,
|
isWithPaidReaction, collectibleStatusEmojis, lang,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const noPopulatedSets = useMemo(() => (
|
const noPopulatedSets = useMemo(() => (
|
||||||
@ -383,7 +406,7 @@ const CustomEmojiPicker: FC<OwnProps & StateProps> = ({
|
|||||||
return (
|
return (
|
||||||
<div className={fullClassName}>
|
<div className={fullClassName}>
|
||||||
{noPopulatedSets ? (
|
{noPopulatedSets ? (
|
||||||
<div className={pickerStyles.pickerDisabled}>{lang('NoStickers')}</div>
|
<div className={pickerStyles.pickerDisabled}>{oldLang('NoStickers')}</div>
|
||||||
) : (
|
) : (
|
||||||
<Loading />
|
<Loading />
|
||||||
)}
|
)}
|
||||||
@ -487,11 +510,13 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
|
|
||||||
const isSavedMessages = Boolean(chatId && selectIsChatWithSelf(global, chatId));
|
const isSavedMessages = Boolean(chatId && selectIsChatWithSelf(global, chatId));
|
||||||
const chatFullInfo = chatId ? selectChatFullInfo(global, chatId) : undefined;
|
const chatFullInfo = chatId ? selectChatFullInfo(global, chatId) : undefined;
|
||||||
|
const collectibleStatuses = global.collectibleEmojiStatuses?.statuses;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
customEmojisById: !isStatusPicker ? customEmojisById : undefined,
|
customEmojisById,
|
||||||
recentCustomEmojiIds: !isStatusPicker ? recentCustomEmojiIds : undefined,
|
recentCustomEmojiIds: !isStatusPicker ? recentCustomEmojiIds : undefined,
|
||||||
recentStatusEmojis: isStatusPicker ? recentStatusEmojis : undefined,
|
recentStatusEmojis: isStatusPicker ? recentStatusEmojis : undefined,
|
||||||
|
collectibleStatuses: isStatusPicker ? collectibleStatuses : undefined,
|
||||||
stickerSetsById,
|
stickerSetsById,
|
||||||
addedCustomEmojiIds: global.customEmojis.added.setIds,
|
addedCustomEmojiIds: global.customEmojis.added.setIds,
|
||||||
canAnimate: selectCanPlayAnimatedEmojis(global),
|
canAnimate: selectCanPlayAnimatedEmojis(global),
|
||||||
|
|||||||
@ -6,12 +6,23 @@
|
|||||||
:global(.custom-emoji) {
|
:global(.custom-emoji) {
|
||||||
color: var(--color-primary);
|
color: var(--color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.statusSparkles) {
|
||||||
|
color: var(--accent-color);
|
||||||
|
:global(.selected) & {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.fullName {
|
.fullName {
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
&.canCopy {
|
&.canCopy {
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import {
|
|||||||
isPeerUser,
|
isPeerUser,
|
||||||
} from '../../global/helpers';
|
} from '../../global/helpers';
|
||||||
import buildClassName from '../../util/buildClassName';
|
import buildClassName from '../../util/buildClassName';
|
||||||
|
import buildStyle from '../../util/buildStyle';
|
||||||
import { copyTextToClipboard } from '../../util/clipboard';
|
import { copyTextToClipboard } from '../../util/clipboard';
|
||||||
import stopEvent from '../../util/stopEvent';
|
import stopEvent from '../../util/stopEvent';
|
||||||
import renderText from './helpers/renderText';
|
import renderText from './helpers/renderText';
|
||||||
@ -47,6 +48,7 @@ type OwnProps = {
|
|||||||
iconElement?: React.ReactNode;
|
iconElement?: React.ReactNode;
|
||||||
onEmojiStatusClick?: NoneToVoidFunction;
|
onEmojiStatusClick?: NoneToVoidFunction;
|
||||||
observeIntersection?: ObserveFn;
|
observeIntersection?: ObserveFn;
|
||||||
|
statusSparklesColor?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const FullNameTitle: FC<OwnProps> = ({
|
const FullNameTitle: FC<OwnProps> = ({
|
||||||
@ -63,6 +65,7 @@ const FullNameTitle: FC<OwnProps> = ({
|
|||||||
iconElement,
|
iconElement,
|
||||||
onEmojiStatusClick,
|
onEmojiStatusClick,
|
||||||
observeIntersection,
|
observeIntersection,
|
||||||
|
statusSparklesColor,
|
||||||
}) => {
|
}) => {
|
||||||
const lang = useOldLang();
|
const lang = useOldLang();
|
||||||
const { showNotification } = getActions();
|
const { showNotification } = getActions();
|
||||||
@ -72,6 +75,7 @@ const FullNameTitle: FC<OwnProps> = ({
|
|||||||
const title = realPeer && (isUser ? getUserFullName(realPeer) : getChatTitle(lang, realPeer));
|
const title = realPeer && (isUser ? getUserFullName(realPeer) : getChatTitle(lang, realPeer));
|
||||||
const isPremium = isUser && realPeer.isPremium;
|
const isPremium = isUser && realPeer.isPremium;
|
||||||
const canShowEmojiStatus = withEmojiStatus && !isSavedMessages && realPeer;
|
const canShowEmojiStatus = withEmojiStatus && !isSavedMessages && realPeer;
|
||||||
|
const emojiStatus = realPeer?.emojiStatus;
|
||||||
|
|
||||||
const handleTitleClick = useLastCallback((e) => {
|
const handleTitleClick = useLastCallback((e) => {
|
||||||
if (!title || !canCopyTitle) {
|
if (!title || !canCopyTitle) {
|
||||||
@ -134,17 +138,20 @@ const FullNameTitle: FC<OwnProps> = ({
|
|||||||
<>
|
<>
|
||||||
{!noVerified && peer?.isVerified && <VerifiedIcon />}
|
{!noVerified && peer?.isVerified && <VerifiedIcon />}
|
||||||
{!noFake && peer?.fakeType && <FakeIcon fakeType={peer.fakeType} />}
|
{!noFake && peer?.fakeType && <FakeIcon fakeType={peer.fakeType} />}
|
||||||
{canShowEmojiStatus && realPeer.emojiStatus && (
|
{canShowEmojiStatus && emojiStatus && (
|
||||||
<Transition
|
<Transition
|
||||||
className={styles.transition}
|
className={styles.transition}
|
||||||
activeKey={Number(realPeer.emojiStatus.documentId)}
|
activeKey={Number(emojiStatus.documentId)}
|
||||||
name="fade"
|
name="fade"
|
||||||
shouldCleanup
|
shouldCleanup
|
||||||
shouldRestoreHeight
|
shouldRestoreHeight
|
||||||
>
|
>
|
||||||
<CustomEmoji
|
<CustomEmoji
|
||||||
forceAlways
|
forceAlways
|
||||||
documentId={realPeer.emojiStatus.documentId}
|
withSparkles={emojiStatus.type === 'collectible'}
|
||||||
|
sparklesClassName="statusSparkles"
|
||||||
|
sparklesStyle={buildStyle(statusSparklesColor && `color: ${statusSparklesColor}`)}
|
||||||
|
documentId={emojiStatus.documentId}
|
||||||
size={emojiStatusSize}
|
size={emojiStatusSize}
|
||||||
loopLimit={!noLoopLimit ? EMOJI_STATUS_LOOP_LIMIT : undefined}
|
loopLimit={!noLoopLimit ? EMOJI_STATUS_LOOP_LIMIT : undefined}
|
||||||
observeIntersectionForLoading={observeIntersection}
|
observeIntersectionForLoading={observeIntersection}
|
||||||
@ -152,7 +159,7 @@ const FullNameTitle: FC<OwnProps> = ({
|
|||||||
/>
|
/>
|
||||||
</Transition>
|
</Transition>
|
||||||
)}
|
)}
|
||||||
{canShowEmojiStatus && !realPeer.emojiStatus && isPremium && <StarIcon />}
|
{canShowEmojiStatus && !emojiStatus && isPremium && <StarIcon />}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{iconElement}
|
{iconElement}
|
||||||
|
|||||||
@ -3,13 +3,12 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
background: var(--color-chat-hover);
|
background: var(--color-chat-hover);
|
||||||
height: 2rem;
|
height: 2rem;
|
||||||
min-width: 2rem;
|
|
||||||
margin-inline: 0.25rem;
|
margin-inline: 0.25rem;
|
||||||
padding-right: 0.75rem;
|
padding-right: 0.75rem;
|
||||||
border-radius: 1rem;
|
border-radius: 1rem;
|
||||||
cursor: var(--custom-cursor, pointer);
|
cursor: var(--custom-cursor, pointer);
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
min-width: 0;
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
transition: background-color 0.15s ease;
|
transition: background-color 0.15s ease;
|
||||||
|
|
||||||
@ -71,7 +70,7 @@
|
|||||||
.name {
|
.name {
|
||||||
margin-left: 0.5rem;
|
margin-left: 0.5rem;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
min-width: 0;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
:global(.emoji.emoji-small) {
|
:global(.emoji.emoji-small) {
|
||||||
|
|||||||
@ -144,6 +144,10 @@
|
|||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
|
:global(.statusSparkles) {
|
||||||
|
color: var(--color-white) !important;
|
||||||
|
}
|
||||||
|
|
||||||
&:dir(rtl) {
|
&:dir(rtl) {
|
||||||
.status {
|
.status {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
|||||||
@ -57,6 +57,7 @@ type StateProps =
|
|||||||
topic?: ApiTopic;
|
topic?: ApiTopic;
|
||||||
messagesCount?: number;
|
messagesCount?: number;
|
||||||
emojiStatusSticker?: ApiSticker;
|
emojiStatusSticker?: ApiSticker;
|
||||||
|
emojiStatusSlug?: string;
|
||||||
profilePhotos?: ApiPeerPhotos;
|
profilePhotos?: ApiPeerPhotos;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -77,6 +78,7 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
|||||||
topic,
|
topic,
|
||||||
messagesCount,
|
messagesCount,
|
||||||
emojiStatusSticker,
|
emojiStatusSticker,
|
||||||
|
emojiStatusSlug,
|
||||||
profilePhotos,
|
profilePhotos,
|
||||||
peerId,
|
peerId,
|
||||||
}) => {
|
}) => {
|
||||||
@ -86,6 +88,7 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
|||||||
openStickerSet,
|
openStickerSet,
|
||||||
openPrivacySettingsNoticeModal,
|
openPrivacySettingsNoticeModal,
|
||||||
loadMoreProfilePhotos,
|
loadMoreProfilePhotos,
|
||||||
|
openUniqueGiftBySlug,
|
||||||
} = getActions();
|
} = getActions();
|
||||||
|
|
||||||
const lang = useOldLang();
|
const lang = useOldLang();
|
||||||
@ -137,6 +140,10 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const handleStatusClick = useLastCallback(() => {
|
const handleStatusClick = useLastCallback(() => {
|
||||||
|
if (emojiStatusSlug) {
|
||||||
|
openUniqueGiftBySlug({ slug: emojiStatusSlug });
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!peerId) {
|
if (!peerId) {
|
||||||
openStickerSet({
|
openStickerSet({
|
||||||
stickerSetInfo: emojiStatusSticker!.stickerSetInfo,
|
stickerSetInfo: emojiStatusSticker!.stickerSetInfo,
|
||||||
@ -383,6 +390,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
|
|
||||||
const emojiStatus = (user || chat)?.emojiStatus;
|
const emojiStatus = (user || chat)?.emojiStatus;
|
||||||
const emojiStatusSticker = emojiStatus ? global.customEmojis.byId[emojiStatus.documentId] : undefined;
|
const emojiStatusSticker = emojiStatus ? global.customEmojis.byId[emojiStatus.documentId] : undefined;
|
||||||
|
const emojiStatusSlug = emojiStatus?.type === 'collectible' ? emojiStatus.slug : undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
user,
|
user,
|
||||||
@ -391,6 +399,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
mediaIndex,
|
mediaIndex,
|
||||||
avatarOwnerId,
|
avatarOwnerId,
|
||||||
emojiStatusSticker,
|
emojiStatusSticker,
|
||||||
|
emojiStatusSlug,
|
||||||
profilePhotos,
|
profilePhotos,
|
||||||
...(topic && {
|
...(topic && {
|
||||||
topic,
|
topic,
|
||||||
|
|||||||
@ -17,6 +17,7 @@ type PresetParameters = ButtonParameters | ProgressParameters;
|
|||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
style?: string;
|
||||||
} & PresetParameters;
|
} & PresetParameters;
|
||||||
|
|
||||||
const SYMBOL = '✦';
|
const SYMBOL = '✦';
|
||||||
@ -83,11 +84,12 @@ const PROGRESS_POSITIONS = generateRandomProgressPositions(100);
|
|||||||
|
|
||||||
const Sparkles = ({
|
const Sparkles = ({
|
||||||
className,
|
className,
|
||||||
|
style,
|
||||||
...presetSettings
|
...presetSettings
|
||||||
}: OwnProps) => {
|
}: OwnProps) => {
|
||||||
if (presetSettings.preset === 'button') {
|
if (presetSettings.preset === 'button') {
|
||||||
return (
|
return (
|
||||||
<div className={buildClassName(styles.root, styles.button, className)}>
|
<div className={buildClassName(styles.root, styles.button, className)} style={style}>
|
||||||
{BUTTON_POSITIONS.map((position) => {
|
{BUTTON_POSITIONS.map((position) => {
|
||||||
const shiftX = Math.cos(Math.atan2(-50 + position.y, -50 + position.x)) * 100;
|
const shiftX = Math.cos(Math.atan2(-50 + position.y, -50 + position.x)) * 100;
|
||||||
const shiftY = Math.sin(Math.atan2(-50 + position.y, -50 + position.x)) * 100;
|
const shiftY = Math.sin(Math.atan2(-50 + position.y, -50 + position.x)) * 100;
|
||||||
@ -113,7 +115,7 @@ const Sparkles = ({
|
|||||||
|
|
||||||
if (presetSettings.preset === 'progress') {
|
if (presetSettings.preset === 'progress') {
|
||||||
return (
|
return (
|
||||||
<div className={buildClassName(styles.root, styles.progress, className)}>
|
<div className={buildClassName(styles.root, styles.progress, className)} style={style}>
|
||||||
{PROGRESS_POSITIONS.map((position) => {
|
{PROGRESS_POSITIONS.map((position) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import Button from '../ui/Button';
|
|||||||
import Menu from '../ui/Menu';
|
import Menu from '../ui/Menu';
|
||||||
import MenuItem from '../ui/MenuItem';
|
import MenuItem from '../ui/MenuItem';
|
||||||
import Icon from './icons/Icon';
|
import Icon from './icons/Icon';
|
||||||
|
import Sparkles from './Sparkles';
|
||||||
import StickerView from './StickerView';
|
import StickerView from './StickerView';
|
||||||
|
|
||||||
import './StickerButton.scss';
|
import './StickerButton.scss';
|
||||||
@ -54,6 +55,7 @@ type OwnProps<T> = {
|
|||||||
onContextMenuClose?: NoneToVoidFunction;
|
onContextMenuClose?: NoneToVoidFunction;
|
||||||
onContextMenuClick?: NoneToVoidFunction;
|
onContextMenuClick?: NoneToVoidFunction;
|
||||||
isEffectEmoji?: boolean;
|
isEffectEmoji?: boolean;
|
||||||
|
withSparkles?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const contentForStatusMenuContext = [
|
const contentForStatusMenuContext = [
|
||||||
@ -92,6 +94,7 @@ const StickerButton = <T extends number | ApiSticker | ApiBotInlineMediaResult |
|
|||||||
onContextMenuClose,
|
onContextMenuClose,
|
||||||
onContextMenuClick,
|
onContextMenuClick,
|
||||||
isEffectEmoji,
|
isEffectEmoji,
|
||||||
|
withSparkles,
|
||||||
}: OwnProps<T>) => {
|
}: OwnProps<T>) => {
|
||||||
const { openStickerSet, openPremiumModal, setEmojiStatus } = getActions();
|
const { openStickerSet, openPremiumModal, setEmojiStatus } = getActions();
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
@ -198,8 +201,7 @@ const StickerButton = <T extends number | ApiSticker | ApiBotInlineMediaResult |
|
|||||||
handleContextMenuClose();
|
handleContextMenuClose();
|
||||||
onContextMenuClick?.();
|
onContextMenuClick?.();
|
||||||
setEmojiStatus({
|
setEmojiStatus({
|
||||||
emojiStatusId: sticker.id,
|
emojiStatus: { type: 'regular', documentId: sticker.id, until: getServerTime() + duration },
|
||||||
expires: getServerTime() + duration,
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -289,6 +291,7 @@ const StickerButton = <T extends number | ApiSticker | ApiBotInlineMediaResult |
|
|||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
onContextMenu={handleContextMenu}
|
onContextMenu={handleContextMenu}
|
||||||
>
|
>
|
||||||
|
{withSparkles && <Sparkles preset="button" /> }
|
||||||
{isIntesectingForShowing && (
|
{isIntesectingForShowing && (
|
||||||
<StickerView
|
<StickerView
|
||||||
containerRef={ref}
|
containerRef={ref}
|
||||||
|
|||||||
@ -2,13 +2,16 @@ import type { FC } from '../../lib/teact/teact';
|
|||||||
import React, {
|
import React, {
|
||||||
memo, useEffect, useMemo, useRef, useState,
|
memo, useEffect, useMemo, useRef, useState,
|
||||||
} from '../../lib/teact/teact';
|
} from '../../lib/teact/teact';
|
||||||
import { getActions, getGlobal } from '../../global';
|
import { getActions, getGlobal, withGlobal } from '../../global';
|
||||||
|
|
||||||
import type { ApiAvailableReaction, ApiReactionWithPaid, ApiSticker } from '../../api/types';
|
import type {
|
||||||
|
ApiAvailableReaction, ApiEmojiStatusType, ApiReactionWithPaid, ApiSticker,
|
||||||
|
} from '../../api/types';
|
||||||
import type { ObserveFn } from '../../hooks/useIntersectionObserver';
|
import type { ObserveFn } from '../../hooks/useIntersectionObserver';
|
||||||
import type { StickerSetOrReactionsSetOrRecent } from '../../types';
|
import type { StickerSetOrReactionsSetOrRecent } from '../../types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
COLLECTIBLE_STATUS_SET_ID,
|
||||||
DEFAULT_STATUS_ICON_ID,
|
DEFAULT_STATUS_ICON_ID,
|
||||||
DEFAULT_TOPIC_ICON_STICKER_ID,
|
DEFAULT_TOPIC_ICON_STICKER_ID,
|
||||||
EFFECT_EMOJIS_SET_ID,
|
EFFECT_EMOJIS_SET_ID,
|
||||||
@ -75,13 +78,17 @@ type OwnProps = {
|
|||||||
onContextMenuClick?: NoneToVoidFunction;
|
onContextMenuClick?: NoneToVoidFunction;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type StateProps = {
|
||||||
|
collectibleStatuses?: ApiEmojiStatusType[];
|
||||||
|
};
|
||||||
|
|
||||||
const ITEMS_PER_ROW_FALLBACK = 8;
|
const ITEMS_PER_ROW_FALLBACK = 8;
|
||||||
const ITEMS_MOBILE_PER_ROW_FALLBACK = 7;
|
const ITEMS_MOBILE_PER_ROW_FALLBACK = 7;
|
||||||
const ITEMS_MINI_MOBILE_PER_ROW_FALLBACK = 6;
|
const ITEMS_MINI_MOBILE_PER_ROW_FALLBACK = 6;
|
||||||
const MOBILE_WIDTH_THRESHOLD_PX = 440;
|
const MOBILE_WIDTH_THRESHOLD_PX = 440;
|
||||||
const MINI_MOBILE_WIDTH_THRESHOLD_PX = 362;
|
const MINI_MOBILE_WIDTH_THRESHOLD_PX = 362;
|
||||||
|
|
||||||
const StickerSet: FC<OwnProps> = ({
|
const StickerSet: FC<OwnProps & StateProps> = ({
|
||||||
stickerSet,
|
stickerSet,
|
||||||
loadAndPlay,
|
loadAndPlay,
|
||||||
index,
|
index,
|
||||||
@ -114,6 +121,7 @@ const StickerSet: FC<OwnProps> = ({
|
|||||||
onContextMenuOpen,
|
onContextMenuOpen,
|
||||||
onContextMenuClose,
|
onContextMenuClose,
|
||||||
onContextMenuClick,
|
onContextMenuClick,
|
||||||
|
collectibleStatuses,
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
clearRecentStickers,
|
clearRecentStickers,
|
||||||
@ -149,6 +157,7 @@ const StickerSet: FC<OwnProps> = ({
|
|||||||
const emojiMarginPx = isMobile ? 8 : 10;
|
const emojiMarginPx = isMobile ? 8 : 10;
|
||||||
const emojiVerticalMarginPx = isMobile ? 8 : 4;
|
const emojiVerticalMarginPx = isMobile ? 8 : 4;
|
||||||
const isRecent = stickerSet.id === RECENT_SYMBOL_SET_ID;
|
const isRecent = stickerSet.id === RECENT_SYMBOL_SET_ID;
|
||||||
|
const isStatusCollectible = stickerSet.id === COLLECTIBLE_STATUS_SET_ID;
|
||||||
const isFavorite = stickerSet.id === FAVORITE_SYMBOL_SET_ID;
|
const isFavorite = stickerSet.id === FAVORITE_SYMBOL_SET_ID;
|
||||||
const isPopular = stickerSet.id === POPULAR_SYMBOL_SET_ID;
|
const isPopular = stickerSet.id === POPULAR_SYMBOL_SET_ID;
|
||||||
const isEmoji = stickerSet.isEmoji;
|
const isEmoji = stickerSet.isEmoji;
|
||||||
@ -255,7 +264,11 @@ const StickerSet: FC<OwnProps> = ({
|
|||||||
const favoriteStickerIdsSet = useMemo(() => (
|
const favoriteStickerIdsSet = useMemo(() => (
|
||||||
favoriteStickers ? new Set(favoriteStickers.map(({ id }) => id)) : undefined
|
favoriteStickers ? new Set(favoriteStickers.map(({ id }) => id)) : undefined
|
||||||
), [favoriteStickers]);
|
), [favoriteStickers]);
|
||||||
const withAddSetButton = !shouldHideHeader && !isRecent && isEmoji && !isPopular && !isChatEmojiSet
|
const collectibleEmojiIdsSet = useMemo(() => (
|
||||||
|
collectibleStatuses ? new Set(collectibleStatuses.map(({ documentId }) => documentId)) : undefined
|
||||||
|
), [collectibleStatuses]);
|
||||||
|
const withAddSetButton = !shouldHideHeader && !isRecent && !isStatusCollectible
|
||||||
|
&& isEmoji && !isPopular && !isChatEmojiSet
|
||||||
&& (!isInstalled || (!isCurrentUserPremium && !isSavedMessages));
|
&& (!isInstalled || (!isCurrentUserPremium && !isSavedMessages));
|
||||||
const addSetButtonText = useMemo(() => {
|
const addSetButtonText = useMemo(() => {
|
||||||
if (isLocked) {
|
if (isLocked) {
|
||||||
@ -370,6 +383,9 @@ const StickerSet: FC<OwnProps> = ({
|
|||||||
const reactionId = sticker.isCustomEmoji ? sticker.id : sticker.emoji;
|
const reactionId = sticker.isCustomEmoji ? sticker.id : sticker.emoji;
|
||||||
const isSelected = reactionId ? selectedReactionIds?.includes(reactionId) : undefined;
|
const isSelected = reactionId ? selectedReactionIds?.includes(reactionId) : undefined;
|
||||||
|
|
||||||
|
const withSparkles = sticker.id === COLLECTIBLE_STATUS_SET_ID
|
||||||
|
|| collectibleEmojiIdsSet?.has(sticker.id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StickerButton
|
<StickerButton
|
||||||
key={sticker.id}
|
key={sticker.id}
|
||||||
@ -399,6 +415,7 @@ const StickerSet: FC<OwnProps> = ({
|
|||||||
isEffectEmoji={stickerSet.id === EFFECT_EMOJIS_SET_ID}
|
isEffectEmoji={stickerSet.id === EFFECT_EMOJIS_SET_ID}
|
||||||
noShowPremium={isCurrentUserPremium
|
noShowPremium={isCurrentUserPremium
|
||||||
&& (stickerSet.id === EFFECT_STICKERS_SET_ID || stickerSet.id === EFFECT_EMOJIS_SET_ID)}
|
&& (stickerSet.id === EFFECT_STICKERS_SET_ID || stickerSet.id === EFFECT_EMOJIS_SET_ID)}
|
||||||
|
withSparkles={withSparkles}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@ -428,7 +445,13 @@ const StickerSet: FC<OwnProps> = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(StickerSet);
|
export default memo(withGlobal<OwnProps>(
|
||||||
|
(global): StateProps => {
|
||||||
|
const collectibleStatuses = global.collectibleEmojiStatuses?.statuses;
|
||||||
|
|
||||||
|
return { collectibleStatuses };
|
||||||
|
},
|
||||||
|
)(StickerSet));
|
||||||
|
|
||||||
function getItemsPerRowFallback(windowWidth: number): number {
|
function getItemsPerRowFallback(windowWidth: number): number {
|
||||||
return windowWidth > MOBILE_WIDTH_THRESHOLD_PX
|
return windowWidth > MOBILE_WIDTH_THRESHOLD_PX
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import type { FC } from '../../../lib/teact/teact';
|
import type { FC } from '../../../lib/teact/teact';
|
||||||
import React, { memo, useMemo } from '../../../lib/teact/teact';
|
import React, { memo, useMemo } from '../../../lib/teact/teact';
|
||||||
|
|
||||||
import type { ApiEmojiStatus, ApiReactionCustomEmoji } from '../../../api/types';
|
import type { ApiEmojiStatusType, ApiReactionCustomEmoji } from '../../../api/types';
|
||||||
|
|
||||||
import { getStickerHashById } from '../../../global/helpers';
|
import { getStickerHashById } from '../../../global/helpers';
|
||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
@ -15,7 +15,7 @@ import CustomEmoji from '../CustomEmoji';
|
|||||||
import styles from './CustomEmojiEffect.module.scss';
|
import styles from './CustomEmojiEffect.module.scss';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
reaction: ApiReactionCustomEmoji | ApiEmojiStatus;
|
reaction: ApiReactionCustomEmoji | ApiEmojiStatusType;
|
||||||
className?: string;
|
className?: string;
|
||||||
isLottie?: boolean;
|
isLottie?: boolean;
|
||||||
particleSize?: number;
|
particleSize?: number;
|
||||||
|
|||||||
@ -117,6 +117,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.emoji-status {
|
.emoji-status {
|
||||||
|
overflow: visible;
|
||||||
--custom-emoji-size: 1.5rem;
|
--custom-emoji-size: 1.5rem;
|
||||||
color: var(--color-primary);
|
color: var(--color-primary);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import type { FC } from '../../../lib/teact/teact';
|
|||||||
import React, { memo, useCallback, useRef } from '../../../lib/teact/teact';
|
import React, { memo, useCallback, useRef } from '../../../lib/teact/teact';
|
||||||
import { getActions, withGlobal } from '../../../global';
|
import { getActions, withGlobal } from '../../../global';
|
||||||
|
|
||||||
import type { ApiEmojiStatus, ApiSticker } from '../../../api/types';
|
import type { ApiEmojiStatusCollectible, ApiEmojiStatusType, ApiSticker } from '../../../api/types';
|
||||||
|
|
||||||
import { EMOJI_STATUS_LOOP_LIMIT } from '../../../config';
|
import { EMOJI_STATUS_LOOP_LIMIT } from '../../../config';
|
||||||
import { selectUser } from '../../../global/selectors';
|
import { selectUser } from '../../../global/selectors';
|
||||||
@ -20,13 +20,14 @@ import Button from '../../ui/Button';
|
|||||||
import StatusPickerMenu from './StatusPickerMenu.async';
|
import StatusPickerMenu from './StatusPickerMenu.async';
|
||||||
|
|
||||||
interface StateProps {
|
interface StateProps {
|
||||||
emojiStatus?: ApiEmojiStatus;
|
emojiStatus?: ApiEmojiStatusType;
|
||||||
|
collectibleStatuses?: ApiEmojiStatusType[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const EFFECT_DURATION_MS = 1500;
|
const EFFECT_DURATION_MS = 1500;
|
||||||
const EMOJI_STATUS_SIZE = 24;
|
const EMOJI_STATUS_SIZE = 24;
|
||||||
|
|
||||||
const StatusButton: FC<StateProps> = ({ emojiStatus }) => {
|
const StatusButton: FC<StateProps> = ({ emojiStatus, collectibleStatuses }) => {
|
||||||
const { setEmojiStatus, loadCurrentUser } = getActions();
|
const { setEmojiStatus, loadCurrentUser } = getActions();
|
||||||
|
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
@ -47,9 +48,14 @@ const StatusButton: FC<StateProps> = ({ emojiStatus }) => {
|
|||||||
}, [emojiStatus, shouldShowEffect, showEffect, unmarkShouldShowEffect]);
|
}, [emojiStatus, shouldShowEffect, showEffect, unmarkShouldShowEffect]);
|
||||||
|
|
||||||
const handleEmojiStatusSet = useCallback((sticker: ApiSticker) => {
|
const handleEmojiStatusSet = useCallback((sticker: ApiSticker) => {
|
||||||
|
const collectibleStatus = collectibleStatuses?.find(
|
||||||
|
((status) => 'collectibleId' in status && status.documentId === sticker.id),
|
||||||
|
) as ApiEmojiStatusCollectible | undefined;
|
||||||
markShouldShowEffect();
|
markShouldShowEffect();
|
||||||
setEmojiStatus({ emojiStatusId: sticker.id });
|
setEmojiStatus({
|
||||||
}, [markShouldShowEffect, setEmojiStatus]);
|
emojiStatus: collectibleStatus || { type: 'regular', documentId: sticker.id },
|
||||||
|
});
|
||||||
|
}, [markShouldShowEffect, setEmojiStatus, collectibleStatuses]);
|
||||||
|
|
||||||
useTimeout(hideEffect, isEffectShown ? EFFECT_DURATION_MS : undefined);
|
useTimeout(hideEffect, isEffectShown ? EFFECT_DURATION_MS : undefined);
|
||||||
|
|
||||||
@ -81,6 +87,7 @@ const StatusButton: FC<StateProps> = ({ emojiStatus }) => {
|
|||||||
documentId={emojiStatus.documentId}
|
documentId={emojiStatus.documentId}
|
||||||
size={EMOJI_STATUS_SIZE}
|
size={EMOJI_STATUS_SIZE}
|
||||||
loopLimit={EMOJI_STATUS_LOOP_LIMIT}
|
loopLimit={EMOJI_STATUS_LOOP_LIMIT}
|
||||||
|
withSparkles={emojiStatus?.type === 'collectible'}
|
||||||
/>
|
/>
|
||||||
) : <StarIcon />}
|
) : <StarIcon />}
|
||||||
</Button>
|
</Button>
|
||||||
@ -97,8 +104,10 @@ const StatusButton: FC<StateProps> = ({ emojiStatus }) => {
|
|||||||
export default memo(withGlobal((global): StateProps => {
|
export default memo(withGlobal((global): StateProps => {
|
||||||
const { currentUserId } = global;
|
const { currentUserId } = global;
|
||||||
const currentUser = currentUserId ? selectUser(global, currentUserId) : undefined;
|
const currentUser = currentUserId ? selectUser(global, currentUserId) : undefined;
|
||||||
|
const collectibleStatuses = global.collectibleEmojiStatuses?.statuses;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
emojiStatus: currentUser?.emojiStatus,
|
emojiStatus: currentUser?.emojiStatus,
|
||||||
|
collectibleStatuses,
|
||||||
};
|
};
|
||||||
})(StatusButton));
|
})(StatusButton));
|
||||||
|
|||||||
@ -230,6 +230,7 @@ const Main = ({
|
|||||||
openThread,
|
openThread,
|
||||||
toggleLeftColumn,
|
toggleLeftColumn,
|
||||||
loadRecentEmojiStatuses,
|
loadRecentEmojiStatuses,
|
||||||
|
loadUserCollectibleStatuses,
|
||||||
updatePageTitle,
|
updatePageTitle,
|
||||||
loadTopReactions,
|
loadTopReactions,
|
||||||
loadRecentReactions,
|
loadRecentReactions,
|
||||||
@ -335,6 +336,7 @@ const Main = ({
|
|||||||
loadTopBotApps();
|
loadTopBotApps();
|
||||||
loadPaidReactionPrivacy();
|
loadPaidReactionPrivacy();
|
||||||
loadPasswordInfo();
|
loadPasswordInfo();
|
||||||
|
loadUserCollectibleStatuses();
|
||||||
}
|
}
|
||||||
}, [isMasterTab, isSynced]);
|
}, [isMasterTab, isSynced]);
|
||||||
|
|
||||||
|
|||||||
@ -69,7 +69,7 @@
|
|||||||
|
|
||||||
.chat-info-wrapper {
|
.chat-info-wrapper {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
overflow: hidden;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-tools {
|
.header-tools {
|
||||||
@ -154,7 +154,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
overflow: hidden;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
|
|||||||
@ -85,6 +85,7 @@ type StateProps = {
|
|||||||
isSyncing?: boolean;
|
isSyncing?: boolean;
|
||||||
isFetchingDifference?: boolean;
|
isFetchingDifference?: boolean;
|
||||||
emojiStatusSticker?: ApiSticker;
|
emojiStatusSticker?: ApiSticker;
|
||||||
|
emojiStatusSlug?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const MiddleHeader: FC<OwnProps & StateProps> = ({
|
const MiddleHeader: FC<OwnProps & StateProps> = ({
|
||||||
@ -108,6 +109,7 @@ const MiddleHeader: FC<OwnProps & StateProps> = ({
|
|||||||
getCurrentPinnedIndex,
|
getCurrentPinnedIndex,
|
||||||
getLoadingPinnedId,
|
getLoadingPinnedId,
|
||||||
emojiStatusSticker,
|
emojiStatusSticker,
|
||||||
|
emojiStatusSlug,
|
||||||
isSavedDialog,
|
isSavedDialog,
|
||||||
onFocusPinnedMessage,
|
onFocusPinnedMessage,
|
||||||
}) => {
|
}) => {
|
||||||
@ -120,6 +122,7 @@ const MiddleHeader: FC<OwnProps & StateProps> = ({
|
|||||||
openPremiumModal,
|
openPremiumModal,
|
||||||
openStickerSet,
|
openStickerSet,
|
||||||
updateMiddleSearch,
|
updateMiddleSearch,
|
||||||
|
openUniqueGiftBySlug,
|
||||||
} = getActions();
|
} = getActions();
|
||||||
|
|
||||||
const lang = useOldLang();
|
const lang = useOldLang();
|
||||||
@ -165,10 +168,18 @@ const MiddleHeader: FC<OwnProps & StateProps> = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const handleUserStatusClick = useLastCallback(() => {
|
const handleUserStatusClick = useLastCallback(() => {
|
||||||
|
if (emojiStatusSlug) {
|
||||||
|
openUniqueGiftBySlug({ slug: emojiStatusSlug });
|
||||||
|
return;
|
||||||
|
}
|
||||||
openPremiumModal({ fromUserId: chatId });
|
openPremiumModal({ fromUserId: chatId });
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleChannelStatusClick = useLastCallback(() => {
|
const handleChannelStatusClick = useLastCallback(() => {
|
||||||
|
if (emojiStatusSlug) {
|
||||||
|
openUniqueGiftBySlug({ slug: emojiStatusSlug });
|
||||||
|
return;
|
||||||
|
}
|
||||||
openStickerSet({
|
openStickerSet({
|
||||||
stickerSetInfo: emojiStatusSticker!.stickerSetInfo,
|
stickerSetInfo: emojiStatusSticker!.stickerSetInfo,
|
||||||
});
|
});
|
||||||
@ -388,6 +399,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
|
|
||||||
const emojiStatus = chat?.emojiStatus;
|
const emojiStatus = chat?.emojiStatus;
|
||||||
const emojiStatusSticker = emojiStatus && global.customEmojis.byId[emojiStatus.documentId];
|
const emojiStatusSticker = emojiStatus && global.customEmojis.byId[emojiStatus.documentId];
|
||||||
|
const emojiStatusSlug = emojiStatus?.type === 'collectible' ? emojiStatus.slug : undefined;
|
||||||
|
|
||||||
const isSavedDialog = getIsSavedDialog(chatId, threadId, global.currentUserId);
|
const isSavedDialog = getIsSavedDialog(chatId, threadId, global.currentUserId);
|
||||||
|
|
||||||
@ -406,6 +418,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
isSyncing: global.isSyncing,
|
isSyncing: global.isSyncing,
|
||||||
isFetchingDifference: global.isFetchingDifference,
|
isFetchingDifference: global.isFetchingDifference,
|
||||||
emojiStatusSticker,
|
emojiStatusSticker,
|
||||||
|
emojiStatusSlug,
|
||||||
isSavedDialog,
|
isSavedDialog,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import EmojiStatusAccessModal from './emojiStatusAccess/EmojiStatusAccessModal.a
|
|||||||
import PremiumGiftModal from './gift/GiftModal.async';
|
import PremiumGiftModal from './gift/GiftModal.async';
|
||||||
import GiftInfoModal from './gift/info/GiftInfoModal.async';
|
import GiftInfoModal from './gift/info/GiftInfoModal.async';
|
||||||
import GiftRecipientPicker from './gift/recipient/GiftRecipientPicker.async';
|
import GiftRecipientPicker from './gift/recipient/GiftRecipientPicker.async';
|
||||||
|
import GiftStatusInfoModal from './gift/status/GiftStatusInfoModal.async';
|
||||||
import GiftTransferModal from './gift/transfer/GiftTransferModal.async';
|
import GiftTransferModal from './gift/transfer/GiftTransferModal.async';
|
||||||
import GiftUpgradeModal from './gift/upgrade/GiftUpgradeModal.async';
|
import GiftUpgradeModal from './gift/upgrade/GiftUpgradeModal.async';
|
||||||
import GiftWithdrawModal from './gift/withdraw/GiftWithdrawModal.async';
|
import GiftWithdrawModal from './gift/withdraw/GiftWithdrawModal.async';
|
||||||
@ -71,6 +72,7 @@ type ModalKey = keyof Pick<TabState,
|
|||||||
'giftUpgradeModal' |
|
'giftUpgradeModal' |
|
||||||
'monetizationVerificationModal' |
|
'monetizationVerificationModal' |
|
||||||
'giftWithdrawModal' |
|
'giftWithdrawModal' |
|
||||||
|
'giftStatusInfoModal' |
|
||||||
'giftTransferModal'
|
'giftTransferModal'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
@ -117,6 +119,7 @@ const MODALS: ModalRegistry = {
|
|||||||
giftUpgradeModal: GiftUpgradeModal,
|
giftUpgradeModal: GiftUpgradeModal,
|
||||||
monetizationVerificationModal: VerificationMonetizationModal,
|
monetizationVerificationModal: VerificationMonetizationModal,
|
||||||
giftWithdrawModal: GiftWithdrawModal,
|
giftWithdrawModal: GiftWithdrawModal,
|
||||||
|
giftStatusInfoModal: GiftStatusInfoModal,
|
||||||
giftTransferModal: GiftTransferModal,
|
giftTransferModal: GiftTransferModal,
|
||||||
};
|
};
|
||||||
const MODAL_KEYS = Object.keys(MODALS) as ModalKey[];
|
const MODAL_KEYS = Object.keys(MODALS) as ModalKey[];
|
||||||
|
|||||||
@ -28,6 +28,10 @@
|
|||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.listItemIcon {
|
||||||
|
color: var(--accent-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@ -2,6 +2,8 @@ import React, { memo, type TeactNode } from '../../../lib/teact/teact';
|
|||||||
|
|
||||||
import type { IconName } from '../../../types/icons';
|
import type { IconName } from '../../../types/icons';
|
||||||
|
|
||||||
|
import buildClassName from '../../../util/buildClassName';
|
||||||
|
|
||||||
import Icon from '../../common/icons/Icon';
|
import Icon from '../../common/icons/Icon';
|
||||||
import Button from '../../ui/Button';
|
import Button from '../../ui/Button';
|
||||||
import ListItem from '../../ui/ListItem';
|
import ListItem from '../../ui/ListItem';
|
||||||
@ -13,6 +15,7 @@ import styles from './TableAboutModal.module.scss';
|
|||||||
export type TableAboutData = [IconName | undefined, TeactNode, TeactNode][];
|
export type TableAboutData = [IconName | undefined, TeactNode, TeactNode][];
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
|
contentClassName?: string;
|
||||||
isOpen?: boolean;
|
isOpen?: boolean;
|
||||||
listItemData?: TableAboutData;
|
listItemData?: TableAboutData;
|
||||||
headerIconName?: IconName;
|
headerIconName?: IconName;
|
||||||
@ -36,11 +39,12 @@ const TableAboutModal = ({
|
|||||||
withSeparator,
|
withSeparator,
|
||||||
onClose,
|
onClose,
|
||||||
onButtonClick,
|
onButtonClick,
|
||||||
|
contentClassName,
|
||||||
}: OwnProps) => {
|
}: OwnProps) => {
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
className={styles.root}
|
className={buildClassName(styles.root, contentClassName)}
|
||||||
contentClassName={styles.content}
|
contentClassName={styles.content}
|
||||||
hasAbsoluteCloseButton
|
hasAbsoluteCloseButton
|
||||||
absoluteCloseButtonColor={hasBackdrop ? 'translucent-white' : undefined}
|
absoluteCloseButtonColor={hasBackdrop ? 'translucent-white' : undefined}
|
||||||
@ -55,6 +59,7 @@ const TableAboutModal = ({
|
|||||||
isStatic
|
isStatic
|
||||||
multiline
|
multiline
|
||||||
icon={icon}
|
icon={icon}
|
||||||
|
iconClassName={styles.listItemIcon}
|
||||||
>
|
>
|
||||||
<span className="title">{title}</span>
|
<span className="title">{title}</span>
|
||||||
<span className="subtitle">{subtitle}</span>
|
<span className="subtitle">{subtitle}</span>
|
||||||
|
|||||||
@ -70,6 +70,7 @@ const EmojiStatusAccessModal: FC<OwnProps & StateProps> = ({
|
|||||||
return {
|
return {
|
||||||
...currentUser,
|
...currentUser,
|
||||||
emojiStatus: {
|
emojiStatus: {
|
||||||
|
type: 'regular',
|
||||||
documentId: stickerSet.stickers[currentStatusIndex].id,
|
documentId: stickerSet.stickers[currentStatusIndex].id,
|
||||||
},
|
},
|
||||||
} satisfies ApiUser;
|
} satisfies ApiUser;
|
||||||
|
|||||||
@ -62,7 +62,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.modalHeader {
|
.modalHeader {
|
||||||
z-index: 1;
|
z-index: 2;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0.375rem;
|
padding: 0.375rem;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@ -3,14 +3,16 @@ import React, { memo, useMemo } from '../../../../lib/teact/teact';
|
|||||||
import { getActions, getGlobal, withGlobal } from '../../../../global';
|
import { getActions, getGlobal, withGlobal } from '../../../../global';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
ApiEmojiStatusCollectible,
|
||||||
|
ApiEmojiStatusType,
|
||||||
ApiPeer,
|
ApiPeer,
|
||||||
} from '../../../../api/types';
|
} from '../../../../api/types';
|
||||||
import type { TabState } from '../../../../global/types';
|
import type { TabState } from '../../../../global/types';
|
||||||
|
|
||||||
import { TME_LINK_PREFIX } from '../../../../config';
|
import { DEFAULT_STATUS_ICON_ID, TME_LINK_PREFIX } from '../../../../config';
|
||||||
import { getHasAdminRight, getPeerTitle } from '../../../../global/helpers';
|
import { getHasAdminRight, getPeerTitle } from '../../../../global/helpers';
|
||||||
import { isApiPeerChat } from '../../../../global/helpers/peers';
|
import { isApiPeerChat } from '../../../../global/helpers/peers';
|
||||||
import { selectPeer } from '../../../../global/selectors';
|
import { selectPeer, selectUser } from '../../../../global/selectors';
|
||||||
import buildClassName from '../../../../util/buildClassName';
|
import buildClassName from '../../../../util/buildClassName';
|
||||||
import { copyTextToClipboard } from '../../../../util/clipboard';
|
import { copyTextToClipboard } from '../../../../util/clipboard';
|
||||||
import { formatDateTimeToString } from '../../../../util/dates/dateFormat';
|
import { formatDateTimeToString } from '../../../../util/dates/dateFormat';
|
||||||
@ -51,6 +53,8 @@ type StateProps = {
|
|||||||
currentUserId?: string;
|
currentUserId?: string;
|
||||||
starGiftMaxConvertPeriod?: number;
|
starGiftMaxConvertPeriod?: number;
|
||||||
hasAdminRights?: boolean;
|
hasAdminRights?: boolean;
|
||||||
|
currentUserEmojiStatus?: ApiEmojiStatusType;
|
||||||
|
collectibleEmojiStatuses?: ApiEmojiStatusType[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const STICKER_SIZE = 120;
|
const STICKER_SIZE = 120;
|
||||||
@ -62,6 +66,8 @@ const GiftInfoModal = ({
|
|||||||
currentUserId,
|
currentUserId,
|
||||||
starGiftMaxConvertPeriod,
|
starGiftMaxConvertPeriod,
|
||||||
hasAdminRights,
|
hasAdminRights,
|
||||||
|
currentUserEmojiStatus,
|
||||||
|
collectibleEmojiStatuses,
|
||||||
}: OwnProps & StateProps) => {
|
}: OwnProps & StateProps) => {
|
||||||
const {
|
const {
|
||||||
closeGiftInfoModal,
|
closeGiftInfoModal,
|
||||||
@ -72,6 +78,8 @@ const GiftInfoModal = ({
|
|||||||
openGiftUpgradeModal,
|
openGiftUpgradeModal,
|
||||||
showNotification,
|
showNotification,
|
||||||
openChatWithDraft,
|
openChatWithDraft,
|
||||||
|
openGiftStatusInfoModal,
|
||||||
|
setEmojiStatus,
|
||||||
openGiftTransferModal,
|
openGiftTransferModal,
|
||||||
} = getActions();
|
} = getActions();
|
||||||
|
|
||||||
@ -99,6 +107,25 @@ const GiftInfoModal = ({
|
|||||||
const gift = isSavedGift ? typeGift.gift : typeGift;
|
const gift = isSavedGift ? typeGift.gift : typeGift;
|
||||||
const giftSticker = gift && getStickerFromGift(gift);
|
const giftSticker = gift && getStickerFromGift(gift);
|
||||||
|
|
||||||
|
const currenUniqueEmojiStatusSlug = currentUserEmojiStatus?.type === 'collectible'
|
||||||
|
? currentUserEmojiStatus.slug : undefined;
|
||||||
|
|
||||||
|
const starGiftUniqueSlug = gift?.type === 'starGiftUnique' ? gift.slug : undefined;
|
||||||
|
const starGiftUniqueLink = useMemo(() => {
|
||||||
|
if (!starGiftUniqueSlug) return undefined;
|
||||||
|
return `${TME_LINK_PREFIX}nft/${starGiftUniqueSlug}`;
|
||||||
|
}, [starGiftUniqueSlug]);
|
||||||
|
const userCollectibleStatus = useMemo(() => {
|
||||||
|
if (!starGiftUniqueSlug) return undefined;
|
||||||
|
return collectibleEmojiStatuses?.find((
|
||||||
|
status,
|
||||||
|
) => status.type === 'collectible' && status.slug === starGiftUniqueSlug) as ApiEmojiStatusCollectible | undefined;
|
||||||
|
}, [starGiftUniqueSlug, collectibleEmojiStatuses]);
|
||||||
|
|
||||||
|
const isGiftUnique = gift && gift.type === 'starGiftUnique';
|
||||||
|
const canTakeOff = isGiftUnique && currenUniqueEmojiStatusSlug === gift.slug;
|
||||||
|
const canWear = userCollectibleStatus && !canTakeOff;
|
||||||
|
|
||||||
const canFocusUpgrade = Boolean(savedGift?.upgradeMsgId);
|
const canFocusUpgrade = Boolean(savedGift?.upgradeMsgId);
|
||||||
const canUpdate = !canFocusUpgrade && savedGift?.inputGift && (
|
const canUpdate = !canFocusUpgrade && savedGift?.inputGift && (
|
||||||
isTargetChat ? hasAdminRights : renderingTargetPeer?.id === currentUserId
|
isTargetChat ? hasAdminRights : renderingTargetPeer?.id === currentUserId
|
||||||
@ -108,12 +135,6 @@ const GiftInfoModal = ({
|
|||||||
closeGiftInfoModal();
|
closeGiftInfoModal();
|
||||||
});
|
});
|
||||||
|
|
||||||
const starGiftUniqueLink = useMemo(() => {
|
|
||||||
const slug = gift?.type === 'starGiftUnique' ? gift.slug : undefined;
|
|
||||||
if (!slug) return undefined;
|
|
||||||
return `${TME_LINK_PREFIX}nft/${slug}`;
|
|
||||||
}, [gift]);
|
|
||||||
|
|
||||||
const handleCopyLink = useLastCallback(() => {
|
const handleCopyLink = useLastCallback(() => {
|
||||||
if (!starGiftUniqueLink) return;
|
if (!starGiftUniqueLink) return;
|
||||||
copyTextToClipboard(starGiftUniqueLink);
|
copyTextToClipboard(starGiftUniqueLink);
|
||||||
@ -133,6 +154,19 @@ const GiftInfoModal = ({
|
|||||||
openGiftTransferModal({ gift: savedGift });
|
openGiftTransferModal({ gift: savedGift });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handleWear = useLastCallback(() => {
|
||||||
|
if (gift?.type !== 'starGiftUnique' || !userCollectibleStatus) return;
|
||||||
|
openGiftStatusInfoModal({ emojiStatus: userCollectibleStatus });
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleTakeOff = useLastCallback(() => {
|
||||||
|
if (canTakeOff) {
|
||||||
|
setEmojiStatus({
|
||||||
|
emojiStatus: { type: 'regular', documentId: DEFAULT_STATUS_ICON_ID },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const handleFocusUpgraded = useLastCallback(() => {
|
const handleFocusUpgraded = useLastCallback(() => {
|
||||||
if (!savedGift?.upgradeMsgId || !renderingTargetPeer) return;
|
if (!savedGift?.upgradeMsgId || !renderingTargetPeer) return;
|
||||||
const { upgradeMsgId } = savedGift;
|
const { upgradeMsgId } = savedGift;
|
||||||
@ -271,37 +305,39 @@ const GiftInfoModal = ({
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
function getTitle() {
|
function getTitle() {
|
||||||
if (gift?.type === 'starGiftUnique') return gift.title;
|
if (isGiftUnique) return gift.title;
|
||||||
if (!savedGift) return lang('GiftInfoSoldOutTitle');
|
if (!savedGift) return lang('GiftInfoSoldOutTitle');
|
||||||
|
|
||||||
return canUpdate ? lang('GiftInfoReceived') : lang('GiftInfoTitle');
|
return canUpdate ? lang('GiftInfoReceived') : lang('GiftInfoTitle');
|
||||||
}
|
}
|
||||||
|
|
||||||
const isUniqueGift = gift.type === 'starGiftUnique';
|
const uniqueGiftContextMenu = (
|
||||||
|
|
||||||
const contextMenu = (
|
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
className="with-menu-transitions"
|
className="with-menu-transitions"
|
||||||
trigger={SettingsMenuButton}
|
trigger={SettingsMenuButton}
|
||||||
positionX="right"
|
positionX="right"
|
||||||
>
|
>
|
||||||
<MenuItem
|
<MenuItem icon="link-badge" onClick={handleCopyLink}>
|
||||||
icon="link-badge"
|
|
||||||
onClick={handleCopyLink}
|
|
||||||
>
|
|
||||||
{lang('CopyLink')}
|
{lang('CopyLink')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem
|
<MenuItem icon="forward" onClick={handleLinkShare}>
|
||||||
icon="forward"
|
|
||||||
onClick={handleLinkShare}
|
|
||||||
>
|
|
||||||
{lang('Share')}
|
{lang('Share')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{canUpdate && isUniqueGift && (
|
{canUpdate && isGiftUnique && (
|
||||||
<MenuItem icon="diamond" onClick={handleTransfer}>
|
<MenuItem icon="diamond" onClick={handleTransfer}>
|
||||||
{lang('GiftInfoTransfer')}
|
{lang('GiftInfoTransfer')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
)}
|
)}
|
||||||
|
{canWear && (
|
||||||
|
<MenuItem icon="crown-wear" onClick={handleWear}>
|
||||||
|
{lang('GiftInfoWear')}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
{canTakeOff && (
|
||||||
|
<MenuItem icon="crown-take-off" onClick={handleTakeOff}>
|
||||||
|
{lang('GiftInfoTakeOff')}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -319,11 +355,11 @@ const GiftInfoModal = ({
|
|||||||
>
|
>
|
||||||
<Icon name="close" />
|
<Icon name="close" />
|
||||||
</Button>
|
</Button>
|
||||||
{isOpen && contextMenu}
|
{isOpen && uniqueGiftContextMenu}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const uniqueGiftHeader = isUniqueGift && (
|
const uniqueGiftHeader = isGiftUnique && (
|
||||||
<div className={buildClassName(styles.header, styles.uniqueGift)}>
|
<div className={buildClassName(styles.header, styles.uniqueGift)}>
|
||||||
<UniqueGiftHeader
|
<UniqueGiftHeader
|
||||||
backdropAttribute={giftAttributes!.backdrop!}
|
backdropAttribute={giftAttributes!.backdrop!}
|
||||||
@ -432,7 +468,7 @@ const GiftInfoModal = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gift.type === 'starGiftUnique') {
|
if (isGiftUnique) {
|
||||||
const { ownerName, ownerAddress, ownerId } = gift;
|
const { ownerName, ownerAddress, ownerId } = gift;
|
||||||
const {
|
const {
|
||||||
model, backdrop, pattern, originalDetails,
|
model, backdrop, pattern, originalDetails,
|
||||||
@ -458,7 +494,7 @@ const GiftInfoModal = ({
|
|||||||
} else {
|
} else {
|
||||||
tableData.push([
|
tableData.push([
|
||||||
lang('GiftInfoOwner'),
|
lang('GiftInfoOwner'),
|
||||||
ownerId ? { chatId: ownerId } : ownerName || '',
|
ownerId ? { chatId: ownerId, withEmojiStatus: true } : ownerName || '',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -590,14 +626,16 @@ const GiftInfoModal = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
modalHeader: isUniqueGift ? uniqueGiftModalHeader : undefined,
|
modalHeader: isGiftUnique ? uniqueGiftModalHeader : undefined,
|
||||||
header: isUniqueGift ? uniqueGiftHeader : regularHeader,
|
header: isGiftUnique ? uniqueGiftHeader : regularHeader,
|
||||||
tableData,
|
tableData,
|
||||||
footer,
|
footer,
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
typeGift, savedGift, renderingTargetPeer, giftSticker, lang, canUpdate, canConvertDifference, isSender, oldLang,
|
typeGift, savedGift, renderingTargetPeer, giftSticker, lang,
|
||||||
gift, giftAttributes, renderFooterButton, isTargetChat, SettingsMenuButton, isOpen,
|
canUpdate, canConvertDifference, isSender, oldLang,
|
||||||
|
gift, giftAttributes, renderFooterButton, isTargetChat,
|
||||||
|
SettingsMenuButton, isOpen, isGiftUnique, canWear, canTakeOff,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -606,7 +644,7 @@ const GiftInfoModal = ({
|
|||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
modalHeader={modalData?.modalHeader}
|
modalHeader={modalData?.modalHeader}
|
||||||
header={modalData?.header}
|
header={modalData?.header}
|
||||||
hasBackdrop={gift?.type === 'starGiftUnique'}
|
hasBackdrop={isGiftUnique}
|
||||||
tableData={modalData?.tableData}
|
tableData={modalData?.tableData}
|
||||||
footer={modalData?.footer}
|
footer={modalData?.footer}
|
||||||
className={styles.modal}
|
className={styles.modal}
|
||||||
@ -656,6 +694,9 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
const targetPeer = modal?.peerId ? selectPeer(global, modal.peerId) : undefined;
|
const targetPeer = modal?.peerId ? selectPeer(global, modal.peerId) : undefined;
|
||||||
const chat = targetPeer && isApiPeerChat(targetPeer) ? targetPeer : undefined;
|
const chat = targetPeer && isApiPeerChat(targetPeer) ? targetPeer : undefined;
|
||||||
const hasAdminRights = chat && getHasAdminRight(chat, 'postMessages');
|
const hasAdminRights = chat && getHasAdminRight(chat, 'postMessages');
|
||||||
|
const currentUser = global.currentUserId ? selectUser(global, global.currentUserId) : undefined;
|
||||||
|
const currentUserEmojiStatus = currentUser?.emojiStatus;
|
||||||
|
const collectibleEmojiStatuses = global.collectibleEmojiStatuses?.statuses;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
fromPeer,
|
fromPeer,
|
||||||
@ -663,6 +704,8 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
currentUserId: global.currentUserId,
|
currentUserId: global.currentUserId,
|
||||||
starGiftMaxConvertPeriod: global.appConfig?.starGiftMaxConvertPeriod,
|
starGiftMaxConvertPeriod: global.appConfig?.starGiftMaxConvertPeriod,
|
||||||
hasAdminRights,
|
hasAdminRights,
|
||||||
|
currentUserEmojiStatus,
|
||||||
|
collectibleEmojiStatuses,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
)(GiftInfoModal));
|
)(GiftInfoModal));
|
||||||
|
|||||||
@ -0,0 +1,18 @@
|
|||||||
|
import type { FC } from '../../../../lib/teact/teact';
|
||||||
|
import React from '../../../../lib/teact/teact';
|
||||||
|
|
||||||
|
import type { OwnProps } from './GiftStatusInfoModal';
|
||||||
|
|
||||||
|
import { Bundles } from '../../../../util/moduleLoader';
|
||||||
|
|
||||||
|
import useModuleLoader from '../../../../hooks/useModuleLoader';
|
||||||
|
|
||||||
|
const GiftStatusInfoModalAsync: FC<OwnProps> = (props) => {
|
||||||
|
const { modal } = props;
|
||||||
|
const GiftStatusInfoModal = useModuleLoader(Bundles.Stars, 'GiftStatusInfoModal', !modal);
|
||||||
|
|
||||||
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||||
|
return GiftStatusInfoModal ? <GiftStatusInfoModal {...props} /> : undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftStatusInfoModalAsync;
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
.header,
|
||||||
|
.profileBlock {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.titleContainer {
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profileBlock {
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radialPattern {
|
||||||
|
position: absolute;
|
||||||
|
inset-inline-start: -1.5rem;
|
||||||
|
height: calc(100% + 2rem);
|
||||||
|
top: -3rem;
|
||||||
|
width: calc(100% + 3rem);
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lockIcon {
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-left: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.userTitle {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
color: white;
|
||||||
|
margin-top: auto;
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
padding-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
text-align: center;
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.userTitle, .status {
|
||||||
|
margin-bottom: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.giftTitle {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
text-align: center;
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoDescription {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
171
src/components/modals/gift/status/GiftStatusInfoModal.tsx
Normal file
171
src/components/modals/gift/status/GiftStatusInfoModal.tsx
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
import React, { memo, useMemo } from '../../../../lib/teact/teact';
|
||||||
|
import { getActions, withGlobal } from '../../../../global';
|
||||||
|
|
||||||
|
import type {
|
||||||
|
ApiUser,
|
||||||
|
} from '../../../../api/types';
|
||||||
|
import type { TabState } from '../../../../global/types';
|
||||||
|
|
||||||
|
import { selectIsCurrentUserPremium, selectUser } from '../../../../global/selectors';
|
||||||
|
import buildClassName from '../../../../util/buildClassName';
|
||||||
|
import buildStyle from '../../../../util/buildStyle';
|
||||||
|
|
||||||
|
import useCurrentOrPrev from '../../../../hooks/useCurrentOrPrev';
|
||||||
|
import useLang from '../../../../hooks/useLang';
|
||||||
|
import useLastCallback from '../../../../hooks/useLastCallback';
|
||||||
|
import useCustomEmoji from '../../../common/hooks/useCustomEmoji';
|
||||||
|
|
||||||
|
import Avatar from '../../../common/Avatar';
|
||||||
|
import FullNameTitle from '../../../common/FullNameTitle';
|
||||||
|
import Icon from '../../../common/icons/Icon';
|
||||||
|
import RadialPatternBackground from '../../../common/profile/RadialPatternBackground';
|
||||||
|
import Button from '../../../ui/Button';
|
||||||
|
import TableAboutModal, { type TableAboutData } from '../../common/TableAboutModal';
|
||||||
|
|
||||||
|
import styles from './GiftStatusInfoModal.module.scss';
|
||||||
|
|
||||||
|
export type OwnProps = {
|
||||||
|
modal: TabState['giftStatusInfoModal'];
|
||||||
|
};
|
||||||
|
|
||||||
|
type StateProps = {
|
||||||
|
currentUser: ApiUser;
|
||||||
|
isCurrentUserPremium?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const GiftStatusInfoModal = ({
|
||||||
|
modal,
|
||||||
|
currentUser,
|
||||||
|
isCurrentUserPremium,
|
||||||
|
}: OwnProps & StateProps) => {
|
||||||
|
const {
|
||||||
|
closeGiftStatusInfoModal,
|
||||||
|
setEmojiStatus,
|
||||||
|
} = getActions();
|
||||||
|
const lang = useLang();
|
||||||
|
const isOpen = Boolean(modal);
|
||||||
|
const renderingModal = useCurrentOrPrev(modal);
|
||||||
|
|
||||||
|
const { emojiStatus } = renderingModal || {};
|
||||||
|
|
||||||
|
const subtitleColor = emojiStatus?.textColor;
|
||||||
|
|
||||||
|
const patternIcon = useCustomEmoji(emojiStatus?.patternDocumentId);
|
||||||
|
|
||||||
|
const handleClose = useLastCallback(() => {
|
||||||
|
closeGiftStatusInfoModal();
|
||||||
|
});
|
||||||
|
|
||||||
|
const onWearClick = useLastCallback(() => {
|
||||||
|
if (emojiStatus) {
|
||||||
|
setEmojiStatus({ emojiStatus });
|
||||||
|
}
|
||||||
|
closeGiftStatusInfoModal();
|
||||||
|
});
|
||||||
|
|
||||||
|
const radialPatternBackdrop = useMemo(() => {
|
||||||
|
if (!emojiStatus || !isOpen) return undefined;
|
||||||
|
|
||||||
|
const backdropColors = [emojiStatus.centerColor, emojiStatus.edgeColor];
|
||||||
|
const patternColor = emojiStatus.patternColor;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<RadialPatternBackground
|
||||||
|
className={styles.radialPattern}
|
||||||
|
backgroundColors={backdropColors}
|
||||||
|
patternColor={patternColor}
|
||||||
|
patternIcon={patternIcon.customEmoji}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}, [emojiStatus, isOpen, patternIcon]);
|
||||||
|
|
||||||
|
const mockPeerWithStatus = useMemo(() => {
|
||||||
|
return {
|
||||||
|
...currentUser,
|
||||||
|
emojiStatus,
|
||||||
|
} satisfies ApiUser;
|
||||||
|
}, [currentUser, emojiStatus]);
|
||||||
|
|
||||||
|
const header = useMemo(() => {
|
||||||
|
return (
|
||||||
|
<div className={styles.header}>
|
||||||
|
<div
|
||||||
|
className={buildClassName(styles.profileBlock)}
|
||||||
|
style={buildStyle(subtitleColor && `color: ${subtitleColor}`)}
|
||||||
|
>
|
||||||
|
|
||||||
|
{radialPatternBackdrop}
|
||||||
|
<Avatar peer={mockPeerWithStatus} size="jumbo" className={styles.avatar} />
|
||||||
|
<FullNameTitle
|
||||||
|
peer={mockPeerWithStatus}
|
||||||
|
className={styles.userTitle}
|
||||||
|
withEmojiStatus
|
||||||
|
noFake
|
||||||
|
noVerified
|
||||||
|
statusSparklesColor={subtitleColor}
|
||||||
|
/>
|
||||||
|
<p className={styles.status} style={buildStyle(subtitleColor && `color: ${subtitleColor}`)}>
|
||||||
|
{lang('Online')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.titleContainer}>
|
||||||
|
<div className={styles.giftTitle}>{
|
||||||
|
lang('UniqueStatusWearTitle', {
|
||||||
|
gift: mockPeerWithStatus?.emojiStatus?.title,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div className={styles.infoDescription}>{
|
||||||
|
lang('UniqueStatusBenefitsDescription')
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}, [subtitleColor, radialPatternBackdrop, mockPeerWithStatus, lang]);
|
||||||
|
|
||||||
|
const listItemData = [
|
||||||
|
['radial-badge', lang('UniqueStatusBadgeBenefitTitle'), lang('UniqueStatusBadgeDescription')],
|
||||||
|
['unique-profile', lang('UniqueStatusProfileDesignBenefitTitle'), lang('UniqueStatusProfileDesignDescription')],
|
||||||
|
['proof-of-ownership', lang('UniqueStatusProofOfOwnershipBenefitTitle'),
|
||||||
|
lang('UniqueStatusProofOfOwnershipDescription')],
|
||||||
|
] satisfies TableAboutData;
|
||||||
|
|
||||||
|
const footer = useMemo(() => {
|
||||||
|
if (!isOpen) return undefined;
|
||||||
|
return (
|
||||||
|
<div className={styles.footer}>
|
||||||
|
<Button
|
||||||
|
size="smaller"
|
||||||
|
onClick={onWearClick}
|
||||||
|
>
|
||||||
|
{lang('UniqueStatusWearButton')}
|
||||||
|
{!isCurrentUserPremium && <Icon name="lock-badge" className={styles.lockIcon} />}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}, [lang, isCurrentUserPremium, isOpen]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableAboutModal
|
||||||
|
isOpen={isOpen}
|
||||||
|
header={header}
|
||||||
|
listItemData={listItemData}
|
||||||
|
footer={footer}
|
||||||
|
hasBackdrop
|
||||||
|
onClose={handleClose}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(withGlobal<OwnProps>(
|
||||||
|
(global): StateProps => {
|
||||||
|
const currentUser = selectUser(global, global.currentUserId!)!;
|
||||||
|
const isCurrentUserPremium = selectIsCurrentUserPremium(global);
|
||||||
|
|
||||||
|
return {
|
||||||
|
currentUser,
|
||||||
|
isCurrentUserPremium,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
)(GiftStatusInfoModal));
|
||||||
@ -45,6 +45,7 @@ const SuggestedStatusModal = ({ modal, currentUser, bot }: OwnProps & StateProps
|
|||||||
return {
|
return {
|
||||||
...currentUser,
|
...currentUser,
|
||||||
emojiStatus: {
|
emojiStatus: {
|
||||||
|
type: 'regular',
|
||||||
documentId: renderingModal.customEmojiId,
|
documentId: renderingModal.customEmojiId,
|
||||||
},
|
},
|
||||||
} satisfies ApiUser;
|
} satisfies ApiUser;
|
||||||
@ -93,8 +94,7 @@ const SuggestedStatusModal = ({ modal, currentUser, bot }: OwnProps & StateProps
|
|||||||
|
|
||||||
setEmojiStatus({
|
setEmojiStatus({
|
||||||
referrerWebAppKey: renderingModal.webAppKey,
|
referrerWebAppKey: renderingModal.webAppKey,
|
||||||
emojiStatusId: renderingModal.customEmojiId,
|
emojiStatus: { type: 'regular', documentId: renderingModal.customEmojiId, until: expires },
|
||||||
expires,
|
|
||||||
});
|
});
|
||||||
closeSuggestedStatusModal();
|
closeSuggestedStatusModal();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -86,6 +86,10 @@
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.info .Transition {
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.Transition {
|
.Transition {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -104,7 +104,6 @@
|
|||||||
text-align: initial;
|
text-align: initial;
|
||||||
unicode-bidi: plaintext;
|
unicode-bidi: plaintext;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.other-usernames {
|
.other-usernames {
|
||||||
@ -225,7 +224,7 @@
|
|||||||
|
|
||||||
.info {
|
.info {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: hidden;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-name-title {
|
.info-name-title {
|
||||||
@ -236,10 +235,10 @@
|
|||||||
.info-row,
|
.info-row,
|
||||||
.title,
|
.title,
|
||||||
.subtitle {
|
.subtitle {
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.separator {
|
.separator {
|
||||||
@ -287,7 +286,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: hidden;
|
min-width: 0;
|
||||||
|
|
||||||
.info {
|
.info {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@ -219,6 +219,7 @@ export const EMOJI_SIZES = 7;
|
|||||||
export const TOP_SYMBOL_SET_ID = 'top';
|
export const TOP_SYMBOL_SET_ID = 'top';
|
||||||
export const POPULAR_SYMBOL_SET_ID = 'popular';
|
export const POPULAR_SYMBOL_SET_ID = 'popular';
|
||||||
export const RECENT_SYMBOL_SET_ID = 'recent';
|
export const RECENT_SYMBOL_SET_ID = 'recent';
|
||||||
|
export const COLLECTIBLE_STATUS_SET_ID = 'collectibleStatus';
|
||||||
export const FAVORITE_SYMBOL_SET_ID = 'favorite';
|
export const FAVORITE_SYMBOL_SET_ID = 'favorite';
|
||||||
export const EFFECT_STICKERS_SET_ID = 'effectStickers';
|
export const EFFECT_STICKERS_SET_ID = 'effectStickers';
|
||||||
export const EFFECT_EMOJIS_SET_ID = 'effectEmojis';
|
export const EFFECT_EMOJIS_SET_ID = 'effectEmojis';
|
||||||
|
|||||||
@ -239,6 +239,31 @@ addActionHandler('loadDefaultStatusIcons', async (global): Promise<void> => {
|
|||||||
setGlobal(global);
|
setGlobal(global);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addActionHandler('loadUserCollectibleStatuses', async (global, actions): Promise<void> => {
|
||||||
|
setGlobal(global);
|
||||||
|
|
||||||
|
const { hash } = global.collectibleEmojiStatuses || {};
|
||||||
|
|
||||||
|
const result = await callApi('fetchCollectibleEmojiStatuses', { hash });
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
global = getGlobal();
|
||||||
|
|
||||||
|
global = {
|
||||||
|
...global,
|
||||||
|
collectibleEmojiStatuses: {
|
||||||
|
hash: result.hash,
|
||||||
|
statuses: result.statuses,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
setGlobal(global);
|
||||||
|
const documentIds = result.statuses.map(({ documentId }) => documentId);
|
||||||
|
|
||||||
|
actions.loadCustomEmojis({ ids: documentIds });
|
||||||
|
});
|
||||||
|
|
||||||
addActionHandler('loadStickers', (global, actions, payload): ActionReturnType => {
|
addActionHandler('loadStickers', (global, actions, payload): ActionReturnType => {
|
||||||
const { stickerSetInfo } = payload;
|
const { stickerSetInfo } = payload;
|
||||||
const cachedSet = selectStickerSet(global, stickerSetInfo);
|
const cachedSet = selectStickerSet(global, stickerSetInfo);
|
||||||
|
|||||||
@ -389,7 +389,7 @@ addActionHandler('reportSpam', (global, actions, payload): ActionReturnType => {
|
|||||||
|
|
||||||
addActionHandler('setEmojiStatus', async (global, actions, payload): Promise<void> => {
|
addActionHandler('setEmojiStatus', async (global, actions, payload): Promise<void> => {
|
||||||
const {
|
const {
|
||||||
emojiStatusId, referrerWebAppKey, expires, tabId = getCurrentTabId(),
|
emojiStatus, referrerWebAppKey, tabId = getCurrentTabId(),
|
||||||
} = payload;
|
} = payload;
|
||||||
|
|
||||||
const isCurrentUserPremium = selectIsCurrentUserPremium(global);
|
const isCurrentUserPremium = selectIsCurrentUserPremium(global);
|
||||||
@ -411,7 +411,7 @@ addActionHandler('setEmojiStatus', async (global, actions, payload): Promise<voi
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await callApi('updateEmojiStatus', emojiStatusId, expires);
|
const result = await callApi('updateEmojiStatus', emojiStatus);
|
||||||
|
|
||||||
if (referrerWebAppKey) {
|
if (referrerWebAppKey) {
|
||||||
if (!result) {
|
if (!result) {
|
||||||
@ -439,7 +439,7 @@ addActionHandler('setEmojiStatus', async (global, actions, payload): Promise<voi
|
|||||||
message: {
|
message: {
|
||||||
key: 'BotSuggestedStatusUpdated',
|
key: 'BotSuggestedStatusUpdated',
|
||||||
},
|
},
|
||||||
customEmojiIconId: emojiStatusId,
|
customEmojiIconId: emojiStatus.documentId,
|
||||||
tabId,
|
tabId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -269,6 +269,24 @@ addActionHandler('openGiftWithdrawModal', (global, actions, payload): ActionRetu
|
|||||||
|
|
||||||
addTabStateResetterAction('closeGiftWithdrawModal', 'giftWithdrawModal');
|
addTabStateResetterAction('closeGiftWithdrawModal', 'giftWithdrawModal');
|
||||||
|
|
||||||
|
addActionHandler('openGiftStatusInfoModal', (global, actions, payload): ActionReturnType => {
|
||||||
|
const { emojiStatus, tabId = getCurrentTabId() } = payload || {};
|
||||||
|
|
||||||
|
return updateTabState(global, {
|
||||||
|
giftStatusInfoModal: {
|
||||||
|
emojiStatus,
|
||||||
|
},
|
||||||
|
}, tabId);
|
||||||
|
});
|
||||||
|
|
||||||
|
addActionHandler('closeGiftStatusInfoModal', (global, actions, payload): ActionReturnType => {
|
||||||
|
const { tabId = getCurrentTabId() } = payload || {};
|
||||||
|
|
||||||
|
return updateTabState(global, {
|
||||||
|
giftStatusInfoModal: undefined,
|
||||||
|
}, tabId);
|
||||||
|
});
|
||||||
|
|
||||||
addActionHandler('clearGiftWithdrawError', (global, actions, payload): ActionReturnType => {
|
addActionHandler('clearGiftWithdrawError', (global, actions, payload): ActionReturnType => {
|
||||||
const { tabId = getCurrentTabId() } = payload || {};
|
const { tabId = getCurrentTabId() } = payload || {};
|
||||||
const tabState = selectTabState(global, tabId);
|
const tabState = selectTabState(global, tabId);
|
||||||
|
|||||||
@ -50,6 +50,7 @@ import type {
|
|||||||
BotsPrivacyType,
|
BotsPrivacyType,
|
||||||
PrivacyVisibility,
|
PrivacyVisibility,
|
||||||
} from '../../api/types';
|
} from '../../api/types';
|
||||||
|
import type { ApiEmojiStatusCollectible, ApiEmojiStatusType } from '../../api/types/users';
|
||||||
import type { ApiCredentials } from '../../components/payment/PaymentModal';
|
import type { ApiCredentials } from '../../components/payment/PaymentModal';
|
||||||
import type { FoldersActions } from '../../hooks/reducers/useFoldersReducer';
|
import type { FoldersActions } from '../../hooks/reducers/useFoldersReducer';
|
||||||
import type { ReducerAction } from '../../hooks/useReducer';
|
import type { ReducerAction } from '../../hooks/useReducer';
|
||||||
@ -1831,6 +1832,7 @@ export interface ActionPayloads {
|
|||||||
clearRecentCustomEmoji: undefined;
|
clearRecentCustomEmoji: undefined;
|
||||||
loadFeaturedEmojiStickers: undefined;
|
loadFeaturedEmojiStickers: undefined;
|
||||||
loadDefaultStatusIcons: undefined;
|
loadDefaultStatusIcons: undefined;
|
||||||
|
loadUserCollectibleStatuses: undefined;
|
||||||
loadRecentEmojiStatuses: undefined;
|
loadRecentEmojiStatuses: undefined;
|
||||||
|
|
||||||
// Bots
|
// Bots
|
||||||
@ -2345,6 +2347,10 @@ export interface ActionPayloads {
|
|||||||
} & WithTabId;
|
} & WithTabId;
|
||||||
clearGiftWithdrawError: WithTabId | undefined;
|
clearGiftWithdrawError: WithTabId | undefined;
|
||||||
closeGiftWithdrawModal: WithTabId | undefined;
|
closeGiftWithdrawModal: WithTabId | undefined;
|
||||||
|
openGiftStatusInfoModal: {
|
||||||
|
emojiStatus: ApiEmojiStatusCollectible;
|
||||||
|
} & WithTabId;
|
||||||
|
closeGiftStatusInfoModal: WithTabId | undefined;
|
||||||
processStarGiftWithdrawal: {
|
processStarGiftWithdrawal: {
|
||||||
gift: ApiInputSavedStarGift;
|
gift: ApiInputSavedStarGift;
|
||||||
password: string;
|
password: string;
|
||||||
@ -2379,8 +2385,7 @@ export interface ActionPayloads {
|
|||||||
closeStarsGiftModal: WithTabId | undefined;
|
closeStarsGiftModal: WithTabId | undefined;
|
||||||
|
|
||||||
setEmojiStatus: {
|
setEmojiStatus: {
|
||||||
emojiStatusId: string;
|
emojiStatus: ApiEmojiStatusType;
|
||||||
expires?: number;
|
|
||||||
referrerWebAppKey?: string;
|
referrerWebAppKey?: string;
|
||||||
} & WithTabId;
|
} & WithTabId;
|
||||||
openSuggestedStatusModal: {
|
openSuggestedStatusModal: {
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import type {
|
|||||||
ApiConfig,
|
ApiConfig,
|
||||||
ApiCountry,
|
ApiCountry,
|
||||||
ApiCountryCode,
|
ApiCountryCode,
|
||||||
|
ApiEmojiStatusType,
|
||||||
ApiGroupCall,
|
ApiGroupCall,
|
||||||
ApiLanguage,
|
ApiLanguage,
|
||||||
ApiMessage,
|
ApiMessage,
|
||||||
@ -361,6 +362,11 @@ export type GlobalState = {
|
|||||||
premiumGifts?: ApiStickerSet;
|
premiumGifts?: ApiStickerSet;
|
||||||
emojiKeywords: Record<string, EmojiKeywords | undefined>;
|
emojiKeywords: Record<string, EmojiKeywords | undefined>;
|
||||||
|
|
||||||
|
collectibleEmojiStatuses?: {
|
||||||
|
statuses: ApiEmojiStatusType[];
|
||||||
|
hash?: string;
|
||||||
|
};
|
||||||
|
|
||||||
gifs: {
|
gifs: {
|
||||||
saved: {
|
saved: {
|
||||||
hash?: string;
|
hash?: string;
|
||||||
|
|||||||
@ -47,6 +47,7 @@ import type {
|
|||||||
ApiVideo,
|
ApiVideo,
|
||||||
ApiWebPage,
|
ApiWebPage,
|
||||||
} from '../../api/types';
|
} from '../../api/types';
|
||||||
|
import type { ApiEmojiStatusCollectible } from '../../api/types/users';
|
||||||
import type { FoldersActions } from '../../hooks/reducers/useFoldersReducer';
|
import type { FoldersActions } from '../../hooks/reducers/useFoldersReducer';
|
||||||
import type { ReducerAction } from '../../hooks/useReducer';
|
import type { ReducerAction } from '../../hooks/useReducer';
|
||||||
import type {
|
import type {
|
||||||
@ -737,6 +738,10 @@ export type TabState = {
|
|||||||
errorKey?: RegularLangFnParameters;
|
errorKey?: RegularLangFnParameters;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
giftStatusInfoModal?: {
|
||||||
|
emojiStatus: ApiEmojiStatusCollectible;
|
||||||
|
};
|
||||||
|
|
||||||
suggestedStatusModal?: {
|
suggestedStatusModal?: {
|
||||||
botId: string;
|
botId: string;
|
||||||
webAppKey?: string;
|
webAppKey?: string;
|
||||||
|
|||||||
@ -1462,6 +1462,7 @@ account.reorderUsernames#ef500eab order:Vector<string> = Bool;
|
|||||||
account.toggleUsername#58d6b376 username:string active:Bool = Bool;
|
account.toggleUsername#58d6b376 username:string active:Bool = Bool;
|
||||||
account.resolveBusinessChatLink#5492e5ee slug:string = account.ResolvedBusinessChatLinks;
|
account.resolveBusinessChatLink#5492e5ee slug:string = account.ResolvedBusinessChatLinks;
|
||||||
account.toggleSponsoredMessages#b9d9a38d enabled:Bool = Bool;
|
account.toggleSponsoredMessages#b9d9a38d enabled:Bool = Bool;
|
||||||
|
account.getCollectibleEmojiStatuses#2e7b4543 hash:long = account.EmojiStatuses;
|
||||||
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
|
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
|
||||||
users.getFullUser#b60f5918 id:InputUser = users.UserFull;
|
users.getFullUser#b60f5918 id:InputUser = users.UserFull;
|
||||||
contacts.getContacts#5dd69e12 hash:long = contacts.Contacts;
|
contacts.getContacts#5dd69e12 hash:long = contacts.Contacts;
|
||||||
|
|||||||
@ -60,6 +60,7 @@
|
|||||||
"account.toggleUsername",
|
"account.toggleUsername",
|
||||||
"account.resolveBusinessChatLink",
|
"account.resolveBusinessChatLink",
|
||||||
"account.toggleSponsoredMessages",
|
"account.toggleSponsoredMessages",
|
||||||
|
"account.getCollectibleEmojiStatuses",
|
||||||
"users.getUsers",
|
"users.getUsers",
|
||||||
"users.getFullUser",
|
"users.getFullUser",
|
||||||
"contacts.getContacts",
|
"contacts.getContacts",
|
||||||
|
|||||||
@ -94,196 +94,201 @@ $icons-map: (
|
|||||||
"comments": "\f139",
|
"comments": "\f139",
|
||||||
"copy-media": "\f13a",
|
"copy-media": "\f13a",
|
||||||
"copy": "\f13b",
|
"copy": "\f13b",
|
||||||
"darkmode": "\f13c",
|
"crown-take-off": "\f13c",
|
||||||
"data": "\f13d",
|
"crown-wear": "\f13d",
|
||||||
"delete-filled": "\f13e",
|
"darkmode": "\f13e",
|
||||||
"delete-left": "\f13f",
|
"data": "\f13f",
|
||||||
"delete-user": "\f140",
|
"delete-filled": "\f140",
|
||||||
"delete": "\f141",
|
"delete-left": "\f141",
|
||||||
"diamond": "\f142",
|
"delete-user": "\f142",
|
||||||
"document": "\f143",
|
"delete": "\f143",
|
||||||
"double-badge": "\f144",
|
"diamond": "\f144",
|
||||||
"down": "\f145",
|
"document": "\f145",
|
||||||
"download": "\f146",
|
"double-badge": "\f146",
|
||||||
"eats": "\f147",
|
"down": "\f147",
|
||||||
"edit": "\f148",
|
"download": "\f148",
|
||||||
"email": "\f149",
|
"eats": "\f149",
|
||||||
"enter": "\f14a",
|
"edit": "\f14a",
|
||||||
"expand-modal": "\f14b",
|
"email": "\f14b",
|
||||||
"expand": "\f14c",
|
"enter": "\f14c",
|
||||||
"eye-closed-outline": "\f14d",
|
"expand-modal": "\f14d",
|
||||||
"eye-closed": "\f14e",
|
"expand": "\f14e",
|
||||||
"eye-outline": "\f14f",
|
"eye-closed-outline": "\f14f",
|
||||||
"eye": "\f150",
|
"eye-closed": "\f150",
|
||||||
"favorite-filled": "\f151",
|
"eye-outline": "\f151",
|
||||||
"favorite": "\f152",
|
"eye": "\f152",
|
||||||
"file-badge": "\f153",
|
"favorite-filled": "\f153",
|
||||||
"flag": "\f154",
|
"favorite": "\f154",
|
||||||
"folder-badge": "\f155",
|
"file-badge": "\f155",
|
||||||
"folder": "\f156",
|
"flag": "\f156",
|
||||||
"fontsize": "\f157",
|
"folder-badge": "\f157",
|
||||||
"forums": "\f158",
|
"folder": "\f158",
|
||||||
"forward": "\f159",
|
"fontsize": "\f159",
|
||||||
"fragment": "\f15a",
|
"forums": "\f15a",
|
||||||
"fullscreen": "\f15b",
|
"forward": "\f15b",
|
||||||
"gifs": "\f15c",
|
"fragment": "\f15c",
|
||||||
"gift": "\f15d",
|
"fullscreen": "\f15d",
|
||||||
"group-filled": "\f15e",
|
"gifs": "\f15e",
|
||||||
"group": "\f15f",
|
"gift": "\f15f",
|
||||||
"grouped-disable": "\f160",
|
"group-filled": "\f160",
|
||||||
"grouped": "\f161",
|
"group": "\f161",
|
||||||
"hand-stop": "\f162",
|
"grouped-disable": "\f162",
|
||||||
"hashtag": "\f163",
|
"grouped": "\f163",
|
||||||
"heart-outline": "\f164",
|
"hand-stop": "\f164",
|
||||||
"heart": "\f165",
|
"hashtag": "\f165",
|
||||||
"help": "\f166",
|
"heart-outline": "\f166",
|
||||||
"info-filled": "\f167",
|
"heart": "\f167",
|
||||||
"info": "\f168",
|
"help": "\f168",
|
||||||
"install": "\f169",
|
"info-filled": "\f169",
|
||||||
"italic": "\f16a",
|
"info": "\f16a",
|
||||||
"key": "\f16b",
|
"install": "\f16b",
|
||||||
"keyboard": "\f16c",
|
"italic": "\f16c",
|
||||||
"lamp": "\f16d",
|
"key": "\f16d",
|
||||||
"language": "\f16e",
|
"keyboard": "\f16e",
|
||||||
"large-pause": "\f16f",
|
"lamp": "\f16f",
|
||||||
"large-play": "\f170",
|
"language": "\f170",
|
||||||
"link-badge": "\f171",
|
"large-pause": "\f171",
|
||||||
"link-broken": "\f172",
|
"large-play": "\f172",
|
||||||
"link": "\f173",
|
"link-badge": "\f173",
|
||||||
"location": "\f174",
|
"link-broken": "\f174",
|
||||||
"lock-badge": "\f175",
|
"link": "\f175",
|
||||||
"lock": "\f176",
|
"location": "\f176",
|
||||||
"logout": "\f177",
|
"lock-badge": "\f177",
|
||||||
"loop": "\f178",
|
"lock": "\f178",
|
||||||
"mention": "\f179",
|
"logout": "\f179",
|
||||||
"message-failed": "\f17a",
|
"loop": "\f17a",
|
||||||
"message-pending": "\f17b",
|
"mention": "\f17b",
|
||||||
"message-read": "\f17c",
|
"message-failed": "\f17c",
|
||||||
"message-succeeded": "\f17d",
|
"message-pending": "\f17d",
|
||||||
"message": "\f17e",
|
"message-read": "\f17e",
|
||||||
"microphone-alt": "\f17f",
|
"message-succeeded": "\f17f",
|
||||||
"microphone": "\f180",
|
"message": "\f180",
|
||||||
"monospace": "\f181",
|
"microphone-alt": "\f181",
|
||||||
"more-circle": "\f182",
|
"microphone": "\f182",
|
||||||
"more": "\f183",
|
"monospace": "\f183",
|
||||||
"move-caption-down": "\f184",
|
"more-circle": "\f184",
|
||||||
"move-caption-up": "\f185",
|
"more": "\f185",
|
||||||
"mute": "\f186",
|
"move-caption-down": "\f186",
|
||||||
"muted": "\f187",
|
"move-caption-up": "\f187",
|
||||||
"my-notes": "\f188",
|
"mute": "\f188",
|
||||||
"new-chat-filled": "\f189",
|
"muted": "\f189",
|
||||||
"next": "\f18a",
|
"my-notes": "\f18a",
|
||||||
"nochannel": "\f18b",
|
"new-chat-filled": "\f18b",
|
||||||
"noise-suppression": "\f18c",
|
"next": "\f18c",
|
||||||
"non-contacts": "\f18d",
|
"nochannel": "\f18d",
|
||||||
"one-filled": "\f18e",
|
"noise-suppression": "\f18e",
|
||||||
"open-in-new-tab": "\f18f",
|
"non-contacts": "\f18f",
|
||||||
"password-off": "\f190",
|
"one-filled": "\f190",
|
||||||
"pause": "\f191",
|
"open-in-new-tab": "\f191",
|
||||||
"permissions": "\f192",
|
"password-off": "\f192",
|
||||||
"phone-discard-outline": "\f193",
|
"pause": "\f193",
|
||||||
"phone-discard": "\f194",
|
"permissions": "\f194",
|
||||||
"phone": "\f195",
|
"phone-discard-outline": "\f195",
|
||||||
"photo": "\f196",
|
"phone-discard": "\f196",
|
||||||
"pin-badge": "\f197",
|
"phone": "\f197",
|
||||||
"pin-list": "\f198",
|
"photo": "\f198",
|
||||||
"pin": "\f199",
|
"pin-badge": "\f199",
|
||||||
"pinned-chat": "\f19a",
|
"pin-list": "\f19a",
|
||||||
"pinned-message": "\f19b",
|
"pin": "\f19b",
|
||||||
"pip": "\f19c",
|
"pinned-chat": "\f19c",
|
||||||
"play-story": "\f19d",
|
"pinned-message": "\f19d",
|
||||||
"play": "\f19e",
|
"pip": "\f19e",
|
||||||
"poll": "\f19f",
|
"play-story": "\f19f",
|
||||||
"previous": "\f1a0",
|
"play": "\f1a0",
|
||||||
"privacy-policy": "\f1a1",
|
"poll": "\f1a1",
|
||||||
"quote-text": "\f1a2",
|
"previous": "\f1a2",
|
||||||
"quote": "\f1a3",
|
"privacy-policy": "\f1a3",
|
||||||
"readchats": "\f1a4",
|
"proof-of-ownership": "\f1a4",
|
||||||
"recent": "\f1a5",
|
"quote-text": "\f1a5",
|
||||||
"reload": "\f1a6",
|
"quote": "\f1a6",
|
||||||
"remove-quote": "\f1a7",
|
"radial-badge": "\f1a7",
|
||||||
"remove": "\f1a8",
|
"readchats": "\f1a8",
|
||||||
"reopen-topic": "\f1a9",
|
"recent": "\f1a9",
|
||||||
"replace": "\f1aa",
|
"reload": "\f1aa",
|
||||||
"replies": "\f1ab",
|
"remove-quote": "\f1ab",
|
||||||
"reply-filled": "\f1ac",
|
"remove": "\f1ac",
|
||||||
"reply": "\f1ad",
|
"reopen-topic": "\f1ad",
|
||||||
"revenue-split": "\f1ae",
|
"replace": "\f1ae",
|
||||||
"revote": "\f1af",
|
"replies": "\f1af",
|
||||||
"save-story": "\f1b0",
|
"reply-filled": "\f1b0",
|
||||||
"saved-messages": "\f1b1",
|
"reply": "\f1b1",
|
||||||
"schedule": "\f1b2",
|
"revenue-split": "\f1b2",
|
||||||
"search": "\f1b3",
|
"revote": "\f1b3",
|
||||||
"select": "\f1b4",
|
"save-story": "\f1b4",
|
||||||
"send-outline": "\f1b5",
|
"saved-messages": "\f1b5",
|
||||||
"send": "\f1b6",
|
"schedule": "\f1b6",
|
||||||
"settings-filled": "\f1b7",
|
"search": "\f1b7",
|
||||||
"settings": "\f1b8",
|
"select": "\f1b8",
|
||||||
"share-filled": "\f1b9",
|
"send-outline": "\f1b9",
|
||||||
"share-screen-outlined": "\f1ba",
|
"send": "\f1ba",
|
||||||
"share-screen-stop": "\f1bb",
|
"settings-filled": "\f1bb",
|
||||||
"share-screen": "\f1bc",
|
"settings": "\f1bc",
|
||||||
"show-message": "\f1bd",
|
"share-filled": "\f1bd",
|
||||||
"sidebar": "\f1be",
|
"share-screen-outlined": "\f1be",
|
||||||
"skip-next": "\f1bf",
|
"share-screen-stop": "\f1bf",
|
||||||
"skip-previous": "\f1c0",
|
"share-screen": "\f1c0",
|
||||||
"smallscreen": "\f1c1",
|
"show-message": "\f1c1",
|
||||||
"smile": "\f1c2",
|
"sidebar": "\f1c2",
|
||||||
"sort": "\f1c3",
|
"skip-next": "\f1c3",
|
||||||
"speaker-muted-story": "\f1c4",
|
"skip-previous": "\f1c4",
|
||||||
"speaker-outline": "\f1c5",
|
"smallscreen": "\f1c5",
|
||||||
"speaker-story": "\f1c6",
|
"smile": "\f1c6",
|
||||||
"speaker": "\f1c7",
|
"sort": "\f1c7",
|
||||||
"spoiler-disable": "\f1c8",
|
"speaker-muted-story": "\f1c8",
|
||||||
"spoiler": "\f1c9",
|
"speaker-outline": "\f1c9",
|
||||||
"sport": "\f1ca",
|
"speaker-story": "\f1ca",
|
||||||
"star": "\f1cb",
|
"speaker": "\f1cb",
|
||||||
"stars-lock": "\f1cc",
|
"spoiler-disable": "\f1cc",
|
||||||
"stats": "\f1cd",
|
"spoiler": "\f1cd",
|
||||||
"stealth-future": "\f1ce",
|
"sport": "\f1ce",
|
||||||
"stealth-past": "\f1cf",
|
"star": "\f1cf",
|
||||||
"stickers": "\f1d0",
|
"stars-lock": "\f1d0",
|
||||||
"stop-raising-hand": "\f1d1",
|
"stats": "\f1d1",
|
||||||
"stop": "\f1d2",
|
"stealth-future": "\f1d2",
|
||||||
"story-caption": "\f1d3",
|
"stealth-past": "\f1d3",
|
||||||
"story-expired": "\f1d4",
|
"stickers": "\f1d4",
|
||||||
"story-priority": "\f1d5",
|
"stop-raising-hand": "\f1d5",
|
||||||
"story-reply": "\f1d6",
|
"stop": "\f1d6",
|
||||||
"strikethrough": "\f1d7",
|
"story-caption": "\f1d7",
|
||||||
"tag-add": "\f1d8",
|
"story-expired": "\f1d8",
|
||||||
"tag-crossed": "\f1d9",
|
"story-priority": "\f1d9",
|
||||||
"tag-filter": "\f1da",
|
"story-reply": "\f1da",
|
||||||
"tag-name": "\f1db",
|
"strikethrough": "\f1db",
|
||||||
"tag": "\f1dc",
|
"tag-add": "\f1dc",
|
||||||
"timer": "\f1dd",
|
"tag-crossed": "\f1dd",
|
||||||
"toncoin": "\f1de",
|
"tag-filter": "\f1de",
|
||||||
"trade": "\f1df",
|
"tag-name": "\f1df",
|
||||||
"transcribe": "\f1e0",
|
"tag": "\f1e0",
|
||||||
"truck": "\f1e1",
|
"timer": "\f1e1",
|
||||||
"unarchive": "\f1e2",
|
"toncoin": "\f1e2",
|
||||||
"underlined": "\f1e3",
|
"trade": "\f1e3",
|
||||||
"unlock-badge": "\f1e4",
|
"transcribe": "\f1e4",
|
||||||
"unlock": "\f1e5",
|
"truck": "\f1e5",
|
||||||
"unmute": "\f1e6",
|
"unarchive": "\f1e6",
|
||||||
"unpin": "\f1e7",
|
"underlined": "\f1e7",
|
||||||
"unread": "\f1e8",
|
"unique-profile": "\f1e8",
|
||||||
"up": "\f1e9",
|
"unlock-badge": "\f1e9",
|
||||||
"user-filled": "\f1ea",
|
"unlock": "\f1ea",
|
||||||
"user-online": "\f1eb",
|
"unmute": "\f1eb",
|
||||||
"user": "\f1ec",
|
"unpin": "\f1ec",
|
||||||
"video-outlined": "\f1ed",
|
"unread": "\f1ed",
|
||||||
"video-stop": "\f1ee",
|
"up": "\f1ee",
|
||||||
"video": "\f1ef",
|
"user-filled": "\f1ef",
|
||||||
"view-once": "\f1f0",
|
"user-online": "\f1f0",
|
||||||
"voice-chat": "\f1f1",
|
"user": "\f1f1",
|
||||||
"volume-1": "\f1f2",
|
"video-outlined": "\f1f2",
|
||||||
"volume-2": "\f1f3",
|
"video-stop": "\f1f3",
|
||||||
"volume-3": "\f1f4",
|
"video": "\f1f4",
|
||||||
"web": "\f1f5",
|
"view-once": "\f1f5",
|
||||||
"webapp": "\f1f6",
|
"voice-chat": "\f1f6",
|
||||||
"word-wrap": "\f1f7",
|
"volume-1": "\f1f7",
|
||||||
"zoom-in": "\f1f8",
|
"volume-2": "\f1f8",
|
||||||
"zoom-out": "\f1f9",
|
"volume-3": "\f1f9",
|
||||||
|
"web": "\f1fa",
|
||||||
|
"webapp": "\f1fb",
|
||||||
|
"word-wrap": "\f1fc",
|
||||||
|
"zoom-in": "\f1fd",
|
||||||
|
"zoom-out": "\f1fe",
|
||||||
);
|
);
|
||||||
|
|
||||||
.icon-active-sessions::before {
|
.icon-active-sessions::before {
|
||||||
@ -463,6 +468,12 @@ $icons-map: (
|
|||||||
.icon-copy::before {
|
.icon-copy::before {
|
||||||
content: map.get($icons-map, "copy");
|
content: map.get($icons-map, "copy");
|
||||||
}
|
}
|
||||||
|
.icon-crown-take-off::before {
|
||||||
|
content: map.get($icons-map, "crown-take-off");
|
||||||
|
}
|
||||||
|
.icon-crown-wear::before {
|
||||||
|
content: map.get($icons-map, "crown-wear");
|
||||||
|
}
|
||||||
.icon-darkmode::before {
|
.icon-darkmode::before {
|
||||||
content: map.get($icons-map, "darkmode");
|
content: map.get($icons-map, "darkmode");
|
||||||
}
|
}
|
||||||
@ -769,12 +780,18 @@ $icons-map: (
|
|||||||
.icon-privacy-policy::before {
|
.icon-privacy-policy::before {
|
||||||
content: map.get($icons-map, "privacy-policy");
|
content: map.get($icons-map, "privacy-policy");
|
||||||
}
|
}
|
||||||
|
.icon-proof-of-ownership::before {
|
||||||
|
content: map.get($icons-map, "proof-of-ownership");
|
||||||
|
}
|
||||||
.icon-quote-text::before {
|
.icon-quote-text::before {
|
||||||
content: map.get($icons-map, "quote-text");
|
content: map.get($icons-map, "quote-text");
|
||||||
}
|
}
|
||||||
.icon-quote::before {
|
.icon-quote::before {
|
||||||
content: map.get($icons-map, "quote");
|
content: map.get($icons-map, "quote");
|
||||||
}
|
}
|
||||||
|
.icon-radial-badge::before {
|
||||||
|
content: map.get($icons-map, "radial-badge");
|
||||||
|
}
|
||||||
.icon-readchats::before {
|
.icon-readchats::before {
|
||||||
content: map.get($icons-map, "readchats");
|
content: map.get($icons-map, "readchats");
|
||||||
}
|
}
|
||||||
@ -967,6 +984,9 @@ $icons-map: (
|
|||||||
.icon-underlined::before {
|
.icon-underlined::before {
|
||||||
content: map.get($icons-map, "underlined");
|
content: map.get($icons-map, "underlined");
|
||||||
}
|
}
|
||||||
|
.icon-unique-profile::before {
|
||||||
|
content: map.get($icons-map, "unique-profile");
|
||||||
|
}
|
||||||
.icon-unlock-badge::before {
|
.icon-unlock-badge::before {
|
||||||
content: map.get($icons-map, "unlock-badge");
|
content: map.get($icons-map, "unlock-badge");
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@ -58,6 +58,8 @@ export type FontIconName =
|
|||||||
| 'comments'
|
| 'comments'
|
||||||
| 'copy-media'
|
| 'copy-media'
|
||||||
| 'copy'
|
| 'copy'
|
||||||
|
| 'crown-take-off'
|
||||||
|
| 'crown-wear'
|
||||||
| 'darkmode'
|
| 'darkmode'
|
||||||
| 'data'
|
| 'data'
|
||||||
| 'delete-filled'
|
| 'delete-filled'
|
||||||
@ -160,8 +162,10 @@ export type FontIconName =
|
|||||||
| 'poll'
|
| 'poll'
|
||||||
| 'previous'
|
| 'previous'
|
||||||
| 'privacy-policy'
|
| 'privacy-policy'
|
||||||
|
| 'proof-of-ownership'
|
||||||
| 'quote-text'
|
| 'quote-text'
|
||||||
| 'quote'
|
| 'quote'
|
||||||
|
| 'radial-badge'
|
||||||
| 'readchats'
|
| 'readchats'
|
||||||
| 'recent'
|
| 'recent'
|
||||||
| 'reload'
|
| 'reload'
|
||||||
@ -226,6 +230,7 @@ export type FontIconName =
|
|||||||
| 'truck'
|
| 'truck'
|
||||||
| 'unarchive'
|
| 'unarchive'
|
||||||
| 'underlined'
|
| 'underlined'
|
||||||
|
| 'unique-profile'
|
||||||
| 'unlock-badge'
|
| 'unlock-badge'
|
||||||
| 'unlock'
|
| 'unlock'
|
||||||
| 'unmute'
|
| 'unmute'
|
||||||
|
|||||||
15
src/types/language.d.ts
vendored
15
src/types/language.d.ts
vendored
@ -1197,6 +1197,9 @@ export interface LangPair {
|
|||||||
'GiftInfoViewUpgraded': undefined;
|
'GiftInfoViewUpgraded': undefined;
|
||||||
'GiftInfoUpgradeBadge': undefined;
|
'GiftInfoUpgradeBadge': undefined;
|
||||||
'GiftInfoUpgradeForFree': undefined;
|
'GiftInfoUpgradeForFree': undefined;
|
||||||
|
'GiftInfoWithdraw': undefined;
|
||||||
|
'GiftInfoWear': undefined;
|
||||||
|
'GiftInfoTakeOff': undefined;
|
||||||
'GiftInfoTransfer': undefined;
|
'GiftInfoTransfer': undefined;
|
||||||
'GiftTransferTitle': undefined;
|
'GiftTransferTitle': undefined;
|
||||||
'GiftTransferTON': undefined;
|
'GiftTransferTON': undefined;
|
||||||
@ -1321,6 +1324,15 @@ export interface LangPair {
|
|||||||
'CheckPasswordTitle': undefined;
|
'CheckPasswordTitle': undefined;
|
||||||
'CheckPasswordPlaceholder': undefined;
|
'CheckPasswordPlaceholder': undefined;
|
||||||
'CheckPasswordDescription': undefined;
|
'CheckPasswordDescription': undefined;
|
||||||
|
'UniqueStatusBenefitsDescription': undefined;
|
||||||
|
'UniqueStatusBadgeBenefitTitle': undefined;
|
||||||
|
'UniqueStatusBadgeDescription': undefined;
|
||||||
|
'UniqueStatusProfileDesignBenefitTitle': undefined;
|
||||||
|
'UniqueStatusProfileDesignDescription': undefined;
|
||||||
|
'UniqueStatusProofOfOwnershipBenefitTitle': undefined;
|
||||||
|
'UniqueStatusProofOfOwnershipDescription': undefined;
|
||||||
|
'UniqueStatusWearButton': undefined;
|
||||||
|
'CollectibleStatusesCategory': undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LangPairWithVariables<V extends unknown = LangVariable> {
|
export interface LangPairWithVariables<V extends unknown = LangVariable> {
|
||||||
@ -1835,6 +1847,9 @@ export interface LangPairWithVariables<V extends unknown = LangVariable> {
|
|||||||
'MoreSimilarBotsText': {
|
'MoreSimilarBotsText': {
|
||||||
'count': V;
|
'count': V;
|
||||||
};
|
};
|
||||||
|
'UniqueStatusWearTitle': {
|
||||||
|
'gift': V;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LangPairPlural {
|
export interface LangPairPlural {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user