Skip to content

Commit 3055df6

Browse files
committed
Paid Messages: Follow up (#5790)
1 parent 71b7c9e commit 3055df6

File tree

78 files changed

+468
-248
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+468
-248
lines changed

src/api/gramjs/apiBuilders/calls.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type {
99
} from '../../../lib/secret-sauce';
1010
import type { ApiGroupCall, ApiPhoneCall } from '../../types';
1111

12-
import { getApiChatIdFromMtpPeer, isPeerUser } from './peers';
12+
import { getApiChatIdFromMtpPeer, isMtpPeerUser } from './peers';
1313

1414
export function buildApiGroupCallParticipant(participant: GramJs.GroupCallParticipant): GroupCallParticipant {
1515
const {
@@ -33,7 +33,7 @@ export function buildApiGroupCallParticipant(participant: GramJs.GroupCallPartic
3333
raiseHandRating: raiseHandRating?.toString(),
3434
volume,
3535
date: new Date(date),
36-
isUser: isPeerUser(peer),
36+
isUser: isMtpPeerUser(peer),
3737
id: getApiChatIdFromMtpPeer(peer),
3838
video: video ? buildApiGroupCallParticipantVideo(video) : undefined,
3939
presentation: presentation ? buildApiGroupCallParticipantVideo(presentation) : undefined,

src/api/gramjs/apiBuilders/chats.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ import {
3636
buildApiPeerColor,
3737
buildApiPeerId,
3838
getApiChatIdFromMtpPeer,
39-
isPeerChat,
40-
isPeerUser,
39+
isMtpPeerChat,
40+
isMtpPeerUser,
4141
} from './peers';
4242
import { buildApiReaction } from './reactions';
4343

@@ -295,17 +295,17 @@ export function getApiChatTypeFromPeerEntity(peerEntity: GramJs.TypeChat | GramJ
295295
}
296296

297297
export function getPeerKey(peer: GramJs.TypePeer) {
298-
if (isPeerUser(peer)) {
298+
if (isMtpPeerUser(peer)) {
299299
return `user${peer.userId}`;
300-
} else if (isPeerChat(peer)) {
300+
} else if (isMtpPeerChat(peer)) {
301301
return `chat${peer.chatId}`;
302302
} else {
303303
return `chat${peer.channelId}`;
304304
}
305305
}
306306

307307
export function getApiChatTitleFromMtpPeer(peer: GramJs.TypePeer, peerEntity: GramJs.User | GramJs.Chat) {
308-
if (isPeerUser(peer)) {
308+
if (isMtpPeerUser(peer)) {
309309
return getUserName(peerEntity as GramJs.User);
310310
} else {
311311
return (peerEntity as GramJs.Chat).title;

src/api/gramjs/apiBuilders/peers.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ import type { ApiEmojiStatusType, ApiPeerColor } from '../../types';
66
import { CHANNEL_ID_LENGTH } from '../../../config';
77
import { numberToHexColor } from '../../../util/colors';
88

9-
export function isPeerUser(peer: GramJs.TypePeer | GramJs.TypeInputPeer): peer is GramJs.PeerUser {
9+
export function isMtpPeerUser(peer: GramJs.TypePeer | GramJs.TypeInputPeer): peer is GramJs.PeerUser {
1010
return peer.hasOwnProperty('userId');
1111
}
1212

13-
export function isPeerChat(peer: GramJs.TypePeer | GramJs.TypeInputPeer): peer is GramJs.PeerChat {
13+
export function isMtpPeerChat(peer: GramJs.TypePeer | GramJs.TypeInputPeer): peer is GramJs.PeerChat {
1414
return peer.hasOwnProperty('chatId');
1515
}
1616

17-
export function isPeerChannel(peer: GramJs.TypePeer | GramJs.TypeInputPeer): peer is GramJs.PeerChannel {
17+
export function isMtpPeerChannel(peer: GramJs.TypePeer | GramJs.TypeInputPeer): peer is GramJs.PeerChannel {
1818
return peer.hasOwnProperty('channelId');
1919
}
2020

@@ -34,9 +34,9 @@ export function buildApiPeerId(id: BigInt.BigInteger, type: 'user' | 'chat' | 'c
3434
}
3535

3636
export function getApiChatIdFromMtpPeer(peer: GramJs.TypePeer | GramJs.TypeInputPeer) {
37-
if (isPeerUser(peer)) {
37+
if (isMtpPeerUser(peer)) {
3838
return buildApiPeerId(peer.userId, 'user');
39-
} else if (isPeerChat(peer)) {
39+
} else if (isMtpPeerChat(peer)) {
4040
return buildApiPeerId(peer.chatId, 'chat');
4141
} else {
4242
return buildApiPeerId((peer as GramJs.InputPeerChannel).channelId, 'channel');

src/api/gramjs/methods/users.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,17 @@ export async function addNoPaidMessagesException({ user, shouldRefundCharged }:
258258
return result;
259259
}
260260

261+
export async function fetchPaidMessagesRevenue({ user }: {
262+
user: ApiUser;
263+
shouldRefundCharged?: boolean;
264+
}) {
265+
const result = await invokeRequest(new GramJs.account.GetPaidMessagesRevenue({
266+
userId: buildInputEntity(user.id, user.accessHash) as GramJs.InputUser,
267+
}));
268+
if (!result) return undefined;
269+
return result.starsAmount.toJSNumber();
270+
}
271+
261272
export async function fetchProfilePhotos({
262273
peer,
263274
offset = 0,

src/assets/localization/fallback.strings

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1890,4 +1890,7 @@
18901890
"PaidMessageTransaction_one" = "Fee for {count} Message";
18911891
"PaidMessageTransaction_other" = "Fee for {count} Messages";
18921892
"PaidMessageTransactionDescription" = "You receive **{percent}** of the price that you charge for each incoming message.";
1893-
"PaidMessageTransactionTotal" = "Total";
1893+
"PaidMessageTransactionTotal" = "Total";
1894+
"DescriptionRestrictedMedia" = "Posting media content is not allowed in this group.";
1895+
"DescriptionScheduledPaidMediaNotAllowed" = "Posting scheduled paid media content is not allowed";
1896+
"DescriptionScheduledPaidMessagesNotAllowed" = "Scheduled paid messages is not allowed";

src/bundles/stars.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ export { default as GiftUpgradeModal } from '../components/modals/gift/upgrade/G
1212
export { default as GiftStatusInfoModal } from '../components/modals/gift/status/GiftStatusInfoModal';
1313
export { default as GiftWithdrawModal } from '../components/modals/gift/withdraw/GiftWithdrawModal';
1414
export { default as GiftTransferModal } from '../components/modals/gift/transfer/GiftTransferModal';
15+
export { default as ChatRefundModal } from '../components/modals/stars/chatRefund/ChatRefundModal';

src/components/common/Avatar.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,9 @@ import {
2121
isAnonymousForwardsChat,
2222
isChatWithRepliesBot,
2323
isDeletedUser,
24-
isPeerChat,
25-
isPeerUser,
2624
isUserId,
2725
} from '../../global/helpers';
26+
import { isApiPeerChat, isApiPeerUser } from '../../global/helpers/peers';
2827
import buildClassName, { createClassNameBuilder } from '../../util/buildClassName';
2928
import buildStyle from '../../util/buildStyle';
3029
import { getFirstLetters } from '../../util/textFormat';
@@ -117,8 +116,8 @@ const Avatar: FC<OwnProps> = ({
117116
const videoLoopCountRef = useRef(0);
118117
const isCustomPeer = peer && 'isCustomPeer' in peer;
119118
const realPeer = peer && !isCustomPeer ? peer : undefined;
120-
const user = realPeer && isPeerUser(realPeer) ? realPeer : undefined;
121-
const chat = realPeer && isPeerChat(realPeer) ? realPeer : undefined;
119+
const user = realPeer && isApiPeerUser(realPeer) ? realPeer : undefined;
120+
const chat = realPeer && isApiPeerChat(realPeer) ? realPeer : undefined;
122121
const isDeleted = user && isDeletedUser(user);
123122
const isReplies = realPeer && isChatWithRepliesBot(realPeer.id);
124123
const isAnonymousForwards = realPeer && isAnonymousForwardsChat(realPeer.id);

src/components/common/Composer.tsx

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ import { requestMeasure, requestNextMutation } from '../../lib/fasterdom/fasterd
5757
import {
5858
canEditMedia,
5959
getAllowedAttachmentOptions,
60-
getPeerTitle,
6160
getReactionKey,
6261
getStoryKey,
6362
isChatAdmin,
@@ -68,6 +67,7 @@ import {
6867
isUserId,
6968
} from '../../global/helpers';
7069
import { getChatNotifySettings } from '../../global/helpers/notifications';
70+
import { getPeerTitle } from '../../global/helpers/peers';
7171
import {
7272
selectBot,
7373
selectCanPlayAnimatedEmojis,
@@ -288,6 +288,8 @@ type StateProps =
288288
shouldPaidMessageAutoApprove?: boolean;
289289
isSilentPosting?: boolean;
290290
isPaymentMessageConfirmDialogOpen: boolean;
291+
starsBalance: number;
292+
isStarsBalanceModalOpen: boolean;
291293
};
292294

293295
enum MainButtonState {
@@ -406,6 +408,8 @@ const Composer: FC<OwnProps & StateProps> = ({
406408
onBlur,
407409
onForward,
408410
isPaymentMessageConfirmDialogOpen,
411+
starsBalance,
412+
isStarsBalanceModalOpen,
409413
}) => {
410414
const {
411415
sendMessage,
@@ -520,8 +524,13 @@ const Composer: FC<OwnProps & StateProps> = ({
520524
canSendStickers, canSendGifs, canAttachMedia, canAttachPolls, canAttachEmbedLinks,
521525
canSendVoices, canSendPlainText, canSendAudios, canSendVideos, canSendPhotos, canSendDocuments,
522526
} = useMemo(
523-
() => getAllowedAttachmentOptions(chat, chatFullInfo, isChatWithBot, isInStoryViewer),
524-
[chat, chatFullInfo, isChatWithBot, isInStoryViewer],
527+
() => getAllowedAttachmentOptions(chat,
528+
chatFullInfo,
529+
isChatWithBot,
530+
isInStoryViewer,
531+
paidMessagesStars,
532+
isInScheduledList),
533+
[chat, chatFullInfo, isChatWithBot, isInStoryViewer, paidMessagesStars, isInScheduledList],
525534
);
526535

527536
const isNeedPremium = isContactRequirePremium && isInStoryViewer;
@@ -541,7 +550,7 @@ const Composer: FC<OwnProps & StateProps> = ({
541550
shouldAutoApprove: shouldPaidMessageAutoApprove,
542551
setAutoApprove: setShouldPaidMessageAutoApprove,
543552
handleWithConfirmation: handleActionWithPaymentConfirmation,
544-
} = usePaidMessageConfirmation(starsForAllMessages);
553+
} = usePaidMessageConfirmation(starsForAllMessages, isStarsBalanceModalOpen, starsBalance);
545554

546555
const hasWebPagePreview = !hasAttachments && canAttachEmbedLinks && !noWebPage && Boolean(webPagePreview);
547556
const isComposerBlocked = isSendTextBlocked && !editingMessage;
@@ -1391,19 +1400,23 @@ const Composer: FC<OwnProps & StateProps> = ({
13911400

13921401
if (isInScheduledList) {
13931402
requestCalendar((scheduledAt) => {
1394-
handleMessageSchedule({ poll }, scheduledAt, currentMessageList);
1403+
handleActionWithPaymentConfirmation(
1404+
handleMessageSchedule,
1405+
{ poll },
1406+
scheduledAt,
1407+
currentMessageList,
1408+
);
13951409
});
13961410
closePollModal();
13971411
} else {
1398-
sendMessage({ messageList: currentMessageList, poll, isSilent: isSilentPosting });
1412+
handleActionWithPaymentConfirmation(
1413+
sendMessage,
1414+
{ messageList: currentMessageList, poll, isSilent: isSilentPosting },
1415+
);
13991416
closePollModal();
14001417
}
14011418
});
14021419

1403-
const handlePollSendWithPaymentConfirmation = useLastCallback((poll: ApiNewPoll) => {
1404-
handleActionWithPaymentConfirmation(handlePollSend, poll);
1405-
});
1406-
14071420
const sendSilent = useLastCallback((additionalArgs?: ScheduledMessageArgs) => {
14081421
if (isInScheduledList) {
14091422
requestCalendar((scheduledAt) => {
@@ -1587,7 +1600,7 @@ const Composer: FC<OwnProps & StateProps> = ({
15871600
message: oldLang('VoiceMessagesRestrictedByPrivacy', chat?.title),
15881601
});
15891602
} else if (!canSendVoices) {
1590-
showAllowedMessageTypesNotification({ chatId });
1603+
showAllowedMessageTypesNotification({ chatId, messageListType });
15911604
}
15921605
} else {
15931606
setIsViewOnceEnabled(false);
@@ -1812,7 +1825,7 @@ const Composer: FC<OwnProps & StateProps> = ({
18121825
isQuiz={pollModal.isQuiz}
18131826
shouldBeAnonymous={isChannel}
18141827
onClear={closePollModal}
1815-
onSend={handlePollSendWithPaymentConfirmation}
1828+
onSend={handlePollSend}
18161829
/>
18171830
<SendAsMenu
18181831
isOpen={isSendAsMenuOpen}
@@ -1998,6 +2011,7 @@ const Composer: FC<OwnProps & StateProps> = ({
19982011
onFocus={markInputHasFocus}
19992012
onBlur={unmarkInputHasFocus}
20002013
isNeedPremium={isNeedPremium}
2014+
messageListType={messageListType}
20012015
/>
20022016
{isInMessageList && (
20032017
<>
@@ -2084,6 +2098,8 @@ const Composer: FC<OwnProps & StateProps> = ({
20842098
theme={theme}
20852099
onMenuOpen={onAttachMenuOpen}
20862100
onMenuClose={onAttachMenuClose}
2101+
messageListType={messageListType}
2102+
paidMessagesStars={paidMessagesStars}
20872103
/>
20882104
)}
20892105
{isInMessageList && Boolean(botKeyboardMessageId) && (
@@ -2354,6 +2370,8 @@ export default memo(withGlobal<OwnProps>(
23542370

23552371
const maxMessageLength = global.config?.maxMessageLength || DEFAULT_MAX_MESSAGE_LENGTH;
23562372
const isForwarding = chatId === tabState.forwardMessages.toChatId;
2373+
const starsBalance = global.stars?.balance.amount || 0;
2374+
const isStarsBalanceModalOpen = Boolean(tabState.starsBalanceModal);
23572375

23582376
return {
23592377
availableReactions: global.reactions.availableReactions,
@@ -2436,6 +2454,8 @@ export default memo(withGlobal<OwnProps>(
24362454
shouldPaidMessageAutoApprove,
24372455
isSilentPosting,
24382456
isPaymentMessageConfirmDialogOpen: tabState.isPaymentMessageConfirmDialogOpen,
2457+
starsBalance,
2458+
isStarsBalanceModalOpen,
24392459
};
24402460
},
24412461
)(Composer));

src/components/common/DeleteMessageModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ import type { IRadioOption } from '../ui/CheckboxGroup';
1212

1313
import {
1414
getHasAdminRight,
15-
getPeerTitle,
1615
getPrivateChatUserId,
1716
getUserFirstOrLastName, isChatBasicGroup,
1817
isChatChannel,
1918
isChatSuperGroup,
2019
isSystemBot,
2120
isUserId,
2221
} from '../../global/helpers';
22+
import { getPeerTitle } from '../../global/helpers/peers';
2323
import {
2424
getSendersFromSelectedMessages,
2525
selectBot,

src/components/common/FullNameTitle.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import {
1515
isAnonymousForwardsChat,
1616
isChatWithRepliesBot,
1717
isChatWithVerificationCodesBot,
18-
isPeerUser,
1918
} from '../../global/helpers';
19+
import { isApiPeerUser } from '../../global/helpers/peers';
2020
import buildClassName from '../../util/buildClassName';
2121
import buildStyle from '../../util/buildStyle';
2222
import { copyTextToClipboard } from '../../util/clipboard';
@@ -71,7 +71,7 @@ const FullNameTitle: FC<OwnProps> = ({
7171
const { showNotification } = getActions();
7272
const realPeer = 'id' in peer ? peer : undefined;
7373
const customPeer = 'isCustomPeer' in peer ? peer : undefined;
74-
const isUser = realPeer && isPeerUser(realPeer);
74+
const isUser = realPeer && isApiPeerUser(realPeer);
7575
const title = realPeer && (isUser ? getUserFullName(realPeer) : getChatTitle(lang, realPeer));
7676
const isPremium = isUser && realPeer.isPremium;
7777
const canShowEmojiStatus = withEmojiStatus && !isSavedMessages && realPeer;

0 commit comments

Comments
 (0)