Browse Source

Recurring payments

master
Eduard Kuzmenko 2 years ago
parent
commit
24bdb104b0
  1. 40
      src/components/popups/payment.ts
  2. 6
      src/components/wrappers/messageActionTextNewUnsafe.ts
  3. 11
      src/lang.ts
  4. 9
      src/lib/appManagers/appDialogsManager.ts
  5. 2
      src/lib/appManagers/appMessagesManager.ts
  6. 5
      src/lib/langPack.ts
  7. 2
      src/lib/mtproto/dcConfigurator.ts
  8. 4
      src/scss/partials/_checkbox.scss
  9. 2
      src/scss/partials/_row.scss
  10. 4
      src/scss/partials/popups/_payment.scss

40
src/components/popups/payment.ts

@ -27,9 +27,11 @@ import { AccountTmpPassword, InputInvoice, InputPaymentCredentials, LabeledPrice @@ -27,9 +27,11 @@ import { AccountTmpPassword, InputInvoice, InputPaymentCredentials, LabeledPrice
import I18n, { i18n, LangPackKey, _i18n } from "../../lib/langPack";
import { ApiError } from "../../lib/mtproto/apiManager";
import wrapEmojiText from "../../lib/richTextProcessor/wrapEmojiText";
import wrapRichText from "../../lib/richTextProcessor/wrapRichText";
import rootScope from "../../lib/rootScope";
import AvatarElement from "../avatar";
import Button from "../button";
import CheckboxField from "../checkboxField";
import PeerTitle from "../peerTitle";
import { putPreloader } from "../putPreloader";
import Row from "../row";
@ -240,10 +242,6 @@ export default class PopupPayment extends PopupElement { @@ -240,10 +242,6 @@ export default class PopupPayment extends PopupElement {
// console.log(paymentForm, lastRequestedInfo);
await peerTitle.update({peerId: paymentForm.bot_id.toPeerId()});
preloaderContainer.remove();
this.element.classList.remove('is-loading');
const wrapAmount = (amount: string | number, skipSymbol?: boolean) => {
return paymentsWrapCurrencyAmount(amount, currency, skipSymbol);
};
@ -251,6 +249,13 @@ export default class PopupPayment extends PopupElement { @@ -251,6 +249,13 @@ export default class PopupPayment extends PopupElement {
const {invoice} = paymentForm;
const currency = invoice.currency;
const isRecurring = invoice.pFlags.recurring && !isReceipt;
await peerTitle.update({peerId: paymentForm.bot_id.toPeerId()});
const peerTitle2 = isRecurring ? await wrapPeerTitle({peerId: paymentForm.bot_id.toPeerId()}) : undefined;
preloaderContainer.remove();
this.element.classList.remove('is-loading');
const makeLabel = () => {
const labelEl = document.createElement('div');
labelEl.classList.add(pricesClassName + '-price');
@ -669,9 +674,23 @@ export default class PopupPayment extends PopupElement { @@ -669,9 +674,23 @@ export default class PopupPayment extends PopupElement {
shippingEmailRow,
shippingPhoneRow,
].filter(Boolean);
const acceptTermsCheckboxField = isRecurring && new CheckboxField({
text: 'Payments.Recurrent.Accept',
textArgs: [wrapRichText(invoice.recurring_terms_url), peerTitle2]
});
const acceptTermsRow = isRecurring && createRow({
checkboxField: acceptTermsCheckboxField,
noCheckboxSubtitle: true
});
const recurringElements = isRecurring ? [document.createElement('hr'), acceptTermsRow.container] : [];
this.scrollable.append(...[
document.createElement('hr'),
...rows.map((row) => row.container)
...rows.map((row) => row.container),
...recurringElements
].filter(Boolean));
///
@ -779,7 +798,11 @@ export default class PopupPayment extends PopupElement { @@ -779,7 +798,11 @@ export default class PopupPayment extends PopupElement {
});
};
let payButton: HTMLElement;
const onChange = () => {
payButton.disabled = !!(acceptTermsCheckboxField && !acceptTermsCheckboxField.checked);
};
let payButton: HTMLButtonElement;
if(isReceipt) {
payButton = PaymentButton({
onClick: () => this.hide(),
@ -792,6 +815,11 @@ export default class PopupPayment extends PopupElement { @@ -792,6 +815,11 @@ export default class PopupPayment extends PopupElement {
});
}
onChange();
if(acceptTermsCheckboxField) {
acceptTermsCheckboxField.input.addEventListener('change', onChange);
}
this.body.append(this.btnConfirmOnEnter = payButton);
this.onContentUpdate();

6
src/components/wrappers/messageActionTextNewUnsafe.ts

@ -250,7 +250,9 @@ export default async function wrapMessageActionTextNewUnsafe(message: MyMessage, @@ -250,7 +250,9 @@ export default async function wrapMessageActionTextNewUnsafe(message: MyMessage,
}
case 'messageActionPaymentSent': {
langPackKey = 'PaymentSuccessfullyPaidNoItem';
const isRecurringInit = action.pFlags.recurring_init;
const isRecurringUsed = action.pFlags.recurring_used;
langPackKey = isRecurringUsed ? 'Chat.Service.PaymentSentRecurringUsedNoTitle' : (isRecurringInit ? 'Chat.Service.PaymentSentRecurringInitNoTitle' : 'Chat.Service.PaymentSent1NoTitle');
const price = paymentsWrapCurrencyAmount(action.total_amount, action.currency);
args = [price, getNameDivHTML(message.peerId, plain)];
@ -263,7 +265,7 @@ export default async function wrapMessageActionTextNewUnsafe(message: MyMessage, @@ -263,7 +265,7 @@ export default async function wrapMessageActionTextNewUnsafe(message: MyMessage,
if(!invoiceMessage) {
managers.appMessagesManager.fetchMessageReplyTo(message);
} else {
langPackKey = 'PaymentSuccessfullyPaid';
langPackKey = isRecurringUsed ? 'Chat.Service.PaymentSentRecurringUsed' : (isRecurringInit ? 'Chat.Service.PaymentSentRecurringInit' : 'Chat.Service.PaymentSent1');
args.push(wrapLinkToMessage(invoiceMessage, plain));
}
}

11
src/lang.ts

@ -703,10 +703,6 @@ const lang = { @@ -703,10 +703,6 @@ const lang = {
"PaymentInvoice": "INVOICE",
"PaymentTestInvoice": "TEST INVOICE",
"PaymentReceipt": "Receipt",
"PaymentSuccessfullyPaid": "You successfully transferred %1$s to %2$s for %3$s",
"PaymentSuccessfullyPaidNoItem": "You successfully transferred %1$s to %2$s",
// "PaymentSuccessfullyPaidRecurrent": "You successfully transferred %1$s to %2$s for %3$s and allowed future recurring payments",
// "PaymentSuccessfullyPaidNoItemRecurrent": "You successfully transferred %1$s to %2$s and allowed future recurring payments",
"PaymentCheckout": "Checkout",
"PaymentTransactionTotal": "Total",
"PaymentTip": "Tip",
@ -835,6 +831,12 @@ const lang = { @@ -835,6 +831,12 @@ const lang = {
"Chat.Service.Channel.UpdatedVideo": "Channel video updated",
"Chat.Service.BotPermissionAllowed": "You allowed this bot to message you when you logged in on %@",
"Chat.Service.Group.UpdatedPinnedMessage": "%@ pinned \"%@\"",
"Chat.Service.PaymentSent1": "You have successfully transferred **%1$@** to **%2$@** for **%3$@**",
"Chat.Service.PaymentSent1NoTitle": "You have successfully transferred **%1$@** to **%2$@**",
"Chat.Service.PaymentSentRecurringInit": "You successfully transferred **%1$@** to **%2$@** for **%3$@** and allowed future recurring payments",
"Chat.Service.PaymentSentRecurringInitNoTitle": "You successfully transferred **%1$@** to **%2$@** and allowed future recurring payments",
"Chat.Service.PaymentSentRecurringUsed": "You have just successfully transferred **%1$@** to **%2$@** for **%3$@** via recurrent payments",
"Chat.Service.PaymentSentRecurringUsedNoTitle": "You have just successfully transferred **%1$@** to **%2$@** via recurrent payments",
"Chat.Service.VoiceChatStarted": "%1$@ started a [video chat](open)",
"Chat.Service.VoiceChatStartedYou": "You started a [video chat](open)",
"Chat.Service.VoiceChatStarted.Channel": "[Live Stream](open) started",
@ -985,6 +987,7 @@ const lang = { @@ -985,6 +987,7 @@ const lang = {
"NewPoll.Quiz": "Quiz Mode",
"Notification.Contact.Reacted": "%1$@ to your \"%2$@\"",
// "Notification.Group.Reacted": "%1$@: %2$@ to your \"%3$@\"",
"Payments.Recurrent.Accept": "I accept [Terms of Service]() of **%@**.",
"Peer.Activity.User.PlayingGame": "playing a game",
"Peer.Activity.User.TypingText": "typing",
"Peer.Activity.User.SendingPhoto": "sending a photo",

9
src/lib/appManagers/appDialogsManager.ts

@ -80,6 +80,7 @@ import noop from "../../helpers/noop"; @@ -80,6 +80,7 @@ import noop from "../../helpers/noop";
import DialogsPlaceholder from "../../helpers/dialogsPlaceholder";
import pause from "../../helpers/schedulers/pause";
import apiManagerProxy from "../mtproto/mtprotoworker";
import filterAsync from "../../helpers/array/filterAsync";
export const DIALOG_LIST_ELEMENT_TAG = 'A';
@ -1287,11 +1288,13 @@ export class AppDialogsManager { @@ -1287,11 +1288,13 @@ export class AppDialogsManager {
this.loadContacts = () => {
const pageCount = windowSize.height / 60 | 0;
const arr = contacts.splice(0, pageCount).filter(this.verifyPeerIdForContacts);
const promise = filterAsync(contacts.splice(0, pageCount), this.verifyPeerIdForContacts);
promise.then((arr) => {
arr.forEach((peerId) => {
sortedUserList.add(peerId);
});
});
if(!contacts.length) {
this.loadContacts = undefined;
@ -1300,12 +1303,12 @@ export class AppDialogsManager { @@ -1300,12 +1303,12 @@ export class AppDialogsManager {
this.loadContacts();
this.processContact = (peerId) => {
this.processContact = async(peerId) => {
if(peerId.isAnyChat()) {
return;
}
const good = this.verifyPeerIdForContacts(peerId);
const good = await this.verifyPeerIdForContacts(peerId);
const added = sortedUserList.has(peerId);
if(!added && good) sortedUserList.add(peerId);
else if(added && !good) sortedUserList.delete(peerId);

2
src/lib/appManagers/appMessagesManager.ts

@ -4027,7 +4027,7 @@ export class AppMessagesManager extends AppManager { @@ -4027,7 +4027,7 @@ export class AppMessagesManager extends AppManager {
this.onUpdateNewMessage(update);
}
if(message._ === 'messageService' && message.action._ === 'messageActionPaymentSent') {
if(message._ === 'messageService' && message.action._ === 'messageActionPaymentSent' && message.reply_to) {
this.rootScope.dispatchEvent('payment_sent', {
peerId: message.reply_to.reply_to_peer_id ? getPeerId(message.reply_to.reply_to_peer_id) : message.peerId,
mid: message.reply_to_mid

5
src/lib/langPack.ts

@ -368,6 +368,11 @@ namespace I18n { @@ -368,6 +368,11 @@ namespace I18n {
a.target = '_blank';
} else {
a = args[indexHolder.i++] as HTMLAnchorElement;
if(a instanceof DocumentFragment) { // right after wrapRichText
a = a.firstChild as any;
}
a.textContent = ''; // reset content
}

2
src/lib/mtproto/dcConfigurator.ts

@ -65,7 +65,7 @@ export class DcConfigurator { @@ -65,7 +65,7 @@ export class DcConfigurator {
/// #if MTPROTO_HAS_WS
private transportSocket = (dcId: DcId, connectionType: ConnectionType, suffix: string, premium?: boolean) => {
const path = connectionType !== 'client' ? 'apiws' + (premium ? PREMIUM_SUFFIX : '') : ('apiws' + TEST_SUFFIX);
const path = connectionType !== 'client' ? 'apiws' + (premium ? PREMIUM_SUFFIX : TEST_SUFFIX) : ('apiws' + TEST_SUFFIX);
const chosenServer = `wss://${App.suffix.toLowerCase()}ws${dcId}${suffix}.web.telegram.org/${path}`;
const logSuffix = connectionType === 'upload' ? '-U' : connectionType === 'download' ? '-D' : '';

4
src/scss/partials/_checkbox.scss

@ -124,6 +124,10 @@ @@ -124,6 +124,10 @@
left: auto;
}
}
.anchor-url {
pointer-events: all;
}
}
.checkbox-ripple {

2
src/scss/partials/_row.scss

@ -119,7 +119,9 @@ $row-border-radius: $border-radius-medium; @@ -119,7 +119,9 @@ $row-border-radius: $border-radius-medium;
}
.checkbox-field {
margin-top: 0;
margin-right: 0;
margin-bottom: 0;
height: auto;
.checkbox-caption {

4
src/scss/partials/popups/_payment.scss

@ -36,6 +36,8 @@ @@ -36,6 +36,8 @@
hr {
display: block !important;
margin: .5rem 0 !important;
padding: 0 !important;
}
.input-field {
@ -158,7 +160,7 @@ @@ -158,7 +160,7 @@
&-prices {
display: flex;
flex-direction: column;
margin: 1rem .25rem;
margin: 1rem .25rem .5rem;
&-price {
color: var(--secondary-text-color);

Loading…
Cancel
Save