Deep Link: Support stars_topup links (#5054)

Co-authored-by: Dmitry Kabanov <dmitrykabanovdev@gmail.com>
Co-authored-by: Dmitry Kabanov <153344039+dmitrykabanovdev@users.noreply.github.com>
Co-authored-by: Alexander Zinchuk <alx.zinchuk@gmail.com>
This commit is contained in:
zubiden 2024-11-02 21:11:14 +04:00 committed by Alexander Zinchuk
parent 1dc29627bd
commit 1c25bf1fe5
8 changed files with 85 additions and 39 deletions

View File

@ -41,6 +41,7 @@ const TRANSACTION_TABS: TabWithProperties[] = [
{ title: 'StarsTransactionsOutgoing' },
];
const TRANSACTION_ITEM_CLASS = 'StarsTransactionItem';
const SUBSCRIPTION_PURPOSE = 'subs';
export type OwnProps = {
modal: TabState['starsBalanceModal'];
@ -69,15 +70,19 @@ const StarsBalanceModal = ({
const isOpen = Boolean(modal && starsBalanceState);
const { originStarsPayment, originReaction, originGift } = modal || {};
const {
originStarsPayment, originReaction, originGift, topup,
} = modal || {};
const shouldOpenOnBuy = originStarsPayment || originReaction || originGift || topup;
const ongoingTransactionAmount = originStarsPayment?.form?.invoice?.totalAmount
|| originStarsPayment?.subscriptionInfo?.subscriptionPricing?.amount
|| originReaction?.amount
|| originGift?.gift.stars;
|| originGift?.gift.stars
|| topup?.balanceNeeded;
const starsNeeded = ongoingTransactionAmount ? ongoingTransactionAmount - (balance || 0) : undefined;
const starsNeededText = useMemo(() => {
if (!starsNeeded || starsNeeded < 0) return undefined;
const global = getGlobal();
if (originReaction) {
@ -98,11 +103,15 @@ const StarsBalanceModal = ({
return oldLang('StarsNeededTextGift', getUserFullName(user));
}
return undefined;
}, [starsNeeded, originReaction, originStarsPayment, originGift, oldLang]);
if (topup?.purpose === SUBSCRIPTION_PURPOSE) {
return oldLang('StarsNeededTextLink');
}
const shouldShowItems = Boolean(history?.all?.transactions.length && !originStarsPayment && !originReaction);
const shouldSuggestGifting = !originStarsPayment && !originReaction;
return undefined;
}, [originReaction, originStarsPayment, originGift, topup?.purpose, oldLang]);
const shouldShowItems = Boolean(history?.all?.transactions.length && !shouldOpenOnBuy);
const shouldSuggestGifting = !shouldOpenOnBuy;
useEffect(() => {
if (!isOpen) {
@ -113,13 +122,13 @@ const StarsBalanceModal = ({
}, [isOpen]);
useEffect(() => {
if (ongoingTransactionAmount) {
if (shouldOpenOnBuy) {
showBuyOptions();
return;
}
hideBuyOptions();
}, [ongoingTransactionAmount]);
}, [shouldOpenOnBuy]);
const tosText = useMemo(() => {
if (!isOpen) return undefined;

View File

@ -40,7 +40,6 @@ export type OwnProps = {
name?: string;
phone?: string;
shippingMethod?: string;
botName?: string;
};
totalPrice?: number;
needAddress?: boolean;

View File

@ -626,7 +626,6 @@ export default memo(withGlobal<OwnProps>(
temporaryPassword,
isExtendedMedia,
url,
botId,
} = selectTabState(global).payment;
const { invoice, nativeParams, nativeProvider } = form || {};
@ -640,7 +639,7 @@ export default memo(withGlobal<OwnProps>(
const chat = inputInvoice && 'chatId' in inputInvoice ? selectChat(global, inputInvoice.chatId!) : undefined;
const isProviderError = Boolean(invoice && (!providerName || !SUPPORTED_PROVIDERS.has(providerName)));
const { needCardholderName, needCountry, needZip } = (nativeParams || {});
const bot = botId ? selectUser(global, botId) : undefined;
const bot = form?.botId ? selectUser(global, form.botId) : undefined;
const botName = getUserFullName(bot);
return {

View File

@ -1,6 +1,5 @@
import type { ActionReturnType } from '../../types';
import { areDeepEqual } from '../../../util/areDeepEqual';
import { formatCurrencyAsString } from '../../../util/formatCurrency';
import * as langProvider from '../../../util/oldLangProvider';
import { addActionHandler, setGlobal } from '../../index';
@ -17,13 +16,24 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
const { totalAmount, currency } = invoice;
actions.showNotification({
tabId,
message: langProvider.oldTranslate('PaymentInfoHint', [
formatCurrencyAsString(totalAmount, currency, langProvider.getTranslationFn().code),
form.title,
]),
});
if (paymentState.inputInvoice?.type === 'stars') {
actions.closeStarsBalanceModal({ tabId });
actions.showNotification({
message: langProvider.oldTranslate('StarsAcquiredInfo', paymentState.inputInvoice.stars),
title: langProvider.oldTranslate('StarsAcquired'),
icon: 'star',
tabId,
});
actions.requestConfetti({ withStars: true, tabId });
} else {
actions.showNotification({
tabId,
message: langProvider.oldTranslate('PaymentInfoHint', [
formatCurrencyAsString(totalAmount, currency, langProvider.getTranslationFn().code),
form.title,
]),
});
}
setGlobal(global);
@ -69,8 +79,7 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
}
const starsModalState = selectTabState(global, tabId).starsGiftModal;
if (starsModalState && starsModalState.isOpen
&& areDeepEqual(inputInvoice.userId, starsModalState.forUserId)) {
if (starsModalState?.isOpen && inputInvoice.userId === starsModalState.forUserId) {
global = updateTabState(global, {
starsGiftModal: {
...starsModalState,
@ -78,22 +87,7 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
},
}, tabId);
}
}
if (inputInvoice?.type === 'stars') {
const starsModalState = selectTabState(global, tabId).starsGiftModal;
if (starsModalState && starsModalState.isOpen) {
global = updateTabState(global, {
starsGiftModal: {
...starsModalState,
isCompleted: true,
},
}, tabId);
}
}
if (inputInvoice?.type === 'stars' || inputInvoice?.type === 'stargift') {
actions.requestConfetti({ withStars: true, tabId });
}
break;

View File

@ -2,6 +2,7 @@ import type { ApiUserStarGift } from '../../../api/types';
import type { ActionReturnType } from '../../types';
import { getCurrentTabId } from '../../../util/establishMultitabRole';
import * as langProvider from '../../../util/oldLangProvider';
import { getPrizeStarsTransactionFromGiveaway, getStarsTransactionFromGift } from '../../helpers/payments';
import { addActionHandler } from '../../index';
import {
@ -12,7 +13,13 @@ import { selectChatMessage, selectStarsPayment } from '../../selectors';
addActionHandler('processOriginStarsPayment', (global, actions, payload): ActionReturnType => {
const { originData, status, tabId = getCurrentTabId() } = payload;
const { originStarsPayment, originReaction, originGift } = originData || {};
const {
originStarsPayment, originReaction, originGift, topup,
} = originData || {};
if (!originStarsPayment && !originReaction && !originGift && !topup) {
return undefined;
}
actions.closeStarsBalanceModal({ tabId });
@ -105,9 +112,27 @@ addActionHandler('openStarsBalanceModal', (global, actions, payload): ActionRetu
originStarsPayment,
originReaction,
originGift,
topup,
shouldIgnoreBalance,
tabId = getCurrentTabId(),
} = payload || {};
const starBalance = global.stars?.balance;
if (!shouldIgnoreBalance && starBalance && topup && topup.balanceNeeded <= starBalance) {
actions.showNotification({
message: langProvider.oldTranslate('StarsTopupLinkEnough'),
actionText: langProvider.oldTranslate('StarsTopupLinkTopupAnyway'),
action: {
action: 'openStarsBalanceModal',
payload: { topup, shouldIgnoreBalance: true, tabId },
},
icon: 'star',
tabId,
});
return undefined;
}
global = clearStarPayment(global, tabId);
// Always refresh status on opening
@ -118,6 +143,7 @@ addActionHandler('openStarsBalanceModal', (global, actions, payload): ActionRetu
originStarsPayment,
originReaction,
originGift,
topup,
},
}, tabId);
});

View File

@ -875,6 +875,10 @@ export type TabState = {
messageId: number;
amount: number;
};
topup?: {
balanceNeeded: number;
purpose?: string;
};
};
giftInfoModal?: {
@ -2375,6 +2379,11 @@ export interface ActionPayloads {
messageId: number;
amount: number;
};
topup?: {
balanceNeeded: number;
purpose?: string;
};
shouldIgnoreBalance?: boolean;
} & WithTabId;
closeStarsBalanceModal: WithTabId | undefined;

View File

@ -6,7 +6,7 @@ import { isUsernameValid } from './username';
export type DeepLinkMethod = 'resolve' | 'login' | 'passport' | 'settings' | 'join' | 'addstickers' | 'addemoji' |
'setlanguage' | 'addtheme' | 'confirmphone' | 'socks' | 'proxy' | 'privatepost' | 'bg' | 'share' | 'msg' | 'msg_url' |
'invoice' | 'addlist' | 'boost' | 'giftcode' | 'message' | 'premium_offer' | 'premium_multigift';
'invoice' | 'addlist' | 'boost' | 'giftcode' | 'message' | 'premium_offer' | 'premium_multigift' | 'stars_topup';
interface PublicMessageLink {
type: 'publicMessageLink';

View File

@ -71,6 +71,7 @@ export const processDeepLink = (url: string): boolean => {
openStoryViewerByUsername,
processBoostParameters,
checkGiftCode,
openStarsBalanceModal,
} = actions;
switch (method) {
@ -176,6 +177,15 @@ export const processDeepLink = (url: string): boolean => {
break;
}
case 'stars_topup': {
const { balance, purpose } = params;
const balanceNeeded = Number(balance);
if (!balanceNeeded || balanceNeeded < 0) return true;
openStarsBalanceModal({ topup: { balanceNeeded, purpose } });
break;
}
case 'boost': {
const { channel, domain } = params;
const isPrivate = Boolean(channel);