Gifts: Support filter in profile (#5533)
This commit is contained in:
parent
0ac730a043
commit
1419d396d3
@ -1,6 +1,9 @@
|
|||||||
import BigInt from 'big-integer';
|
import BigInt from 'big-integer';
|
||||||
import { Api as GramJs } from '../../../lib/gramjs';
|
import { Api as GramJs } from '../../../lib/gramjs';
|
||||||
|
|
||||||
|
import type {
|
||||||
|
GiftProfileFilterOptions,
|
||||||
|
} from '../../../types';
|
||||||
import type {
|
import type {
|
||||||
ApiChat,
|
ApiChat,
|
||||||
ApiInputStorePaymentPurpose,
|
ApiInputStorePaymentPurpose,
|
||||||
@ -451,16 +454,30 @@ export async function fetchSavedStarGifts({
|
|||||||
peer,
|
peer,
|
||||||
offset = '',
|
offset = '',
|
||||||
limit,
|
limit,
|
||||||
|
filter,
|
||||||
}: {
|
}: {
|
||||||
peer: ApiPeer;
|
peer: ApiPeer;
|
||||||
offset?: string;
|
offset?: string;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
|
filter?: GiftProfileFilterOptions;
|
||||||
}) {
|
}) {
|
||||||
const result = await invokeRequest(new GramJs.payments.GetSavedStarGifts({
|
type GetSavedStarGiftsParams = ConstructorParameters<typeof GramJs.payments.GetSavedStarGifts>[0];
|
||||||
|
|
||||||
|
const params : GetSavedStarGiftsParams = {
|
||||||
peer: buildInputPeer(peer.id, peer.accessHash),
|
peer: buildInputPeer(peer.id, peer.accessHash),
|
||||||
offset,
|
offset,
|
||||||
limit,
|
limit,
|
||||||
}));
|
...(filter && {
|
||||||
|
sortByValue: filter.sortType === 'byValue' || undefined,
|
||||||
|
excludeUnlimited: !filter.shouldIncludeUnlimited || undefined,
|
||||||
|
excludeLimited: !filter.shouldIncludeLimited || undefined,
|
||||||
|
excludeUnique: !filter.shouldIncludeUnique || undefined,
|
||||||
|
excludeSaved: !filter.shouldIncludeDisplayed || undefined,
|
||||||
|
excludeUnsaved: !filter.shouldIncludeHidden || undefined,
|
||||||
|
} satisfies GetSavedStarGiftsParams),
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await invokeRequest(new GramJs.payments.GetSavedStarGifts(params));
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|||||||
@ -1599,6 +1599,15 @@
|
|||||||
"ViewButtonGiftUnique" = "VIEW COLLECTIBLE";
|
"ViewButtonGiftUnique" = "VIEW COLLECTIBLE";
|
||||||
"AuthContinueOnThisLanguage" = "Continue in English";
|
"AuthContinueOnThisLanguage" = "Continue in English";
|
||||||
"Share" = "Share";
|
"Share" = "Share";
|
||||||
|
"GiftSortByDate" = "Sort by Date";
|
||||||
|
"GiftSortByValue" = "Sort by Value";
|
||||||
|
"GiftFilterUnlimited" = "Unlimited";
|
||||||
|
"GiftFilterLimited" = "Limited";
|
||||||
|
"GiftFilterUnique" = "Unique";
|
||||||
|
"GiftFilterDisplayed" = "Displayed";
|
||||||
|
"GiftFilterHidden" = "Hidden";
|
||||||
|
"GiftSearchEmpty" = "No matching gifts";
|
||||||
|
"GiftSearchReset" = "View All Gifts";
|
||||||
"CheckPasswordTitle" = "Enter Password";
|
"CheckPasswordTitle" = "Enter Password";
|
||||||
"CheckPasswordPlaceholder" = "Password";
|
"CheckPasswordPlaceholder" = "Password";
|
||||||
"CheckPasswordDescription" = "Please enter your password to continue.";
|
"CheckPasswordDescription" = "Please enter your password to continue.";
|
||||||
|
|||||||
BIN
src/assets/tgs/SearchingDuck.tgs
Normal file
BIN
src/assets/tgs/SearchingDuck.tgs
Normal file
Binary file not shown.
@ -20,6 +20,7 @@ import MonkeyPeek from '../../../assets/tgs/monkeys/TwoFactorSetupMonkeyPeek.tgs
|
|||||||
import MonkeyTracking from '../../../assets/tgs/monkeys/TwoFactorSetupMonkeyTracking.tgs';
|
import MonkeyTracking from '../../../assets/tgs/monkeys/TwoFactorSetupMonkeyTracking.tgs';
|
||||||
import ReadTime from '../../../assets/tgs/ReadTime.tgs';
|
import ReadTime from '../../../assets/tgs/ReadTime.tgs';
|
||||||
import Report from '../../../assets/tgs/Report.tgs';
|
import Report from '../../../assets/tgs/Report.tgs';
|
||||||
|
import SearchingDuck from '../../../assets/tgs/SearchingDuck.tgs';
|
||||||
import Congratulations from '../../../assets/tgs/settings/Congratulations.tgs';
|
import Congratulations from '../../../assets/tgs/settings/Congratulations.tgs';
|
||||||
import DiscussionGroups from '../../../assets/tgs/settings/DiscussionGroupsDucks.tgs';
|
import DiscussionGroups from '../../../assets/tgs/settings/DiscussionGroupsDucks.tgs';
|
||||||
import Experimental from '../../../assets/tgs/settings/Experimental.tgs';
|
import Experimental from '../../../assets/tgs/settings/Experimental.tgs';
|
||||||
@ -64,4 +65,5 @@ export const LOCAL_TGS_URLS = {
|
|||||||
StarReactionEffect,
|
StarReactionEffect,
|
||||||
StarReaction,
|
StarReaction,
|
||||||
Report,
|
Report,
|
||||||
|
SearchingDuck,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -46,6 +46,36 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nothing-found-gifts {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
padding-top: 5rem;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.description {
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: var(--font-weight-medium);
|
||||||
|
text-align: center;
|
||||||
|
margin-block: 1rem;
|
||||||
|
unicode-bidi: plaintext;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Link {
|
||||||
|
color: var(--color-links);
|
||||||
|
font-weight: var(--font-weight-medium);
|
||||||
|
transition: opacity 0.15s ease-in;
|
||||||
|
|
||||||
|
&:active,
|
||||||
|
&:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.shared-media {
|
.shared-media {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
|
|||||||
@ -49,6 +49,7 @@ import {
|
|||||||
selectChatMessages,
|
selectChatMessages,
|
||||||
selectCurrentSharedMediaSearch,
|
selectCurrentSharedMediaSearch,
|
||||||
selectIsCurrentUserPremium,
|
selectIsCurrentUserPremium,
|
||||||
|
selectIsGiftProfileFilterDefault,
|
||||||
selectIsRightColumnShown,
|
selectIsRightColumnShown,
|
||||||
selectPeerStories,
|
selectPeerStories,
|
||||||
selectSimilarBotsIds,
|
selectSimilarBotsIds,
|
||||||
@ -63,6 +64,7 @@ import { selectPremiumLimit } from '../../global/selectors/limits';
|
|||||||
import buildClassName from '../../util/buildClassName';
|
import buildClassName from '../../util/buildClassName';
|
||||||
import { captureEvents, SwipeDirection } from '../../util/captureEvents';
|
import { captureEvents, SwipeDirection } from '../../util/captureEvents';
|
||||||
import { IS_TOUCH_ENV } from '../../util/windowEnvironment';
|
import { IS_TOUCH_ENV } from '../../util/windowEnvironment';
|
||||||
|
import { LOCAL_TGS_URLS } from '../common/helpers/animatedAssets';
|
||||||
import renderText from '../common/helpers/renderText';
|
import renderText from '../common/helpers/renderText';
|
||||||
import { getSenderName } from '../left/search/helpers/getSenderName';
|
import { getSenderName } from '../left/search/helpers/getSenderName';
|
||||||
|
|
||||||
@ -79,6 +81,7 @@ import useProfileState from './hooks/useProfileState';
|
|||||||
import useProfileViewportIds from './hooks/useProfileViewportIds';
|
import useProfileViewportIds from './hooks/useProfileViewportIds';
|
||||||
import useTransitionFixes from './hooks/useTransitionFixes';
|
import useTransitionFixes from './hooks/useTransitionFixes';
|
||||||
|
|
||||||
|
import AnimatedIconWithPreview from '../common/AnimatedIconWithPreview';
|
||||||
import Audio from '../common/Audio';
|
import Audio from '../common/Audio';
|
||||||
import Document from '../common/Document';
|
import Document from '../common/Document';
|
||||||
import SavedGift from '../common/gift/SavedGift';
|
import SavedGift from '../common/gift/SavedGift';
|
||||||
@ -96,6 +99,7 @@ import MediaStory from '../story/MediaStory';
|
|||||||
import Button from '../ui/Button';
|
import Button from '../ui/Button';
|
||||||
import FloatingActionButton from '../ui/FloatingActionButton';
|
import FloatingActionButton from '../ui/FloatingActionButton';
|
||||||
import InfiniteScroll from '../ui/InfiniteScroll';
|
import InfiniteScroll from '../ui/InfiniteScroll';
|
||||||
|
import Link from '../ui/Link';
|
||||||
import ListItem, { type MenuItemContextAction } from '../ui/ListItem';
|
import ListItem, { type MenuItemContextAction } from '../ui/ListItem';
|
||||||
import Spinner from '../ui/Spinner';
|
import Spinner from '../ui/Spinner';
|
||||||
import TabList from '../ui/TabList';
|
import TabList from '../ui/TabList';
|
||||||
@ -155,6 +159,7 @@ type StateProps = {
|
|||||||
isSavedDialog?: boolean;
|
isSavedDialog?: boolean;
|
||||||
forceScrollProfileTab?: boolean;
|
forceScrollProfileTab?: boolean;
|
||||||
isSynced?: boolean;
|
isSynced?: boolean;
|
||||||
|
isNotDefaultGiftFilter?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type TabProps = {
|
type TabProps = {
|
||||||
@ -219,6 +224,7 @@ const Profile: FC<OwnProps & StateProps> = ({
|
|||||||
forceScrollProfileTab,
|
forceScrollProfileTab,
|
||||||
isSynced,
|
isSynced,
|
||||||
onProfileStateChange,
|
onProfileStateChange,
|
||||||
|
isNotDefaultGiftFilter,
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
setSharedMediaSearchType,
|
setSharedMediaSearchType,
|
||||||
@ -237,6 +243,7 @@ const Profile: FC<OwnProps & StateProps> = ({
|
|||||||
loadBotRecommendations,
|
loadBotRecommendations,
|
||||||
loadPreviewMedias,
|
loadPreviewMedias,
|
||||||
loadPeerSavedGifts,
|
loadPeerSavedGifts,
|
||||||
|
resetGiftProfileFilter,
|
||||||
} = getActions();
|
} = getActions();
|
||||||
|
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
@ -482,6 +489,10 @@ const Profile: FC<OwnProps & StateProps> = ({
|
|||||||
setActiveTab(Math.min(newActiveTab, tabs.length - 1));
|
setActiveTab(Math.min(newActiveTab, tabs.length - 1));
|
||||||
}, [hasMembersTab, activeTab, tabs]);
|
}, [hasMembersTab, activeTab, tabs]);
|
||||||
|
|
||||||
|
const handleResetGiftsFilter = useLastCallback(() => {
|
||||||
|
resetGiftProfileFilter();
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!transitionRef.current || !IS_TOUCH_ENV) {
|
if (!transitionRef.current || !IS_TOUCH_ENV) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -523,6 +534,28 @@ const Profile: FC<OwnProps & StateProps> = ({
|
|||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderNothingFoundGiftsWithFilter() {
|
||||||
|
return (
|
||||||
|
<div className="nothing-found-gifts">
|
||||||
|
<AnimatedIconWithPreview
|
||||||
|
size={160}
|
||||||
|
tgsUrl={LOCAL_TGS_URLS.SearchingDuck}
|
||||||
|
nonInteractive
|
||||||
|
noLoop
|
||||||
|
/>
|
||||||
|
<div className="description">
|
||||||
|
{lang('GiftSearchEmpty')}
|
||||||
|
</div>
|
||||||
|
<Link
|
||||||
|
className="date"
|
||||||
|
onClick={handleResetGiftsFilter}
|
||||||
|
>
|
||||||
|
{lang('GiftSearchReset')}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function renderContent() {
|
function renderContent() {
|
||||||
if (resultType === 'dialogs') {
|
if (resultType === 'dialogs') {
|
||||||
return (
|
return (
|
||||||
@ -535,7 +568,9 @@ const Profile: FC<OwnProps & StateProps> = ({
|
|||||||
const forceRenderHiddenMembers = Boolean(resultType === 'members' && areMembersHidden);
|
const forceRenderHiddenMembers = Boolean(resultType === 'members' && areMembersHidden);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="content empty-list">
|
<div
|
||||||
|
className="content empty-list"
|
||||||
|
>
|
||||||
{!noSpinner && !forceRenderHiddenMembers && <Spinner />}
|
{!noSpinner && !forceRenderHiddenMembers && <Spinner />}
|
||||||
{forceRenderHiddenMembers && <NothingFound text="You have no access to group members list." />}
|
{forceRenderHiddenMembers && <NothingFound text="You have no access to group members list." />}
|
||||||
</div>
|
</div>
|
||||||
@ -545,6 +580,10 @@ const Profile: FC<OwnProps & StateProps> = ({
|
|||||||
if (viewportIds && !viewportIds?.length) {
|
if (viewportIds && !viewportIds?.length) {
|
||||||
let text: string;
|
let text: string;
|
||||||
|
|
||||||
|
if (resultType === 'gifts' && isNotDefaultGiftFilter) {
|
||||||
|
return renderNothingFoundGiftsWithFilter();
|
||||||
|
}
|
||||||
|
|
||||||
switch (resultType) {
|
switch (resultType) {
|
||||||
case 'members':
|
case 'members':
|
||||||
text = areMembersHidden ? 'You have no access to group members list.' : 'No members found';
|
text = areMembersHidden ? 'You have no access to group members list.' : 'No members found';
|
||||||
@ -912,7 +951,9 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
const archiveStoryIds = peerStories?.archiveIds;
|
const archiveStoryIds = peerStories?.archiveIds;
|
||||||
|
|
||||||
const hasGiftsTab = Boolean(peerFullInfo?.starGiftCount) && !isSavedDialog;
|
const hasGiftsTab = Boolean(peerFullInfo?.starGiftCount) && !isSavedDialog;
|
||||||
const peerGifts = global.peers.giftsById[chatId];
|
const peerGifts = selectTabState(global).savedGifts.giftsByPeerId[chatId];
|
||||||
|
|
||||||
|
const isNotDefaultGiftFilter = !selectIsGiftProfileFilterDefault(global);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
theme: selectTheme(global),
|
theme: selectTheme(global),
|
||||||
@ -952,6 +993,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
isTopicInfo,
|
isTopicInfo,
|
||||||
isSavedDialog,
|
isSavedDialog,
|
||||||
isSynced: global.isSynced,
|
isSynced: global.isSynced,
|
||||||
|
isNotDefaultGiftFilter,
|
||||||
limitSimilarPeers: selectPremiumLimit(global, 'recommendedChannels'),
|
limitSimilarPeers: selectPremiumLimit(global, 'recommendedChannels'),
|
||||||
...(hasMembersTab && members && { members, adminMembersById }),
|
...(hasMembersTab && members && { members, adminMembersById }),
|
||||||
...(hasCommonChatsTab && user && { commonChatIds: commonChats?.ids }),
|
...(hasCommonChatsTab && user && { commonChatIds: commonChats?.ids }),
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
import type { FC } from '../../lib/teact/teact';
|
import type { FC } from '../../lib/teact/teact';
|
||||||
import React, { useEffect, useRef, useState } from '../../lib/teact/teact';
|
import React, {
|
||||||
|
useEffect, useMemo, useRef, useState,
|
||||||
|
} from '../../lib/teact/teact';
|
||||||
import { getActions, withGlobal } from '../../global';
|
import { getActions, withGlobal } from '../../global';
|
||||||
|
|
||||||
import type { ApiExportedInvite } from '../../api/types';
|
import type { ApiExportedInvite } from '../../api/types';
|
||||||
|
import type { GiftProfileFilterOptions, ThreadId } from '../../types';
|
||||||
import { MAIN_THREAD_ID } from '../../api/types';
|
import { MAIN_THREAD_ID } from '../../api/types';
|
||||||
import { ManagementScreens, ProfileState, type ThreadId } from '../../types';
|
import { ManagementScreens, ProfileState } from '../../types';
|
||||||
|
|
||||||
import { ANIMATION_END_DELAY, SAVED_FOLDER_ID } from '../../config';
|
import { ANIMATION_END_DELAY, SAVED_FOLDER_ID } from '../../config';
|
||||||
import {
|
import {
|
||||||
@ -12,6 +15,8 @@ import {
|
|||||||
} from '../../global/helpers';
|
} from '../../global/helpers';
|
||||||
import {
|
import {
|
||||||
selectCanManage,
|
selectCanManage,
|
||||||
|
selectCanUseGiftProfileAdminFilter,
|
||||||
|
selectCanUseGiftProfileFilter,
|
||||||
selectChat,
|
selectChat,
|
||||||
selectChatFullInfo,
|
selectChatFullInfo,
|
||||||
selectCurrentGifSearch,
|
selectCurrentGifSearch,
|
||||||
@ -28,12 +33,16 @@ import useCurrentOrPrev from '../../hooks/useCurrentOrPrev';
|
|||||||
import useElectronDrag from '../../hooks/useElectronDrag';
|
import useElectronDrag from '../../hooks/useElectronDrag';
|
||||||
import useFlag from '../../hooks/useFlag';
|
import useFlag from '../../hooks/useFlag';
|
||||||
import { useFolderManagerForChatsCount } from '../../hooks/useFolderManager';
|
import { useFolderManagerForChatsCount } from '../../hooks/useFolderManager';
|
||||||
|
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 Icon from '../common/icons/Icon';
|
import Icon from '../common/icons/Icon';
|
||||||
import Button from '../ui/Button';
|
import Button from '../ui/Button';
|
||||||
import ConfirmDialog from '../ui/ConfirmDialog';
|
import ConfirmDialog from '../ui/ConfirmDialog';
|
||||||
|
import DropdownMenu from '../ui/DropdownMenu';
|
||||||
|
import MenuItem from '../ui/MenuItem';
|
||||||
|
import MenuSeparator from '../ui/MenuSeparator';
|
||||||
import SearchInput from '../ui/SearchInput';
|
import SearchInput from '../ui/SearchInput';
|
||||||
import Transition from '../ui/Transition';
|
import Transition from '../ui/Transition';
|
||||||
|
|
||||||
@ -76,6 +85,9 @@ type StateProps = {
|
|||||||
shouldSkipHistoryAnimations?: boolean;
|
shouldSkipHistoryAnimations?: boolean;
|
||||||
isBot?: boolean;
|
isBot?: boolean;
|
||||||
canEditBot?: boolean;
|
canEditBot?: boolean;
|
||||||
|
giftProfileFilter: GiftProfileFilterOptions;
|
||||||
|
canUseGiftFilter?: boolean;
|
||||||
|
canUseGiftAdminFilter?:boolean;
|
||||||
isInsideTopic?: boolean;
|
isInsideTopic?: boolean;
|
||||||
canEditTopic?: boolean;
|
canEditTopic?: boolean;
|
||||||
isSavedMessages?: boolean;
|
isSavedMessages?: boolean;
|
||||||
@ -86,6 +98,7 @@ const COLUMN_ANIMATION_DURATION = 450 + ANIMATION_END_DELAY;
|
|||||||
enum HeaderContent {
|
enum HeaderContent {
|
||||||
Profile,
|
Profile,
|
||||||
MemberList,
|
MemberList,
|
||||||
|
GiftList,
|
||||||
SharedMedia,
|
SharedMedia,
|
||||||
StoryList,
|
StoryList,
|
||||||
Search,
|
Search,
|
||||||
@ -161,6 +174,9 @@ const RightHeader: FC<OwnProps & StateProps> = ({
|
|||||||
onClose,
|
onClose,
|
||||||
onScreenSelect,
|
onScreenSelect,
|
||||||
canEditBot,
|
canEditBot,
|
||||||
|
giftProfileFilter,
|
||||||
|
canUseGiftFilter,
|
||||||
|
canUseGiftAdminFilter,
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
setStickerSearchQuery,
|
setStickerSearchQuery,
|
||||||
@ -171,11 +187,21 @@ const RightHeader: FC<OwnProps & StateProps> = ({
|
|||||||
setEditingExportedInvite,
|
setEditingExportedInvite,
|
||||||
deleteExportedChatInvite,
|
deleteExportedChatInvite,
|
||||||
openEditTopicPanel,
|
openEditTopicPanel,
|
||||||
|
updateGiftProfileFilter,
|
||||||
} = getActions();
|
} = getActions();
|
||||||
|
|
||||||
const [isDeleteDialogOpen, openDeleteDialog, closeDeleteDialog] = useFlag();
|
const [isDeleteDialogOpen, openDeleteDialog, closeDeleteDialog] = useFlag();
|
||||||
const { isMobile } = useAppLayout();
|
const { isMobile } = useAppLayout();
|
||||||
|
|
||||||
|
const {
|
||||||
|
sortType: giftsSortType,
|
||||||
|
shouldIncludeUnlimited: shouldIncludeUnlimitedGifts,
|
||||||
|
shouldIncludeLimited: shouldIncludeLimitedGifts,
|
||||||
|
shouldIncludeUnique: shouldIncludeUniqueGifts,
|
||||||
|
shouldIncludeDisplayed: shouldIncludeDisplayedGifts,
|
||||||
|
shouldIncludeHidden: shouldIncludeHiddenGifts,
|
||||||
|
} = giftProfileFilter;
|
||||||
|
|
||||||
const foldersChatCount = useFolderManagerForChatsCount();
|
const foldersChatCount = useFolderManagerForChatsCount();
|
||||||
|
|
||||||
const handleEditInviteClick = useLastCallback(() => {
|
const handleEditInviteClick = useLastCallback(() => {
|
||||||
@ -226,7 +252,8 @@ const RightHeader: FC<OwnProps & StateProps> = ({
|
|||||||
}, COLUMN_ANIMATION_DURATION);
|
}, COLUMN_ANIMATION_DURATION);
|
||||||
}, [isColumnOpen]);
|
}, [isColumnOpen]);
|
||||||
|
|
||||||
const lang = useOldLang();
|
const oldLang = useOldLang();
|
||||||
|
const lang = useLang();
|
||||||
const contentKey = isProfile ? (
|
const contentKey = isProfile ? (
|
||||||
profileState === ProfileState.Profile ? (
|
profileState === ProfileState.Profile ? (
|
||||||
HeaderContent.Profile
|
HeaderContent.Profile
|
||||||
@ -234,6 +261,8 @@ const RightHeader: FC<OwnProps & StateProps> = ({
|
|||||||
HeaderContent.SharedMedia
|
HeaderContent.SharedMedia
|
||||||
) : profileState === ProfileState.MemberList ? (
|
) : profileState === ProfileState.MemberList ? (
|
||||||
HeaderContent.MemberList
|
HeaderContent.MemberList
|
||||||
|
) : profileState === ProfileState.GiftList ? (
|
||||||
|
HeaderContent.GiftList
|
||||||
) : profileState === ProfileState.StoryList ? (
|
) : profileState === ProfileState.StoryList ? (
|
||||||
HeaderContent.StoryList
|
HeaderContent.StoryList
|
||||||
) : profileState === ProfileState.SavedDialogs ? (
|
) : profileState === ProfileState.SavedDialogs ? (
|
||||||
@ -309,24 +338,40 @@ const RightHeader: FC<OwnProps & StateProps> = ({
|
|||||||
|
|
||||||
function getHeaderTitle() {
|
function getHeaderTitle() {
|
||||||
if (isSavedMessages) {
|
if (isSavedMessages) {
|
||||||
return lang('SavedMessages');
|
return oldLang('SavedMessages');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isInsideTopic) {
|
if (isInsideTopic) {
|
||||||
return lang('AccDescrTopic');
|
return oldLang('AccDescrTopic');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isChannel) {
|
if (isChannel) {
|
||||||
return lang('Channel.TitleInfo');
|
return oldLang('Channel.TitleInfo');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userId) {
|
if (userId) {
|
||||||
return lang(isBot ? 'lng_info_bot_title' : 'lng_info_user_title');
|
return oldLang(isBot ? 'lng_info_bot_title' : 'lng_info_user_title');
|
||||||
}
|
}
|
||||||
|
|
||||||
return lang('GroupInfo.Title');
|
return oldLang('GroupInfo.Title');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PrimaryLinkMenuButton: FC<{ onTrigger: () => void; isOpen?: boolean }> = useMemo(() => {
|
||||||
|
return ({ onTrigger, isOpen }) => (
|
||||||
|
<Button
|
||||||
|
round
|
||||||
|
ripple={!isMobile}
|
||||||
|
size="smaller"
|
||||||
|
color="translucent"
|
||||||
|
className={isOpen ? 'active' : ''}
|
||||||
|
onClick={onTrigger}
|
||||||
|
ariaLabel={lang('AccDescrOpenMenu2')}
|
||||||
|
>
|
||||||
|
<Icon name="more" />
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}, [isMobile, lang]);
|
||||||
|
|
||||||
function renderHeaderContent() {
|
function renderHeaderContent() {
|
||||||
if (renderingContentKey === -1) {
|
if (renderingContentKey === -1) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -334,48 +379,48 @@ const RightHeader: FC<OwnProps & StateProps> = ({
|
|||||||
|
|
||||||
switch (renderingContentKey) {
|
switch (renderingContentKey) {
|
||||||
case HeaderContent.PollResults:
|
case HeaderContent.PollResults:
|
||||||
return <h3 className="title">{lang('PollResults')}</h3>;
|
return <h3 className="title">{oldLang('PollResults')}</h3>;
|
||||||
case HeaderContent.AddingMembers:
|
case HeaderContent.AddingMembers:
|
||||||
return <h3 className="title">{lang(isChannel ? 'ChannelAddSubscribers' : 'GroupAddMembers')}</h3>;
|
return <h3 className="title">{oldLang(isChannel ? 'ChannelAddSubscribers' : 'GroupAddMembers')}</h3>;
|
||||||
case HeaderContent.ManageInitial:
|
case HeaderContent.ManageInitial:
|
||||||
return <h3 className="title">{lang('Edit')}</h3>;
|
return <h3 className="title">{oldLang('Edit')}</h3>;
|
||||||
case HeaderContent.ManageChatPrivacyType:
|
case HeaderContent.ManageChatPrivacyType:
|
||||||
return <h3 className="title">{lang(isChannel ? 'ChannelTypeHeader' : 'GroupTypeHeader')}</h3>;
|
return <h3 className="title">{oldLang(isChannel ? 'ChannelTypeHeader' : 'GroupTypeHeader')}</h3>;
|
||||||
case HeaderContent.ManageDiscussion:
|
case HeaderContent.ManageDiscussion:
|
||||||
return <h3 className="title">{lang('Discussion')}</h3>;
|
return <h3 className="title">{oldLang('Discussion')}</h3>;
|
||||||
case HeaderContent.ManageChatAdministrators:
|
case HeaderContent.ManageChatAdministrators:
|
||||||
return <h3 className="title">{lang('ChannelAdministrators')}</h3>;
|
return <h3 className="title">{oldLang('ChannelAdministrators')}</h3>;
|
||||||
case HeaderContent.ManageGroupRecentActions:
|
case HeaderContent.ManageGroupRecentActions:
|
||||||
return <h3 className="title">{lang('Group.Info.AdminLog')}</h3>;
|
return <h3 className="title">{oldLang('Group.Info.AdminLog')}</h3>;
|
||||||
case HeaderContent.ManageGroupAdminRights:
|
case HeaderContent.ManageGroupAdminRights:
|
||||||
return <h3 className="title">{lang('EditAdminRights')}</h3>;
|
return <h3 className="title">{oldLang('EditAdminRights')}</h3>;
|
||||||
case HeaderContent.ManageGroupNewAdminRights:
|
case HeaderContent.ManageGroupNewAdminRights:
|
||||||
return <h3 className="title">{lang('SetAsAdmin')}</h3>;
|
return <h3 className="title">{oldLang('SetAsAdmin')}</h3>;
|
||||||
case HeaderContent.ManageGroupPermissions:
|
case HeaderContent.ManageGroupPermissions:
|
||||||
return <h3 className="title">{lang('ChannelPermissions')}</h3>;
|
return <h3 className="title">{oldLang('ChannelPermissions')}</h3>;
|
||||||
case HeaderContent.ManageGroupRemovedUsers:
|
case HeaderContent.ManageGroupRemovedUsers:
|
||||||
return <h3 className="title">{lang('BlockedUsers')}</h3>;
|
return <h3 className="title">{oldLang('BlockedUsers')}</h3>;
|
||||||
case HeaderContent.ManageChannelRemovedUsers:
|
case HeaderContent.ManageChannelRemovedUsers:
|
||||||
return <h3 className="title">{lang('ChannelBlockedUsers')}</h3>;
|
return <h3 className="title">{oldLang('ChannelBlockedUsers')}</h3>;
|
||||||
case HeaderContent.ManageGroupUserPermissionsCreate:
|
case HeaderContent.ManageGroupUserPermissionsCreate:
|
||||||
return <h3 className="title">{lang('ChannelAddException')}</h3>;
|
return <h3 className="title">{oldLang('ChannelAddException')}</h3>;
|
||||||
case HeaderContent.ManageGroupUserPermissions:
|
case HeaderContent.ManageGroupUserPermissions:
|
||||||
return <h3 className="title">{lang('UserRestrictions')}</h3>;
|
return <h3 className="title">{oldLang('UserRestrictions')}</h3>;
|
||||||
case HeaderContent.ManageInvites:
|
case HeaderContent.ManageInvites:
|
||||||
return <h3 className="title">{lang('lng_group_invite_title')}</h3>;
|
return <h3 className="title">{oldLang('lng_group_invite_title')}</h3>;
|
||||||
case HeaderContent.ManageEditInvite:
|
case HeaderContent.ManageEditInvite:
|
||||||
return <h3 className="title">{isEditingInvite ? lang('EditLink') : lang('NewLink')}</h3>;
|
return <h3 className="title">{isEditingInvite ? oldLang('EditLink') : oldLang('NewLink')}</h3>;
|
||||||
case HeaderContent.ManageInviteInfo:
|
case HeaderContent.ManageInviteInfo:
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h3 className="title">{lang('InviteLink')}</h3>
|
<h3 className="title">{oldLang('InviteLink')}</h3>
|
||||||
<section className="tools">
|
<section className="tools">
|
||||||
{currentInviteInfo && !currentInviteInfo.isRevoked && (
|
{currentInviteInfo && !currentInviteInfo.isRevoked && (
|
||||||
<Button
|
<Button
|
||||||
round
|
round
|
||||||
color="translucent"
|
color="translucent"
|
||||||
size="smaller"
|
size="smaller"
|
||||||
ariaLabel={lang('Edit')}
|
ariaLabel={oldLang('Edit')}
|
||||||
onClick={handleEditInviteClick}
|
onClick={handleEditInviteClick}
|
||||||
>
|
>
|
||||||
<Icon name="edit" />
|
<Icon name="edit" />
|
||||||
@ -387,7 +432,7 @@ const RightHeader: FC<OwnProps & StateProps> = ({
|
|||||||
round
|
round
|
||||||
color="danger"
|
color="danger"
|
||||||
size="smaller"
|
size="smaller"
|
||||||
ariaLabel={lang('Delete')}
|
ariaLabel={oldLang('Delete')}
|
||||||
onClick={openDeleteDialog}
|
onClick={openDeleteDialog}
|
||||||
>
|
>
|
||||||
<Icon name="delete" />
|
<Icon name="delete" />
|
||||||
@ -395,10 +440,10 @@ const RightHeader: FC<OwnProps & StateProps> = ({
|
|||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
isOpen={isDeleteDialogOpen}
|
isOpen={isDeleteDialogOpen}
|
||||||
onClose={closeDeleteDialog}
|
onClose={closeDeleteDialog}
|
||||||
title={lang('DeleteLink')}
|
title={oldLang('DeleteLink')}
|
||||||
text={lang('DeleteLinkHelp')}
|
text={oldLang('DeleteLinkHelp')}
|
||||||
confirmIsDestructive
|
confirmIsDestructive
|
||||||
confirmLabel={lang('Delete')}
|
confirmLabel={oldLang('Delete')}
|
||||||
confirmHandler={handleDeleteInviteClick}
|
confirmHandler={handleDeleteInviteClick}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
@ -407,14 +452,14 @@ const RightHeader: FC<OwnProps & StateProps> = ({
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
case HeaderContent.ManageJoinRequests:
|
case HeaderContent.ManageJoinRequests:
|
||||||
return <h3 className="title">{isChannel ? lang('SubscribeRequests') : lang('MemberRequests')}</h3>;
|
return <h3 className="title">{isChannel ? oldLang('SubscribeRequests') : oldLang('MemberRequests')}</h3>;
|
||||||
case HeaderContent.ManageGroupAddAdmins:
|
case HeaderContent.ManageGroupAddAdmins:
|
||||||
return <h3 className="title">{lang('Channel.Management.AddModerator')}</h3>;
|
return <h3 className="title">{oldLang('Channel.Management.AddModerator')}</h3>;
|
||||||
case HeaderContent.StickerSearch:
|
case HeaderContent.StickerSearch:
|
||||||
return (
|
return (
|
||||||
<SearchInput
|
<SearchInput
|
||||||
value={stickerSearchQuery}
|
value={stickerSearchQuery}
|
||||||
placeholder={lang('SearchStickersHint')}
|
placeholder={oldLang('SearchStickersHint')}
|
||||||
autoFocusSearch
|
autoFocusSearch
|
||||||
onChange={handleStickerSearchQueryChange}
|
onChange={handleStickerSearchQueryChange}
|
||||||
/>
|
/>
|
||||||
@ -423,43 +468,125 @@ const RightHeader: FC<OwnProps & StateProps> = ({
|
|||||||
return (
|
return (
|
||||||
<SearchInput
|
<SearchInput
|
||||||
value={gifSearchQuery}
|
value={gifSearchQuery}
|
||||||
placeholder={lang('SearchGifsTitle')}
|
placeholder={oldLang('SearchGifsTitle')}
|
||||||
autoFocusSearch
|
autoFocusSearch
|
||||||
onChange={handleGifSearchQueryChange}
|
onChange={handleGifSearchQueryChange}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case HeaderContent.Statistics:
|
case HeaderContent.Statistics:
|
||||||
return <h3 className="title">{lang(isChannel ? 'ChannelStats.Title' : 'GroupStats.Title')}</h3>;
|
return <h3 className="title">{oldLang(isChannel ? 'ChannelStats.Title' : 'GroupStats.Title')}</h3>;
|
||||||
case HeaderContent.MessageStatistics:
|
case HeaderContent.MessageStatistics:
|
||||||
return <h3 className="title">{lang('Stats.MessageTitle')}</h3>;
|
return <h3 className="title">{oldLang('Stats.MessageTitle')}</h3>;
|
||||||
case HeaderContent.StoryStatistics:
|
case HeaderContent.StoryStatistics:
|
||||||
return <h3 className="title">{lang('Stats.StoryTitle')}</h3>;
|
return <h3 className="title">{oldLang('Stats.StoryTitle')}</h3>;
|
||||||
case HeaderContent.BoostStatistics:
|
case HeaderContent.BoostStatistics:
|
||||||
return <h3 className="title">{lang('Boosts')}</h3>;
|
return <h3 className="title">{oldLang('Boosts')}</h3>;
|
||||||
case HeaderContent.MonetizationStatistics:
|
case HeaderContent.MonetizationStatistics:
|
||||||
return <h3 className="title">{lang('lng_channel_earn_title')}</h3>;
|
return <h3 className="title">{oldLang('lng_channel_earn_title')}</h3>;
|
||||||
case HeaderContent.SharedMedia:
|
case HeaderContent.SharedMedia:
|
||||||
return <h3 className="title">{lang('SharedMedia')}</h3>;
|
return <h3 className="title">{oldLang('SharedMedia')}</h3>;
|
||||||
case HeaderContent.ManageChannelSubscribers:
|
case HeaderContent.ManageChannelSubscribers:
|
||||||
return <h3 className="title">{lang('ChannelSubscribers')}</h3>;
|
return <h3 className="title">{oldLang('ChannelSubscribers')}</h3>;
|
||||||
case HeaderContent.MemberList:
|
case HeaderContent.MemberList:
|
||||||
case HeaderContent.ManageGroupMembers:
|
case HeaderContent.ManageGroupMembers:
|
||||||
return <h3 className="title">{lang('GroupMembers')}</h3>;
|
return <h3 className="title">{oldLang('GroupMembers')}</h3>;
|
||||||
case HeaderContent.StoryList:
|
case HeaderContent.StoryList:
|
||||||
return <h3 className="title">{lang(isSelf ? 'Settings.MyStories' : 'PeerInfo.PaneStories')}</h3>;
|
return <h3 className="title">{oldLang(isSelf ? 'Settings.MyStories' : 'PeerInfo.PaneStories')}</h3>;
|
||||||
case HeaderContent.SavedDialogs:
|
case HeaderContent.SavedDialogs:
|
||||||
return (
|
return (
|
||||||
<div className="header">
|
<div className="header">
|
||||||
<h3 className="title">{lang('SavedMessagesTab')}</h3>
|
<h3 className="title">{oldLang('SavedMessagesTab')}</h3>
|
||||||
<div className="subtitle">{lang('Chats', foldersChatCount[SAVED_FOLDER_ID])}</div>
|
<div className="subtitle">{oldLang('Chats', foldersChatCount[SAVED_FOLDER_ID])}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
case HeaderContent.ManageReactions:
|
case HeaderContent.ManageReactions:
|
||||||
return <h3 className="title">{lang('Reactions')}</h3>;
|
return <h3 className="title">{oldLang('Reactions')}</h3>;
|
||||||
case HeaderContent.CreateTopic:
|
case HeaderContent.CreateTopic:
|
||||||
return <h3 className="title">{lang('NewTopic')}</h3>;
|
return <h3 className="title">{oldLang('NewTopic')}</h3>;
|
||||||
case HeaderContent.EditTopic:
|
case HeaderContent.EditTopic:
|
||||||
return <h3 className="title">{lang('EditTopic')}</h3>;
|
return <h3 className="title">{oldLang('EditTopic')}</h3>;
|
||||||
|
case HeaderContent.GiftList:
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h3 className="title">{lang('ProfileTabGifts')}</h3>
|
||||||
|
{canUseGiftFilter && (
|
||||||
|
<section className="tools">
|
||||||
|
<DropdownMenu
|
||||||
|
trigger={PrimaryLinkMenuButton}
|
||||||
|
positionX="right"
|
||||||
|
autoClose={false}
|
||||||
|
>
|
||||||
|
<MenuItem
|
||||||
|
icon={giftsSortType === 'byDate' ? 'calendar-filter' : 'cash-circle'}
|
||||||
|
// eslint-disable-next-line react/jsx-no-bind
|
||||||
|
onClick={() => updateGiftProfileFilter(
|
||||||
|
{ filter: { sortType: giftsSortType === 'byDate' ? 'byValue' : 'byDate' } },
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{lang(giftsSortType === 'byDate' ? 'GiftSortByDate' : 'GiftSortByValue')}
|
||||||
|
</MenuItem>
|
||||||
|
|
||||||
|
<MenuSeparator />
|
||||||
|
|
||||||
|
<MenuItem
|
||||||
|
icon={shouldIncludeUnlimitedGifts ? 'check' : 'placeholder'}
|
||||||
|
// eslint-disable-next-line react/jsx-no-bind
|
||||||
|
onClick={() => updateGiftProfileFilter(
|
||||||
|
{ filter: { shouldIncludeUnlimited: !shouldIncludeUnlimitedGifts } },
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{lang('GiftFilterUnlimited')}
|
||||||
|
</MenuItem>
|
||||||
|
|
||||||
|
<MenuItem
|
||||||
|
icon={shouldIncludeLimitedGifts ? 'check' : 'placeholder'}
|
||||||
|
// eslint-disable-next-line react/jsx-no-bind
|
||||||
|
onClick={() => updateGiftProfileFilter(
|
||||||
|
{ filter: { shouldIncludeLimited: !shouldIncludeLimitedGifts } },
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{lang('GiftFilterLimited')}
|
||||||
|
</MenuItem>
|
||||||
|
|
||||||
|
<MenuItem
|
||||||
|
icon={shouldIncludeUniqueGifts ? 'check' : 'placeholder'}
|
||||||
|
// eslint-disable-next-line react/jsx-no-bind
|
||||||
|
onClick={() => updateGiftProfileFilter(
|
||||||
|
{ filter: { shouldIncludeUnique: !shouldIncludeUniqueGifts } },
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{lang('GiftFilterUnique')}
|
||||||
|
</MenuItem>
|
||||||
|
|
||||||
|
{canUseGiftAdminFilter && (
|
||||||
|
<>
|
||||||
|
<MenuSeparator />
|
||||||
|
<MenuItem
|
||||||
|
icon={shouldIncludeDisplayedGifts ? 'check' : 'placeholder'}
|
||||||
|
// eslint-disable-next-line react/jsx-no-bind
|
||||||
|
onClick={() => updateGiftProfileFilter(
|
||||||
|
{ filter: { shouldIncludeDisplayed: !shouldIncludeDisplayedGifts } },
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{lang('GiftFilterDisplayed')}
|
||||||
|
</MenuItem>
|
||||||
|
|
||||||
|
<MenuItem
|
||||||
|
icon={shouldIncludeHiddenGifts ? 'check' : 'placeholder'}
|
||||||
|
// eslint-disable-next-line react/jsx-no-bind
|
||||||
|
onClick={() => updateGiftProfileFilter(
|
||||||
|
{ filter: { shouldIncludeHidden: !shouldIncludeHiddenGifts } },
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{lang('GiftFilterHidden')}
|
||||||
|
</MenuItem>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</DropdownMenu>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -472,7 +599,7 @@ const RightHeader: FC<OwnProps & StateProps> = ({
|
|||||||
round
|
round
|
||||||
color="translucent"
|
color="translucent"
|
||||||
size="smaller"
|
size="smaller"
|
||||||
ariaLabel={lang('AddContact')}
|
ariaLabel={oldLang('AddContact')}
|
||||||
onClick={handleAddContact}
|
onClick={handleAddContact}
|
||||||
>
|
>
|
||||||
<Icon name="add-user" />
|
<Icon name="add-user" />
|
||||||
@ -483,7 +610,7 @@ const RightHeader: FC<OwnProps & StateProps> = ({
|
|||||||
round
|
round
|
||||||
color="translucent"
|
color="translucent"
|
||||||
size="smaller"
|
size="smaller"
|
||||||
ariaLabel={lang('Edit')}
|
ariaLabel={oldLang('Edit')}
|
||||||
onClick={handleToggleManagement}
|
onClick={handleToggleManagement}
|
||||||
>
|
>
|
||||||
<Icon name="edit" />
|
<Icon name="edit" />
|
||||||
@ -494,7 +621,7 @@ const RightHeader: FC<OwnProps & StateProps> = ({
|
|||||||
round
|
round
|
||||||
color="translucent"
|
color="translucent"
|
||||||
size="smaller"
|
size="smaller"
|
||||||
ariaLabel={lang('Edit')}
|
ariaLabel={oldLang('Edit')}
|
||||||
onClick={handleToggleManagement}
|
onClick={handleToggleManagement}
|
||||||
>
|
>
|
||||||
<Icon name="edit" />
|
<Icon name="edit" />
|
||||||
@ -505,7 +632,7 @@ const RightHeader: FC<OwnProps & StateProps> = ({
|
|||||||
round
|
round
|
||||||
color="translucent"
|
color="translucent"
|
||||||
size="smaller"
|
size="smaller"
|
||||||
ariaLabel={lang('EditTopic')}
|
ariaLabel={oldLang('EditTopic')}
|
||||||
onClick={toggleEditTopic}
|
onClick={toggleEditTopic}
|
||||||
>
|
>
|
||||||
<Icon name="edit" />
|
<Icon name="edit" />
|
||||||
@ -516,7 +643,7 @@ const RightHeader: FC<OwnProps & StateProps> = ({
|
|||||||
round
|
round
|
||||||
color="translucent"
|
color="translucent"
|
||||||
size="smaller"
|
size="smaller"
|
||||||
ariaLabel={lang('Statistics')}
|
ariaLabel={oldLang('Statistics')}
|
||||||
onClick={handleToggleStatistics}
|
onClick={handleToggleStatistics}
|
||||||
>
|
>
|
||||||
<Icon name="stats" />
|
<Icon name="stats" />
|
||||||
@ -531,6 +658,7 @@ const RightHeader: FC<OwnProps & StateProps> = ({
|
|||||||
const isBackButton = isMobile || (
|
const isBackButton = isMobile || (
|
||||||
!isSavedMessages && (
|
!isSavedMessages && (
|
||||||
contentKey === HeaderContent.SharedMedia
|
contentKey === HeaderContent.SharedMedia
|
||||||
|
|| contentKey === HeaderContent.GiftList
|
||||||
|| contentKey === HeaderContent.MemberList
|
|| contentKey === HeaderContent.MemberList
|
||||||
|| contentKey === HeaderContent.StoryList
|
|| contentKey === HeaderContent.StoryList
|
||||||
|| contentKey === HeaderContent.AddingMembers
|
|| contentKey === HeaderContent.AddingMembers
|
||||||
@ -558,7 +686,7 @@ const RightHeader: FC<OwnProps & StateProps> = ({
|
|||||||
color="translucent"
|
color="translucent"
|
||||||
size="smaller"
|
size="smaller"
|
||||||
onClick={handleClose}
|
onClick={handleClose}
|
||||||
ariaLabel={isBackButton ? lang('Common.Back') : lang('Common.Close')}
|
ariaLabel={isBackButton ? oldLang('Common.Back') : oldLang('Common.Close')}
|
||||||
>
|
>
|
||||||
<div className={buttonClassName} />
|
<div className={buttonClassName} />
|
||||||
</Button>
|
</Button>
|
||||||
@ -599,6 +727,10 @@ export default withGlobal<OwnProps>(
|
|||||||
const currentInviteInfo = chatId
|
const currentInviteInfo = chatId
|
||||||
? tabState.management.byChatId[chatId]?.inviteInfo?.invite : undefined;
|
? tabState.management.byChatId[chatId]?.inviteInfo?.invite : undefined;
|
||||||
|
|
||||||
|
const giftProfileFilter = tabState.savedGifts.filter;
|
||||||
|
const canUseGiftFilter = chatId ? selectCanUseGiftProfileFilter(global, chatId) : false;
|
||||||
|
const canUseGiftAdminFilter = chatId ? selectCanUseGiftProfileAdminFilter(global, chatId) : false;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
canManage,
|
canManage,
|
||||||
canAddContact,
|
canAddContact,
|
||||||
@ -616,6 +748,9 @@ export default withGlobal<OwnProps>(
|
|||||||
isSavedMessages,
|
isSavedMessages,
|
||||||
shouldSkipHistoryAnimations: tabState.shouldSkipHistoryAnimations,
|
shouldSkipHistoryAnimations: tabState.shouldSkipHistoryAnimations,
|
||||||
canEditBot,
|
canEditBot,
|
||||||
|
giftProfileFilter,
|
||||||
|
canUseGiftFilter,
|
||||||
|
canUseGiftAdminFilter,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
)(RightHeader);
|
)(RightHeader);
|
||||||
|
|||||||
@ -121,6 +121,8 @@ function getStateFromTabType(tabType: ProfileTabType) {
|
|||||||
switch (tabType) {
|
switch (tabType) {
|
||||||
case 'members':
|
case 'members':
|
||||||
return ProfileState.MemberList;
|
return ProfileState.MemberList;
|
||||||
|
case 'gifts':
|
||||||
|
return ProfileState.GiftList;
|
||||||
case 'stories':
|
case 'stories':
|
||||||
return ProfileState.StoryList;
|
return ProfileState.StoryList;
|
||||||
case 'dialogs':
|
case 'dialogs':
|
||||||
|
|||||||
@ -24,6 +24,7 @@ type OwnProps = {
|
|||||||
onTransitionEnd?: NoneToVoidFunction;
|
onTransitionEnd?: NoneToVoidFunction;
|
||||||
onMouseEnterBackdrop?: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
|
onMouseEnterBackdrop?: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
autoClose?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DropdownMenu: FC<OwnProps> = ({
|
const DropdownMenu: FC<OwnProps> = ({
|
||||||
@ -41,6 +42,7 @@ const DropdownMenu: FC<OwnProps> = ({
|
|||||||
onTransitionEnd,
|
onTransitionEnd,
|
||||||
onMouseEnterBackdrop,
|
onMouseEnterBackdrop,
|
||||||
onHide,
|
onHide,
|
||||||
|
autoClose = true,
|
||||||
}) => {
|
}) => {
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
const menuRef = useRef<HTMLDivElement>(null);
|
const menuRef = useRef<HTMLDivElement>(null);
|
||||||
@ -110,7 +112,7 @@ const DropdownMenu: FC<OwnProps> = ({
|
|||||||
positionX={positionX}
|
positionX={positionX}
|
||||||
positionY={positionY}
|
positionY={positionY}
|
||||||
footer={footer}
|
footer={footer}
|
||||||
autoClose
|
autoClose={autoClose}
|
||||||
onClose={handleClose}
|
onClose={handleClose}
|
||||||
onCloseAnimationEnd={onHide}
|
onCloseAnimationEnd={onHide}
|
||||||
onMouseEnterBackdrop={onMouseEnterBackdrop}
|
onMouseEnterBackdrop={onMouseEnterBackdrop}
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
import type {
|
import type {
|
||||||
ApiLimitType, ApiLimitTypeForPromo, ApiPremiumSection, ApiReactionEmoji,
|
ApiLimitType, ApiLimitTypeForPromo, ApiPremiumSection, ApiReactionEmoji,
|
||||||
} from './api/types';
|
} from './api/types';
|
||||||
|
import type {
|
||||||
|
GiftProfileFilterOptions,
|
||||||
|
} from './types';
|
||||||
|
|
||||||
export const APP_CODE_NAME = 'A';
|
export const APP_CODE_NAME = 'A';
|
||||||
export const APP_NAME = process.env.APP_NAME || `Telegram Web ${APP_CODE_NAME}`;
|
export const APP_NAME = process.env.APP_NAME || `Telegram Web ${APP_CODE_NAME}`;
|
||||||
@ -427,3 +430,12 @@ export const PREMIUM_LIMITS_ORDER: ApiLimitTypeForPromo[] = [
|
|||||||
'dialogFiltersChats',
|
'dialogFiltersChats',
|
||||||
'recommendedChannels',
|
'recommendedChannels',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const DEFAULT_GIFT_PROFILE_FILTER_OPTIONS : GiftProfileFilterOptions = {
|
||||||
|
sortType: 'byDate',
|
||||||
|
shouldIncludeUnlimited: true,
|
||||||
|
shouldIncludeLimited: true,
|
||||||
|
shouldIncludeUnique: true,
|
||||||
|
shouldIncludeDisplayed: true,
|
||||||
|
shouldIncludeHidden: true,
|
||||||
|
} as const;
|
||||||
|
|||||||
@ -15,7 +15,10 @@ import {
|
|||||||
} from '../../reducers';
|
} from '../../reducers';
|
||||||
import { updateTabState } from '../../reducers/tabs';
|
import { updateTabState } from '../../reducers/tabs';
|
||||||
import {
|
import {
|
||||||
|
selectGiftProfileFilter,
|
||||||
selectPeer,
|
selectPeer,
|
||||||
|
selectPeerSavedGifts,
|
||||||
|
selectTabState,
|
||||||
} from '../../selectors';
|
} from '../../selectors';
|
||||||
|
|
||||||
addActionHandler('loadStarStatus', async (global): Promise<void> => {
|
addActionHandler('loadStarStatus', async (global): Promise<void> => {
|
||||||
@ -134,12 +137,14 @@ addActionHandler('loadStarGifts', async (global): Promise<void> => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
addActionHandler('loadPeerSavedGifts', async (global, actions, payload): Promise<void> => {
|
addActionHandler('loadPeerSavedGifts', async (global, actions, payload): Promise<void> => {
|
||||||
const { peerId, shouldRefresh } = payload;
|
const {
|
||||||
|
peerId, shouldRefresh, tabId = getCurrentTabId(),
|
||||||
|
} = payload;
|
||||||
|
|
||||||
const peer = selectPeer(global, peerId);
|
const peer = selectPeer(global, peerId);
|
||||||
if (!peer) return;
|
if (!peer) return;
|
||||||
|
|
||||||
const currentGifts = global.peers.giftsById[peerId];
|
const currentGifts = selectPeerSavedGifts(global, peerId, tabId);
|
||||||
const localNextOffset = currentGifts?.nextOffset;
|
const localNextOffset = currentGifts?.nextOffset;
|
||||||
|
|
||||||
if (!shouldRefresh && currentGifts && !localNextOffset) return; // Already loaded all
|
if (!shouldRefresh && currentGifts && !localNextOffset) return; // Already loaded all
|
||||||
@ -147,6 +152,7 @@ addActionHandler('loadPeerSavedGifts', async (global, actions, payload): Promise
|
|||||||
const result = await callApi('fetchSavedStarGifts', {
|
const result = await callApi('fetchSavedStarGifts', {
|
||||||
peer,
|
peer,
|
||||||
offset: !shouldRefresh ? localNextOffset : '',
|
offset: !shouldRefresh ? localNextOffset : '',
|
||||||
|
filter: selectGiftProfileFilter(global, peerId, tabId),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
@ -157,7 +163,7 @@ addActionHandler('loadPeerSavedGifts', async (global, actions, payload): Promise
|
|||||||
|
|
||||||
const newGifts = currentGifts && !shouldRefresh ? currentGifts.gifts.concat(result.gifts) : result.gifts;
|
const newGifts = currentGifts && !shouldRefresh ? currentGifts.gifts.concat(result.gifts) : result.gifts;
|
||||||
|
|
||||||
global = replacePeerSavedGifts(global, peerId, newGifts, result.nextOffset);
|
global = replacePeerSavedGifts(global, peerId, newGifts, result.nextOffset, tabId);
|
||||||
setGlobal(global);
|
setGlobal(global);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -216,14 +222,14 @@ addActionHandler('fulfillStarsSubscription', async (global, actions, payload): P
|
|||||||
});
|
});
|
||||||
|
|
||||||
addActionHandler('changeGiftVisibility', async (global, actions, payload): Promise<void> => {
|
addActionHandler('changeGiftVisibility', async (global, actions, payload): Promise<void> => {
|
||||||
const { gift, shouldUnsave } = payload;
|
const { gift, shouldUnsave, tabId = getCurrentTabId() } = payload;
|
||||||
|
|
||||||
const peerId = gift.type === 'user' ? global.currentUserId! : gift.chatId;
|
const peerId = gift.type === 'user' ? global.currentUserId! : gift.chatId;
|
||||||
|
|
||||||
const requestInputGift = getRequestInputSavedStarGift(global, gift);
|
const requestInputGift = getRequestInputSavedStarGift(global, gift);
|
||||||
if (!requestInputGift) return;
|
if (!requestInputGift) return;
|
||||||
|
|
||||||
const oldGifts = global.peers.giftsById[peerId];
|
const oldGifts = selectTabState(global, tabId).savedGifts.giftsByPeerId[peerId];
|
||||||
if (oldGifts?.gifts?.length) {
|
if (oldGifts?.gifts?.length) {
|
||||||
const newGifts = oldGifts.gifts.map((g) => {
|
const newGifts = oldGifts.gifts.map((g) => {
|
||||||
if (g.inputGift && areInputSavedGiftsEqual(g.inputGift, gift)) {
|
if (g.inputGift && areInputSavedGiftsEqual(g.inputGift, gift)) {
|
||||||
@ -234,7 +240,7 @@ addActionHandler('changeGiftVisibility', async (global, actions, payload): Promi
|
|||||||
}
|
}
|
||||||
return g;
|
return g;
|
||||||
});
|
});
|
||||||
global = replacePeerSavedGifts(global, peerId, newGifts, oldGifts.nextOffset);
|
global = replacePeerSavedGifts(global, peerId, newGifts, oldGifts.nextOffset, tabId);
|
||||||
setGlobal(global);
|
setGlobal(global);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,13 +251,17 @@ addActionHandler('changeGiftVisibility', async (global, actions, payload): Promi
|
|||||||
global = getGlobal();
|
global = getGlobal();
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
global = replacePeerSavedGifts(global, peerId, oldGifts.gifts, oldGifts.nextOffset);
|
global = replacePeerSavedGifts(global, peerId, oldGifts.gifts, oldGifts.nextOffset, tabId);
|
||||||
setGlobal(global);
|
setGlobal(global);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reload gift list to avoid issues with pagination
|
// Reload gift list to avoid issues with pagination
|
||||||
actions.loadPeerSavedGifts({ peerId, shouldRefresh: true });
|
Object.values(global.byTabId).forEach((tabState) => {
|
||||||
|
if (selectPeerSavedGifts(global, peerId, tabId)) {
|
||||||
|
actions.loadPeerSavedGifts({ peerId, shouldRefresh: true, tabId: tabState.id });
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
addActionHandler('convertGiftToStars', async (global, actions, payload): Promise<void> => {
|
addActionHandler('convertGiftToStars', async (global, actions, payload): Promise<void> => {
|
||||||
@ -268,7 +278,12 @@ addActionHandler('convertGiftToStars', async (global, actions, payload): Promise
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
actions.loadPeerSavedGifts({ peerId: global.currentUserId!, shouldRefresh: true });
|
const peerId = gift.type === 'user' ? global.currentUserId! : gift.chatId;
|
||||||
|
Object.values(global.byTabId).forEach((tabState) => {
|
||||||
|
if (selectPeerSavedGifts(global, peerId, tabId)) {
|
||||||
|
actions.loadPeerSavedGifts({ peerId, shouldRefresh: true, tabId: tabState.id });
|
||||||
|
}
|
||||||
|
});
|
||||||
actions.openStarsBalanceModal({ tabId });
|
actions.openStarsBalanceModal({ tabId });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import type { ActionReturnType } from '../../types';
|
import type { ActionReturnType } from '../../types';
|
||||||
|
|
||||||
|
import { DEFAULT_GIFT_PROFILE_FILTER_OPTIONS } from '../../../config';
|
||||||
import { getCurrentTabId } from '../../../util/establishMultitabRole';
|
import { getCurrentTabId } from '../../../util/establishMultitabRole';
|
||||||
import { addActionHandler } from '../../index';
|
import { addActionHandler } from '../../index';
|
||||||
import {
|
import {
|
||||||
@ -65,3 +66,55 @@ addActionHandler('closeGiftCodeModal', (global, actions, payload): ActionReturnT
|
|||||||
giftCodeModal: undefined,
|
giftCodeModal: undefined,
|
||||||
}, tabId);
|
}, tabId);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addActionHandler('updateGiftProfileFilter', (global, actions, payload): ActionReturnType => {
|
||||||
|
const { filter, tabId = getCurrentTabId() } = payload || {};
|
||||||
|
const tabState = selectTabState(global, tabId);
|
||||||
|
|
||||||
|
const prevFilter = tabState.savedGifts.filter;
|
||||||
|
let updatedFilter = {
|
||||||
|
...prevFilter,
|
||||||
|
...filter,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!updatedFilter.shouldIncludeUnlimited
|
||||||
|
&& !updatedFilter.shouldIncludeLimited
|
||||||
|
&& !updatedFilter.shouldIncludeUnique) {
|
||||||
|
updatedFilter = {
|
||||||
|
...prevFilter,
|
||||||
|
shouldIncludeUnlimited: true,
|
||||||
|
shouldIncludeLimited: true,
|
||||||
|
shouldIncludeUnique: true,
|
||||||
|
...filter,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!updatedFilter.shouldIncludeDisplayed && !updatedFilter.shouldIncludeHidden) {
|
||||||
|
updatedFilter = {
|
||||||
|
...prevFilter,
|
||||||
|
shouldIncludeDisplayed: true,
|
||||||
|
shouldIncludeHidden: true,
|
||||||
|
...filter,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return updateTabState(global, {
|
||||||
|
savedGifts: {
|
||||||
|
giftsByPeerId: {},
|
||||||
|
filter: updatedFilter,
|
||||||
|
},
|
||||||
|
}, tabId);
|
||||||
|
});
|
||||||
|
|
||||||
|
addActionHandler('resetGiftProfileFilter', (global, actions, payload): ActionReturnType => {
|
||||||
|
const { tabId = getCurrentTabId() } = payload || {};
|
||||||
|
|
||||||
|
return updateTabState(global, {
|
||||||
|
savedGifts: {
|
||||||
|
giftsByPeerId: {},
|
||||||
|
filter: {
|
||||||
|
...DEFAULT_GIFT_PROFILE_FILTER_OPTIONS,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, tabId);
|
||||||
|
});
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { NewChatMembersProgress } from '../types';
|
|||||||
import {
|
import {
|
||||||
ANIMATION_LEVEL_DEFAULT,
|
ANIMATION_LEVEL_DEFAULT,
|
||||||
DARK_THEME_PATTERN_COLOR,
|
DARK_THEME_PATTERN_COLOR,
|
||||||
|
DEFAULT_GIFT_PROFILE_FILTER_OPTIONS,
|
||||||
DEFAULT_MESSAGE_TEXT_SIZE_PX,
|
DEFAULT_MESSAGE_TEXT_SIZE_PX,
|
||||||
DEFAULT_PATTERN_COLOR,
|
DEFAULT_PATTERN_COLOR,
|
||||||
DEFAULT_PLAYBACK_RATE,
|
DEFAULT_PLAYBACK_RATE,
|
||||||
@ -106,7 +107,6 @@ export const INITIAL_GLOBAL_STATE: GlobalState = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
peers: {
|
peers: {
|
||||||
giftsById: {},
|
|
||||||
profilePhotosById: {},
|
profilePhotosById: {},
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -365,6 +365,13 @@ export const INITIAL_TAB_STATE: TabState = {
|
|||||||
byChatId: {},
|
byChatId: {},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
savedGifts: {
|
||||||
|
filter: {
|
||||||
|
...DEFAULT_GIFT_PROFILE_FILTER_OPTIONS,
|
||||||
|
},
|
||||||
|
giftsByPeerId: {},
|
||||||
|
},
|
||||||
|
|
||||||
storyViewer: {
|
storyViewer: {
|
||||||
isMuted: true,
|
isMuted: true,
|
||||||
isRibbonShown: false,
|
isRibbonShown: false,
|
||||||
|
|||||||
@ -329,20 +329,20 @@ export function replacePeerSavedGifts<T extends GlobalState>(
|
|||||||
peerId: string,
|
peerId: string,
|
||||||
gifts: ApiSavedStarGift[],
|
gifts: ApiSavedStarGift[],
|
||||||
nextOffset?: string,
|
nextOffset?: string,
|
||||||
|
...[tabId = getCurrentTabId()]: TabArgs<T>
|
||||||
): T {
|
): T {
|
||||||
global = {
|
const tabState = selectTabState(global, tabId);
|
||||||
...global,
|
|
||||||
peers: {
|
return updateTabState(global, {
|
||||||
...global.peers,
|
savedGifts: {
|
||||||
giftsById: {
|
...tabState.savedGifts,
|
||||||
...global.peers.giftsById,
|
giftsByPeerId: {
|
||||||
|
...tabState.savedGifts.giftsByPeerId,
|
||||||
[peerId]: {
|
[peerId]: {
|
||||||
gifts,
|
gifts,
|
||||||
nextOffset,
|
nextOffset,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
}, tabId);
|
||||||
|
|
||||||
return global;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,12 @@
|
|||||||
import type { GlobalState, TabArgs } from '../types';
|
import type { GlobalState, TabArgs } from '../types';
|
||||||
|
|
||||||
|
import { DEFAULT_GIFT_PROFILE_FILTER_OPTIONS } from '../../config';
|
||||||
|
import arePropsShallowEqual from '../../util/arePropsShallowEqual';
|
||||||
import { getCurrentTabId } from '../../util/establishMultitabRole';
|
import { getCurrentTabId } from '../../util/establishMultitabRole';
|
||||||
|
import {
|
||||||
|
getHasAdminRight, isChatAdmin, isChatChannel,
|
||||||
|
} from '../helpers';
|
||||||
|
import { selectChat } from './chats';
|
||||||
import { selectTabState } from './tabs';
|
import { selectTabState } from './tabs';
|
||||||
|
|
||||||
export function selectPaymentInputInvoice<T extends GlobalState>(
|
export function selectPaymentInputInvoice<T extends GlobalState>(
|
||||||
@ -58,3 +64,32 @@ export function selectSmartGlocalCredentials<T extends GlobalState>(
|
|||||||
) {
|
) {
|
||||||
return selectTabState(global, tabId).payment.smartGlocalCredentials;
|
return selectTabState(global, tabId).payment.smartGlocalCredentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function selectCanUseGiftProfileAdminFilter<T extends GlobalState>(
|
||||||
|
global: T, peerId: string,
|
||||||
|
) {
|
||||||
|
const chat = selectChat(global, peerId);
|
||||||
|
return chat && isChatChannel(chat) && isChatAdmin(chat) && getHasAdminRight(chat, 'postMessages');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectCanUseGiftProfileFilter<T extends GlobalState>(
|
||||||
|
global: T, peerId: string,
|
||||||
|
) {
|
||||||
|
const chat = selectChat(global, peerId);
|
||||||
|
return chat && isChatChannel(chat);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectGiftProfileFilter<T extends GlobalState>(
|
||||||
|
global: T,
|
||||||
|
peerId: string,
|
||||||
|
...[tabId = getCurrentTabId()]: TabArgs<T>
|
||||||
|
) {
|
||||||
|
return selectCanUseGiftProfileFilter(global, peerId) ? selectTabState(global, tabId).savedGifts.filter : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectIsGiftProfileFilterDefault<T extends GlobalState>(
|
||||||
|
global: T,
|
||||||
|
...[tabId = getCurrentTabId()]: TabArgs<T>
|
||||||
|
) {
|
||||||
|
return arePropsShallowEqual(selectTabState(global, tabId).savedGifts.filter, DEFAULT_GIFT_PROFILE_FILTER_OPTIONS);
|
||||||
|
}
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
import type { ApiPeer } from '../../api/types';
|
import type { ApiPeer, ApiSavedGifts } from '../../api/types';
|
||||||
import type { GlobalState } from '../types';
|
import type { GlobalState, TabArgs } from '../types';
|
||||||
|
|
||||||
import { SERVICE_NOTIFICATIONS_USER_ID } from '../../config';
|
import { SERVICE_NOTIFICATIONS_USER_ID } from '../../config';
|
||||||
|
import { getCurrentTabId } from '../../util/establishMultitabRole';
|
||||||
import { selectChat, selectChatFullInfo } from './chats';
|
import { selectChat, selectChatFullInfo } from './chats';
|
||||||
|
import { selectTabState } from './tabs';
|
||||||
import { selectBot, selectIsPremiumPurchaseBlocked, selectUser } from './users';
|
import { selectBot, selectIsPremiumPurchaseBlocked, selectUser } from './users';
|
||||||
|
|
||||||
export function selectPeer<T extends GlobalState>(global: T, peerId: string): ApiPeer | undefined {
|
export function selectPeer<T extends GlobalState>(global: T, peerId: string): ApiPeer | undefined {
|
||||||
@ -22,3 +24,11 @@ export function selectCanGift<T extends GlobalState>(global: T, peerId: string)
|
|||||||
return Boolean(!selectIsPremiumPurchaseBlocked(global) && !bot && peerId !== SERVICE_NOTIFICATIONS_USER_ID
|
return Boolean(!selectIsPremiumPurchaseBlocked(global) && !bot && peerId !== SERVICE_NOTIFICATIONS_USER_ID
|
||||||
&& areStarGiftsAvailable);
|
&& areStarGiftsAvailable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function selectPeerSavedGifts<T extends GlobalState>(
|
||||||
|
global: T,
|
||||||
|
peerId: string,
|
||||||
|
...[tabId = getCurrentTabId()]: TabArgs<T>
|
||||||
|
) : ApiSavedGifts {
|
||||||
|
return selectTabState(global, tabId).savedGifts.giftsByPeerId[peerId];
|
||||||
|
}
|
||||||
|
|||||||
@ -59,6 +59,7 @@ import type {
|
|||||||
CallSound,
|
CallSound,
|
||||||
ChatListType,
|
ChatListType,
|
||||||
ConfettiParams,
|
ConfettiParams,
|
||||||
|
GiftProfileFilterOptions,
|
||||||
GlobalSearchContent,
|
GlobalSearchContent,
|
||||||
IAlbum,
|
IAlbum,
|
||||||
IAnchorPosition,
|
IAnchorPosition,
|
||||||
@ -2341,11 +2342,11 @@ export interface ActionPayloads {
|
|||||||
loadPeerSavedGifts: {
|
loadPeerSavedGifts: {
|
||||||
peerId: string;
|
peerId: string;
|
||||||
shouldRefresh?: boolean;
|
shouldRefresh?: boolean;
|
||||||
};
|
} & WithTabId;
|
||||||
changeGiftVisibility: {
|
changeGiftVisibility: {
|
||||||
gift: ApiInputSavedStarGift;
|
gift: ApiInputSavedStarGift;
|
||||||
shouldUnsave?: boolean;
|
shouldUnsave?: boolean;
|
||||||
};
|
} & WithTabId;
|
||||||
convertGiftToStars: {
|
convertGiftToStars: {
|
||||||
gift: ApiInputSavedStarGift;
|
gift: ApiInputSavedStarGift;
|
||||||
} & WithTabId;
|
} & WithTabId;
|
||||||
@ -2369,6 +2370,11 @@ export interface ActionPayloads {
|
|||||||
} & WithTabId;
|
} & WithTabId;
|
||||||
closeSuggestedStatusModal: WithTabId | undefined;
|
closeSuggestedStatusModal: WithTabId | undefined;
|
||||||
|
|
||||||
|
updateGiftProfileFilter: {
|
||||||
|
filter: Partial<GiftProfileFilterOptions>;
|
||||||
|
} & WithTabId;
|
||||||
|
resetGiftProfileFilter: WithTabId | undefined;
|
||||||
|
|
||||||
// Invoice
|
// Invoice
|
||||||
openInvoice: Exclude<ApiInputInvoice, ApiInputInvoiceStarGift> & WithTabId;
|
openInvoice: Exclude<ApiInputInvoice, ApiInputInvoiceStarGift> & WithTabId;
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,6 @@ import type {
|
|||||||
ApiQuickReply,
|
ApiQuickReply,
|
||||||
ApiReaction,
|
ApiReaction,
|
||||||
ApiReactionKey,
|
ApiReactionKey,
|
||||||
ApiSavedGifts,
|
|
||||||
ApiSavedReactionTag,
|
ApiSavedReactionTag,
|
||||||
ApiSession,
|
ApiSession,
|
||||||
ApiSponsoredMessage,
|
ApiSponsoredMessage,
|
||||||
@ -176,7 +175,6 @@ export type GlobalState = {
|
|||||||
|
|
||||||
peers: {
|
peers: {
|
||||||
profilePhotosById: Record<string, ApiPeerPhotos>;
|
profilePhotosById: Record<string, ApiPeerPhotos>;
|
||||||
giftsById: Record<string, ApiSavedGifts>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
chats: {
|
chats: {
|
||||||
|
|||||||
@ -32,6 +32,7 @@ import type {
|
|||||||
ApiPremiumSection,
|
ApiPremiumSection,
|
||||||
ApiReactionWithPaid,
|
ApiReactionWithPaid,
|
||||||
ApiReceiptRegular,
|
ApiReceiptRegular,
|
||||||
|
ApiSavedGifts,
|
||||||
ApiSavedStarGift,
|
ApiSavedStarGift,
|
||||||
ApiStarGift,
|
ApiStarGift,
|
||||||
ApiStarGiftAttribute,
|
ApiStarGiftAttribute,
|
||||||
@ -57,6 +58,7 @@ import type {
|
|||||||
ChatRequestedTranslations,
|
ChatRequestedTranslations,
|
||||||
ConfettiStyle,
|
ConfettiStyle,
|
||||||
FocusDirection,
|
FocusDirection,
|
||||||
|
GiftProfileFilterOptions,
|
||||||
GlobalSearchContent,
|
GlobalSearchContent,
|
||||||
IAlbum,
|
IAlbum,
|
||||||
IAnchorPosition,
|
IAnchorPosition,
|
||||||
@ -202,6 +204,11 @@ export type TabState = {
|
|||||||
byUsername: Record<string, false | InlineBotSettings>;
|
byUsername: Record<string, false | InlineBotSettings>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
savedGifts: {
|
||||||
|
giftsByPeerId: Record<string, ApiSavedGifts>;
|
||||||
|
filter: GiftProfileFilterOptions;
|
||||||
|
};
|
||||||
|
|
||||||
globalSearch: {
|
globalSearch: {
|
||||||
query?: string;
|
query?: string;
|
||||||
minDate?: number;
|
minDate?: number;
|
||||||
|
|||||||
@ -417,6 +417,7 @@ export enum ProfileState {
|
|||||||
Profile,
|
Profile,
|
||||||
SharedMedia,
|
SharedMedia,
|
||||||
MemberList,
|
MemberList,
|
||||||
|
GiftList,
|
||||||
StoryList,
|
StoryList,
|
||||||
SavedDialogs,
|
SavedDialogs,
|
||||||
}
|
}
|
||||||
@ -657,3 +658,12 @@ export type CallSound = (
|
|||||||
export type BotAppPermissions = {
|
export type BotAppPermissions = {
|
||||||
geolocation?: boolean;
|
geolocation?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type GiftProfileFilterOptions = {
|
||||||
|
sortType: 'byDate' | 'byValue';
|
||||||
|
shouldIncludeUnlimited: boolean;
|
||||||
|
shouldIncludeLimited: boolean;
|
||||||
|
shouldIncludeUnique: boolean;
|
||||||
|
shouldIncludeDisplayed: boolean;
|
||||||
|
shouldIncludeHidden: boolean;
|
||||||
|
};
|
||||||
|
|||||||
9
src/types/language.d.ts
vendored
9
src/types/language.d.ts
vendored
@ -1306,6 +1306,15 @@ export interface LangPair {
|
|||||||
'ViewButtonGiftUnique': undefined;
|
'ViewButtonGiftUnique': undefined;
|
||||||
'AuthContinueOnThisLanguage': undefined;
|
'AuthContinueOnThisLanguage': undefined;
|
||||||
'Share': undefined;
|
'Share': undefined;
|
||||||
|
'GiftSortByDate': undefined;
|
||||||
|
'GiftSortByValue': undefined;
|
||||||
|
'GiftFilterUnlimited': undefined;
|
||||||
|
'GiftFilterLimited': undefined;
|
||||||
|
'GiftFilterUnique': undefined;
|
||||||
|
'GiftFilterDisplayed': undefined;
|
||||||
|
'GiftFilterHidden': undefined;
|
||||||
|
'GiftSearchEmpty': undefined;
|
||||||
|
'GiftSearchReset': undefined;
|
||||||
'CheckPasswordTitle': undefined;
|
'CheckPasswordTitle': undefined;
|
||||||
'CheckPasswordPlaceholder': undefined;
|
'CheckPasswordPlaceholder': undefined;
|
||||||
'CheckPasswordDescription': undefined;
|
'CheckPasswordDescription': undefined;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user