From bb0d8468382c672adfc545ff82c4f8eb77ee6e33 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Wed, 2 Feb 2022 22:49:18 +0100 Subject: [PATCH] Management / Join Requests: Add animated stickers, various fixes (#1679) --- src/@types/global.d.ts | 1 + src/assets/tgs/invites/Invite.tgs | Bin 0 -> 29706 bytes src/assets/tgs/invites/Requests.tgs | Bin 0 -> 14465 bytes .../common/helpers/animatedAssets.ts | 26 +++------ src/components/main/Dialogs.tsx | 14 ++++- src/components/right/RightHeader.tsx | 38 ++++++++---- .../right/management/JoinRequest.scss | 12 ++++ .../right/management/JoinRequest.tsx | 2 +- .../right/management/ManageGroupMembers.tsx | 3 +- .../right/management/ManageInvite.tsx | 6 +- .../right/management/ManageInviteInfo.tsx | 54 +++++++++++++++--- .../right/management/ManageInvites.tsx | 44 +++++++++++++- .../right/management/ManageJoinRequests.tsx | 49 +++++++++++++--- .../right/management/Management.scss | 16 +++++- src/components/ui/ListItem.tsx | 4 +- src/components/ui/Modal.scss | 6 +- src/config.ts | 4 +- src/global/types.ts | 1 + src/modules/actions/api/management.ts | 34 ++++++++++- src/types/index.ts | 1 + 20 files changed, 255 insertions(+), 60 deletions(-) create mode 100644 src/assets/tgs/invites/Invite.tgs create mode 100644 src/assets/tgs/invites/Requests.tgs 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 0000000000000000000000000000000000000000..de9333de4440c30ee700e934d5f1308545b7aa39 GIT binary patch literal 29706 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 = ({ 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[]; }; }