parent
5b1097d7f9
commit
c1f87d1b3e
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 240 KiB After Width: | Height: | Size: 241 KiB |
Binary file not shown.
Binary file not shown.
|
@ -29,6 +29,7 @@ import PopupForward from './popups/forward';
|
|||
import Scrollable from './scrollable';
|
||||
import appSidebarRight from './sidebarRight';
|
||||
import AppSharedMediaTab from './sidebarRight/tabs/sharedMedia';
|
||||
import PopupElement from './popups';
|
||||
|
||||
type AppMediaViewerTargetType = {
|
||||
element: HTMLElement,
|
||||
|
@ -193,7 +194,7 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet
|
|||
|
||||
onDeleteClick = () => {
|
||||
const target = this.target;
|
||||
new PopupDeleteMessages(target.peerId, [target.mid], 'chat', () => {
|
||||
PopupElement.createPopup(PopupDeleteMessages, target.peerId, [target.mid], 'chat', () => {
|
||||
this.target = {element: this.content.media} as any;
|
||||
this.close();
|
||||
});
|
||||
|
@ -203,7 +204,7 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet
|
|||
const target = this.target;
|
||||
if(target.mid) {
|
||||
// appSidebarRight.forwardTab.open([target.mid]);
|
||||
new PopupForward({
|
||||
PopupElement.createPopup(PopupForward, {
|
||||
[target.peerId]: [target.mid]
|
||||
}, () => {
|
||||
return this.close();
|
||||
|
|
|
@ -1151,7 +1151,7 @@
|
|||
// onForwardClick = () => {
|
||||
// if(this.currentMessageId) {
|
||||
// //appSidebarRight.forwardTab.open([this.currentMessageId]);
|
||||
// new PopupForward(this.currentPeerId, [this.currentMessageId], () => {
|
||||
// PopupElement.createPopup(PopupForward(this.currentPeerId, [this.currentMessageId], , ) => {
|
||||
// return this.close();
|
||||
// });
|
||||
// }
|
||||
|
|
|
@ -77,6 +77,7 @@ import noop from '../helpers/noop';
|
|||
import wrapMediaSpoiler, {onMediaSpoilerClick} from './wrappers/mediaSpoiler';
|
||||
import filterAsync from '../helpers/array/filterAsync';
|
||||
import ChatContextMenu from './chat/contextMenu';
|
||||
import PopupElement from './popups';
|
||||
|
||||
// const testScroll = false;
|
||||
|
||||
|
@ -257,7 +258,7 @@ class SearchContextMenu {
|
|||
if(this.searchSuper.selection.isSelecting) {
|
||||
simulateClickEvent(this.searchSuper.selection.selectionForwardBtn);
|
||||
} else {
|
||||
new PopupForward({
|
||||
PopupElement.createPopup(PopupForward, {
|
||||
[this.peerId]: [this.mid]
|
||||
});
|
||||
}
|
||||
|
@ -275,7 +276,7 @@ class SearchContextMenu {
|
|||
if(this.searchSuper.selection.isSelecting) {
|
||||
simulateClickEvent(this.searchSuper.selection.selectionDeleteBtn);
|
||||
} else {
|
||||
new PopupDeleteMessages(this.peerId, [this.mid], 'chat');
|
||||
PopupElement.createPopup(PopupDeleteMessages, this.peerId, [this.mid], 'chat');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import {i18n, LangPackKey} from '../lib/langPack';
|
||||
import {FormatterArguments, i18n, LangPackKey} from '../lib/langPack';
|
||||
import ripple from './ripple';
|
||||
|
||||
export type ButtonOptions = Partial<{
|
||||
|
@ -13,6 +13,7 @@ export type ButtonOptions = Partial<{
|
|||
icon: string,
|
||||
rippleSquare: true,
|
||||
text: LangPackKey,
|
||||
textArgs?: FormatterArguments,
|
||||
disabled: boolean,
|
||||
asDiv: boolean,
|
||||
asLink: boolean
|
||||
|
@ -39,7 +40,7 @@ export default function Button<T extends ButtonOptions>(className: string, optio
|
|||
}
|
||||
|
||||
if(options.text) {
|
||||
button.append(i18n(options.text));
|
||||
button.append(i18n(options.text, options.textArgs));
|
||||
}
|
||||
|
||||
return button as any;
|
||||
|
|
|
@ -8,6 +8,7 @@ import Button from './button';
|
|||
|
||||
const ButtonCorner = (options: Partial<{className: string, icon: string, noRipple: true, onlyMobile: true, asDiv: boolean}> = {}) => {
|
||||
const button = Button('btn-circle btn-corner z-depth-1' + (options.className ? ' ' + options.className : ''), options);
|
||||
button.tabIndex = -1;
|
||||
return button;
|
||||
};
|
||||
|
||||
|
|
|
@ -785,13 +785,30 @@ export default class ChatBubbles {
|
|||
const bubble = this.bubbles[mid];
|
||||
if(!bubble) return;
|
||||
|
||||
const message = (await this.chat.getMessage(mid)) as Message.message;
|
||||
const [message, originalMessage] = await Promise.all([
|
||||
(await this.chat.getMessage(mid)) as Message.message,
|
||||
(await this.managers.appMessagesManager.getMessageByPeer(replyToPeerId, replyMid)) as Message.message
|
||||
]);
|
||||
if(!middleware()) return;
|
||||
|
||||
MessageRender.setReply({
|
||||
chat: this.chat,
|
||||
bubble,
|
||||
message
|
||||
});
|
||||
|
||||
let maxMediaTimestamp: number;
|
||||
const timestamps = bubble.querySelectorAll<HTMLAnchorElement>('.timestamp');
|
||||
if(originalMessage && (maxMediaTimestamp = getMediaDurationFromMessage(originalMessage))) {
|
||||
timestamps.forEach((timestamp) => {
|
||||
const value = +timestamp.dataset.timestamp;
|
||||
if(value < maxMediaTimestamp) {
|
||||
timestamp.classList.remove('is-disabled');
|
||||
} else {
|
||||
timestamp.removeAttribute('href');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1787,7 +1804,8 @@ export default class ChatBubbles {
|
|||
return;
|
||||
}
|
||||
|
||||
new PopupPayment(
|
||||
PopupElement.createPopup(
|
||||
PopupPayment,
|
||||
message as Message.message,
|
||||
await this.managers.appPaymentsManager.getInputInvoiceByPeerId(message.peerId, message.mid)
|
||||
);
|
||||
|
@ -1878,7 +1896,7 @@ export default class ChatBubbles {
|
|||
const message = await this.managers.appMessagesManager.getMessageByPeer(peerId.toPeerId(), +mid);
|
||||
if(message) {
|
||||
const inputInvoice = await this.managers.appPaymentsManager.getInputInvoiceByPeerId(this.peerId, +bubble.dataset.mid);
|
||||
new PopupPayment(message as Message.message, inputInvoice, undefined, true);
|
||||
PopupElement.createPopup(PopupPayment, message as Message.message, inputInvoice, undefined, true);
|
||||
}
|
||||
} else {
|
||||
this.chat.appImManager.setInnerPeer({
|
||||
|
@ -1916,7 +1934,7 @@ export default class ChatBubbles {
|
|||
const doc = ((message as Message.message).media as MessageMedia.messageMediaDocument)?.document as Document.document;
|
||||
|
||||
if(doc?.stickerSetInput) {
|
||||
new PopupStickers(doc.stickerSetInput).show();
|
||||
PopupElement.createPopup(PopupStickers, doc.stickerSetInput).show();
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -1941,7 +1959,7 @@ export default class ChatBubbles {
|
|||
} else if(target.classList.contains('forward')) {
|
||||
const mid = +bubble.dataset.mid;
|
||||
const message = await this.managers.appMessagesManager.getMessageByPeer(this.peerId, mid);
|
||||
new PopupForward({
|
||||
PopupElement.createPopup(PopupForward, {
|
||||
[this.peerId]: await this.managers.appMessagesManager.getMidsByMessage(message)
|
||||
});
|
||||
// appSidebarRight.forwardTab.open([mid]);
|
||||
|
@ -3024,6 +3042,16 @@ export default class ChatBubbles {
|
|||
this.chat.input.setStartParam(startParam);
|
||||
}
|
||||
|
||||
if(options.mediaTimestamp) {
|
||||
getHeavyAnimationPromise().then(() => {
|
||||
this.playMediaWithTimestampAndMid({
|
||||
lastMsgId,
|
||||
middleware,
|
||||
mediaTimestamp: options.mediaTimestamp
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
|
@ -3251,13 +3279,11 @@ export default class ChatBubbles {
|
|||
pause(400) :
|
||||
Promise.resolve();
|
||||
p.then(() => {
|
||||
return this.getMountedBubble(lastMsgId);
|
||||
}).then((mounted) => {
|
||||
if(!middleware() || !mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.playMediaWithTimestamp(mounted.bubble, options.mediaTimestamp);
|
||||
return this.playMediaWithTimestampAndMid({
|
||||
lastMsgId,
|
||||
middleware,
|
||||
mediaTimestamp: options.mediaTimestamp
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -3305,6 +3331,24 @@ export default class ChatBubbles {
|
|||
return {cached, promise: setPeerPromise};
|
||||
}
|
||||
|
||||
public playMediaWithTimestampAndMid({
|
||||
middleware,
|
||||
lastMsgId,
|
||||
mediaTimestamp
|
||||
}: {
|
||||
middleware: () => boolean,
|
||||
lastMsgId: number,
|
||||
mediaTimestamp: number
|
||||
}) {
|
||||
this.getMountedBubble(lastMsgId).then((mounted) => {
|
||||
if(!middleware() || !mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.playMediaWithTimestamp(mounted.bubble, mediaTimestamp);
|
||||
});
|
||||
}
|
||||
|
||||
public playMediaWithTimestamp(element: HTMLElement, timestamp: number) {
|
||||
const bubble = findUpClassName(element, 'bubble');
|
||||
const groupedItem = findUpClassName(element, 'grouped-item');
|
||||
|
@ -3325,6 +3369,19 @@ export default class ChatBubbles {
|
|||
audio.playWithTimestamp(timestamp);
|
||||
return;
|
||||
}
|
||||
|
||||
const replyToPeerId = bubble.dataset.replyToPeerId.toPeerId();
|
||||
const replyToMid = +bubble.dataset.replyToMid;
|
||||
if(replyToPeerId && replyToMid) {
|
||||
if(replyToPeerId === this.peerId) {
|
||||
this.chat.setMessageId(replyToMid, timestamp);
|
||||
} else {
|
||||
this.chat.appImManager.setInnerPeer({
|
||||
peerId: replyToPeerId,
|
||||
mediaTimestamp: timestamp
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async setFetchReactionsInterval(afterSetPromise: Promise<any>) {
|
||||
|
@ -3937,11 +3994,28 @@ export default class ChatBubbles {
|
|||
|
||||
customEmojiSize ??= this.chat.appImManager.customEmojiSize;
|
||||
|
||||
const maxMediaTimestamp = getMediaDurationFromMessage(albumTextMessage || message as Message.message);
|
||||
let maxMediaTimestamp = getMediaDurationFromMessage(albumTextMessage || message as Message.message);
|
||||
if(albumTextMessage && needToSetHTML) {
|
||||
bubble.dataset.textMid = '' + albumTextMessage.mid;
|
||||
}
|
||||
|
||||
if(message.reply_to) {
|
||||
const replyToPeerId = message.reply_to.reply_to_peer_id ? getPeerId(message.reply_to.reply_to_peer_id) : this.peerId;
|
||||
bubble.dataset.replyToPeerId = '' + replyToPeerId;
|
||||
bubble.dataset.replyToMid = '' + message.reply_to_mid;
|
||||
|
||||
if(maxMediaTimestamp === undefined) {
|
||||
const originalMessage = await rootScope.managers.appMessagesManager.getMessageByPeer(replyToPeerId, message.reply_to_mid);
|
||||
if(originalMessage) {
|
||||
maxMediaTimestamp = getMediaDurationFromMessage(originalMessage as Message.message);
|
||||
} else {
|
||||
// this.managers.appMessagesManager.fetchMessageReplyTo(message);
|
||||
// this.needUpdate.push({replyToPeerId, replyMid: message.reply_to_mid, mid: message.mid});
|
||||
maxMediaTimestamp = Infinity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const richTextOptions: Parameters<typeof wrapRichText>[1] = {
|
||||
entities: totalEntities,
|
||||
passEntities: this.passEntities,
|
||||
|
@ -4095,7 +4169,7 @@ export default class ChatBubbles {
|
|||
}
|
||||
|
||||
return new Promise<PeerId>((resolve, reject) => {
|
||||
const popup = new PopupForward(undefined, (peerId) => {
|
||||
const popup = PopupElement.createPopup(PopupForward, undefined, (peerId) => {
|
||||
resolve(peerId);
|
||||
});
|
||||
|
||||
|
@ -5726,7 +5800,7 @@ export default class ChatBubbles {
|
|||
|
||||
if(sponsoredMessage.chat_invite) {
|
||||
callback = () => {
|
||||
new PopupJoinChatInvite(sponsoredMessage.chat_invite_hash, sponsoredMessage.chat_invite as ChatInvite.chatInvite);
|
||||
PopupElement.createPopup(PopupJoinChatInvite, sponsoredMessage.chat_invite_hash, sponsoredMessage.chat_invite as ChatInvite.chatInvite);
|
||||
};
|
||||
} else if(sponsoredMessage.chat_invite_hash) {
|
||||
callback = () => {
|
||||
|
@ -6147,6 +6221,11 @@ export default class ChatBubbles {
|
|||
return result;
|
||||
}
|
||||
|
||||
// private async getDiscussionMessages() {
|
||||
// const mids = await this.chat.getMidsByMid(this.chat.threadId);
|
||||
// return Promise.all(mids.map((mid) => this.chat.getMessage(mid)));
|
||||
// }
|
||||
|
||||
/**
|
||||
* Load and render history
|
||||
* @param maxId max message id
|
||||
|
|
|
@ -571,11 +571,12 @@ export default class Chat extends EventListenerBase<{
|
|||
this.autoDownload = await getAutoDownloadSettingsByPeerId(this.peerId);
|
||||
}
|
||||
|
||||
public setMessageId(messageId?: number) {
|
||||
public setMessageId(messageId?: number, mediaTimestamp?: number) {
|
||||
return this.setPeer({
|
||||
peerId: this.peerId,
|
||||
threadId: this.threadId,
|
||||
lastMsgId: messageId
|
||||
lastMsgId: messageId,
|
||||
mediaTimestamp
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -711,4 +712,9 @@ export default class Chat extends EventListenerBase<{
|
|||
public isPinnedMessagesNeeded() {
|
||||
return this.type === 'chat' || this.isForum;
|
||||
}
|
||||
|
||||
public canGiftPremium() {
|
||||
const peerId = this.peerId;
|
||||
return peerId.isUser() && this.managers.appProfileManager.canGiftPremium(this.peerId.toUserId());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ import PopupStickers from '../popups/stickers';
|
|||
import getMediaFromMessage from '../../lib/appManagers/utils/messages/getMediaFromMessage';
|
||||
import canSaveMessageMedia from '../../lib/appManagers/utils/messages/canSaveMessageMedia';
|
||||
import getAlbumText from '../../lib/appManagers/utils/messages/getAlbumText';
|
||||
import PopupElement from '../popups';
|
||||
|
||||
export default class ChatContextMenu {
|
||||
private buttons: (ButtonMenuItemOptions & {verify: () => boolean | Promise<boolean>, notDirect?: () => boolean, withSelection?: true, isSponsored?: true, localName?: 'views' | 'emojis'})[];
|
||||
|
@ -490,7 +491,7 @@ export default class ChatContextMenu {
|
|||
icon: 'flag',
|
||||
text: 'ReportChat',
|
||||
onClick: () => {
|
||||
new PopupReportMessages(this.peerId, [this.mid]);
|
||||
PopupElement.createPopup(PopupReportMessages, this.peerId, [this.mid]);
|
||||
},
|
||||
verify: async() => !this.message.pFlags.out && this.message._ === 'message' && !this.message.pFlags.is_outgoing && await this.managers.appPeersManager.isChannel(this.peerId),
|
||||
notDirect: () => true,
|
||||
|
@ -516,7 +517,7 @@ export default class ChatContextMenu {
|
|||
peerId: this.viewerPeerId
|
||||
});
|
||||
} else if(this.canOpenReactedList) {
|
||||
new PopupReactedList(this.message as Message.message);
|
||||
PopupElement.createPopup(PopupReactedList, this.message as Message.message);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -540,7 +541,7 @@ export default class ChatContextMenu {
|
|||
icon: 'info',
|
||||
text: 'Chat.Message.Sponsored.What',
|
||||
onClick: () => {
|
||||
new PopupSponsored();
|
||||
PopupElement.createPopup(PopupSponsored);
|
||||
},
|
||||
verify: () => false,
|
||||
isSponsored: true
|
||||
|
@ -549,7 +550,7 @@ export default class ChatContextMenu {
|
|||
text: 'Loading',
|
||||
onClick: () => {
|
||||
this.emojiInputsPromise.then((inputs) => {
|
||||
new PopupStickers(inputs, true).show();
|
||||
PopupElement.createPopup(PopupStickers, inputs, true).show();
|
||||
});
|
||||
},
|
||||
verify: () => !!this.getUniqueCustomEmojisFromMessage().length,
|
||||
|
@ -890,7 +891,7 @@ export default class ChatContextMenu {
|
|||
if(this.chat.selection.isSelecting) {
|
||||
simulateClickEvent(this.chat.selection.selectionSendNowBtn);
|
||||
} else {
|
||||
new PopupSendNow(this.peerId, await this.chat.getMidsByMid(this.mid));
|
||||
PopupElement.createPopup(PopupSendNow, this.peerId, await this.chat.getMidsByMid(this.mid));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -929,11 +930,11 @@ export default class ChatContextMenu {
|
|||
};
|
||||
|
||||
private onPinClick = () => {
|
||||
new PopupPinMessage(this.peerId, this.mid);
|
||||
PopupElement.createPopup(PopupPinMessage, this.peerId, this.mid);
|
||||
};
|
||||
|
||||
private onUnpinClick = () => {
|
||||
new PopupPinMessage(this.peerId, this.mid, true);
|
||||
PopupElement.createPopup(PopupPinMessage, this.peerId, this.mid, true);
|
||||
};
|
||||
|
||||
private onRetractVote = () => {
|
||||
|
@ -968,7 +969,7 @@ export default class ChatContextMenu {
|
|||
if(this.chat.selection.isSelecting) {
|
||||
simulateClickEvent(this.chat.selection.selectionDeleteBtn);
|
||||
} else {
|
||||
new PopupDeleteMessages(this.peerId, this.isTargetAGroupedItem ? [this.mid] : await this.chat.getMidsByMid(this.mid), this.chat.type);
|
||||
PopupElement.createPopup(PopupDeleteMessages, this.peerId, this.isTargetAGroupedItem ? [this.mid] : await this.chat.getMidsByMid(this.mid), this.chat.type);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -111,6 +111,7 @@ import {MARKDOWN_ENTITIES} from '../../lib/richTextProcessor';
|
|||
import IMAGE_MIME_TYPES_SUPPORTED from '../../environment/imageMimeTypesSupport';
|
||||
import VIDEO_MIME_TYPES_SUPPORTED from '../../environment/videoMimeTypesSupport';
|
||||
import {ChatRights} from '../../lib/appManagers/appChatsManager';
|
||||
import PopupGiftPremium from '../popups/giftPremium';
|
||||
|
||||
const RECORD_MIN_TIME = 500;
|
||||
|
||||
|
@ -644,6 +645,11 @@ export default class ChatInput {
|
|||
this.fileInput.click();
|
||||
}
|
||||
// verify: () => this.chat.canSend('send_docs')
|
||||
}, {
|
||||
icon: 'gift',
|
||||
text: 'GiftPremium',
|
||||
onClick: () => this.chat.appImManager.giftPremium(this.chat.peerId),
|
||||
verify: () => this.chat.canGiftPremium()
|
||||
}, {
|
||||
icon: 'poll',
|
||||
text: 'Poll',
|
||||
|
@ -1049,7 +1055,7 @@ export default class ChatInput {
|
|||
this.listenerSetter.add(this.pinnedControlBtn)('click', () => {
|
||||
const peerId = this.chat.peerId;
|
||||
|
||||
new PopupPinMessage(peerId, 0, true, () => {
|
||||
PopupElement.createPopup(PopupPinMessage, peerId, 0, true, () => {
|
||||
this.chat.appImManager.setPeer(); // * close tab
|
||||
|
||||
// ! костыль, это скроет закреплённые сообщения сразу, вместо того, чтобы ждать пока анимация перехода закончится
|
||||
|
@ -1219,7 +1225,7 @@ export default class ChatInput {
|
|||
const middleware = this.chat.bubbles.getMiddleware();
|
||||
const canSendWhenOnline = rootScope.myId !== peerId && peerId.isUser() && await this.managers.appUsersManager.isUserOnlineVisible(peerId);
|
||||
|
||||
new PopupSchedule(initDate, (timestamp) => {
|
||||
PopupElement.createPopup(PopupSchedule, initDate, (timestamp) => {
|
||||
if(!middleware()) {
|
||||
return;
|
||||
}
|
||||
|
@ -2470,7 +2476,7 @@ export default class ChatInput {
|
|||
opusDecodeController.setKeepAlive(true);
|
||||
|
||||
const showDiscardPopup = () => {
|
||||
new PopupPeer('popup-cancel-record', {
|
||||
PopupElement.createPopup(PopupPeer, 'popup-cancel-record', {
|
||||
titleLangKey: 'DiscardVoiceMessageTitle',
|
||||
descriptionLangKey: 'DiscardVoiceMessageDescription',
|
||||
buttons: [{
|
||||
|
@ -2614,7 +2620,7 @@ export default class ChatInput {
|
|||
}
|
||||
|
||||
if(!draftsAreEqual(draft, originalDraft)) {
|
||||
new PopupPeer('discard-editing', {
|
||||
PopupElement.createPopup(PopupPeer, 'discard-editing', {
|
||||
buttons: [{
|
||||
langKey: 'Alert.Confirm.Discard',
|
||||
callback: () => {
|
||||
|
@ -2657,7 +2663,7 @@ export default class ChatInput {
|
|||
this.clearHelper();
|
||||
this.updateSendBtn();
|
||||
let selected = false;
|
||||
const popup = new PopupForward(forwarding, () => {
|
||||
const popup = PopupElement.createPopup(PopupForward, forwarding, () => {
|
||||
selected = true;
|
||||
});
|
||||
|
||||
|
@ -2800,7 +2806,7 @@ export default class ChatInput {
|
|||
|
||||
this.onMessageSent();
|
||||
} else {
|
||||
new PopupDeleteMessages(peerId, [editMsgId], chat.type);
|
||||
PopupElement.createPopup(PopupDeleteMessages, peerId, [editMsgId], chat.type);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import throttle from '../../helpers/schedulers/throttle';
|
|||
import {AppManagers} from '../../lib/appManagers/managers';
|
||||
import {Message} from '../../layer';
|
||||
import {logger} from '../../lib/logger';
|
||||
import PopupElement from '../popups';
|
||||
|
||||
class AnimatedSuper {
|
||||
static DURATION = 200;
|
||||
|
@ -275,9 +276,9 @@ export default class ChatPinnedMessage {
|
|||
divAndCaption: dAC,
|
||||
onClose: async() => {
|
||||
if(await managers.appPeersManager.canPinMessage(this.chat.peerId)) {
|
||||
new PopupPinMessage(this.chat.peerId, this.pinnedMid, true);
|
||||
PopupElement.createPopup(PopupPinMessage, this.chat.peerId, this.pinnedMid, true);
|
||||
} else {
|
||||
new PopupPinMessage(this.chat.peerId, 0, true);
|
||||
PopupElement.createPopup(PopupPinMessage, this.chat.peerId, 0, true);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -38,6 +38,7 @@ import {attachContextMenuListener} from '../../helpers/dom/attachContextMenuList
|
|||
import filterUnique from '../../helpers/array/filterUnique';
|
||||
import appImManager from '../../lib/appManagers/appImManager';
|
||||
import {Message} from '../../layer';
|
||||
import PopupElement from '../popups';
|
||||
|
||||
const accumulateMapSet = (map: Map<any, Set<number>>) => {
|
||||
return [...map.values()].reduce((acc, v) => acc + v.size, 0);
|
||||
|
@ -676,7 +677,7 @@ export class SearchSelection extends AppSelection {
|
|||
obj[fromPeerId] = Array.from(mids).sort((a, b) => a - b);
|
||||
}
|
||||
|
||||
new PopupForward(obj, () => {
|
||||
PopupElement.createPopup(PopupForward, obj, () => {
|
||||
this.cancelSelection();
|
||||
});
|
||||
}, attachClickOptions);
|
||||
|
@ -685,7 +686,7 @@ export class SearchSelection extends AppSelection {
|
|||
this.selectionDeleteBtn = ButtonIcon(`delete danger ${BASE_CLASS}-delete`);
|
||||
attachClickEvent(this.selectionDeleteBtn, () => {
|
||||
const peerId = [...this.selectedMids.keys()][0];
|
||||
new PopupDeleteMessages(peerId, [...this.selectedMids.get(peerId)], 'chat', () => {
|
||||
PopupElement.createPopup(PopupDeleteMessages, peerId, [...this.selectedMids.get(peerId)], 'chat', () => {
|
||||
this.cancelSelection();
|
||||
});
|
||||
}, attachClickOptions);
|
||||
|
@ -949,7 +950,7 @@ export default class ChatSelection extends AppSelection {
|
|||
this.selectionSendNowBtn = Button('btn-primary btn-transparent btn-short text-bold selection-container-send', {icon: 'send2'});
|
||||
this.selectionSendNowBtn.append(i18n('MessageScheduleSend'));
|
||||
attachClickEvent(this.selectionSendNowBtn, () => {
|
||||
new PopupSendNow(this.chat.peerId, [...this.selectedMids.get(this.chat.peerId)], () => {
|
||||
PopupElement.createPopup(PopupSendNow, this.chat.peerId, [...this.selectedMids.get(this.chat.peerId)], () => {
|
||||
this.cancelSelection();
|
||||
});
|
||||
}, attachClickOptions);
|
||||
|
@ -962,7 +963,7 @@ export default class ChatSelection extends AppSelection {
|
|||
obj[fromPeerId] = Array.from(mids).sort((a, b) => a - b);
|
||||
}
|
||||
|
||||
new PopupForward(obj, () => {
|
||||
PopupElement.createPopup(PopupForward, obj, () => {
|
||||
this.cancelSelection();
|
||||
});
|
||||
}, attachClickOptions);
|
||||
|
@ -971,7 +972,7 @@ export default class ChatSelection extends AppSelection {
|
|||
this.selectionDeleteBtn = Button('btn-primary btn-transparent danger text-bold selection-container-delete', {icon: 'delete'});
|
||||
this.selectionDeleteBtn.append(i18n('Delete'));
|
||||
attachClickEvent(this.selectionDeleteBtn, () => {
|
||||
new PopupDeleteMessages(this.chat.peerId, [...this.selectedMids.get(this.chat.peerId)], this.chat.type, () => {
|
||||
PopupElement.createPopup(PopupDeleteMessages, this.chat.peerId, [...this.selectedMids.get(this.chat.peerId)], this.chat.type, () => {
|
||||
this.cancelSelection();
|
||||
});
|
||||
}, attachClickOptions);
|
||||
|
|
|
@ -47,6 +47,7 @@ import apiManagerProxy from '../../lib/mtproto/mtprotoworker';
|
|||
import {makeMediaSize} from '../../helpers/mediaSize';
|
||||
import {FOLDER_ID_ALL} from '../../lib/mtproto/mtproto_config';
|
||||
import formatNumber from '../../helpers/number/formatNumber';
|
||||
import PopupElement from '../popups';
|
||||
|
||||
type ButtonToVerify = {element?: HTMLElement, verify: () => boolean | Promise<boolean>};
|
||||
|
||||
|
@ -419,11 +420,11 @@ export default class ChatTopbar {
|
|||
text: 'ShareContact',
|
||||
onClick: () => {
|
||||
const contactPeerId = this.peerId;
|
||||
new PopupPickUser({
|
||||
PopupElement.createPopup(PopupPickUser, {
|
||||
peerTypes: ['dialogs', 'contacts'],
|
||||
onSelect: (peerId) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
new PopupPeer('', {
|
||||
PopupElement.createPopup(PopupPeer, '', {
|
||||
titleLangKey: 'SendMessageTitle',
|
||||
descriptionLangKey: 'SendContactToGroupText',
|
||||
descriptionLangArgs: [new PeerTitle({peerId, dialog: true}).element],
|
||||
|
@ -453,6 +454,11 @@ export default class ChatTopbar {
|
|||
});
|
||||
},
|
||||
verify: async() => rootScope.myId !== this.peerId && this.peerId.isUser() && (await this.managers.appPeersManager.isContact(this.peerId)) && !!(await this.managers.appUsersManager.getUser(this.peerId.toUserId())).phone
|
||||
}, {
|
||||
icon: 'gift',
|
||||
text: 'GiftPremium',
|
||||
onClick: () => this.chat.appImManager.giftPremium(this.peerId),
|
||||
verify: () => this.chat.canGiftPremium()
|
||||
}, {
|
||||
icon: 'bots',
|
||||
text: 'Settings',
|
||||
|
@ -471,7 +477,7 @@ export default class ChatTopbar {
|
|||
icon: 'lock',
|
||||
text: 'BlockUser',
|
||||
onClick: () => {
|
||||
new PopupPeer('', {
|
||||
PopupElement.createPopup(PopupPeer, '', {
|
||||
peerId: this.peerId,
|
||||
titleLangKey: 'BlockUser',
|
||||
descriptionLangKey: 'AreYouSureBlockContact2',
|
||||
|
@ -512,7 +518,7 @@ export default class ChatTopbar {
|
|||
icon: 'delete danger',
|
||||
text: 'Delete',
|
||||
onClick: () => {
|
||||
new PopupDeleteDialog(this.peerId/* , 'leave' */);
|
||||
PopupElement.createPopup(PopupDeleteDialog, this.peerId/* , 'leave' */);
|
||||
},
|
||||
verify: async() => this.chat.type === 'chat' && !!(await this.managers.appMessagesManager.getDialogOnly(this.peerId))
|
||||
}];
|
||||
|
@ -680,7 +686,7 @@ export default class ChatTopbar {
|
|||
}
|
||||
|
||||
private onMuteClick = () => {
|
||||
new PopupMute(this.peerId);
|
||||
PopupElement.createPopup(PopupMute, this.peerId);
|
||||
};
|
||||
|
||||
private onResize = () => {
|
||||
|
|
|
@ -26,7 +26,8 @@ export type CheckboxFieldOptions = {
|
|||
restriction?: boolean,
|
||||
withRipple?: boolean,
|
||||
withHover?: boolean,
|
||||
listenerSetter?: ListenerSetter
|
||||
listenerSetter?: ListenerSetter,
|
||||
asRadio?: boolean
|
||||
};
|
||||
export default class CheckboxField {
|
||||
public input: HTMLInputElement;
|
||||
|
@ -54,9 +55,9 @@ export default class CheckboxField {
|
|||
|
||||
const input = this.input = document.createElement('input');
|
||||
input.classList.add('checkbox-field-input');
|
||||
input.type = 'checkbox';
|
||||
input.type = options.asRadio ? 'radio' : 'checkbox';
|
||||
if(options.name) {
|
||||
input.id = 'input-' + options.name;
|
||||
input[options.asRadio ? 'name' : 'id'] = 'input-' + options.name;
|
||||
}
|
||||
|
||||
if(options.checked) {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import {addCancelButton} from './popups';
|
||||
import PopupElement, {addCancelButton} from './popups';
|
||||
import PopupPeer, {PopupPeerCheckboxOptions, PopupPeerOptions} from './popups/peer';
|
||||
|
||||
// type PopupConfirmationOptions = Pick<PopupPeerOptions, 'titleLangKey'>;
|
||||
|
@ -35,6 +35,6 @@ export default function confirmationPopup<T extends PopupConfirmationOptions>(
|
|||
options.buttons = buttons;
|
||||
options.checkboxes ??= checkbox && [checkbox];
|
||||
|
||||
new PopupPeer('popup-confirmation', options).show();
|
||||
PopupElement.createPopup(PopupPeer, 'popup-confirmation', options).show();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import {AppManagers} from '../lib/appManagers/managers';
|
|||
import {GENERAL_TOPIC_ID} from '../lib/mtproto/mtproto_config';
|
||||
import showLimitPopup from './popups/limit';
|
||||
import createContextMenu from '../helpers/dom/createContextMenu';
|
||||
import PopupElement from './popups';
|
||||
|
||||
export default class DialogsContextMenu {
|
||||
private buttons: ButtonMenuItemOptionsVerifiable[];
|
||||
|
@ -216,7 +217,7 @@ export default class DialogsContextMenu {
|
|||
};
|
||||
|
||||
private onMuteClick = () => {
|
||||
new PopupMute(this.peerId, this.threadId);
|
||||
PopupElement.createPopup(PopupMute, this.peerId, this.threadId);
|
||||
};
|
||||
|
||||
private onUnreadClick = async() => {
|
||||
|
@ -233,6 +234,6 @@ export default class DialogsContextMenu {
|
|||
};
|
||||
|
||||
private onDeleteClick = () => {
|
||||
new PopupDeleteDialog(this.peerId, undefined, undefined, this.threadId);
|
||||
PopupElement.createPopup(PopupDeleteDialog, this.peerId, undefined, undefined, this.threadId);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ import {hideToast, toastNew} from '../../toast';
|
|||
import safeAssign from '../../../helpers/object/safeAssign';
|
||||
import type {AppStickersManager} from '../../../lib/appManagers/appStickersManager';
|
||||
import liteMode from '../../../helpers/liteMode';
|
||||
import PopupElement from '../../popups';
|
||||
|
||||
const loadedURLs: Set<string> = new Set();
|
||||
export function appendEmoji(emoji: string, container?: HTMLElement, prepend = false, unify = false) {
|
||||
|
@ -703,7 +704,7 @@ export default class EmojiTab extends EmoticonsTabC<EmojiTabCategory> {
|
|||
return;
|
||||
}
|
||||
|
||||
new PopupStickers({id: category.set.id, access_hash: category.set.access_hash}, true).show();
|
||||
PopupElement.createPopup(PopupStickers, {id: category.set.id, access_hash: category.set.access_hash}, true).show();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ import {AnyFunction} from '../../../types';
|
|||
import {IgnoreMouseOutType} from '../../../helpers/dropdownHover';
|
||||
import customProperties from '../../../helpers/dom/customProperties';
|
||||
import windowSize from '../../../helpers/windowSize';
|
||||
import PopupElement from '../../popups';
|
||||
|
||||
export class SuperStickerRenderer {
|
||||
public lazyLoadQueue: LazyLoadQueueRepeat;
|
||||
|
@ -617,7 +618,7 @@ export default class StickersTab extends EmoticonsTabC<StickersTabCategory<Stick
|
|||
return;
|
||||
}
|
||||
|
||||
new PopupStickers({id: category.set.id, access_hash: category.set.access_hash}).show();
|
||||
PopupElement.createPopup(PopupStickers, {id: category.set.id, access_hash: category.set.access_hash}).show();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -373,7 +373,7 @@ export default class PopupGroupCall extends PopupElement {
|
|||
};
|
||||
|
||||
if(await this.managers.appChatsManager.hasRights(this.instance.chatId, 'manage_call')) {
|
||||
new PopupPeer('popup-end-video-chat', {
|
||||
PopupElement.createPopup(PopupPeer, 'popup-end-video-chat', {
|
||||
titleLangKey: 'VoiceChat.End.Title',
|
||||
descriptionLangKey: 'VoiceChat.End.Text',
|
||||
checkboxes: [{
|
||||
|
|
|
@ -183,7 +183,7 @@ export default class PopupDeleteDialog {
|
|||
}
|
||||
}
|
||||
|
||||
new PopupPeer('popup-delete-chat', {
|
||||
PopupElement.createPopup(PopupPeer, 'popup-delete-chat', {
|
||||
peerId,
|
||||
threadId,
|
||||
titleLangKey: title,
|
||||
|
|
|
@ -102,7 +102,7 @@ export default class PopupDeleteMessages {
|
|||
|
||||
addCancelButton(buttons);
|
||||
|
||||
const popup = new PopupPeer('popup-delete-chat', {
|
||||
const popup = PopupElement.createPopup(PopupPeer, 'popup-delete-chat', {
|
||||
peerId,
|
||||
threadId,
|
||||
titleLangKey: title,
|
||||
|
|
|
@ -11,6 +11,7 @@ import rootScope from '../../lib/rootScope';
|
|||
import {toastNew} from '../toast';
|
||||
import PopupPickUser from './pickUser';
|
||||
import getMediaFromMessage from '../../lib/appManagers/utils/messages/getMediaFromMessage';
|
||||
import PopupElement from '.';
|
||||
|
||||
export default class PopupForward extends PopupPickUser {
|
||||
constructor(
|
||||
|
@ -115,6 +116,6 @@ export default class PopupForward extends PopupPickUser {
|
|||
}
|
||||
});
|
||||
|
||||
new PopupForward(args[0], args[1], Array.from(actions));
|
||||
PopupElement.createPopup(PopupForward, args[0], args[1], Array.from(actions));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* https://github.com/morethanwords/tweb
|
||||
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import PopupElement from '.';
|
||||
import {attachClickEvent} from '../../helpers/dom/clickEvent';
|
||||
import paymentsWrapCurrencyAmount from '../../helpers/paymentsWrapCurrencyAmount';
|
||||
import {PremiumGiftOption} from '../../layer';
|
||||
import appImManager from '../../lib/appManagers/appImManager';
|
||||
import I18n, {i18n, _i18n} from '../../lib/langPack';
|
||||
import AvatarElement from '../avatar';
|
||||
import Button from '../button';
|
||||
import CheckboxField from '../checkboxField';
|
||||
import Row from '../row';
|
||||
import wrapPeerTitle from '../wrappers/peerTitle';
|
||||
|
||||
const className = 'popup-gift-premium';
|
||||
|
||||
export default class PopupGiftPremium extends PopupElement {
|
||||
constructor(
|
||||
private peerId: PeerId,
|
||||
private giftOptions: PremiumGiftOption[]
|
||||
) {
|
||||
super(className, {closable: true, overlayClosable: true, body: true, scrollable: true});
|
||||
|
||||
this.construct();
|
||||
}
|
||||
|
||||
public async construct() {
|
||||
const {peerId, giftOptions} = this;
|
||||
const avatar = new AvatarElement();
|
||||
avatar.classList.add('avatar-100', className + '-avatar');
|
||||
await avatar.updateWithOptions({
|
||||
peerId
|
||||
});
|
||||
|
||||
const title = document.createElement('span');
|
||||
_i18n(title, 'GiftTelegramPremiumTitle');
|
||||
title.classList.add(className + '-title');
|
||||
|
||||
const subtitle = i18n('GiftTelegramPremiumDescription', [await wrapPeerTitle({peerId})]);
|
||||
subtitle.classList.add(className + '-subtitle');
|
||||
|
||||
const shortestOption = this.giftOptions.slice().sort((a, b) => a.months - b.months)[0];
|
||||
|
||||
const wrapCurrency = (amount: number | string) => paymentsWrapCurrencyAmount(amount, shortestOption.currency, false, true);
|
||||
|
||||
const rows = this.giftOptions.map((giftOption, idx) => {
|
||||
let subtitle = i18n('PricePerMonth', [wrapCurrency(+giftOption.amount / giftOption.months)]);
|
||||
if(giftOption !== shortestOption) {
|
||||
const span = document.createElement('span');
|
||||
const badge = document.createElement('span');
|
||||
badge.classList.add(className + '-discount');
|
||||
const shortestAmount = +shortestOption.amount * giftOption.months / shortestOption.months;
|
||||
const discount = Math.round((1 - +giftOption.amount / shortestAmount) * 100);
|
||||
badge.textContent = '-' + discount + '%';
|
||||
span.append(badge, subtitle);
|
||||
subtitle = span;
|
||||
}
|
||||
|
||||
const isYears = !(giftOption.months % 12);
|
||||
const checkboxField = new CheckboxField({
|
||||
// text: 'Months',
|
||||
// textArgs: [giftOption.months],
|
||||
checked: idx === 0,
|
||||
round: true,
|
||||
name: 'gift-months',
|
||||
asRadio: true
|
||||
});
|
||||
|
||||
const row = new Row({
|
||||
title: i18n(isYears ? 'Years' : 'Months', [isYears ? giftOption.months / 12 : giftOption.months]),
|
||||
checkboxField,
|
||||
clickable: true,
|
||||
subtitle,
|
||||
titleRightSecondary: wrapCurrency(giftOption.amount)
|
||||
});
|
||||
|
||||
row.container.classList.add(className + '-option');
|
||||
|
||||
return row;
|
||||
});
|
||||
|
||||
const form = document.createElement('form');
|
||||
form.classList.add(className + '-options');
|
||||
form.append(...rows.map((row) => row.container));
|
||||
|
||||
const buttonText = new I18n.IntlElement({key: 'GiftSubscriptionFor', args: [wrapCurrency(giftOptions[0].amount)]});
|
||||
|
||||
const getSelectedOption = () => giftOptions[rows.findIndex((row) => row.checkboxField.checked)];
|
||||
|
||||
this.listenerSetter.add(form)('change', () => {
|
||||
buttonText.compareAndUpdate({
|
||||
args: [
|
||||
wrapCurrency(getSelectedOption().amount)
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
const giftButton = Button(`btn-primary ${className}-confirm shimmer`);
|
||||
giftButton.append(buttonText.element);
|
||||
|
||||
attachClickEvent(giftButton, () => {
|
||||
const giftOption = getSelectedOption();
|
||||
appImManager.openUrl(giftOption.bot_url);
|
||||
this.hide();
|
||||
}, {listenerSetter: this.listenerSetter});
|
||||
|
||||
this.scrollable.append(
|
||||
avatar,
|
||||
title,
|
||||
subtitle,
|
||||
form,
|
||||
giftButton
|
||||
);
|
||||
|
||||
this.show();
|
||||
}
|
||||
}
|
|
@ -318,7 +318,7 @@ export default class PopupElement<T extends EventListenerListeners = {}> extends
|
|||
return this.POPUPS.filter((element) => element instanceof popupConstructor) as T[];
|
||||
}
|
||||
|
||||
public static createPopup<T extends PopupElement, A extends Array<any>>(ctor: {new(...args: A): T}, ...args: A) {
|
||||
public static createPopup<T extends /* PopupElement */any, A extends Array<any>>(ctor: {new(...args: A): T}, ...args: A) {
|
||||
const popup = new ctor(...args);
|
||||
return popup;
|
||||
}
|
||||
|
|
|
@ -531,7 +531,7 @@ export default class PopupPayment extends PopupElement {
|
|||
};
|
||||
|
||||
const onMethodClick = () => {
|
||||
new PopupPaymentCard(paymentForm as PaymentsPaymentForm, previousCardDetails as PaymentCardDetails).addEventListener('finish', ({token, card}) => {
|
||||
PopupElement.createPopup(PopupPaymentCard, paymentForm as PaymentsPaymentForm, previousCardDetails as PaymentCardDetails).addEventListener('finish', ({token, card}) => {
|
||||
previousToken = token, previousCardDetails = card;
|
||||
|
||||
setCardSubtitle(card);
|
||||
|
@ -587,7 +587,7 @@ export default class PopupPayment extends PopupElement {
|
|||
|
||||
if(!isReceipt) {
|
||||
onShippingAddressClick = (focus) => {
|
||||
new PopupPaymentShipping(paymentForm as PaymentsPaymentForm, inputInvoice, focus).addEventListener('finish', ({shippingAddress, requestedInfo}) => {
|
||||
PopupElement.createPopup(PopupPaymentShipping, paymentForm as PaymentsPaymentForm, inputInvoice, focus).addEventListener('finish', ({shippingAddress, requestedInfo}) => {
|
||||
lastRequestedInfo = requestedInfo;
|
||||
savedInfo = (paymentForm as PaymentsPaymentForm).saved_info = shippingAddress;
|
||||
setShippingInfo(shippingAddress);
|
||||
|
@ -643,7 +643,7 @@ export default class PopupPayment extends PopupElement {
|
|||
icon: 'shipping',
|
||||
titleLangKey: 'PaymentCheckoutShippingMethod',
|
||||
clickable: !isReceipt && (onShippingMethodClick = () => {
|
||||
new PopupPaymentShippingMethods(paymentForm as PaymentsPaymentForm, lastRequestedInfo, lastShippingOption).addEventListener('finish', (shippingOption) => {
|
||||
PopupElement.createPopup(PopupPaymentShippingMethods, paymentForm as PaymentsPaymentForm, lastRequestedInfo, lastShippingOption).addEventListener('finish', (shippingOption) => {
|
||||
setShippingOption(shippingOption);
|
||||
});
|
||||
})
|
||||
|
@ -736,7 +736,7 @@ export default class PopupPayment extends PopupElement {
|
|||
}
|
||||
|
||||
Promise.resolve(passwordState ?? this.managers.passwordManager.getState()).then((_passwordState) => {
|
||||
new PopupPaymentCardConfirmation(savedCredentials.title, _passwordState).addEventListener('finish', (tmpPassword) => {
|
||||
PopupElement.createPopup(PopupPaymentCardConfirmation, savedCredentials.title, _passwordState).addEventListener('finish', (tmpPassword) => {
|
||||
passwordState = undefined;
|
||||
lastTmpPasword = tmpPassword;
|
||||
simulateClickEvent(payButton);
|
||||
|
@ -783,7 +783,7 @@ export default class PopupPayment extends PopupElement {
|
|||
if(paymentResult._ === 'payments.paymentResult') {
|
||||
onConfirmed();
|
||||
} else {
|
||||
popupPaymentVerification = new PopupPaymentVerification(paymentResult.url, !mediaInvoice.extended_media);
|
||||
popupPaymentVerification = PopupElement.createPopup(PopupPaymentVerification, paymentResult.url, !mediaInvoice.extended_media);
|
||||
popupPaymentVerification.addEventListener('finish', () => {
|
||||
popupPaymentVerification = undefined;
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import PopupElement from '.';
|
||||
import {attachClickEvent} from '../../helpers/dom/clickEvent';
|
||||
import findUpClassName from '../../helpers/dom/findUpClassName';
|
||||
import whichChild from '../../helpers/dom/whichChild';
|
||||
|
@ -45,7 +46,7 @@ export default class PopupReportMessages extends PopupPeer {
|
|||
preloadStickerPromise.then(() => {
|
||||
this.hide();
|
||||
|
||||
new PopupReportMessagesConfirm(peerId, mids, reason, onConfirm);
|
||||
PopupElement.createPopup(PopupReportMessagesConfirm, peerId, mids, reason, onConfirm);
|
||||
});
|
||||
}, {listenerSetter: this.listenerSetter});
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ export default class PopupPinMessage {
|
|||
|
||||
addCancelButton(buttons);
|
||||
|
||||
const popup = new PopupPeer('popup-delete-chat', {
|
||||
const popup = PopupElement.createPopup(PopupPeer, 'popup-delete-chat', {
|
||||
peerId,
|
||||
titleLangKey: title,
|
||||
descriptionLangKey: description,
|
||||
|
|
|
@ -33,7 +33,6 @@ export type RowMediaSizeType = 'small' | 'medium' | 'big' | 'abitbigger' | 'bigg
|
|||
|
||||
export default class Row {
|
||||
public container: HTMLElement;
|
||||
public title: HTMLElement;
|
||||
public titleRow: HTMLElement;
|
||||
public titleRight: HTMLElement;
|
||||
public media: HTMLElement;
|
||||
|
@ -48,6 +47,7 @@ export default class Row {
|
|||
|
||||
public buttonRight: HTMLElement;
|
||||
|
||||
private _title: HTMLElement;
|
||||
private _subtitle: HTMLElement;
|
||||
private _midtitle: HTMLElement;
|
||||
|
||||
|
@ -127,6 +127,9 @@ export default class Row {
|
|||
options.titleRight = this.checkboxField.label;
|
||||
} else {
|
||||
havePadding = true;
|
||||
if(!this.checkboxField.span) {
|
||||
this.checkboxField.label.classList.add('checkbox-field-absolute');
|
||||
}
|
||||
this.container.append(this.checkboxField.label);
|
||||
}
|
||||
|
||||
|
@ -144,7 +147,7 @@ export default class Row {
|
|||
i.label.classList.add('disable-hover');
|
||||
}
|
||||
|
||||
if(options.title || options.titleLangKey) {
|
||||
if(options.title || options.titleLangKey || options.titleRight || options.titleRightSecondary) {
|
||||
let c: HTMLElement;
|
||||
const titleRightContent = options.titleRight || options.titleRightSecondary;
|
||||
if(titleRightContent) {
|
||||
|
@ -154,7 +157,7 @@ export default class Row {
|
|||
c = this.container;
|
||||
}
|
||||
|
||||
this.title = this.createTitle();
|
||||
this._title = this.createTitle();
|
||||
if(options.noWrap) this.title.classList.add('no-wrap');
|
||||
if(options.title) {
|
||||
setContent(this.title, options.title);
|
||||
|
@ -227,6 +230,10 @@ export default class Row {
|
|||
}
|
||||
}
|
||||
|
||||
public get title() {
|
||||
return this._title;
|
||||
}
|
||||
|
||||
public get subtitle() {
|
||||
return this._subtitle ??= this.createSubtitle();
|
||||
}
|
||||
|
|
|
@ -288,6 +288,7 @@ export class AppSidebarLeft extends SidebarSlider {
|
|||
}]
|
||||
});
|
||||
this.newBtnMenu.className = 'btn-circle rp btn-corner z-depth-1 btn-menu-toggle animated-button-icon';
|
||||
this.newBtnMenu.tabIndex = -1;
|
||||
this.newBtnMenu.insertAdjacentHTML('afterbegin', `
|
||||
<span class="tgico tgico-newchat_filled"></span>
|
||||
<span class="tgico tgico-close"></span>
|
||||
|
@ -297,6 +298,7 @@ export class AppSidebarLeft extends SidebarSlider {
|
|||
|
||||
this.updateBtn = document.createElement('div');
|
||||
this.updateBtn.className = 'btn-circle rp btn-corner z-depth-1 btn-update is-hidden';
|
||||
this.updateBtn.tabIndex = -1;
|
||||
ripple(this.updateBtn);
|
||||
this.updateBtn.append(i18n('Update'));
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ import {attachClickEvent} from '../../../../helpers/dom/clickEvent';
|
|||
import matchEmail from '../../../../lib/richTextProcessor/matchEmail';
|
||||
import wrapStickerEmoji from '../../../wrappers/stickerEmoji';
|
||||
import SettingSection from '../../../settingSection';
|
||||
import PopupElement from '../../../popups';
|
||||
|
||||
export default class AppTwoStepVerificationEmailTab extends SliderSuperTab {
|
||||
public inputField: InputField;
|
||||
|
@ -125,7 +126,7 @@ export default class AppTwoStepVerificationEmailTab extends SliderSuperTab {
|
|||
};
|
||||
|
||||
attachClickEvent(btnSkip, (e) => {
|
||||
const popup = new PopupPeer('popup-skip-email', {
|
||||
const popup = PopupElement.createPopup(PopupPeer, 'popup-skip-email', {
|
||||
buttons: [{
|
||||
langKey: 'Cancel',
|
||||
isCancel: true
|
||||
|
|
|
@ -8,6 +8,7 @@ import {attachClickEvent} from '../../../../helpers/dom/clickEvent';
|
|||
import {AccountPassword} from '../../../../layer';
|
||||
import {_i18n} from '../../../../lib/langPack';
|
||||
import Button from '../../../button';
|
||||
import PopupElement from '../../../popups';
|
||||
import PopupPeer from '../../../popups/peer';
|
||||
import SettingSection from '../../../settingSection';
|
||||
import {SliderSuperTab} from '../../../slider';
|
||||
|
@ -57,7 +58,7 @@ export default class AppTwoStepVerificationTab extends SliderSuperTab {
|
|||
});
|
||||
|
||||
attachClickEvent(btnDisablePassword, () => {
|
||||
const popup = new PopupPeer('popup-disable-password', {
|
||||
const popup = PopupElement.createPopup(PopupPeer, 'popup-disable-password', {
|
||||
buttons: [{
|
||||
langKey: 'Disable',
|
||||
callback: () => {
|
||||
|
|
|
@ -21,6 +21,7 @@ import {attachContextMenuListener} from '../../../helpers/dom/attachContextMenuL
|
|||
import positionMenu from '../../../helpers/positionMenu';
|
||||
import contextMenuController from '../../../helpers/contextMenuController';
|
||||
import SettingSection from '../../settingSection';
|
||||
import PopupElement from '../../popups';
|
||||
|
||||
export default class AppActiveSessionsTab extends SliderSuperTabEventable {
|
||||
public authorizations: Authorization.authorization[];
|
||||
|
@ -61,7 +62,7 @@ export default class AppActiveSessionsTab extends SliderSuperTabEventable {
|
|||
if(authorizations.length) {
|
||||
const btnTerminate = Button('btn-primary btn-transparent danger', {icon: 'stop', text: 'TerminateAllSessions'});
|
||||
attachClickEvent(btnTerminate, (e) => {
|
||||
new PopupPeer('revoke-session', {
|
||||
PopupElement.createPopup(PopupPeer, 'revoke-session', {
|
||||
buttons: [{
|
||||
langKey: 'Terminate',
|
||||
isDanger: true,
|
||||
|
@ -112,7 +113,7 @@ export default class AppActiveSessionsTab extends SliderSuperTabEventable {
|
|||
const onTerminateClick = () => {
|
||||
const hash = target.dataset.hash;
|
||||
|
||||
new PopupPeer('revoke-session', {
|
||||
PopupElement.createPopup(PopupPeer, 'revoke-session', {
|
||||
buttons: [{
|
||||
langKey: 'Terminate',
|
||||
isDanger: true,
|
||||
|
|
|
@ -19,6 +19,7 @@ import positionMenu from '../../../helpers/positionMenu';
|
|||
import contextMenuController from '../../../helpers/contextMenuController';
|
||||
import getPeerActiveUsernames from '../../../lib/appManagers/utils/peers/getPeerActiveUsernames';
|
||||
import SettingSection from '../../settingSection';
|
||||
import PopupElement from '../../popups';
|
||||
|
||||
export default class AppBlockedUsersTab extends SliderSuperTab {
|
||||
public peerIds: PeerId[];
|
||||
|
@ -40,7 +41,7 @@ export default class AppBlockedUsersTab extends SliderSuperTab {
|
|||
this.content.append(btnAdd);
|
||||
|
||||
attachClickEvent(btnAdd, (e) => {
|
||||
new PopupPickUser({
|
||||
PopupElement.createPopup(PopupPickUser, {
|
||||
peerTypes: ['contacts'],
|
||||
placeholder: 'BlockModal.Search.Placeholder',
|
||||
onSelect: (peerId) => {
|
||||
|
|
|
@ -24,6 +24,7 @@ import wrapDraftText from '../../../lib/richTextProcessor/wrapDraftText';
|
|||
import filterAsync from '../../../helpers/array/filterAsync';
|
||||
import {attachClickEvent} from '../../../helpers/dom/clickEvent';
|
||||
import SettingSection from '../../settingSection';
|
||||
import PopupElement from '../../popups';
|
||||
|
||||
const MAX_FOLDER_NAME_LENGTH = 12;
|
||||
|
||||
|
@ -66,7 +67,7 @@ export default class AppEditFolderTab extends SliderSuperTab {
|
|||
icon: 'delete danger',
|
||||
text: 'FilterMenuDelete',
|
||||
onClick: () => {
|
||||
new PopupPeer('filter-delete', {
|
||||
PopupElement.createPopup(PopupPeer, 'filter-delete', {
|
||||
titleLangKey: 'ChatList.Filter.Confirm.Remove.Header',
|
||||
descriptionLangKey: 'ChatList.Filter.Confirm.Remove.Text',
|
||||
buttons: [{
|
||||
|
|
|
@ -34,6 +34,7 @@ import {toastNew} from '../../toast';
|
|||
import AppPrivacyVoicesTab from './privacy/voices';
|
||||
import SettingSection from '../../settingSection';
|
||||
import AppActiveWebSessionsTab from './activeWebSessions';
|
||||
import PopupElement from '../../popups';
|
||||
|
||||
export default class AppPrivacyAndSecurityTab extends SliderSuperTabEventable {
|
||||
private activeSessionsRow: Row;
|
||||
|
@ -424,7 +425,7 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTabEventable {
|
|||
const section = new SettingSection({name: 'FilterChats'});
|
||||
|
||||
const onDeleteClick = () => {
|
||||
const popup = new PopupPeer('popup-delete-drafts', {
|
||||
const popup = PopupElement.createPopup(PopupPeer, 'popup-delete-drafts', {
|
||||
buttons: [{
|
||||
langKey: 'Delete',
|
||||
callback: () => {
|
||||
|
|
|
@ -29,6 +29,7 @@ import PopupElement from '../../popups';
|
|||
import {attachClickEvent} from '../../../helpers/dom/clickEvent';
|
||||
import SettingSection from '../../settingSection';
|
||||
import AppStickersAndEmojiTab from './stickersAndEmoji';
|
||||
import ButtonCorner from '../../buttonCorner';
|
||||
|
||||
export default class AppSettingsTab extends SliderSuperTab {
|
||||
private buttons: {
|
||||
|
@ -58,7 +59,7 @@ export default class AppSettingsTab extends SliderSuperTab {
|
|||
icon: 'logout',
|
||||
text: 'EditAccount.Logout',
|
||||
onClick: () => {
|
||||
new PopupPeer('logout', {
|
||||
PopupElement.createPopup(PopupPeer, 'logout', {
|
||||
titleLangKey: 'LogOut',
|
||||
descriptionLangKey: 'LogOut.Description',
|
||||
buttons: [{
|
||||
|
@ -82,7 +83,7 @@ export default class AppSettingsTab extends SliderSuperTab {
|
|||
this.profile.setPeer(rootScope.myId);
|
||||
const fillPromise = this.profile.fillProfileElements();
|
||||
|
||||
const changeAvatarBtn = Button('btn-circle btn-corner z-depth-1 profile-change-avatar', {icon: 'cameraadd'});
|
||||
const changeAvatarBtn = ButtonCorner({icon: 'cameraadd', className: 'profile-change-avatar'});
|
||||
attachClickEvent(changeAvatarBtn, () => {
|
||||
const canvas = document.createElement('canvas');
|
||||
PopupElement.createPopup(PopupAvatar).open(canvas, (upload) => {
|
||||
|
|
|
@ -15,6 +15,7 @@ import wrapEmojiText from '../../../lib/richTextProcessor/wrapEmojiText';
|
|||
import rootScope from '../../../lib/rootScope';
|
||||
import CheckboxField from '../../checkboxField';
|
||||
import LazyLoadQueue from '../../lazyLoadQueue';
|
||||
import PopupElement from '../../popups';
|
||||
import PopupStickers from '../../popups/stickers';
|
||||
import Row, {CreateRowFromCheckboxField} from '../../row';
|
||||
import SettingSection from '../../settingSection';
|
||||
|
@ -209,7 +210,7 @@ export default class AppStickersAndEmojiTab extends SliderSuperTab {
|
|||
subtitleLangArgs: [stickerSet.count],
|
||||
havePadding: true,
|
||||
clickable: () => {
|
||||
new PopupStickers({id: stickerSet.id, access_hash: stickerSet.access_hash}).show();
|
||||
PopupElement.createPopup(PopupStickers, {id: stickerSet.id, access_hash: stickerSet.access_hash}).show();
|
||||
},
|
||||
listenerSetter: this.listenerSetter
|
||||
});
|
||||
|
|
|
@ -27,6 +27,7 @@ import getPeerEditableUsername from '../../../lib/appManagers/utils/peers/getPee
|
|||
import getPeerActiveUsernames from '../../../lib/appManagers/utils/peers/getPeerActiveUsernames';
|
||||
import {purchaseUsernameCaption} from '../../sidebarLeft/tabs/editProfile';
|
||||
import confirmationPopup from '../../confirmationPopup';
|
||||
import PopupElement from '../../popups';
|
||||
|
||||
export default class AppChatTypeTab extends SliderSuperTabEventable {
|
||||
public chatId: ChatId;
|
||||
|
@ -102,7 +103,7 @@ export default class AppChatTypeTab extends SliderSuperTabEventable {
|
|||
const btnRevoke = Button('btn-primary btn-transparent danger', {icon: 'delete', text: 'RevokeLink'});
|
||||
|
||||
attachClickEvent(btnRevoke, () => {
|
||||
new PopupPeer('revoke-link', {
|
||||
PopupElement.createPopup(PopupPeer, 'revoke-link', {
|
||||
buttons: [{
|
||||
langKey: 'RevokeButton',
|
||||
callback: () => {
|
||||
|
|
|
@ -24,6 +24,7 @@ import hasRights from '../../../lib/appManagers/utils/chats/hasRights';
|
|||
import replaceContent from '../../../helpers/dom/replaceContent';
|
||||
import SettingSection from '../../settingSection';
|
||||
import getPeerActiveUsernames from '../../../lib/appManagers/utils/peers/getPeerActiveUsernames';
|
||||
import PopupElement from '../../popups';
|
||||
|
||||
export default class AppEditChatTab extends SliderSuperTab {
|
||||
private chatNameInputField: InputField;
|
||||
|
@ -377,7 +378,7 @@ export default class AppEditChatTab extends SliderSuperTab {
|
|||
const btnDelete = Button('btn-primary btn-transparent danger', {icon: 'delete', text: isBroadcast ? 'PeerInfo.DeleteChannel' : 'DeleteAndExitButton'});
|
||||
|
||||
attachClickEvent(btnDelete, () => {
|
||||
new PopupDeleteDialog(peerId/* , 'delete' */, undefined, (promise) => {
|
||||
PopupElement.createPopup(PopupDeleteDialog, peerId/* , 'delete' */, undefined, (promise) => {
|
||||
const toggle = toggleDisability([btnDelete], true);
|
||||
promise.then(() => {
|
||||
this.close();
|
||||
|
|
|
@ -13,7 +13,7 @@ import Button from '../../button';
|
|||
import PeerTitle from '../../peerTitle';
|
||||
import rootScope from '../../../lib/rootScope';
|
||||
import PopupPeer from '../../popups/peer';
|
||||
import {addCancelButton} from '../../popups';
|
||||
import PopupElement, {addCancelButton} from '../../popups';
|
||||
import {i18n} from '../../../lib/langPack';
|
||||
import {attachClickEvent} from '../../../helpers/dom/clickEvent';
|
||||
import toggleDisability from '../../../helpers/dom/toggleDisability';
|
||||
|
@ -160,7 +160,7 @@ export default class AppEditContactTab extends SliderSuperTab {
|
|||
const btnDelete = Button('btn-primary btn-transparent danger', {icon: 'delete', text: 'PeerInfo.DeleteContact'});
|
||||
|
||||
attachClickEvent(btnDelete, () => {
|
||||
new PopupPeer('popup-delete-contact', {
|
||||
PopupElement.createPopup(PopupPeer, 'popup-delete-contact', {
|
||||
peerId: peerId,
|
||||
titleLangKey: 'DeleteContact',
|
||||
descriptionLangKey: 'AreYouSureDeleteContact',
|
||||
|
|
|
@ -26,6 +26,7 @@ import {SliderSuperTabEventable} from '../../sliderTab';
|
|||
import {toast} from '../../toast';
|
||||
import AppUserPermissionsTab from './userPermissions';
|
||||
import CheckboxFields, {CheckboxFieldsField} from '../../checkboxFields';
|
||||
import PopupElement from '../../popups';
|
||||
|
||||
type PermissionsCheckboxFieldsField = CheckboxFieldsField & {
|
||||
flags: ChatRights[],
|
||||
|
@ -186,7 +187,7 @@ export default class AppGroupPermissionsTab extends SliderSuperTabEventable {
|
|||
subtitleLangKey: 'Loading',
|
||||
icon: 'adduser',
|
||||
clickable: () => {
|
||||
new PopupPickUser({
|
||||
PopupElement.createPopup(PopupPickUser, {
|
||||
peerTypes: ['channelParticipants'],
|
||||
onSelect: (peerId) => {
|
||||
setTimeout(() => {
|
||||
|
|
|
@ -25,6 +25,7 @@ import {Message} from '../../../layer';
|
|||
import getMessageThreadId from '../../../lib/appManagers/utils/messages/getMessageThreadId';
|
||||
import AppEditTopicTab from './editTopic';
|
||||
import liteMode from '../../../helpers/liteMode';
|
||||
import PopupElement from '../../popups';
|
||||
|
||||
type SharedMediaHistoryStorage = Partial<{
|
||||
[type in SearchSuperType]: {mid: number, peerId: PeerId}[]
|
||||
|
@ -296,7 +297,7 @@ export default class AppSharedMediaTab extends SliderSuperTab {
|
|||
peerId
|
||||
}).element);
|
||||
|
||||
new PopupPeer('popup-add-members', {
|
||||
PopupElement.createPopup(PopupPeer, 'popup-add-members', {
|
||||
peerId,
|
||||
titleLangKey,
|
||||
descriptionLangKey,
|
||||
|
@ -333,7 +334,7 @@ export default class AppSharedMediaTab extends SliderSuperTab {
|
|||
placeholder: 'SendMessageTo'
|
||||
});
|
||||
} else {
|
||||
new PopupPickUser({
|
||||
PopupElement.createPopup(PopupPickUser, {
|
||||
peerTypes: ['contacts'],
|
||||
placeholder: 'Search',
|
||||
onSelect: (peerId) => {
|
||||
|
|
|
@ -20,6 +20,7 @@ import setInnerHTML from '../../../helpers/dom/setInnerHTML';
|
|||
import wrapEmojiText from '../../../lib/richTextProcessor/wrapEmojiText';
|
||||
import attachStickerViewerListeners from '../../stickerViewer';
|
||||
import wrapSticker from '../../wrappers/sticker';
|
||||
import PopupElement from '../../popups';
|
||||
|
||||
export default class AppStickersTab extends SliderSuperTab {
|
||||
private inputSearch: InputSearch;
|
||||
|
@ -79,7 +80,7 @@ export default class AppStickersTab extends SliderSuperTab {
|
|||
});
|
||||
} else {
|
||||
this.managers.appStickersManager.getStickerSet({id, access_hash}).then((full) => {
|
||||
new PopupStickers(full.set).show();
|
||||
PopupElement.createPopup(PopupStickers, full.set).show();
|
||||
});
|
||||
}
|
||||
}, {listenerSetter: this.listenerSetter});
|
||||
|
|
|
@ -263,14 +263,14 @@ export default class TopbarCall {
|
|||
return;
|
||||
}
|
||||
|
||||
new PopupGroupCall().show();
|
||||
PopupElement.createPopup(PopupGroupCall).show();
|
||||
} else if(this.instance instanceof CallInstance) {
|
||||
const popups = PopupElement.getPopups(PopupCall);
|
||||
if(popups.find((popup) => popup.getCallInstance() === this.instance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
new PopupCall(this.instance).show();
|
||||
PopupElement.createPopup(PopupCall, this.instance).show();
|
||||
}
|
||||
}, {listenerSetter});
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ import wrapStickerAnimation from './stickerAnimation';
|
|||
import framesCache from '../../helpers/framesCache';
|
||||
import {IS_MOBILE} from '../../environment/userAgent';
|
||||
import liteMode, {LiteModeKey} from '../../helpers/liteMode';
|
||||
import PopupElement from '../popups';
|
||||
|
||||
// https://github.com/telegramdesktop/tdesktop/blob/master/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp#L40
|
||||
export const STICKER_EFFECT_MULTIPLIER = 1 + 0.245 * 2;
|
||||
|
@ -699,7 +700,7 @@ function attachStickerEffectHandler({container, doc, managers, middleware, isOut
|
|||
const a = document.createElement('a');
|
||||
a.onclick = () => {
|
||||
hideToast();
|
||||
new PopupStickers(doc.stickerSetInput).show();
|
||||
PopupElement.createPopup(PopupStickers, doc.stickerSetInput).show();
|
||||
};
|
||||
|
||||
toastNew({
|
||||
|
@ -782,7 +783,7 @@ export async function onEmojiStickerClick({event, container, managers, peerId, m
|
|||
}
|
||||
|
||||
const activeAnimations: Set<{}> = (container as any).activeAnimations ??= new Set();
|
||||
if(activeAnimations.size >= (IS_MOBILE ? 3 : 5)) {
|
||||
if(activeAnimations.size >= 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ const App = {
|
|||
version: process.env.VERSION,
|
||||
versionFull: process.env.VERSION_FULL,
|
||||
build: +process.env.BUILD,
|
||||
langPackVersion: '1.0.1',
|
||||
langPackVersion: '1.0.3',
|
||||
langPack: 'webk',
|
||||
langPackCode: 'en',
|
||||
domains: MAIN_DOMAINS,
|
||||
|
|
|
@ -22,6 +22,10 @@ export default function addAnchorListener<Params extends {pathnameParams?: any,
|
|||
!options.noCancelEvent && cancelEvent(null);
|
||||
|
||||
let href = element.href;
|
||||
if(!href) {
|
||||
return;
|
||||
}
|
||||
|
||||
let pathnameParams: any[];
|
||||
let uriParams: any;
|
||||
|
||||
|
|
|
@ -10,7 +10,8 @@ import appImManager from '../../lib/appManagers/appImManager';
|
|||
import rootScope from '../../lib/rootScope';
|
||||
import createContextMenu from './createContextMenu';
|
||||
import findUpClassName from './findUpClassName';
|
||||
import emoticonsDropdown, {EmoticonsDropdown} from '../../components/emoticonsDropdown';
|
||||
import {EmoticonsDropdown} from '../../components/emoticonsDropdown';
|
||||
import PopupElement from '../../components/popups';
|
||||
|
||||
export default function createStickersContextMenu(options: {
|
||||
listenTo: HTMLElement,
|
||||
|
@ -45,7 +46,7 @@ export default function createStickersContextMenu(options: {
|
|||
buttons: [{
|
||||
icon: 'stickers',
|
||||
text: 'Context.ViewStickerSet',
|
||||
onClick: () => new PopupStickers(doc.stickerSetInput).show(),
|
||||
onClick: () => PopupElement.createPopup(PopupStickers, doc.stickerSetInput).show(),
|
||||
verify: () => !isStickerPack
|
||||
}, {
|
||||
icon: 'favourites',
|
||||
|
|
|
@ -25,7 +25,12 @@ function number_format(number: any, decimals: any, dec_point: any, thousands_sep
|
|||
return s.join(dec);
|
||||
}
|
||||
|
||||
export default function paymentsWrapCurrencyAmount(amount: number | string, currency: string, skipSymbol?: boolean) {
|
||||
export default function paymentsWrapCurrencyAmount(
|
||||
amount: number | string,
|
||||
currency: string,
|
||||
skipSymbol?: boolean,
|
||||
useNative?: boolean
|
||||
) {
|
||||
amount = +amount;
|
||||
|
||||
const isNegative = amount < 0;
|
||||
|
@ -47,7 +52,7 @@ export default function paymentsWrapCurrencyAmount(amount: number | string, curr
|
|||
return formatted;
|
||||
}
|
||||
|
||||
let symbol = currencyData.symbol;
|
||||
let symbol = useNative ? currencyData.native || currencyData.symbol : currencyData.symbol;
|
||||
if(isNegative && !currencyData.space_between && currencyData.symbol_left) {
|
||||
symbol = '-' + symbol;
|
||||
formatted = formatted.replace('-', '');
|
||||
|
|
|
@ -940,6 +940,11 @@ const lang = {
|
|||
'SuggestStickersNone': 'None',
|
||||
'DynamicPackOrder': 'Dynamic Pack Order',
|
||||
'DynamicPackOrderInfo': 'Automatically place recently used sticker packs at the front of the panel.',
|
||||
'GiftPremium': 'Gift Premium',
|
||||
'GiftTelegramPremiumTitle': 'Gift Telegram Premium',
|
||||
'GiftTelegramPremiumDescription': 'Give **%1$s** access to exclusive features with **Telegram Premium**.',
|
||||
'PricePerMonth': '%1$s / month',
|
||||
'GiftSubscriptionFor': 'Gift Subscription for %1$s',
|
||||
|
||||
// * macos
|
||||
'AccountSettings.Filters': 'Chat Folders',
|
||||
|
|
|
@ -107,6 +107,7 @@ import partition from '../../helpers/array/partition';
|
|||
import indexOfAndSplice from '../../helpers/array/indexOfAndSplice';
|
||||
import liteMode, {LiteModeKey} from '../../helpers/liteMode';
|
||||
import RLottiePlayer from '../rlottie/rlottiePlayer';
|
||||
import PopupGiftPremium from '../../components/popups/giftPremium';
|
||||
|
||||
export type ChatSavedPosition = {
|
||||
mids: number[],
|
||||
|
@ -345,7 +346,7 @@ export class AppImManager extends EventListenerBase<{
|
|||
|
||||
const onInstanceDeactivated = (reason: InstanceDeactivateReason) => {
|
||||
const isUpdated = reason === 'version';
|
||||
const popup = new PopupElement('popup-instance-deactivated', {overlayClosable: true});
|
||||
const popup = PopupElement.createPopup(PopupElement, 'popup-instance-deactivated', {overlayClosable: true});
|
||||
const c = document.createElement('div');
|
||||
c.classList.add('instance-deactivated-container');
|
||||
(popup as any).container.replaceWith(c);
|
||||
|
@ -530,7 +531,7 @@ export class AppImManager extends EventListenerBase<{
|
|||
// return;
|
||||
// }
|
||||
|
||||
const popup = new PopupCall(instance);
|
||||
const popup = PopupElement.createPopup(PopupCall, instance);
|
||||
|
||||
instance.addEventListener('acceptCallOverride', () => {
|
||||
return this.discardCurrentCall(instance.interlocutorUserId.toPeerId(), undefined, instance)
|
||||
|
@ -582,7 +583,7 @@ export class AppImManager extends EventListenerBase<{
|
|||
a.innerText = href;
|
||||
a.removeAttribute('onclick');
|
||||
|
||||
new PopupPeer('popup-masked-url', {
|
||||
PopupElement.createPopup(PopupPeer, 'popup-masked-url', {
|
||||
titleLangKey: 'OpenUrlTitle',
|
||||
descriptionLangKey: 'OpenUrlAlert2',
|
||||
descriptionLangArgs: [a],
|
||||
|
@ -862,11 +863,11 @@ export class AppImManager extends EventListenerBase<{
|
|||
const share = apiManagerProxy.share;
|
||||
if(share) {
|
||||
apiManagerProxy.share = undefined;
|
||||
new PopupForward(undefined, async(peerId) => {
|
||||
PopupElement.createPopup(PopupForward, undefined, async(peerId) => {
|
||||
await this.setPeer({peerId});
|
||||
if(share.files?.length) {
|
||||
const foundMedia = share.files.some((file) => MEDIA_MIME_TYPES_SUPPORTED.has(file.type));
|
||||
new PopupNewMedia(this.chat, share.files, foundMedia ? 'media' : 'document');
|
||||
PopupElement.createPopup(PopupNewMedia, this.chat, share.files, foundMedia ? 'media' : 'document');
|
||||
} else {
|
||||
this.managers.appMessagesManager.sendText(peerId, share.text);
|
||||
}
|
||||
|
@ -1184,7 +1185,7 @@ export class AppImManager extends EventListenerBase<{
|
|||
|
||||
case INTERNAL_LINK_TYPE.EMOJI_SET:
|
||||
case INTERNAL_LINK_TYPE.STICKER_SET: {
|
||||
new PopupStickers({id: link.set}, link._ === INTERNAL_LINK_TYPE.EMOJI_SET).show();
|
||||
PopupElement.createPopup(PopupStickers, {id: link.set}, link._ === INTERNAL_LINK_TYPE.EMOJI_SET).show();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1204,7 +1205,7 @@ export class AppImManager extends EventListenerBase<{
|
|||
return;
|
||||
}
|
||||
|
||||
new PopupJoinChatInvite(link.invite, chatInvite);
|
||||
PopupElement.createPopup(PopupJoinChatInvite, link.invite, chatInvite);
|
||||
}, (err) => {
|
||||
if(err.type === 'INVITE_HASH_EXPIRED') {
|
||||
toast(i18n('InviteExpired'));
|
||||
|
@ -1252,7 +1253,7 @@ export class AppImManager extends EventListenerBase<{
|
|||
|
||||
// }
|
||||
// };
|
||||
new PopupPayment(undefined, inputInvoice, paymentForm);
|
||||
PopupElement.createPopup(PopupPayment, undefined, inputInvoice, paymentForm);
|
||||
});
|
||||
});
|
||||
break;
|
||||
|
@ -2546,6 +2547,12 @@ export class AppImManager extends EventListenerBase<{
|
|||
options1.threadId === options2.threadId &&
|
||||
(typeof(options1.type) !== typeof(options2.type) || options1.type === options2.type);
|
||||
}
|
||||
|
||||
public giftPremium(peerId: PeerId) {
|
||||
this.managers.appProfileManager.getProfile(peerId.toUserId()).then((profile) => {
|
||||
PopupElement.createPopup(PopupGiftPremium, peerId, profile.premium_gifts);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const appImManager = new AppImManager();
|
||||
|
|
|
@ -5904,18 +5904,54 @@ export class AppMessagesManager extends AppManager {
|
|||
});
|
||||
}
|
||||
|
||||
public isHistoryResultEnd(historyResult: Exclude<MessagesMessages, MessagesMessages.messagesMessagesNotModified>, limit: number, add_offset: number) {
|
||||
public isHistoryResultEnd(
|
||||
historyResult: Exclude<MessagesMessages, MessagesMessages.messagesMessagesNotModified>,
|
||||
limit: number,
|
||||
add_offset: number,
|
||||
offset_id: number
|
||||
) {
|
||||
const {offset_id_offset, messages} = historyResult as MessagesMessages.messagesMessagesSlice;
|
||||
|
||||
const mids = messages.map((message) => {
|
||||
return (message as MyMessage).mid;
|
||||
});
|
||||
|
||||
const count = (historyResult as MessagesMessages.messagesMessagesSlice).count || messages.length;
|
||||
const offsetIdOffset = offset_id_offset ?? count - 1;
|
||||
|
||||
const topWasMeantToLoad = add_offset < 0 ? limit + add_offset : limit;
|
||||
const bottomWasMeantToLoad = Math.abs(add_offset);
|
||||
|
||||
const isTopEnd = offsetIdOffset >= (count - topWasMeantToLoad) || count < topWasMeantToLoad;
|
||||
const isBottomEnd = !offsetIdOffset || (add_offset < 0 && (offsetIdOffset + add_offset) <= 0);
|
||||
let offsetIdOffset = offset_id_offset;
|
||||
let isTopEnd = false, isBottomEnd = false;
|
||||
|
||||
return {count, offsetIdOffset, isTopEnd, isBottomEnd};
|
||||
// if(offsetIdOffset === undefined && !bottomWasMeantToLoad) {
|
||||
// offsetIdOffset = 0;
|
||||
// }
|
||||
|
||||
if(offsetIdOffset !== undefined) {
|
||||
isTopEnd = offsetIdOffset >= (count - topWasMeantToLoad) || count < topWasMeantToLoad;
|
||||
isBottomEnd = !offsetIdOffset || (add_offset < 0 && (offsetIdOffset + add_offset) <= 0);
|
||||
} else if(offset_id && getServerMessageId(offset_id)) {
|
||||
let i = 0;
|
||||
for(const length = mids.length; i < length; ++i) {
|
||||
if(offset_id > mids[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const topLoaded = messages.length - i;
|
||||
const bottomLoaded = mids.includes(offset_id) ? i - 1 : i;
|
||||
if(topWasMeantToLoad) isTopEnd = topLoaded < topWasMeantToLoad;
|
||||
if(bottomWasMeantToLoad) isBottomEnd = bottomLoaded < bottomWasMeantToLoad;
|
||||
|
||||
if(isTopEnd || isBottomEnd) {
|
||||
offsetIdOffset = isTopEnd ? count - topLoaded : bottomLoaded;
|
||||
}
|
||||
}
|
||||
|
||||
offsetIdOffset ??= 0;
|
||||
|
||||
return {count, offsetIdOffset, isTopEnd, isBottomEnd, mids};
|
||||
}
|
||||
|
||||
public mergeHistoryResult(
|
||||
|
@ -5926,11 +5962,8 @@ export class AppMessagesManager extends AppManager {
|
|||
add_offset: number
|
||||
) {
|
||||
const {messages} = historyResult as MessagesMessages.messagesMessagesSlice;
|
||||
const isEnd = this.isHistoryResultEnd(historyResult, limit, add_offset);
|
||||
const {count, offsetIdOffset, isTopEnd, isBottomEnd} = isEnd;
|
||||
const mids = messages.map((message) => {
|
||||
return (message as MyMessage).mid;
|
||||
});
|
||||
const isEnd = this.isHistoryResultEnd(historyResult, limit, add_offset, offset_id);
|
||||
const {count, offsetIdOffset, isTopEnd, isBottomEnd, mids} = isEnd;
|
||||
|
||||
// * add bound manually.
|
||||
// * offset_id will be inclusive only if there is 'add_offset' <= -1 (-1 - will only include the 'offset_id')
|
||||
|
|
|
@ -22,6 +22,7 @@ import {ReferenceContext} from '../mtproto/referenceDatabase';
|
|||
import generateMessageId from './utils/messageId/generateMessageId';
|
||||
import assumeType from '../../helpers/assumeType';
|
||||
import makeError from '../../helpers/makeError';
|
||||
import callbackify from '../../helpers/callbackify';
|
||||
|
||||
export type UserTyping = Partial<{userId: UserId, action: SendMessageAction, timeout: number}>;
|
||||
|
||||
|
@ -669,6 +670,18 @@ export class AppProfileManager extends AppManager {
|
|||
return this.typingsInPeer[this.getTypingsKey(peerId, threadId)];
|
||||
}
|
||||
|
||||
public canGiftPremium(userId: UserId) {
|
||||
const user = this.appUsersManager.getUser(userId);
|
||||
if(user?.pFlags?.premium || true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return callbackify(this.getProfile(userId), (userFull) => {
|
||||
const user = this.appUsersManager.getUser(userId);
|
||||
return !!userFull.premium_gifts && !user?.pFlags?.premium;
|
||||
});
|
||||
}
|
||||
|
||||
private onUpdateChatParticipants = (update: Update.updateChatParticipants) => {
|
||||
const participants = update.participants;
|
||||
if(participants._ !== 'chatParticipants') {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {Document, Message, MessageMedia} from '../../../../layer';
|
||||
|
||||
export default function getMediaDurationFromMessage(message: Message.message) {
|
||||
if(!message) return undefined;
|
||||
const doc = (message.media as MessageMedia.messageMediaDocument)?.document as Document.document;
|
||||
const duration = ((['voice', 'audio', 'video'] as Document.document['type'][]).includes(doc?.type) && doc.duration) || undefined;
|
||||
return duration;
|
||||
|
|
|
@ -1475,6 +1475,10 @@ export default function wrapRichText(text: string, options: Partial<{
|
|||
(element as HTMLAnchorElement).href = '#';
|
||||
element.setAttribute('onclick', 'setMediaTimestamp(this)');
|
||||
|
||||
if(options.maxMediaTimestamp === Infinity) {
|
||||
element.classList.add('is-disabled');
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -686,6 +686,31 @@ $btn-menu-z-index: 4;
|
|||
pointer-events: none !important;
|
||||
opacity: var(--disabled-opacity);
|
||||
}
|
||||
|
||||
&.shimmer {
|
||||
&:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(to right, transparent 0%, rgba(var(--surface-color-rgb), .2) 50%, transparent 100%);
|
||||
animation: wave 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||
|
||||
@keyframes wave {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
50% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-control {
|
||||
|
|
|
@ -2475,6 +2475,12 @@ $bubble-border-radius-big: 12px;
|
|||
// }
|
||||
}
|
||||
|
||||
.timestamp.is-disabled {
|
||||
color: inherit;
|
||||
text-decoration: none !important;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
@keyframes audio-dots {
|
||||
0% {
|
||||
content: "";
|
||||
|
|
|
@ -254,6 +254,19 @@ $row-border-radius: $border-radius-medium;
|
|||
margin-inline: .125rem .125rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&-absolute {
|
||||
position: absolute;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&-round {
|
||||
.checkbox-box-border {
|
||||
z-index: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-subtitle {
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* https://github.com/morethanwords/tweb
|
||||
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
.popup-gift-premium {
|
||||
$parent: ".popup";
|
||||
|
||||
#{$parent} {
|
||||
&-container {
|
||||
padding: 0;
|
||||
width: 26.25rem;
|
||||
max-width: 26.25rem;
|
||||
|
||||
max-height: unquote('min(100%, 43.5rem)');
|
||||
border-radius: $border-radius-huge;
|
||||
}
|
||||
|
||||
&-header {
|
||||
height: 3.5rem;
|
||||
margin: 0;
|
||||
padding: 0 1rem;
|
||||
margin-bottom: -2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.scrollable-y {
|
||||
flex: 1 1 auto;
|
||||
padding: 0 1rem 1rem;
|
||||
}
|
||||
|
||||
&-avatar {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
&-title,
|
||||
&-subtitle {
|
||||
text-align: center;
|
||||
display: block;
|
||||
}
|
||||
|
||||
&-title {
|
||||
font-size: var(--font-size-20);
|
||||
font-weight: var(--font-weight-bold);
|
||||
margin: .75rem 0;
|
||||
}
|
||||
|
||||
&-options {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: .5rem 0 1rem;
|
||||
}
|
||||
|
||||
&-option {
|
||||
margin-top: .5rem;
|
||||
|
||||
&:nth-child(1) {
|
||||
--primary-color: #C564F3;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
--primary-color: #AC64F3;
|
||||
}
|
||||
|
||||
&:nth-child(3) {
|
||||
--primary-color: #9377FF;
|
||||
}
|
||||
}
|
||||
|
||||
&-discount {
|
||||
background-color: var(--primary-color);
|
||||
border-radius: 6px;
|
||||
color: #fff;
|
||||
margin-right: .375rem;
|
||||
padding: 0 0.3125rem;
|
||||
height: 20px;
|
||||
display: inline-block;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
&-confirm {
|
||||
--ripple-color: rgba(255, 255, 255, #{$hover-alpha});
|
||||
background: linear-gradient(88.39deg, #6C93FF -2.56%, #976FFF 51.27%, #DF69D1 107.39%) !important;
|
||||
font-weight: var(--font-weight-bold);
|
||||
color: #fff;
|
||||
text-transform: uppercase;
|
||||
|
||||
@include hover() {
|
||||
&:after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: #fff;
|
||||
opacity: $hover-alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -119,6 +119,12 @@
|
|||
.scrollable {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.scrollable-y-bordered {
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-buttons {
|
||||
|
|
|
@ -411,6 +411,7 @@ $chat-input-inner-padding-handhelds: .25rem;
|
|||
@import "partials/popups/paymentVerification";
|
||||
@import "partials/popups/paymentCardConfirmation";
|
||||
@import "partials/popups/limit";
|
||||
@import "partials/popups/giftPremium";
|
||||
|
||||
@import "partials/pages/pages";
|
||||
@import "partials/pages/authCode";
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
@font-face {
|
||||
font-family: '#{$tgico-font-family}';
|
||||
src:
|
||||
url('#{$tgico-font-path}/#{$tgico-font-family}.ttf?2fcrrv') format('truetype'),
|
||||
url('#{$tgico-font-path}/#{$tgico-font-family}.woff?2fcrrv') format('woff'),
|
||||
url('#{$tgico-font-path}/#{$tgico-font-family}.svg?2fcrrv##{$tgico-font-family}') format('svg');
|
||||
url('#{$tgico-font-path}/#{$tgico-font-family}.ttf?bv435t') format('truetype'),
|
||||
url('#{$tgico-font-path}/#{$tgico-font-family}.woff?bv435t') format('woff'),
|
||||
url('#{$tgico-font-path}/#{$tgico-font-family}.svg?bv435t##{$tgico-font-family}') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
|
@ -432,6 +432,11 @@
|
|||
content: $tgico-gifs;
|
||||
}
|
||||
}
|
||||
.tgico-gift {
|
||||
&:before {
|
||||
content: $tgico-gift;
|
||||
}
|
||||
}
|
||||
.tgico-group {
|
||||
&:before {
|
||||
content: $tgico-group;
|
||||
|
|
|
@ -78,135 +78,136 @@ $tgico-fullscreen: "\e94c";
|
|||
$tgico-gc_microphone: "\e94d";
|
||||
$tgico-gc_microphoneoff: "\e94e";
|
||||
$tgico-gifs: "\e94f";
|
||||
$tgico-group: "\e950";
|
||||
$tgico-groupmedia: "\e951";
|
||||
$tgico-groupmediaoff: "\e952";
|
||||
$tgico-help: "\e953";
|
||||
$tgico-hide: "\e954";
|
||||
$tgico-image: "\e955";
|
||||
$tgico-info: "\e956";
|
||||
$tgico-info2: "\e957";
|
||||
$tgico-italic: "\e958";
|
||||
$tgico-keyboard: "\e959";
|
||||
$tgico-lamp: "\e95a";
|
||||
$tgico-language: "\e95b";
|
||||
$tgico-largepause: "\e95c";
|
||||
$tgico-largeplay: "\e95d";
|
||||
$tgico-left: "\e95e";
|
||||
$tgico-limit_chat: "\e95f";
|
||||
$tgico-limit_chats: "\e960";
|
||||
$tgico-limit_file: "\e961";
|
||||
$tgico-limit_folders: "\e962";
|
||||
$tgico-limit_link: "\e963";
|
||||
$tgico-limit_pin: "\e964";
|
||||
$tgico-link: "\e965";
|
||||
$tgico-listscreenshare: "\e966";
|
||||
$tgico-livelocation: "\e967";
|
||||
$tgico-location: "\e968";
|
||||
$tgico-lock: "\e969";
|
||||
$tgico-lockoff: "\e96a";
|
||||
$tgico-loginlogodesktop: "\e96b";
|
||||
$tgico-loginlogomobile: "\e96c";
|
||||
$tgico-logout: "\e96d";
|
||||
$tgico-mediaspoiler: "\e96e";
|
||||
$tgico-mediaspoileroff: "\e96f";
|
||||
$tgico-mention: "\e970";
|
||||
$tgico-menu: "\e971";
|
||||
$tgico-message: "\e972";
|
||||
$tgico-messageunread: "\e973";
|
||||
$tgico-microphone: "\e974";
|
||||
$tgico-microphone_crossed: "\e975";
|
||||
$tgico-microphone_crossed_filled: "\e976";
|
||||
$tgico-microphone_filled: "\e977";
|
||||
$tgico-minus: "\e978";
|
||||
$tgico-monospace: "\e979";
|
||||
$tgico-more: "\e97a";
|
||||
$tgico-mute: "\e97b";
|
||||
$tgico-muted: "\e97c";
|
||||
$tgico-newchannel: "\e97d";
|
||||
$tgico-newchat_filled: "\e97e";
|
||||
$tgico-newgroup: "\e97f";
|
||||
$tgico-newprivate: "\e980";
|
||||
$tgico-next: "\e981";
|
||||
$tgico-noncontacts: "\e982";
|
||||
$tgico-nosound: "\e983";
|
||||
$tgico-passwordoff: "\e984";
|
||||
$tgico-pause: "\e985";
|
||||
$tgico-permissions: "\e986";
|
||||
$tgico-phone: "\e987";
|
||||
$tgico-pin: "\e988";
|
||||
$tgico-pinlist: "\e989";
|
||||
$tgico-pinned_filled: "\e98a";
|
||||
$tgico-pinnedchat: "\e98b";
|
||||
$tgico-pip: "\e98c";
|
||||
$tgico-play: "\e98d";
|
||||
$tgico-playback_05: "\e98e";
|
||||
$tgico-playback_15: "\e98f";
|
||||
$tgico-playback_1x: "\e990";
|
||||
$tgico-playback_2x: "\e991";
|
||||
$tgico-plus: "\e992";
|
||||
$tgico-poll: "\e993";
|
||||
$tgico-premium_addone: "\e994";
|
||||
$tgico-premium_double: "\e995";
|
||||
$tgico-premium_lock: "\e996";
|
||||
$tgico-premium_unlock: "\e997";
|
||||
$tgico-previous: "\e998";
|
||||
$tgico-radiooff: "\e999";
|
||||
$tgico-radioon: "\e99a";
|
||||
$tgico-reactions: "\e99b";
|
||||
$tgico-readchats: "\e99c";
|
||||
$tgico-recent: "\e99d";
|
||||
$tgico-replace: "\e99e";
|
||||
$tgico-reply: "\e99f";
|
||||
$tgico-reply_filled: "\e9a0";
|
||||
$tgico-rightpanel: "\e9a1";
|
||||
$tgico-rotate_left: "\e9a2";
|
||||
$tgico-rotate_right: "\e9a3";
|
||||
$tgico-saved: "\e9a4";
|
||||
$tgico-savedmessages: "\e9a5";
|
||||
$tgico-schedule: "\e9a6";
|
||||
$tgico-scheduled: "\e9a7";
|
||||
$tgico-search: "\e9a8";
|
||||
$tgico-select: "\e9a9";
|
||||
$tgico-send: "\e9aa";
|
||||
$tgico-send2: "\e9ab";
|
||||
$tgico-sending: "\e9ac";
|
||||
$tgico-sendingerror: "\e9ad";
|
||||
$tgico-settings: "\e9ae";
|
||||
$tgico-settings_filled: "\e9af";
|
||||
$tgico-sharescreen_filled: "\e9b0";
|
||||
$tgico-shipping: "\e9b1";
|
||||
$tgico-shuffle: "\e9b2";
|
||||
$tgico-smallscreen: "\e9b3";
|
||||
$tgico-smile: "\e9b4";
|
||||
$tgico-spoiler: "\e9b5";
|
||||
$tgico-sport: "\e9b6";
|
||||
$tgico-star: "\e9b7";
|
||||
$tgico-stickers: "\e9b8";
|
||||
$tgico-stickers_face: "\e9b9";
|
||||
$tgico-stop: "\e9ba";
|
||||
$tgico-strikethrough: "\e9bb";
|
||||
$tgico-textedit: "\e9bc";
|
||||
$tgico-tip: "\e9bd";
|
||||
$tgico-tools: "\e9be";
|
||||
$tgico-topics: "\e9bf";
|
||||
$tgico-transcribe: "\e9c0";
|
||||
$tgico-unarchive: "\e9c1";
|
||||
$tgico-underline: "\e9c2";
|
||||
$tgico-unmute: "\e9c3";
|
||||
$tgico-unpin: "\e9c4";
|
||||
$tgico-unread: "\e9c5";
|
||||
$tgico-up: "\e9c6";
|
||||
$tgico-user: "\e9c7";
|
||||
$tgico-username: "\e9c8";
|
||||
$tgico-videocamera: "\e9c9";
|
||||
$tgico-videocamera_crossed_filled: "\e9ca";
|
||||
$tgico-videocamera_filled: "\e9cb";
|
||||
$tgico-videochat: "\e9cc";
|
||||
$tgico-volume_down: "\e9cd";
|
||||
$tgico-volume_mute: "\e9ce";
|
||||
$tgico-volume_off: "\e9cf";
|
||||
$tgico-volume_up: "\e9d0";
|
||||
$tgico-zoomin: "\e9d1";
|
||||
$tgico-zoomout: "\e9d2";
|
||||
$tgico-gift: "\e950";
|
||||
$tgico-group: "\e951";
|
||||
$tgico-groupmedia: "\e952";
|
||||
$tgico-groupmediaoff: "\e953";
|
||||
$tgico-help: "\e954";
|
||||
$tgico-hide: "\e955";
|
||||
$tgico-image: "\e956";
|
||||
$tgico-info: "\e957";
|
||||
$tgico-info2: "\e958";
|
||||
$tgico-italic: "\e959";
|
||||
$tgico-keyboard: "\e95a";
|
||||
$tgico-lamp: "\e95b";
|
||||
$tgico-language: "\e95c";
|
||||
$tgico-largepause: "\e95d";
|
||||
$tgico-largeplay: "\e95e";
|
||||
$tgico-left: "\e95f";
|
||||
$tgico-limit_chat: "\e960";
|
||||
$tgico-limit_chats: "\e961";
|
||||
$tgico-limit_file: "\e962";
|
||||
$tgico-limit_folders: "\e963";
|
||||
$tgico-limit_link: "\e964";
|
||||
$tgico-limit_pin: "\e965";
|
||||
$tgico-link: "\e966";
|
||||
$tgico-listscreenshare: "\e967";
|
||||
$tgico-livelocation: "\e968";
|
||||
$tgico-location: "\e969";
|
||||
$tgico-lock: "\e96a";
|
||||
$tgico-lockoff: "\e96b";
|
||||
$tgico-loginlogodesktop: "\e96c";
|
||||
$tgico-loginlogomobile: "\e96d";
|
||||
$tgico-logout: "\e96e";
|
||||
$tgico-mediaspoiler: "\e96f";
|
||||
$tgico-mediaspoileroff: "\e970";
|
||||
$tgico-mention: "\e971";
|
||||
$tgico-menu: "\e972";
|
||||
$tgico-message: "\e973";
|
||||
$tgico-messageunread: "\e974";
|
||||
$tgico-microphone: "\e975";
|
||||
$tgico-microphone_crossed: "\e976";
|
||||
$tgico-microphone_crossed_filled: "\e977";
|
||||
$tgico-microphone_filled: "\e978";
|
||||
$tgico-minus: "\e979";
|
||||
$tgico-monospace: "\e97a";
|
||||
$tgico-more: "\e97b";
|
||||
$tgico-mute: "\e97c";
|
||||
$tgico-muted: "\e97d";
|
||||
$tgico-newchannel: "\e97e";
|
||||
$tgico-newchat_filled: "\e97f";
|
||||
$tgico-newgroup: "\e980";
|
||||
$tgico-newprivate: "\e981";
|
||||
$tgico-next: "\e982";
|
||||
$tgico-noncontacts: "\e983";
|
||||
$tgico-nosound: "\e984";
|
||||
$tgico-passwordoff: "\e985";
|
||||
$tgico-pause: "\e986";
|
||||
$tgico-permissions: "\e987";
|
||||
$tgico-phone: "\e988";
|
||||
$tgico-pin: "\e989";
|
||||
$tgico-pinlist: "\e98a";
|
||||
$tgico-pinned_filled: "\e98b";
|
||||
$tgico-pinnedchat: "\e98c";
|
||||
$tgico-pip: "\e98d";
|
||||
$tgico-play: "\e98e";
|
||||
$tgico-playback_05: "\e98f";
|
||||
$tgico-playback_15: "\e990";
|
||||
$tgico-playback_1x: "\e991";
|
||||
$tgico-playback_2x: "\e992";
|
||||
$tgico-plus: "\e993";
|
||||
$tgico-poll: "\e994";
|
||||
$tgico-premium_addone: "\e995";
|
||||
$tgico-premium_double: "\e996";
|
||||
$tgico-premium_lock: "\e997";
|
||||
$tgico-premium_unlock: "\e998";
|
||||
$tgico-previous: "\e999";
|
||||
$tgico-radiooff: "\e99a";
|
||||
$tgico-radioon: "\e99b";
|
||||
$tgico-reactions: "\e99c";
|
||||
$tgico-readchats: "\e99d";
|
||||
$tgico-recent: "\e99e";
|
||||
$tgico-replace: "\e99f";
|
||||
$tgico-reply: "\e9a0";
|
||||
$tgico-reply_filled: "\e9a1";
|
||||
$tgico-rightpanel: "\e9a2";
|
||||
$tgico-rotate_left: "\e9a3";
|
||||
$tgico-rotate_right: "\e9a4";
|
||||
$tgico-saved: "\e9a5";
|
||||
$tgico-savedmessages: "\e9a6";
|
||||
$tgico-schedule: "\e9a7";
|
||||
$tgico-scheduled: "\e9a8";
|
||||
$tgico-search: "\e9a9";
|
||||
$tgico-select: "\e9aa";
|
||||
$tgico-send: "\e9ab";
|
||||
$tgico-send2: "\e9ac";
|
||||
$tgico-sending: "\e9ad";
|
||||
$tgico-sendingerror: "\e9ae";
|
||||
$tgico-settings: "\e9af";
|
||||
$tgico-settings_filled: "\e9b0";
|
||||
$tgico-sharescreen_filled: "\e9b1";
|
||||
$tgico-shipping: "\e9b2";
|
||||
$tgico-shuffle: "\e9b3";
|
||||
$tgico-smallscreen: "\e9b4";
|
||||
$tgico-smile: "\e9b5";
|
||||
$tgico-spoiler: "\e9b6";
|
||||
$tgico-sport: "\e9b7";
|
||||
$tgico-star: "\e9b8";
|
||||
$tgico-stickers: "\e9b9";
|
||||
$tgico-stickers_face: "\e9ba";
|
||||
$tgico-stop: "\e9bb";
|
||||
$tgico-strikethrough: "\e9bc";
|
||||
$tgico-textedit: "\e9bd";
|
||||
$tgico-tip: "\e9be";
|
||||
$tgico-tools: "\e9bf";
|
||||
$tgico-topics: "\e9c0";
|
||||
$tgico-transcribe: "\e9c1";
|
||||
$tgico-unarchive: "\e9c2";
|
||||
$tgico-underline: "\e9c3";
|
||||
$tgico-unmute: "\e9c4";
|
||||
$tgico-unpin: "\e9c5";
|
||||
$tgico-unread: "\e9c6";
|
||||
$tgico-up: "\e9c7";
|
||||
$tgico-user: "\e9c8";
|
||||
$tgico-username: "\e9c9";
|
||||
$tgico-videocamera: "\e9ca";
|
||||
$tgico-videocamera_crossed_filled: "\e9cb";
|
||||
$tgico-videocamera_filled: "\e9cc";
|
||||
$tgico-videochat: "\e9cd";
|
||||
$tgico-volume_down: "\e9ce";
|
||||
$tgico-volume_mute: "\e9cf";
|
||||
$tgico-volume_off: "\e9d0";
|
||||
$tgico-volume_up: "\e9d1";
|
||||
$tgico-zoomin: "\e9d2";
|
||||
$tgico-zoomout: "\e9d3";
|
||||
|
||||
|
|
Loading…
Reference in New Issue