diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index 777144138..dfc0c9c8e 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -46,6 +46,7 @@ type EmojiWithSkins = Record; type AllEmojis = Record; declare module '*.png'; +declare module '*.tgs'; declare module 'pako/dist/pako_inflate' { function inflate(...args: any[]): string; diff --git a/src/assets/tgs/invites/Invite.tgs b/src/assets/tgs/invites/Invite.tgs new file mode 100644 index 000000000..de9333de4 Binary files /dev/null and b/src/assets/tgs/invites/Invite.tgs differ diff --git a/src/assets/tgs/invites/Requests.tgs b/src/assets/tgs/invites/Requests.tgs new file mode 100644 index 000000000..dd00e386d Binary files /dev/null and b/src/assets/tgs/invites/Requests.tgs differ diff --git a/src/components/common/helpers/animatedAssets.ts b/src/components/common/helpers/animatedAssets.ts index 691003c8b..cc502e12e 100644 --- a/src/components/common/helpers/animatedAssets.ts +++ b/src/components/common/helpers/animatedAssets.ts @@ -2,43 +2,31 @@ import { ApiMediaFormat } from '../../../api/types'; import * as mediaLoader from '../../../util/mediaLoader'; -// @ts-ignore import MonkeyIdle from '../../../assets/tgs/monkeys/TwoFactorSetupMonkeyIdle.tgs'; -// @ts-ignore import MonkeyTracking from '../../../assets/tgs/monkeys/TwoFactorSetupMonkeyTracking.tgs'; -// @ts-ignore import MonkeyClose from '../../../assets/tgs/monkeys/TwoFactorSetupMonkeyClose.tgs'; -// @ts-ignore import MonkeyPeek from '../../../assets/tgs/monkeys/TwoFactorSetupMonkeyPeek.tgs'; -// @ts-ignore + import FoldersAll from '../../../assets/tgs/settings/FoldersAll.tgs'; -// @ts-ignore import FoldersNew from '../../../assets/tgs/settings/FoldersNew.tgs'; -// @ts-ignore import DiscussionGroups from '../../../assets/tgs/settings/DiscussionGroupsDucks.tgs'; -// @ts-ignore + import CameraFlip from '../../../assets/tgs/calls/CameraFlip.tgs'; -// @ts-ignore import HandFilled from '../../../assets/tgs/calls/HandFilled.tgs'; -// @ts-ignore import HandOutline from '../../../assets/tgs/calls/HandOutline.tgs'; -// @ts-ignore import Speaker from '../../../assets/tgs/calls/Speaker.tgs'; -// @ts-ignore import VoiceAllowTalk from '../../../assets/tgs/calls/VoiceAllowTalk.tgs'; -// @ts-ignore import VoiceMini from '../../../assets/tgs/calls/VoiceMini.tgs'; -// @ts-ignore import VoiceMuted from '../../../assets/tgs/calls/VoiceMuted.tgs'; -// @ts-ignore import VoiceOutlined from '../../../assets/tgs/calls/VoiceOutlined.tgs'; -// @ts-ignore + import Peach from '../../../assets/tgs/animatedEmojis/Peach.tgs'; -// @ts-ignore import Eggplant from '../../../assets/tgs/animatedEmojis/Eggplant.tgs'; -// @ts-ignore import Cumshot from '../../../assets/tgs/animatedEmojis/Cumshot.tgs'; +import JoinRequest from '../../../assets/tgs/invites/Requests.tgs'; +import Invite from '../../../assets/tgs/invites/Invite.tgs'; + export const ANIMATED_STICKERS_PATHS = { MonkeyIdle, MonkeyTracking, @@ -58,6 +46,8 @@ export const ANIMATED_STICKERS_PATHS = { Peach, Eggplant, Cumshot, + JoinRequest, + Invite, }; export default function getAnimationData(name: keyof typeof ANIMATED_STICKERS_PATHS) { diff --git a/src/components/main/Dialogs.tsx b/src/components/main/Dialogs.tsx index 2dca2e163..d10112286 100644 --- a/src/components/main/Dialogs.tsx +++ b/src/components/main/Dialogs.tsx @@ -22,7 +22,12 @@ type StateProps = { }; const Dialogs: FC = ({ dialogs }) => { - const { dismissDialog, acceptInviteConfirmation, sendMessage } = getDispatch(); + const { + dismissDialog, + acceptInviteConfirmation, + sendMessage, + showNotification, + } = getDispatch(); const [isModalOpen, openModal, closeModal] = useFlag(); const lang = useLang(); @@ -60,6 +65,9 @@ const Dialogs: FC = ({ dialogs }) => { acceptInviteConfirmation({ hash, }); + showNotification({ + message: isChannel ? lang('RequestToJoinChannelSentDescription') : lang('RequestToJoinGroupSentDescription'), + }); closeModal(); }; @@ -79,8 +87,8 @@ const Dialogs: FC = ({ dialogs }) => { header={renderInviteHeader(title, photo)} onCloseAnimationEnd={dismissDialog} > - {about &&

{renderText(about)}

} - {participantsCount !== undefined &&

{participantsText}

} + {participantsCount !== undefined &&

{participantsText}

} + {about &&

{renderText(about, ['br'])}

} {isRequestNeeded && (

{isChannel diff --git a/src/components/right/RightHeader.tsx b/src/components/right/RightHeader.tsx index f8125e5bd..86b068845 100644 --- a/src/components/right/RightHeader.tsx +++ b/src/components/right/RightHeader.tsx @@ -22,12 +22,15 @@ import { } from '../../modules/helpers'; import useCurrentOrPrev from '../../hooks/useCurrentOrPrev'; import useLang from '../../hooks/useLang'; +import useFlag from '../../hooks/useFlag'; +import { getDayStartAt } from '../../util/dateFormat'; import SearchInput from '../ui/SearchInput'; import Button from '../ui/Button'; import Transition from '../ui/Transition'; +import ConfirmDialog from '../ui/ConfirmDialog'; + import './RightHeader.scss'; -import { getDayStartAt } from '../../util/dateFormat'; type OwnProps = { chatId?: string; @@ -131,6 +134,7 @@ const RightHeader: FC = ({ // eslint-disable-next-line no-null/no-null const backButtonRef = useRef(null); + const [isDeleteDialogOpen, openDeleteDialog, closeDeleteDialog] = useFlag(); const handleEditInviteClick = useCallback(() => { setEditingExportedInvite({ chatId: chatId!, invite: currentInviteInfo! }); @@ -140,7 +144,8 @@ const RightHeader: FC = ({ const handleDeleteInviteClick = useCallback(() => { deleteExportedChatInvite({ chatId: chatId!, link: currentInviteInfo!.link }); onScreenSelect(ManagementScreens.Invites); - }, [chatId, currentInviteInfo, deleteExportedChatInvite, onScreenSelect]); + closeDeleteDialog(); + }, [chatId, closeDeleteDialog, currentInviteInfo, deleteExportedChatInvite, onScreenSelect]); const handleMessageSearchQueryChange = useCallback((query: string) => { setLocalTextSearchQuery({ query }); @@ -305,15 +310,26 @@ const RightHeader: FC = ({ )} {currentInviteInfo && currentInviteInfo.isRevoked && ( - + <> + + + )} diff --git a/src/components/right/management/JoinRequest.scss b/src/components/right/management/JoinRequest.scss index 390455574..518f1dc28 100644 --- a/src/components/right/management/JoinRequest.scss +++ b/src/components/right/management/JoinRequest.scss @@ -21,17 +21,29 @@ &__user { display: flex; flex-grow: 1; + min-width: 0; + overflow: hidden; } &__user-info { display: flex; flex-direction: column; justify-content: center; + overflow: hidden; margin-left: 1rem; } &__user-subtitle { color: var(--color-text-secondary); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + &__user-name { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } &__date { diff --git a/src/components/right/management/JoinRequest.tsx b/src/components/right/management/JoinRequest.tsx index b033770ba..92955eabf 100644 --- a/src/components/right/management/JoinRequest.tsx +++ b/src/components/right/management/JoinRequest.tsx @@ -50,7 +50,7 @@ const JoinRequest: FC = ({ ? formatTime(lang, fixedDate) : formatHumanDate(lang, fixedDate, true, false, true); const handleUserClick = () => { - openUserInfo({ userId }); + openUserInfo({ id: userId }); }; const handleAcceptRequest = useCallback(() => { diff --git a/src/components/right/management/ManageGroupMembers.tsx b/src/components/right/management/ManageGroupMembers.tsx index 199079b1f..37ef882f1 100644 --- a/src/components/right/management/ManageGroupMembers.tsx +++ b/src/components/right/management/ManageGroupMembers.tsx @@ -111,8 +111,7 @@ const ManageGroupMembers: FC = ({ return true; } - return !user.isSelf - && (isChannel || user.canBeInvitedToGroup || !isUserBot(user)) + return (isChannel || user.canBeInvitedToGroup || !isUserBot(user)) && (!noAdmins || !adminIds.includes(contactId)); }), chatsById, diff --git a/src/components/right/management/ManageInvite.tsx b/src/components/right/management/ManageInvite.tsx index 756e35539..09beb9383 100644 --- a/src/components/right/management/ManageInvite.tsx +++ b/src/components/right/management/ManageInvite.tsx @@ -59,6 +59,7 @@ const ManageInvite: FC = ({ const [selectedExpireOption, setSelectedExpireOption] = useState('unlimited'); const [customUsageLimit, setCustomUsageLimit] = useState(10); const [selectedUsageOption, setSelectedUsageOption] = useState('0'); + const [isSubmitBlocked, setIsSubmitBlocked] = useState(false); useHistoryBack(isActive, onClose); @@ -81,8 +82,9 @@ const ManageInvite: FC = ({ setCustomUsageLimit(usageLimit); } if (expireDate) { + const minSafeDate = getServerTime(serverTimeOffset) + DEFAULT_CUSTOM_EXPIRE_DATE; setSelectedExpireOption('custom'); - setCustomExpireDate(expireDate * 1000); + setCustomExpireDate(Math.max(expireDate, minSafeDate) * 1000); } if (editingIsRequestNeeded) { setIsRequestNeeded(true); @@ -108,6 +110,7 @@ const ManageInvite: FC = ({ }, [closeCalendar]); const handleSaveClick = useCallback(() => { + setIsSubmitBlocked(true); const usageLimit = selectedUsageOption === 'custom' ? customUsageLimit : selectedUsageOption; let expireDate; switch (selectedExpireOption) { @@ -240,6 +243,7 @@ const ManageInvite: FC = ({ diff --git a/src/components/right/management/ManageInviteInfo.tsx b/src/components/right/management/ManageInviteInfo.tsx index ba0d753aa..e0df2fe1f 100644 --- a/src/components/right/management/ManageInviteInfo.tsx +++ b/src/components/right/management/ManageInviteInfo.tsx @@ -10,10 +10,13 @@ import useLang from '../../../hooks/useLang'; import { copyTextToClipboard } from '../../../util/clipboard'; import { getServerTime } from '../../../util/serverTime'; import { formatFullDate, formatMediaDateTime, formatTime } from '../../../util/dateFormat'; +import { isChatChannel } from '../../../modules/helpers'; +import { selectChat } from '../../../modules/selectors'; import PrivateChatInfo from '../../common/PrivateChatInfo'; import ListItem from '../../ui/ListItem'; import Button from '../../ui/Button'; +import Spinner from '../../ui/Spinner'; type OwnProps = { chatId: string; @@ -24,7 +27,9 @@ type OwnProps = { type StateProps = { invite?: ApiExportedInvite; importers?: ApiChatInviteImporter[]; + requesters?: ApiChatInviteImporter[]; admin?: ApiUser; + isChannel?: boolean; serverTimeOffset: number; }; @@ -32,6 +37,8 @@ const ManageInviteInfo: FC = ({ chatId, invite, importers, + requesters, + isChannel, isActive, serverTimeOffset, onClose, @@ -39,6 +46,7 @@ const ManageInviteInfo: FC = ({ const { showNotification, loadChatInviteImporters, + loadChatInviteRequesters, openUserInfo, } = getDispatch(); @@ -50,8 +58,11 @@ const ManageInviteInfo: FC = ({ const isExpired = ((invite?.expireDate || 0) - getServerTime(serverTimeOffset)) < 0; useEffect(() => { - if (link) loadChatInviteImporters({ chatId, link }); - }, [chatId, link, loadChatInviteImporters]); + if (link) { + loadChatInviteImporters({ chatId, link }); + loadChatInviteRequesters({ chatId, link }); + } + }, [chatId, link, loadChatInviteImporters, loadChatInviteRequesters]); const handleCopyClicked = useCallback(() => { copyTextToClipboard(invite!.link); @@ -63,8 +74,8 @@ const ManageInviteInfo: FC = ({ useHistoryBack(isActive, onClose); const renderImporters = () => { - if (invite?.isRevoked) return undefined; - if (!importers) return

{lang('Loading')}

; + if (!importers?.length && requesters?.length) return undefined; + if (!importers) return ; return (

{importers.length ? lang('PeopleJoined', usage) : lang('NoOneJoined')}

@@ -89,6 +100,31 @@ const ManageInviteInfo: FC = ({ ); }; + const renderRequesters = () => { + if (invite?.isRevoked) return undefined; + if (!requesters && importers) return ; + if (!requesters?.length) return undefined; + return ( +
+

{isChannel ? lang('SubscribeRequests') : lang('MemberRequests')}

+

+ {requesters.map((requester) => ( + openUserInfo({ id: requester.userId })} + > + + + ))} +

+
+ ); + }; + return (
@@ -98,7 +134,7 @@ const ManageInviteInfo: FC = ({ {invite && ( <>
-

{invite.title || invite.link}

+

{invite.title || invite.link}

= ({
)} {renderImporters()} + {renderRequesters()} )}
@@ -140,12 +177,15 @@ const ManageInviteInfo: FC = ({ export default memo(withGlobal( (global, { chatId }): StateProps => { const { inviteInfo } = global.management.byChatId[chatId]; - const invite = inviteInfo?.invite; - const importers = inviteInfo?.importers; + const { invite, importers, requesters } = inviteInfo || {}; + const chat = selectChat(global, chatId); + const isChannel = chat && isChatChannel(chat); return { invite, importers, + requesters, + isChannel, serverTimeOffset: global.serverTimeOffset, }; }, diff --git a/src/components/right/management/ManageInvites.tsx b/src/components/right/management/ManageInvites.tsx index 34377d694..9a45e5da7 100644 --- a/src/components/right/management/ManageInvites.tsx +++ b/src/components/right/management/ManageInvites.tsx @@ -1,11 +1,13 @@ import React, { - FC, memo, useCallback, useMemo, useState, + FC, memo, useCallback, useEffect, useMemo, useState, } from '../../../lib/teact/teact'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn'; import { ApiChat, ApiExportedInvite } from '../../../api/types'; import { ManagementScreens } from '../../../types'; +import { STICKER_SIZE_INVITES } from '../../../config'; +import getAnimationData from '../../common/helpers/animatedAssets'; import useHistoryBack from '../../../hooks/useHistoryBack'; import useLang from '../../../hooks/useLang'; import { formatCountdown, MILLISECONDS_IN_DAY } from '../../../util/dateFormat'; @@ -16,6 +18,7 @@ import { copyTextToClipboard } from '../../../util/clipboard'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment'; import { getServerTime } from '../../../util/serverTime'; import useFlag from '../../../hooks/useFlag'; +import { isChatChannel } from '../../../modules/helpers'; import ListItem from '../../ui/ListItem'; import NothingFound from '../../common/NothingFound'; @@ -23,6 +26,7 @@ import Button from '../../ui/Button'; import DropdownMenu from '../../ui/DropdownMenu'; import MenuItem from '../../ui/MenuItem'; import ConfirmDialog from '../../ui/ConfirmDialog'; +import AnimatedSticker from '../../common/AnimatedSticker'; type OwnProps = { chatId: string; @@ -33,6 +37,7 @@ type OwnProps = { type StateProps = { chat?: ApiChat; + isChannel?: boolean; exportedInvites?: ApiExportedInvite[]; revokedExportedInvites?: ApiExportedInvite[]; serverTimeOffset: number; @@ -54,6 +59,7 @@ const ManageInvites: FC = ({ exportedInvites, revokedExportedInvites, isActive, + isChannel, serverTimeOffset, onClose, onScreenSelect, @@ -66,14 +72,26 @@ const ManageInvites: FC = ({ deleteRevokedExportedChatInvites, setOpenedInviteInfo, } = getDispatch(); + + const lang = useLang(); + const [isDeleteRevokeAllDialogOpen, openDeleteRevokeAllDialog, closeDeleteRevokeAllDialog] = useFlag(); const [isRevokeDialogOpen, openRevokeDialog, closeRevokeDialog] = useFlag(); const [revokingInvite, setRevokingInvite] = useState(); const [isDeleteDialogOpen, openDeleteDialog, closeDeleteDialog] = useFlag(); const [deletingInvite, setDeletingInvite] = useState(); + const [animationData, setAnimationData] = useState(); + const [isAnimationLoaded, setIsAnimationLoaded] = useState(false); + const handleAnimationLoad = useCallback(() => setIsAnimationLoaded(true), []); + + useEffect(() => { + if (!animationData) { + getAnimationData('Invite').then(setAnimationData); + } + }, [animationData]); + useHistoryBack(isActive, onClose); - const lang = useLang(); const hasDetailedCountdown = useMemo(() => { if (!exportedInvites) return undefined; @@ -265,6 +283,20 @@ const ManageInvites: FC = ({ return (
+
+
+ {animationData && ( + + )} +
+

{isChannel ? lang('PrimaryLinkHelpChannel') : lang('PrimaryLinkHelp')}

+
{primaryInviteLink && (

@@ -347,6 +379,8 @@ const ManageInvites: FC = ({ onClose={closeDeleteRevokeAllDialog} title={lang('DeleteAllRevokedLinks')} text={lang('DeleteAllRevokedLinkHelp')} + confirmIsDestructive + confirmLabel={lang('DeleteAll')} confirmHandler={handleDeleteAllRevoked} /> = ({ onClose={closeRevokeDialog} title={lang('RevokeLink')} text={lang('RevokeAlert')} + confirmIsDestructive + confirmLabel={lang('RevokeButton')} confirmHandler={handleRevoke} /> = ({ onClose={closeDeleteDialog} title={lang('DeleteLink')} text={lang('DeleteLinkHelp')} + confirmIsDestructive + confirmLabel={lang('Delete')} confirmHandler={handleDelete} />

@@ -371,12 +409,14 @@ export default memo(withGlobal( (global, { chatId }): StateProps => { const { invites, revokedInvites } = global.management.byChatId[chatId]; const chat = selectChat(global, chatId); + const isChannel = chat && isChatChannel(chat); return { exportedInvites: invites, revokedExportedInvites: revokedInvites, chat, serverTimeOffset: global.serverTimeOffset, + isChannel, }; }, )(ManageInvites)); diff --git a/src/components/right/management/ManageJoinRequests.tsx b/src/components/right/management/ManageJoinRequests.tsx index ac3f1ea93..1e4c3b33f 100644 --- a/src/components/right/management/ManageJoinRequests.tsx +++ b/src/components/right/management/ManageJoinRequests.tsx @@ -1,19 +1,23 @@ import React, { - FC, memo, useCallback, useEffect, + FC, memo, useCallback, useEffect, useState, } from '../../../lib/teact/teact'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn'; import { ApiChat } from '../../../api/types'; +import { STICKER_SIZE_JOIN_REQUESTS } from '../../../config'; import useHistoryBack from '../../../hooks/useHistoryBack'; import { selectChat } from '../../../modules/selectors'; -import { isChatChannel } from '../../../modules/helpers'; +import { isChatChannel, isUserId } from '../../../modules/helpers'; import useLang from '../../../hooks/useLang'; import useFlag from '../../../hooks/useFlag'; +import getAnimationData from '../../common/helpers/animatedAssets'; import JoinRequest from './JoinRequest'; import Button from '../../ui/Button'; import ConfirmDialog from '../../ui/ConfirmDialog'; +import AnimatedSticker from '../../common/AnimatedSticker'; +import Spinner from '../../ui/Spinner'; type OwnProps = { chatId: string; @@ -40,10 +44,20 @@ const ManageJoinRequests: FC = ({ const lang = useLang(); + const [animationData, setAnimationData] = useState(); + const [isAnimationLoaded, setIsAnimationLoaded] = useState(false); + const handleAnimationLoad = useCallback(() => setIsAnimationLoaded(true), []); + + useEffect(() => { + if (!animationData) { + getAnimationData('JoinRequest').then(setAnimationData); + } + }, [animationData]); + useHistoryBack(isActive, onClose); useEffect(() => { - if (!chat?.joinRequests) { + if (!chat?.joinRequests && !isUserId(chatId)) { loadChatJoinRequests({ chatId }); } }, [chat, chatId, loadChatJoinRequests]); @@ -60,17 +74,34 @@ const ManageJoinRequests: FC = ({ return (
- {Boolean(chat?.joinRequests?.length) && ( -
- - +
+
+ {animationData && ( + + )}
- )} + {Boolean(chat?.joinRequests?.length) && ( +
+ + +
+ )} +

- {chat?.joinRequests?.length ? lang('JoinRequests', chat?.joinRequests?.length) : lang('NoMemberRequests')} + {!chat?.joinRequests ? lang('Loading') : chat.joinRequests.length + ? lang('JoinRequests', chat.joinRequests.length) : lang('NoMemberRequests')}

+ {!chat?.joinRequests && ( + + )} {chat?.joinRequests?.length === 0 && (

{isChannel ? lang('NoSubscribeRequestsDescription') : lang('NoMemberRequestsDescription')} diff --git a/src/components/right/management/Management.scss b/src/components/right/management/Management.scss index 7307c2fd8..ea20c51a5 100644 --- a/src/components/right/management/Management.scss +++ b/src/components/right/management/Management.scss @@ -183,6 +183,10 @@ box-shadow: none; } } + + .Spinner { + margin: 2rem auto; + } } .ManageGroupMembers { @@ -197,6 +201,7 @@ .primary-link-input { cursor: pointer; margin-bottom: 1rem; + padding-right: 3rem; } .primary-link-more-menu { @@ -230,6 +235,10 @@ -webkit-appearance: none; } } + + .custom-scroll { + padding-bottom: 4rem; + } } .ManageInviteInfo { @@ -237,6 +246,10 @@ margin-top: 1rem; margin-bottom: 1rem; } + + .link-title { + text-align: center; + } } .ManageJoinRequests { @@ -251,7 +264,8 @@ } } -.ManageInvite, .ManageInvites { +.ManageInvite, +.ManageInvites { .hint { font-size: 0.875rem; margin-bottom: 0; diff --git a/src/components/ui/ListItem.tsx b/src/components/ui/ListItem.tsx index 138a90fc0..3820894c3 100644 --- a/src/components/ui/ListItem.tsx +++ b/src/components/ui/ListItem.tsx @@ -114,7 +114,6 @@ const ListItem: FC = ({ const handleSecondaryIconClick = (e: React.MouseEvent) => { if (disabled || e.button !== 0 || (!onSecondaryIconClick && !contextActions)) return; - e.stopPropagation(); if (onSecondaryIconClick) { onSecondaryIconClick(e); @@ -188,7 +187,8 @@ const ListItem: FC = ({ round color="translucent" size="smaller" - onMouseDown={handleSecondaryIconClick} + onClick={IS_TOUCH_ENV ? handleSecondaryIconClick : undefined} + onMouseDown={!IS_TOUCH_ENV ? handleSecondaryIconClick : undefined} > diff --git a/src/components/ui/Modal.scss b/src/components/ui/Modal.scss index 0c5c5a367..ae9e146cc 100644 --- a/src/components/ui/Modal.scss +++ b/src/components/ui/Modal.scss @@ -140,7 +140,11 @@ } .modal-about { - font-weight: bold; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 5; + text-overflow: ellipsis; + overflow: hidden; } .modal-help { diff --git a/src/config.ts b/src/config.ts index 753b64d2b..e78a4a97e 100644 --- a/src/config.ts +++ b/src/config.ts @@ -121,8 +121,10 @@ export const STICKER_SIZE_SEARCH = 64; export const STICKER_SIZE_MODAL = 64; export const STICKER_SIZE_TWO_FA = 160; export const STICKER_SIZE_DISCUSSION_GROUPS = 140; -export const STICKER_SIZE_FOLDER_SETTINGS = 80; +export const STICKER_SIZE_FOLDER_SETTINGS = 100; export const STICKER_SIZE_INLINE_BOT_RESULT = 100; +export const STICKER_SIZE_JOIN_REQUESTS = 140; +export const STICKER_SIZE_INVITES = 140; export const RECENT_STICKERS_LIMIT = 20; export const MEMOJI_STICKER_ID = 'MEMOJI_STICKER'; diff --git a/src/global/types.ts b/src/global/types.ts index c4aafa0e4..c878c162b 100644 --- a/src/global/types.ts +++ b/src/global/types.ts @@ -558,6 +558,7 @@ export type ActionTypes = ( 'setEditingExportedInvite' | 'loadExportedChatInvites' | 'editExportedChatInvite' | 'exportChatInvite' | 'deleteExportedChatInvite' | 'deleteRevokedExportedChatInvites' | 'setOpenedInviteInfo' | 'loadChatInviteImporters' | 'loadChatJoinRequests' | 'hideChatJoinRequest' | 'hideAllChatJoinRequests' | 'requestNextManagementScreen' | + 'loadChatInviteRequesters' | // groups 'togglePreHistoryHidden' | 'updateChatDefaultBannedRights' | 'updateChatMemberBannedRights' | 'updateChatAdmin' | 'acceptInviteConfirmation' | diff --git a/src/modules/actions/api/management.ts b/src/modules/actions/api/management.ts index 2ac976285..0a7021e81 100644 --- a/src/modules/actions/api/management.ts +++ b/src/modules/actions/api/management.ts @@ -243,7 +243,7 @@ addReducer('loadChatInviteImporters', (global, actions, payload) => { } global = getGlobal(); const currentInviteInfo = global.management.byChatId[chatId]?.inviteInfo; - if (!currentInviteInfo?.invite) return; + if (!currentInviteInfo?.invite || currentInviteInfo.invite.link !== link) return; setGlobal(updateManagement(global, chatId, { inviteInfo: { ...currentInviteInfo, @@ -253,6 +253,38 @@ addReducer('loadChatInviteImporters', (global, actions, payload) => { })(); }); +addReducer('loadChatInviteRequesters', (global, actions, payload) => { + const { + chatId, link, offsetDate, offsetUserId, limit, + } = payload!; + const peer = selectChat(global, chatId); + const offsetUser = selectUser(global, offsetUserId); + if (!peer || (offsetUserId && !offsetUser)) return; + + (async () => { + const result = await callApi('fetchChatInviteImporters', { + peer, + link, + offsetDate, + offsetUser, + limit, + isRequested: true, + }); + if (!result) { + return; + } + global = getGlobal(); + const currentInviteInfo = global.management.byChatId[chatId]?.inviteInfo; + if (!currentInviteInfo?.invite || currentInviteInfo.invite.link !== link) return; + setGlobal(updateManagement(global, chatId, { + inviteInfo: { + ...currentInviteInfo, + requesters: result, + }, + })); + })(); +}); + addReducer('loadChatJoinRequests', (global, actions, payload) => { const { chatId, offsetDate, offsetUserId, limit, diff --git a/src/types/index.ts b/src/types/index.ts index 540a4d35f..4a37fd049 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -293,6 +293,7 @@ export interface ManagementState { inviteInfo?: { invite: ApiExportedInvite; importers?: ApiChatInviteImporter[]; + requesters?: ApiChatInviteImporter[]; }; }