Gifts: Support remove gift message (#6404)
Co-authored-by: zubiden <19638254+zubiden@users.noreply.github.com>
This commit is contained in:
parent
f8c61646b1
commit
cf8a933b4c
@ -158,7 +158,7 @@ export function buildApiStarGiftAttribute(attribute: GramJs.TypeStarGiftAttribut
|
||||
export function buildApiSavedStarGift(userStarGift: GramJs.SavedStarGift, peerId: string): ApiSavedStarGift {
|
||||
const {
|
||||
gift, date, convertStars, fromId, message, msgId, nameHidden, unsaved, upgradeStars, transferStars, canUpgrade,
|
||||
savedId, canExportAt, pinnedToTop, canResellAt, canTransferAt, prepaidUpgradeHash,
|
||||
savedId, canExportAt, pinnedToTop, canResellAt, canTransferAt, prepaidUpgradeHash, dropOriginalDetailsStars,
|
||||
} = userStarGift;
|
||||
|
||||
const inputGift: ApiInputSavedStarGift | undefined = savedId && peerId
|
||||
@ -183,6 +183,7 @@ export function buildApiSavedStarGift(userStarGift: GramJs.SavedStarGift, peerId
|
||||
canResellAt,
|
||||
canTransferAt,
|
||||
isPinned: pinnedToTop,
|
||||
dropOriginalDetailsStars: dropOriginalDetailsStars !== undefined ? toJSNumber(dropOriginalDetailsStars) : undefined,
|
||||
prepaidUpgradeHash,
|
||||
};
|
||||
}
|
||||
|
||||
@ -422,7 +422,7 @@ export function buildApiMessageAction(action: GramJs.TypeMessageAction): ApiMess
|
||||
if (action instanceof GramJs.MessageActionStarGiftUnique) {
|
||||
const {
|
||||
upgrade, transferred, saved, refunded, gift, canExportAt, transferStars, fromId, peer, savedId,
|
||||
resaleAmount, prepaidUpgrade,
|
||||
resaleAmount, prepaidUpgrade, dropOriginalDetailsStars,
|
||||
} = action;
|
||||
|
||||
const starGift = buildApiStarGift(gift);
|
||||
@ -443,6 +443,9 @@ export function buildApiMessageAction(action: GramJs.TypeMessageAction): ApiMess
|
||||
peerId: peer && getApiChatIdFromMtpPeer(peer),
|
||||
savedId: savedId !== undefined ? buildApiPeerId(savedId, 'user') : undefined,
|
||||
resaleAmount: resaleAmount ? buildApiCurrencyAmount(resaleAmount) : undefined,
|
||||
dropOriginalDetailsStars: dropOriginalDetailsStars !== undefined
|
||||
? toJSNumber(dropOriginalDetailsStars)
|
||||
: undefined,
|
||||
};
|
||||
}
|
||||
if (action instanceof GramJs.MessageActionPaidMessagesPrice) {
|
||||
|
||||
@ -553,7 +553,7 @@ export function buildApiStarsTransaction(transaction: GramJs.StarsTransaction):
|
||||
const {
|
||||
date, id, peer, amount, description, photo, title, refund, extendedMedia, failed, msgId, pending, gift, reaction,
|
||||
subscriptionPeriod, stargift, giveawayPostId, starrefCommissionPermille, stargiftUpgrade, paidMessages,
|
||||
stargiftResale, postsSearch, stargiftPrepaidUpgrade,
|
||||
stargiftResale, postsSearch, stargiftPrepaidUpgrade, stargiftDropOriginalDetails,
|
||||
} = transaction;
|
||||
|
||||
if (photo) {
|
||||
@ -593,6 +593,7 @@ export function buildApiStarsTransaction(transaction: GramJs.StarsTransaction):
|
||||
isGiftResale: stargiftResale,
|
||||
paidMessages,
|
||||
isPostsSearch: postsSearch,
|
||||
isDropOriginalDetails: stargiftDropOriginalDetails,
|
||||
isPrepaidUpgrade: stargiftPrepaidUpgrade,
|
||||
};
|
||||
}
|
||||
|
||||
@ -781,6 +781,12 @@ export function buildInputInvoice(invoice: ApiRequestInputInvoice) {
|
||||
});
|
||||
}
|
||||
|
||||
case 'stargiftDropOriginalDetails': {
|
||||
return new GramJs.InputInvoiceStarGiftDropOriginalDetails({
|
||||
stargift: buildInputSavedStarGift(invoice.inputSavedGift),
|
||||
});
|
||||
}
|
||||
|
||||
case 'stargiftPrepaidUpgrade': {
|
||||
return new GramJs.InputInvoiceStarGiftPrepaidUpgrade({
|
||||
peer: buildInputPeer(invoice.peer.id, invoice.peer.accessHash),
|
||||
|
||||
@ -269,6 +269,7 @@ export interface ApiMessageActionStarGiftUnique extends ActionMediaType {
|
||||
peerId?: string;
|
||||
savedId?: string;
|
||||
resaleAmount?: ApiTypeCurrencyAmount;
|
||||
dropOriginalDetailsStars?: number;
|
||||
}
|
||||
|
||||
export interface ApiMessageActionChannelJoined extends ActionMediaType {
|
||||
|
||||
@ -399,6 +399,11 @@ export type ApiInputInvoiceStarGiftTransfer = {
|
||||
recipientId: string;
|
||||
};
|
||||
|
||||
export type ApiInputInvoiceStarGiftDropOriginalDetails = {
|
||||
type: 'stargiftDropOriginalDetails';
|
||||
inputSavedGift: ApiInputSavedStarGift;
|
||||
};
|
||||
|
||||
export type ApiInputInvoiceStarGiftPrepaidUpgrade = {
|
||||
type: 'stargiftPrepaidUpgrade';
|
||||
peerId: string;
|
||||
@ -409,7 +414,7 @@ export type ApiInputInvoice = ApiInputInvoiceMessage | ApiInputInvoiceSlug | Api
|
||||
| ApiInputInvoiceGiftCode | ApiInputInvoicePremiumGiftStars | ApiInputInvoiceStars | ApiInputInvoiceStarsGift
|
||||
| ApiInputInvoiceStarsGiveaway | ApiInputInvoiceStarGift | ApiInputInvoiceChatInviteSubscription
|
||||
| ApiInputInvoiceStarGiftUpgrade | ApiInputInvoiceStarGiftTransfer | ApiInputInvoiceStarGiftResale
|
||||
| ApiInputInvoiceStarGiftPrepaidUpgrade;
|
||||
| ApiInputInvoiceStarGiftDropOriginalDetails | ApiInputInvoiceStarGiftPrepaidUpgrade;
|
||||
|
||||
/* Used for Invoice request */
|
||||
export type ApiRequestInputInvoiceMessage = {
|
||||
@ -479,6 +484,11 @@ export type ApiRequestInputInvoiceStarGiftTransfer = {
|
||||
recipient: ApiPeer;
|
||||
};
|
||||
|
||||
export type ApiRequestInputInvoiceStarGiftDropOriginalDetails = {
|
||||
type: 'stargiftDropOriginalDetails';
|
||||
inputSavedGift: ApiRequestInputSavedStarGift;
|
||||
};
|
||||
|
||||
export type ApiRequestInputInvoiceStarGiftPrepaidUpgrade = {
|
||||
type: 'stargiftPrepaidUpgrade';
|
||||
peer: ApiPeer;
|
||||
@ -490,7 +500,7 @@ export type ApiRequestInputInvoice = ApiRequestInputInvoiceMessage | ApiRequestI
|
||||
| ApiRequestInputInvoiceChatInviteSubscription | ApiRequestInputInvoiceStarGift
|
||||
| ApiRequestInputInvoiceStarGiftUpgrade | ApiRequestInputInvoiceStarGiftTransfer
|
||||
| ApiRequestInputInvoicePremiumGiftStars | ApiRequestInputInvoiceStarGiftResale
|
||||
| ApiRequestInputInvoiceStarGiftPrepaidUpgrade;
|
||||
| ApiRequestInputInvoiceStarGiftDropOriginalDetails | ApiRequestInputInvoiceStarGiftPrepaidUpgrade;
|
||||
|
||||
export interface ApiUniqueStarGiftValueInfo {
|
||||
isLastSaleOnFragment?: true;
|
||||
|
||||
@ -111,6 +111,7 @@ export interface ApiSavedStarGift {
|
||||
isConverted?: boolean; // Local field, used for Action Message
|
||||
upgradeMsgId?: number; // Local field, used for Action Message
|
||||
localTag?: number; // Local field, used for key in list
|
||||
dropOriginalDetailsStars?: number;
|
||||
}
|
||||
|
||||
export type StarGiftAttributeIdModel = {
|
||||
@ -245,6 +246,7 @@ export interface ApiStarsTransaction {
|
||||
isGiftResale?: true;
|
||||
paidMessages?: number;
|
||||
isPostsSearch?: true;
|
||||
isDropOriginalDetails?: true;
|
||||
isPrepaidUpgrade?: true;
|
||||
}
|
||||
|
||||
|
||||
@ -1558,6 +1558,10 @@
|
||||
"GiftTransferConfirmButton" = "Transfer for {amount}";
|
||||
"GiftTransferConfirmButtonFree" = "Transfer";
|
||||
"GiftTransferSuccessMessage" = "You have successfully gifted {gift} to {peer}.";
|
||||
"RemoveGiftDescriptionTitle" = "Remove Description";
|
||||
"RemoveGiftDescriptionConfirmText" = "Do you want to permanently remove this description from your gift?";
|
||||
"RemoveGiftDescriptionButton" = "Remove for {amount}";
|
||||
"RemoveGiftDescriptionSuccessMessage" = "Gift's Description Removed!";
|
||||
"GiftUpgradeUniqueTitle" = "Unique";
|
||||
"GiftUpgradeUniqueDescription" = "Turn your gift into a unique collectible that you can transfer or auction.";
|
||||
"GiftUpgradeTransferableTitle" = "Transferable";
|
||||
@ -2301,6 +2305,8 @@
|
||||
"TitleGiftLocked" = "Gift Locked";
|
||||
"GiftLockedMessage" = "This gift is currently only available to earlier Telegram users. It will unlock for your account in about **{relativeDate}**.";
|
||||
"QuickPreview" = "Quick Preview";
|
||||
"DropOriginalDetailsTransaction" = "Removed Gift Description";
|
||||
"StarGiftReasonDropOriginalDetails" = "Removed Description";
|
||||
"GiftAnUpgradeButton" = "Gift an Upgrade";
|
||||
"GiftPrepaidUpgradeTransactionTitle" = "Gift Upgrade";
|
||||
"ActionStarGiftPrepaidUpgraded" = "{user} turned the gift into a unique collectible";
|
||||
|
||||
@ -16,5 +16,6 @@ export { default as GiftStatusInfoModal } from '../components/modals/gift/status
|
||||
export { default as GiftWithdrawModal } from '../components/modals/gift/withdraw/GiftWithdrawModal';
|
||||
export { default as GiftTransferModal } from '../components/modals/gift/transfer/GiftTransferModal';
|
||||
export { default as GiftTransferConfirmModal } from '../components/modals/gift/transfer/GiftTransferConfirmModal';
|
||||
export { default as GiftDescriptionRemoveModal } from '../components/modals/gift/message/GiftDescriptionRemoveModal';
|
||||
export { default as ChatRefundModal } from '../components/modals/stars/chatRefund/ChatRefundModal';
|
||||
export { default as PriceConfirmModal } from '../components/modals/priceConfirm/PriceConfirmModal';
|
||||
|
||||
75
src/components/common/helpers/giftOriginalInfo.tsx
Normal file
75
src/components/common/helpers/giftOriginalInfo.tsx
Normal file
@ -0,0 +1,75 @@
|
||||
import type { TeactNode } from '../../../lib/teact/teact';
|
||||
|
||||
import type { ApiPeer, ApiStarGiftAttributeOriginalDetails } from '../../../api/types';
|
||||
|
||||
import { getPeerTitle } from '../../../global/helpers/peers';
|
||||
import { formatDateTimeToString } from '../../../util/dates/dateFormat';
|
||||
import { type LangFn } from '../../../util/localization';
|
||||
import { renderTextWithEntities } from './renderTextWithEntities';
|
||||
|
||||
import Link from '../../ui/Link';
|
||||
|
||||
type GiftOriginalInfoOptions = {
|
||||
originalDetails: ApiStarGiftAttributeOriginalDetails;
|
||||
recipient: ApiPeer;
|
||||
sender?: ApiPeer;
|
||||
onOpenChat: (peerId: string) => void;
|
||||
lang: LangFn;
|
||||
};
|
||||
|
||||
export function renderGiftOriginalInfo({
|
||||
originalDetails,
|
||||
recipient,
|
||||
sender,
|
||||
onOpenChat,
|
||||
lang,
|
||||
}: GiftOriginalInfoOptions): TeactNode | undefined {
|
||||
const { recipientId, senderId, date, message } = originalDetails;
|
||||
|
||||
const formattedDate = formatDateTimeToString(date * 1000, lang.code, true);
|
||||
const recipientLink = (
|
||||
<Link onClick={() => onOpenChat(recipientId)} isPrimary>
|
||||
{getPeerTitle(lang, recipient)}
|
||||
</Link>
|
||||
);
|
||||
|
||||
if (!sender || senderId === recipientId) {
|
||||
return message
|
||||
? lang('GiftInfoPeerOriginalInfoText', {
|
||||
peer: recipientLink,
|
||||
text: renderTextWithEntities(message),
|
||||
date: formattedDate,
|
||||
}, {
|
||||
withNodes: true,
|
||||
})
|
||||
: lang('GiftInfoPeerOriginalInfo', {
|
||||
peer: recipientLink,
|
||||
date: formattedDate,
|
||||
}, {
|
||||
withNodes: true,
|
||||
});
|
||||
}
|
||||
|
||||
const senderLink = (
|
||||
<Link onClick={() => onOpenChat(sender.id)} isPrimary>
|
||||
{getPeerTitle(lang, sender)}
|
||||
</Link>
|
||||
);
|
||||
|
||||
return message
|
||||
? lang('GiftInfoPeerOriginalInfoTextSender', {
|
||||
peer: recipientLink,
|
||||
sender: senderLink,
|
||||
text: renderTextWithEntities(message),
|
||||
date: formattedDate,
|
||||
}, {
|
||||
withNodes: true,
|
||||
})
|
||||
: lang('GiftInfoPeerOriginalInfoSender', {
|
||||
peer: recipientLink,
|
||||
date: formattedDate,
|
||||
sender: senderLink,
|
||||
}, {
|
||||
withNodes: true,
|
||||
});
|
||||
}
|
||||
@ -22,6 +22,7 @@ import FrozenAccountModal from './frozenAccount/FrozenAccountModal.async';
|
||||
import PremiumGiftModal from './gift/GiftModal.async';
|
||||
import GiftInfoModal from './gift/info/GiftInfoModal.async';
|
||||
import GiftLockedModal from './gift/locked/GiftLockedModal.async';
|
||||
import GiftDescriptionRemoveModal from './gift/message/GiftDescriptionRemoveModal.async';
|
||||
import GiftRecipientPicker from './gift/recipient/GiftRecipientPicker.async';
|
||||
import GiftResalePriceComposerModal from './gift/resale/GiftResalePriceComposerModal.async';
|
||||
import GiftStatusInfoModal from './gift/status/GiftStatusInfoModal.async';
|
||||
@ -97,6 +98,7 @@ type ModalKey = keyof Pick<TabState,
|
||||
'giftStatusInfoModal' |
|
||||
'giftTransferModal' |
|
||||
'giftTransferConfirmModal' |
|
||||
'giftDescriptionRemoveModal' |
|
||||
'chatRefundModal' |
|
||||
'priceConfirmModal' |
|
||||
'isFrozenAccountModalOpen' |
|
||||
@ -159,6 +161,7 @@ const MODALS: ModalRegistry = {
|
||||
sharePreparedMessageModal: SharePreparedMessageModal,
|
||||
giftTransferModal: GiftTransferModal,
|
||||
giftTransferConfirmModal: GiftTransferConfirmModal,
|
||||
giftDescriptionRemoveModal: GiftDescriptionRemoveModal,
|
||||
chatRefundModal: ChatRefundModal,
|
||||
priceConfirmModal: PriceConfirmModal,
|
||||
isFrozenAccountModalOpen: FrozenAccountModal,
|
||||
|
||||
@ -49,7 +49,7 @@
|
||||
|
||||
.modalContent {
|
||||
position: relative;
|
||||
max-height: min(92vh, 48rem) !important;
|
||||
max-height: min(97vh, 48rem) !important;
|
||||
}
|
||||
|
||||
.headerSplitButton {
|
||||
@ -197,3 +197,14 @@
|
||||
margin-inline-start: 0.25rem;
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.messageContainer {
|
||||
position: relative;
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.removeMessageButton {
|
||||
color: var(--color-primary) !important;
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import type { TeactNode } from '../../../../lib/teact/teact';
|
||||
import { memo, useMemo, useRef, useState } from '../../../../lib/teact/teact';
|
||||
import { getActions, getGlobal, withGlobal } from '../../../../global';
|
||||
|
||||
@ -24,6 +23,7 @@ import {
|
||||
import { CUSTOM_PEER_HIDDEN } from '../../../../util/objects/customPeer';
|
||||
import { getServerTime } from '../../../../util/serverTime';
|
||||
import { formatPercent } from '../../../../util/textFormat';
|
||||
import { renderGiftOriginalInfo } from '../../../common/helpers/giftOriginalInfo';
|
||||
import { getGiftAttributes, getStickerFromGift } from '../../../common/helpers/gifts';
|
||||
import { renderTextWithEntities } from '../../../common/helpers/renderTextWithEntities';
|
||||
|
||||
@ -98,6 +98,7 @@ const GiftInfoModal = ({
|
||||
openGiftInfoValueModal,
|
||||
updateResaleGiftsFilter,
|
||||
openGiftInMarket,
|
||||
openGiftDescriptionRemoveModal,
|
||||
} = getActions();
|
||||
|
||||
const [isConvertConfirmOpen, openConvertConfirm, closeConvertConfirm] = useFlag();
|
||||
@ -280,6 +281,19 @@ const GiftInfoModal = ({
|
||||
handleClose();
|
||||
});
|
||||
|
||||
const handleRemoveMessage = useLastCallback(() => {
|
||||
if (!savedGift?.inputGift || !savedGift.dropOriginalDetailsStars || !gift || !giftAttributes) return;
|
||||
|
||||
const { originalDetails } = giftAttributes;
|
||||
if (!originalDetails) return;
|
||||
|
||||
openGiftDescriptionRemoveModal({
|
||||
gift: savedGift,
|
||||
price: savedGift.dropOriginalDetailsStars,
|
||||
details: originalDetails,
|
||||
});
|
||||
});
|
||||
|
||||
const handleOpenUpgradeModal = useLastCallback(() => {
|
||||
if (!savedGift) return;
|
||||
const giftOwnerId = renderingTargetPeer?.id;
|
||||
@ -761,9 +775,7 @@ const GiftInfoModal = ({
|
||||
}
|
||||
|
||||
if (originalDetails) {
|
||||
const {
|
||||
date, recipientId, message, senderId,
|
||||
} = originalDetails;
|
||||
const { recipientId, senderId } = originalDetails;
|
||||
const global = getGlobal(); // Peer titles do not need to be reactive
|
||||
|
||||
const openChat = (id: string) => {
|
||||
@ -774,54 +786,29 @@ const GiftInfoModal = ({
|
||||
const recipient = selectPeer(global, recipientId)!;
|
||||
const sender = senderId ? selectPeer(global, senderId) : undefined;
|
||||
|
||||
const formattedDate = formatDateTimeToString(date * 1000, lang.code, true);
|
||||
const recipientLink = (
|
||||
|
||||
<Link onClick={() => openChat(recipientId)} isPrimary>
|
||||
{getPeerTitle(lang, recipient)}
|
||||
</Link>
|
||||
);
|
||||
|
||||
let text: TeactNode | undefined;
|
||||
if (!sender || senderId === recipientId) {
|
||||
text = message ? lang('GiftInfoPeerOriginalInfoText', {
|
||||
peer: recipientLink,
|
||||
text: renderTextWithEntities(message),
|
||||
date: formattedDate,
|
||||
}, {
|
||||
withNodes: true,
|
||||
}) : lang('GiftInfoPeerOriginalInfo', {
|
||||
peer: recipientLink,
|
||||
date: formattedDate,
|
||||
}, {
|
||||
withNodes: true,
|
||||
});
|
||||
} else {
|
||||
const senderLink = (
|
||||
|
||||
<Link onClick={() => openChat(sender.id)} isPrimary>
|
||||
{getPeerTitle(lang, sender)}
|
||||
</Link>
|
||||
);
|
||||
text = message ? lang('GiftInfoPeerOriginalInfoTextSender', {
|
||||
peer: recipientLink,
|
||||
sender: senderLink,
|
||||
text: renderTextWithEntities(message),
|
||||
date: formattedDate,
|
||||
}, {
|
||||
withNodes: true,
|
||||
}) : lang('GiftInfoPeerOriginalInfoSender', {
|
||||
peer: recipientLink,
|
||||
date: formattedDate,
|
||||
sender: senderLink,
|
||||
}, {
|
||||
withNodes: true,
|
||||
});
|
||||
}
|
||||
const text = renderGiftOriginalInfo({
|
||||
originalDetails, recipient, sender, onOpenChat: openChat, lang,
|
||||
});
|
||||
|
||||
tableData.push([
|
||||
undefined,
|
||||
<span>{text}</span>,
|
||||
<div className={styles.messageContainer}>
|
||||
<div>
|
||||
{text}
|
||||
</div>
|
||||
{Boolean(savedGift?.dropOriginalDetailsStars) && (
|
||||
<Button
|
||||
round
|
||||
className={styles.removeMessageButton}
|
||||
size="smaller"
|
||||
color="translucent"
|
||||
ariaLabel="Delete original details"
|
||||
onClick={handleRemoveMessage}
|
||||
>
|
||||
<Icon name="delete" />
|
||||
</Button>
|
||||
)}
|
||||
</div>,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
import type { FC } from '../../../../lib/teact/teact';
|
||||
|
||||
import type { OwnProps } from './GiftDescriptionRemoveModal';
|
||||
|
||||
import { Bundles } from '../../../../util/moduleLoader';
|
||||
|
||||
import useModuleLoader from '../../../../hooks/useModuleLoader';
|
||||
|
||||
const GiftDescriptionRemoveModalAsync: FC<OwnProps> = (props) => {
|
||||
const { modal } = props;
|
||||
const GiftDescriptionRemoveModal = useModuleLoader(Bundles.Stars, 'GiftDescriptionRemoveModal', !modal);
|
||||
|
||||
return GiftDescriptionRemoveModal ? <GiftDescriptionRemoveModal {...props} /> : undefined;
|
||||
};
|
||||
|
||||
export default GiftDescriptionRemoveModalAsync;
|
||||
@ -0,0 +1,14 @@
|
||||
.confirmText {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.giftDescription {
|
||||
margin-bottom: 1rem;
|
||||
padding: 0.375rem;
|
||||
border: 0.0625rem solid var(--color-borders);
|
||||
border-radius: 0.25rem;
|
||||
|
||||
text-align: center;
|
||||
|
||||
background-color: var(--color-background-secondary);
|
||||
}
|
||||
@ -0,0 +1,94 @@
|
||||
import { memo } from '../../../../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../../../../global';
|
||||
|
||||
import type { ApiPeer } from '../../../../api/types';
|
||||
import type { TabState } from '../../../../global/types';
|
||||
|
||||
import { selectPeer } from '../../../../global/selectors';
|
||||
import { formatStarsAsIcon } from '../../../../util/localization/format';
|
||||
import { renderGiftOriginalInfo } from '../../../common/helpers/giftOriginalInfo';
|
||||
|
||||
import useCurrentOrPrev from '../../../../hooks/useCurrentOrPrev';
|
||||
import useLang from '../../../../hooks/useLang';
|
||||
import useLastCallback from '../../../../hooks/useLastCallback';
|
||||
|
||||
import ConfirmDialog from '../../../ui/ConfirmDialog';
|
||||
|
||||
import styles from './GiftDescriptionRemoveModal.module.scss';
|
||||
|
||||
export type OwnProps = {
|
||||
modal: TabState['giftDescriptionRemoveModal'];
|
||||
};
|
||||
|
||||
type StateProps = {
|
||||
senderPeer?: ApiPeer;
|
||||
recipientPeer?: ApiPeer;
|
||||
};
|
||||
|
||||
const GiftDescriptionRemoveModal = ({
|
||||
modal, senderPeer, recipientPeer,
|
||||
}: OwnProps & StateProps) => {
|
||||
const {
|
||||
closeGiftDescriptionRemoveModal, removeGiftDescription, openChat,
|
||||
} = getActions();
|
||||
const lang = useLang();
|
||||
|
||||
const isOpen = Boolean(modal);
|
||||
const renderingModal = useCurrentOrPrev(modal);
|
||||
const renderingSenderPeer = useCurrentOrPrev(senderPeer);
|
||||
const renderingRecipientPeer = useCurrentOrPrev(recipientPeer);
|
||||
|
||||
const openChatHandler = useLastCallback((id: string) => {
|
||||
closeGiftDescriptionRemoveModal();
|
||||
openChat({ id });
|
||||
});
|
||||
|
||||
const handleConfirm = useLastCallback(() => {
|
||||
if (!renderingModal?.gift.inputGift || !renderingModal.price) return;
|
||||
|
||||
removeGiftDescription({
|
||||
gift: renderingModal.gift.inputGift,
|
||||
price: renderingModal.price,
|
||||
});
|
||||
});
|
||||
|
||||
if (!renderingModal || !renderingRecipientPeer) return undefined;
|
||||
|
||||
const { price, details } = renderingModal;
|
||||
|
||||
const description = renderGiftOriginalInfo({
|
||||
originalDetails: details, recipient: renderingRecipientPeer,
|
||||
sender: renderingSenderPeer, onOpenChat: openChatHandler, lang,
|
||||
});
|
||||
|
||||
return (
|
||||
<ConfirmDialog
|
||||
isOpen={isOpen}
|
||||
title={lang('RemoveGiftDescriptionTitle')}
|
||||
onClose={closeGiftDescriptionRemoveModal}
|
||||
confirmLabel={lang('RemoveGiftDescriptionButton', {
|
||||
amount: formatStarsAsIcon(lang, price, { asFont: true }),
|
||||
}, { withNodes: true })}
|
||||
confirmHandler={handleConfirm}
|
||||
>
|
||||
<div className={styles.confirmText}>{lang('RemoveGiftDescriptionConfirmText')}</div>
|
||||
{Boolean(description) && (
|
||||
<div className={styles.giftDescription}>
|
||||
{description}
|
||||
</div>
|
||||
)}
|
||||
</ConfirmDialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(
|
||||
withGlobal<OwnProps>((global, { modal }): Complete<StateProps> => {
|
||||
const senderPeer = modal?.details.senderId ? selectPeer(global, modal.details.senderId) : undefined;
|
||||
const recipientPeer = modal?.details.recipientId ? selectPeer(global, modal.details.recipientId) : undefined;
|
||||
|
||||
return {
|
||||
senderPeer,
|
||||
recipientPeer,
|
||||
};
|
||||
})(GiftDescriptionRemoveModal),
|
||||
);
|
||||
@ -29,6 +29,10 @@ export function getTransactionTitle(oldLang: OldLangFn, lang: LangFn, transactio
|
||||
return lang('PostsSearchTransaction');
|
||||
}
|
||||
|
||||
if (transaction.isDropOriginalDetails) {
|
||||
return lang('DropOriginalDetailsTransaction');
|
||||
}
|
||||
|
||||
if (transaction.isPrepaidUpgrade) {
|
||||
return lang('GiftPrepaidUpgradeTransactionTitle');
|
||||
}
|
||||
|
||||
@ -83,7 +83,8 @@ const StarsTransactionItem = ({ transaction, className }: OwnProps) => {
|
||||
avatarPeer = customPeer;
|
||||
}
|
||||
|
||||
if (transaction.isGiftUpgrade && transaction.starGift?.type === 'starGiftUnique') {
|
||||
if ((transaction.isGiftUpgrade || transaction.isDropOriginalDetails)
|
||||
&& transaction.starGift?.type === 'starGiftUnique') {
|
||||
description = lang('GiftUnique', { title: transaction.starGift.title, number: transaction.starGift.number });
|
||||
}
|
||||
|
||||
|
||||
@ -98,7 +98,7 @@ const StarsTransactionModal: FC<OwnProps & StateProps> = ({
|
||||
}
|
||||
|
||||
const {
|
||||
giveawayPostId, photo, amount, isGiftUpgrade, starGift, isGiftResale,
|
||||
giveawayPostId, photo, amount, isGiftUpgrade, isDropOriginalDetails, starGift, isGiftResale,
|
||||
starRefCommision,
|
||||
} = transaction;
|
||||
|
||||
@ -116,7 +116,7 @@ const StarsTransactionModal: FC<OwnProps & StateProps> = ({
|
||||
|
||||
const title = getTransactionTitle(oldLang, lang, transaction);
|
||||
|
||||
const messageLink = peer && transaction.messageId && !isGiftUpgrade
|
||||
const messageLink = peer && transaction.messageId && !isGiftUpgrade && !isDropOriginalDetails
|
||||
? getMessageLink(peer, undefined, transaction.messageId) : undefined;
|
||||
const giveawayMessageLink = peer && giveawayPostId ? getMessageLink(peer, undefined, giveawayPostId) : undefined;
|
||||
|
||||
@ -131,7 +131,7 @@ const StarsTransactionModal: FC<OwnProps & StateProps> = ({
|
||||
: oldLang('Media', mediaAmount);
|
||||
|
||||
const description = transaction.description
|
||||
|| (isGiftUpgrade && starGift?.type === 'starGiftUnique' ? starGift.title : undefined)
|
||||
|| ((isGiftUpgrade || isDropOriginalDetails) && starGift?.type === 'starGiftUnique' ? starGift.title : undefined)
|
||||
|| (media ? mediaText : undefined);
|
||||
|
||||
const shouldDisplayAvatar = !media && !sticker && !transaction.isPostsSearch;
|
||||
@ -231,6 +231,13 @@ const StarsTransactionModal: FC<OwnProps & StateProps> = ({
|
||||
]);
|
||||
}
|
||||
|
||||
if (isDropOriginalDetails) {
|
||||
tableData.push([
|
||||
oldLang('StarGiftReason'),
|
||||
lang('StarGiftReasonDropOriginalDetails'),
|
||||
]);
|
||||
}
|
||||
|
||||
if (isGiftResale) {
|
||||
tableData.push([
|
||||
oldLang('StarGiftReason'),
|
||||
@ -253,7 +260,7 @@ const StarsTransactionModal: FC<OwnProps & StateProps> = ({
|
||||
peerLabel = oldLang('Stars.Transaction.Via');
|
||||
}
|
||||
|
||||
if (!transaction.isPostsSearch) {
|
||||
if (!transaction.isPostsSearch && !isDropOriginalDetails) {
|
||||
tableData.push([
|
||||
peerLabel,
|
||||
peerId ? { chatId: peerId } : toName || '',
|
||||
|
||||
@ -1117,6 +1117,17 @@ addActionHandler('transferGift', (global, actions, payload): ActionReturnType =>
|
||||
payInputStarInvoice(global, invoice, transferStars, tabId);
|
||||
});
|
||||
|
||||
addActionHandler('removeGiftDescription', (global, actions, payload): ActionReturnType => {
|
||||
const { gift, price, tabId = getCurrentTabId() } = payload;
|
||||
|
||||
const invoice: ApiInputInvoice = {
|
||||
type: 'stargiftDropOriginalDetails',
|
||||
inputSavedGift: gift,
|
||||
};
|
||||
|
||||
payInputStarInvoice(global, invoice, price, tabId);
|
||||
});
|
||||
|
||||
addActionHandler('upgradePrepaidGift', (global, actions, payload): ActionReturnType => {
|
||||
const { peerId, hash, stars, tabId = getCurrentTabId() } = payload;
|
||||
|
||||
|
||||
@ -3,8 +3,8 @@ import type { ActionReturnType } from '../../types';
|
||||
import { formatCurrencyAsString } from '../../../util/formatCurrency';
|
||||
import * as langProvider from '../../../util/oldLangProvider';
|
||||
import { getPeerTitle } from '../../helpers/peers';
|
||||
import { addActionHandler, setGlobal } from '../../index';
|
||||
import { updateStarsBalance } from '../../reducers';
|
||||
import { addActionHandler, getGlobal, setGlobal } from '../../index';
|
||||
import { removeGiftInfoOriginalDetails, updateStarsBalance } from '../../reducers';
|
||||
import { updateTabState } from '../../reducers/tabs';
|
||||
import { selectPeer, selectTabState } from '../../selectors';
|
||||
|
||||
@ -176,6 +176,22 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
|
||||
actions.reloadPeerSavedGifts({ peerId: global.currentUserId });
|
||||
}
|
||||
|
||||
if (inputInvoice?.type === 'stargiftDropOriginalDetails') {
|
||||
global = getGlobal();
|
||||
global = removeGiftInfoOriginalDetails(global, tabId);
|
||||
setGlobal(global);
|
||||
|
||||
actions.closeGiftDescriptionRemoveModal({ tabId });
|
||||
actions.showNotification({
|
||||
message: { key: 'RemoveGiftDescriptionSuccessMessage' },
|
||||
tabId,
|
||||
});
|
||||
|
||||
if (global.currentUserId) {
|
||||
actions.reloadPeerSavedGifts({ peerId: global.currentUserId });
|
||||
}
|
||||
}
|
||||
|
||||
if (inputInvoice?.type === 'stargiftPrepaidUpgrade') {
|
||||
actions.reloadPeerSavedGifts({ peerId: inputInvoice.peerId });
|
||||
|
||||
|
||||
@ -266,6 +266,7 @@ addActionHandler('openGiftInfoModalFromMessage', async (global, actions, payload
|
||||
canExportAt: uniqueGift?.canExportAt,
|
||||
savedId: action.savedId,
|
||||
transferStars: uniqueGift?.transferStars,
|
||||
dropOriginalDetailsStars: uniqueGift?.dropOriginalDetailsStars,
|
||||
prepaidUpgradeHash: starGift?.prepaidUpgradeHash,
|
||||
};
|
||||
|
||||
@ -457,6 +458,22 @@ addActionHandler('openGiftTransferConfirmModal', (global, actions, payload): Act
|
||||
|
||||
addTabStateResetterAction('closeGiftTransferConfirmModal', 'giftTransferConfirmModal');
|
||||
|
||||
addActionHandler('openGiftDescriptionRemoveModal', (global, actions, payload): ActionReturnType => {
|
||||
const {
|
||||
gift, price, details, tabId = getCurrentTabId(),
|
||||
} = payload;
|
||||
|
||||
return updateTabState(global, {
|
||||
giftDescriptionRemoveModal: {
|
||||
gift,
|
||||
price,
|
||||
details,
|
||||
},
|
||||
}, tabId);
|
||||
});
|
||||
|
||||
addTabStateResetterAction('closeGiftDescriptionRemoveModal', 'giftDescriptionRemoveModal');
|
||||
|
||||
addActionHandler('updateSelectedGiftCollection', (global, actions, payload): ActionReturnType => {
|
||||
const { peerId, collectionId, tabId = getCurrentTabId() } = payload;
|
||||
const tabState = selectTabState(global, tabId);
|
||||
|
||||
@ -235,6 +235,17 @@ export function getRequestInputInvoice<T extends GlobalState>(
|
||||
};
|
||||
}
|
||||
|
||||
if (inputInvoice.type === 'stargiftDropOriginalDetails') {
|
||||
const { inputSavedGift } = inputInvoice;
|
||||
const savedGift = getRequestInputSavedStarGift(global, inputSavedGift);
|
||||
if (!savedGift) return undefined;
|
||||
|
||||
return {
|
||||
type: 'stargiftDropOriginalDetails',
|
||||
inputSavedGift: savedGift,
|
||||
};
|
||||
}
|
||||
|
||||
if (inputInvoice.type === 'stargiftPrepaidUpgrade') {
|
||||
const { peerId, hash } = inputInvoice;
|
||||
const peer = selectPeer(global, peerId);
|
||||
|
||||
48
src/global/reducers/gifts.ts
Normal file
48
src/global/reducers/gifts.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import type { ApiSavedStarGift } from '../../api/types';
|
||||
import type { GlobalState } from '../types';
|
||||
|
||||
import { getCurrentTabId } from '../../util/establishMultitabRole';
|
||||
import { updateTabState } from './tabs';
|
||||
|
||||
export function removeGiftInfoOriginalDetails<T extends GlobalState>(
|
||||
global: T,
|
||||
tabId: number = getCurrentTabId(),
|
||||
): T {
|
||||
const tabState = global.byTabId[tabId];
|
||||
const { giftInfoModal } = tabState;
|
||||
if (!giftInfoModal) {
|
||||
return global;
|
||||
}
|
||||
|
||||
const typeGift = giftInfoModal.gift;
|
||||
const isSavedGift = typeGift && 'gift' in typeGift;
|
||||
|
||||
if (!isSavedGift) {
|
||||
return global;
|
||||
}
|
||||
|
||||
const savedGift = typeGift;
|
||||
const innerGift = savedGift.gift;
|
||||
|
||||
if (innerGift.type !== 'starGiftUnique') {
|
||||
return global;
|
||||
}
|
||||
|
||||
const updatedInnerGift = {
|
||||
...innerGift,
|
||||
attributes: innerGift.attributes?.filter((attr) => attr.type !== 'originalDetails'),
|
||||
};
|
||||
|
||||
const updatedGift: ApiSavedStarGift = {
|
||||
...savedGift,
|
||||
dropOriginalDetailsStars: undefined,
|
||||
gift: updatedInnerGift,
|
||||
};
|
||||
|
||||
return updateTabState(global, {
|
||||
giftInfoModal: {
|
||||
...giftInfoModal,
|
||||
gift: updatedGift,
|
||||
},
|
||||
}, tabId);
|
||||
}
|
||||
@ -14,3 +14,4 @@ export * from './stories';
|
||||
export * from './translations';
|
||||
export * from './peers';
|
||||
export * from './topics';
|
||||
export * from './gifts';
|
||||
|
||||
@ -45,6 +45,7 @@ import type {
|
||||
ApiSendMessageAction,
|
||||
ApiSessionData,
|
||||
ApiStarGift,
|
||||
ApiStarGiftAttributeOriginalDetails,
|
||||
ApiStarGiftUnique,
|
||||
ApiStarsSubscription,
|
||||
ApiStarsTransaction,
|
||||
@ -2661,12 +2662,22 @@ export interface ActionPayloads {
|
||||
transferStars?: number;
|
||||
recipientId: string;
|
||||
} & WithTabId;
|
||||
removeGiftDescription: {
|
||||
gift: ApiInputSavedStarGift;
|
||||
price: number;
|
||||
} & WithTabId;
|
||||
closeGiftTransferModal: WithTabId | undefined;
|
||||
openGiftTransferConfirmModal: {
|
||||
gift: ApiSavedStarGift;
|
||||
recipientId: string;
|
||||
} & WithTabId;
|
||||
closeGiftTransferConfirmModal: WithTabId | undefined;
|
||||
openGiftDescriptionRemoveModal: {
|
||||
gift: ApiSavedStarGift;
|
||||
price: number;
|
||||
details: ApiStarGiftAttributeOriginalDetails;
|
||||
} & WithTabId;
|
||||
closeGiftDescriptionRemoveModal: WithTabId | undefined;
|
||||
updateSelectedGiftCollection: {
|
||||
peerId: string;
|
||||
collectionId: number;
|
||||
|
||||
@ -42,6 +42,7 @@ import type {
|
||||
ApiStarGift,
|
||||
ApiStarGiftAttribute,
|
||||
ApiStarGiftAttributeCounter,
|
||||
ApiStarGiftAttributeOriginalDetails,
|
||||
ApiStarGiftUnique,
|
||||
ApiStarGiveawayOption,
|
||||
ApiStarsSubscription,
|
||||
@ -854,6 +855,12 @@ export type TabState = {
|
||||
recipientId: string;
|
||||
};
|
||||
|
||||
giftDescriptionRemoveModal?: {
|
||||
gift: ApiSavedStarGift;
|
||||
price: number;
|
||||
details: ApiStarGiftAttributeOriginalDetails;
|
||||
};
|
||||
|
||||
giftUpgradeModal?: {
|
||||
sampleAttributes: ApiStarGiftAttribute[];
|
||||
recipientId?: string;
|
||||
|
||||
8
src/types/language.d.ts
vendored
8
src/types/language.d.ts
vendored
@ -1292,6 +1292,9 @@ export interface LangPair {
|
||||
'GiftTransferTitle': undefined;
|
||||
'GiftTransferTON': undefined;
|
||||
'GiftTransferConfirmButtonFree': undefined;
|
||||
'RemoveGiftDescriptionTitle': undefined;
|
||||
'RemoveGiftDescriptionConfirmText': undefined;
|
||||
'RemoveGiftDescriptionSuccessMessage': undefined;
|
||||
'GiftUpgradeUniqueTitle': undefined;
|
||||
'GiftUpgradeUniqueDescription': undefined;
|
||||
'GiftUpgradeTransferableTitle': undefined;
|
||||
@ -1717,6 +1720,8 @@ export interface LangPair {
|
||||
'ConfirmBuyGiftForTonDescription': undefined;
|
||||
'TitleGiftLocked': undefined;
|
||||
'QuickPreview': undefined;
|
||||
'DropOriginalDetailsTransaction': undefined;
|
||||
'StarGiftReasonDropOriginalDetails': undefined;
|
||||
'GiftAnUpgradeButton': undefined;
|
||||
'GiftPrepaidUpgradeTransactionTitle': undefined;
|
||||
'ActionStarGiftPrepaidUpgradedYou': undefined;
|
||||
@ -2191,6 +2196,9 @@ export interface LangPairWithVariables<V = LangVariable> {
|
||||
'gift': V;
|
||||
'peer': V;
|
||||
};
|
||||
'RemoveGiftDescriptionButton': {
|
||||
'amount': V;
|
||||
};
|
||||
'GiftPeerUpgradeText': {
|
||||
'peer': V;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user