Telegram Web K with changes to work inside I2P https://web.telegram.i2p/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

748 lines
26 KiB

3 years ago
/*
* https://github.com/morethanwords/tweb
* Copyright (C) 2019-2021 Eduard Kuzmenko
* https://github.com/morethanwords/tweb/blob/master/LICENSE
*/
import type { AppMessagesManager } from "../../lib/appManagers/appMessagesManager";
import type { AppPeersManager } from "../../lib/appManagers/appPeersManager";
3 years ago
import type { AppPollsManager } from "../../lib/appManagers/appPollsManager";
3 years ago
import type { AppDocsManager, MyDocument } from "../../lib/appManagers/appDocsManager";
import type { AppMessagesIdsManager } from "../../lib/appManagers/appMessagesIdsManager";
3 years ago
import type { AppReactionsManager } from "../../lib/appManagers/appReactionsManager";
3 years ago
import type Chat from "./chat";
import { IS_TOUCH_SUPPORTED } from "../../environment/touchSupport";
3 years ago
import ButtonMenu, { ButtonMenuItemOptions } from "../buttonMenu";
import { attachContextMenuListener, openBtnMenu, positionMenu } from "../misc";
import PopupDeleteMessages from "../popups/deleteMessages";
import PopupForward from "../popups/forward";
import PopupPinMessage from "../popups/unpinMessage";
import { copyTextToClipboard } from "../../helpers/clipboard";
import PopupSendNow from "../popups/sendNow";
import { toast } from "../toast";
import I18n, { i18n, LangPackKey } from "../../lib/langPack";
3 years ago
import findUpClassName from "../../helpers/dom/findUpClassName";
import { cancelEvent } from "../../helpers/dom/cancelEvent";
import { attachClickEvent, simulateClickEvent } from "../../helpers/dom/clickEvent";
3 years ago
import isSelectionEmpty from "../../helpers/dom/isSelectionEmpty";
3 years ago
import { Message, Poll, Chat as MTChat, MessageMedia, AvailableReaction } from "../../layer";
3 years ago
import PopupReportMessages from "../popups/reportMessages";
import assumeType from "../../helpers/assumeType";
import PopupSponsored from "../popups/sponsored";
3 years ago
import { ScrollableX } from "../scrollable";
import { wrapSticker } from "../wrappers";
import RLottiePlayer from "../../lib/rlottie/rlottiePlayer";
import getVisibleRect from "../../helpers/dom/getVisibleRect";
import ListenerSetter from "../../helpers/listenerSetter";
import animationIntersector from "../animationIntersector";
import { getMiddleware } from "../../helpers/middleware";
import noop from "../../helpers/noop";
const REACTIONS_CLASS_NAME = 'btn-menu-reactions';
const REACTION_CLASS_NAME = REACTIONS_CLASS_NAME + '-reaction';
const REACTION_SIZE = 24;
const PADDING = 4;
const REACTION_CONTAINER_SIZE = REACTION_SIZE + PADDING * 2;
type ChatReactionsMenuPlayers = {
select?: RLottiePlayer,
appear?: RLottiePlayer,
selectWrapper: HTMLElement,
appearWrapper: HTMLElement
};
export class ChatReactionsMenu {
public container: HTMLElement;
private reactionsMap: Map<HTMLElement, ChatReactionsMenuPlayers>;
private scrollable: ScrollableX;
private animationGroup: string;
private middleware: ReturnType<typeof getMiddleware>;
constructor(
private appReactionsManager: AppReactionsManager
) {
const reactionsContainer = this.container = document.createElement('div');
reactionsContainer.classList.add(REACTIONS_CLASS_NAME);
const reactionsScrollable = this.scrollable = new ScrollableX(undefined);
reactionsContainer.append(reactionsScrollable.container);
reactionsScrollable.onAdditionalScroll = this.onScroll;
reactionsScrollable.setListeners();
this.reactionsMap = new Map();
this.animationGroup = 'CHAT-MENU-REACTIONS-' + Date.now();
animationIntersector.setOverrideIdleGroup(this.animationGroup, true);
if(!IS_TOUCH_SUPPORTED) {
reactionsContainer.addEventListener('mousemove', this.onMouseMove);
}
this.middleware = getMiddleware();
const middleware = this.middleware.get();
appReactionsManager.getAvailableReactions().then(reactions => {
if(!middleware()) return;
reactions.forEach(reaction => {
this.renderReaction(reaction);
});
});
}
public cleanup() {
this.middleware.clean();
this.scrollable.removeListeners();
this.reactionsMap.clear();
animationIntersector.setOverrideIdleGroup(this.animationGroup, false);
animationIntersector.checkAnimations(true, this.animationGroup, true);
}
private onScroll = () => {
this.reactionsMap.forEach((players, div) => {
this.onScrollProcessItem(div, players);
});
};
private renderReaction(reaction: AvailableReaction) {
const reactionDiv = document.createElement('div');
reactionDiv.classList.add(REACTION_CLASS_NAME);
const scaleContainer = document.createElement('div');
scaleContainer.classList.add(REACTION_CLASS_NAME + '-scale');
const appearWrapper = document.createElement('div');
const selectWrapper = document.createElement('div');
appearWrapper.classList.add(REACTION_CLASS_NAME + '-appear');
selectWrapper.classList.add(REACTION_CLASS_NAME + '-select', 'hide');
const hoverScale = IS_TOUCH_SUPPORTED ? 1 : 1.25;
const size = REACTION_SIZE * hoverScale;
const players: ChatReactionsMenuPlayers = {
selectWrapper,
appearWrapper
};
this.reactionsMap.set(reactionDiv, players);
const middleware = this.middleware.get();
const options = {
width: size,
height: size,
skipRatio: 1,
needFadeIn: false,
withThumb: false,
group: this.animationGroup,
middleware
};
let isFirst = true;
wrapSticker({
doc: reaction.appear_animation,
div: appearWrapper,
play: true,
...options
}).then(player => {
assumeType<RLottiePlayer>(player);
players.appear = player;
player.addEventListener('enterFrame', (frameNo) => {
if(player.maxFrame === frameNo) {
selectLoadPromise.then((selectPlayer) => {
assumeType<RLottiePlayer>(selectPlayer);
appearWrapper.classList.add('hide');
selectWrapper.classList.remove('hide');
if(isFirst) {
players.select = selectPlayer;
isFirst = false;
}
}, noop);
}
});
}, noop);
const selectLoadPromise = wrapSticker({
doc: reaction.select_animation,
div: selectWrapper,
...options
}).catch(noop);
scaleContainer.append(appearWrapper, selectWrapper);
reactionDiv.append(scaleContainer);
this.scrollable.append(reactionDiv);
}
private onScrollProcessItem(div: HTMLElement, players: ChatReactionsMenuPlayers) {
if(!players.appear) {
return;
}
const scaleContainer = div.firstElementChild as HTMLElement;
const visibleRect = getVisibleRect(div, this.scrollable.container);
if(!visibleRect) {
if(!players.appearWrapper.classList.contains('hide')) {
return;
}
if(players.select) {
players.select.stop();
}
players.appear.stop();
players.appear.autoplay = true;
players.appearWrapper.classList.remove('hide');
players.selectWrapper.classList.add('hide');
scaleContainer.style.transform = '';
} else if(visibleRect.overflow.left || visibleRect.overflow.right) {
const diff = Math.abs(visibleRect.rect.left - visibleRect.rect.right);
const scale = Math.min(diff ** 2 / REACTION_CONTAINER_SIZE ** 2, 1);
scaleContainer.style.transform = `scale(${scale})`;
} else {
scaleContainer.style.transform = '';
}
}
private onMouseMove = (e: MouseEvent) => {
const reactionDiv = findUpClassName(e.target, REACTION_CLASS_NAME);
if(!reactionDiv) {
return;
}
const players = this.reactionsMap.get(reactionDiv);
if(!players) {
return;
}
// do not play select animation when appearing
if(!players.appear?.paused) {
return;
}
const player = players.select;
if(!player) {
return;
}
if(player.paused) {
player.autoplay = true;
player.restart();
}
};
}
3 years ago
export default class ChatContextMenu {
private buttons: (ButtonMenuItemOptions & {verify: () => boolean, notDirect?: () => boolean, withSelection?: true, isSponsored?: true})[];
3 years ago
private element: HTMLElement;
private isSelectable: boolean;
private isSelected: boolean;
3 years ago
private target: HTMLElement;
private isTargetAGroupedItem: boolean;
private isTextSelected: boolean;
private isAnchorTarget: boolean;
private isUsernameTarget: boolean;
3 years ago
private isSponsored: boolean;
private isOverBubble: boolean;
3 years ago
private peerId: PeerId;
3 years ago
private mid: number;
private message: Message.message | Message.messageService;
private noForwards: boolean;
3 years ago
3 years ago
private reactionsMenu: ChatReactionsMenu;
private listenerSetter: ListenerSetter;
constructor(
private attachTo: HTMLElement,
3 years ago
private chat: Chat,
private appMessagesManager: AppMessagesManager,
private appPeersManager: AppPeersManager,
private appPollsManager: AppPollsManager,
private appDocsManager: AppDocsManager,
3 years ago
private appMessagesIdsManager: AppMessagesIdsManager,
private appReactionsManager: AppReactionsManager
3 years ago
) {
3 years ago
this.listenerSetter = new ListenerSetter();
3 years ago
if(IS_TOUCH_SUPPORTED/* && false */) {
3 years ago
attachClickEvent(attachTo, (e) => {
if(chat.selection.isSelecting) {
return;
}
const className = (e.target as HTMLElement).className;
if(!className || !className.includes) return;
chat.log('touchend', e);
const good = ['bubble', 'bubble-content-wrapper', 'bubble-content', 'message', 'time', 'inner'].find(c => className.match(new RegExp(c + '($|\\s)')));
if(good) {
cancelEvent(e);
//onContextMenu((e as TouchEvent).changedTouches[0]);
// onContextMenu((e as TouchEvent).changedTouches ? (e as TouchEvent).changedTouches[0] : e as MouseEvent);
3 years ago
this.onContextMenu(e);
3 years ago
}
}, {listenerSetter: this.chat.bubbles.listenerSetter});
3 years ago
} else attachContextMenuListener(attachTo, this.onContextMenu, this.chat.bubbles.listenerSetter);
3 years ago
}
3 years ago
private onContextMenu = (e: MouseEvent | Touch | TouchEvent) => {
let bubble: HTMLElement, contentWrapper: HTMLElement;
try {
contentWrapper = findUpClassName(e.target, 'bubble-content-wrapper');
bubble = contentWrapper ? contentWrapper.parentElement : findUpClassName(e.target, 'bubble');
} catch(e) {}
// ! context menu click by date bubble (there is no pointer-events)
if(!bubble || bubble.classList.contains('bubble-first')) return;
let element = this.element;
if(e instanceof MouseEvent || e.hasOwnProperty('preventDefault')) (e as any).preventDefault();
if(element && element.classList.contains('active')) {
return false;
}
if(e instanceof MouseEvent || e.hasOwnProperty('cancelBubble')) (e as any).cancelBubble = true;
let mid = +bubble.dataset.mid;
if(!mid) return;
const isSponsored = this.isSponsored = mid < 0;
this.isSelectable = this.chat.selection.canSelectBubble(bubble);
this.peerId = this.chat.peerId;
//this.msgID = msgID;
this.target = e.target as HTMLElement;
this.isTextSelected = !isSelectionEmpty();
this.isAnchorTarget = this.target.tagName === 'A' && (
(this.target as HTMLAnchorElement).target === '_blank' ||
this.target.classList.contains('anchor-url')
);
this.isUsernameTarget = this.target.tagName === 'A' && this.target.classList.contains('mention');
// * если открыть контекстное меню для альбома не по бабблу, и последний элемент не выбран, чтобы показать остальные пункты
if(this.chat.selection.isSelecting && !contentWrapper) {
if(isSponsored) {
return;
}
const mids = this.chat.getMidsByMid(mid);
if(mids.length > 1) {
const selectedMid = this.chat.selection.isMidSelected(this.peerId, mid) ?
mid :
mids.find(mid => this.chat.selection.isMidSelected(this.peerId, mid));
if(selectedMid) {
mid = selectedMid;
}
}
}
this.isOverBubble = !!contentWrapper;
const groupedItem = findUpClassName(this.target, 'grouped-item');
this.isTargetAGroupedItem = !!groupedItem;
if(groupedItem) {
this.mid = +groupedItem.dataset.mid;
} else {
this.mid = mid;
}
this.isSelected = this.chat.selection.isMidSelected(this.peerId, this.mid);
this.message = this.chat.getMessage(this.mid);
this.noForwards = !isSponsored && !this.appMessagesManager.canForward(this.message);
const initResult = this.init();
element = initResult.element;
const {cleanup, destroy} = initResult;
const side: 'left' | 'right' = bubble.classList.contains('is-in') ? 'left' : 'right';
//bubble.parentElement.append(element);
//appImManager.log('contextmenu', e, bubble, side);
positionMenu((e as TouchEvent).touches ? (e as TouchEvent).touches[0] : e as MouseEvent, element, side);
openBtnMenu(element, () => {
this.mid = 0;
this.peerId = undefined;
this.target = null;
cleanup();
setTimeout(() => {
destroy();
}, 300);
});
};
public cleanup() {
this.listenerSetter.removeAll();
this.reactionsMenu && this.reactionsMenu.cleanup();
}
public destroy() {
this.cleanup();
}
private filterButtons(buttons: ChatContextMenu['buttons']) {
if(this.isSponsored) {
return buttons.filter(button => {
return button.isSponsored;
});
} else {
return buttons.filter(button => {
let good: boolean;
//if((appImManager.chatSelection.isSelecting && !button.withSelection) || (button.withSelection && !appImManager.chatSelection.isSelecting)) {
if(this.chat.selection.isSelecting && !button.withSelection) {
good = false;
} else {
good = this.isOverBubble || IS_TOUCH_SUPPORTED || true ?
button.verify() :
button.notDirect && button.verify() && button.notDirect();
}
return good;
});
}
}
private setButtons() {
3 years ago
this.buttons = [{
icon: 'send2',
text: 'MessageScheduleSend',
onClick: this.onSendScheduledClick,
verify: () => this.chat.type === 'scheduled' && !this.message.pFlags.is_outgoing
}, {
icon: 'send2',
text: 'Message.Context.Selection.SendNow',
onClick: this.onSendScheduledClick,
verify: () => this.chat.type === 'scheduled' && this.isSelected && !this.chat.selection.selectionSendNowBtn.hasAttribute('disabled'),
3 years ago
notDirect: () => true,
withSelection: true
}, {
icon: 'schedule',
text: 'MessageScheduleEditTime',
onClick: () => {
this.chat.input.scheduleSending(() => {
assumeType<Message.message>(this.message);
3 years ago
this.appMessagesManager.editMessage(this.message, this.message.message, {
scheduleDate: this.chat.input.scheduleDate,
entities: this.message.entities
});
this.chat.input.onMessageSent(false, false);
}, new Date(this.message.date * 1000));
},
verify: () => this.chat.type === 'scheduled'
}, {
icon: 'reply',
text: 'Reply',
onClick: this.onReplyClick,
verify: () => this.chat.canSend() &&
3 years ago
!this.message.pFlags.is_outgoing &&
!!this.chat.input.messageInput &&
this.chat.type !== 'scheduled'/* ,
cancelEvent: true */
}, {
icon: 'edit',
text: 'Edit',
onClick: this.onEditClick,
verify: () => this.appMessagesManager.canEditMessage(this.message, 'text') && !!this.chat.input.messageInput
}, {
icon: 'copy',
text: 'Copy',
onClick: this.onCopyClick,
verify: () => !this.noForwards && !!(this.message as Message.message).message && !this.isTextSelected && (!this.isAnchorTarget || (this.message as Message.message).message !== this.target.innerText)
3 years ago
}, {
icon: 'copy',
text: 'Chat.CopySelectedText',
onClick: this.onCopyClick,
verify: () => !this.noForwards && !!(this.message as Message.message).message && this.isTextSelected
3 years ago
}, {
icon: 'copy',
text: 'Message.Context.Selection.Copy',
onClick: this.onCopyClick,
verify: () => {
if(!this.isSelected || this.noForwards) {
return false;
}
for(const [peerId, mids] of this.chat.selection.selectedMids) {
for(const mid of mids) {
if(!!this.appMessagesManager.getMessageByPeer(peerId, mid).message) {
return true;
}
}
}
return false;
},
3 years ago
notDirect: () => true,
withSelection: true
}, {
icon: 'copy',
text: 'CopyLink',
onClick: this.onCopyAnchorLinkClick,
verify: () => this.isAnchorTarget,
withSelection: true
}, {
icon: 'copy',
text: 'Text.Context.Copy.Username',
onClick: () => {
copyTextToClipboard(this.target.innerHTML);
},
verify: () => this.isUsernameTarget,
withSelection: true
}, {
icon: 'copy',
text: 'Text.Context.Copy.Hashtag',
onClick: () => {
copyTextToClipboard(this.target.innerHTML);
},
verify: () => this.target.classList.contains('anchor-hashtag'),
withSelection: true
3 years ago
}, {
icon: 'link',
text: 'MessageContext.CopyMessageLink1',
onClick: this.onCopyLinkClick,
verify: () => this.appPeersManager.isChannel(this.peerId) && !this.message.pFlags.is_outgoing
}, {
icon: 'pin',
text: 'Message.Context.Pin',
onClick: this.onPinClick,
verify: () => !this.message.pFlags.is_outgoing &&
this.message._ !== 'messageService' &&
!this.message.pFlags.pinned &&
this.appPeersManager.canPinMessage(this.peerId) &&
this.chat.type !== 'scheduled',
}, {
icon: 'unpin',
text: 'Message.Context.Unpin',
onClick: this.onUnpinClick,
verify: () => (this.message as Message.message).pFlags.pinned && this.appPeersManager.canPinMessage(this.peerId),
3 years ago
}, {
icon: 'download',
text: 'MediaViewer.Context.Download',
onClick: () => {
this.appDocsManager.saveDocFile((this.message as any).media.document);
3 years ago
},
verify: () => {
if(this.message.pFlags.is_outgoing) {
return false;
}
const doc: MyDocument = ((this.message as Message.message).media as MessageMedia.messageMediaDocument)?.document as any;
if(!doc) return false;
let hasTarget = !!IS_TOUCH_SUPPORTED;
const isGoodType = !doc.type || !(['gif', 'video', 'sticker'] as MyDocument['type'][]).includes(doc.type);
if(isGoodType) hasTarget = hasTarget || !!findUpClassName(this.target, 'document') || !!findUpClassName(this.target, 'audio');
return isGoodType && hasTarget;
3 years ago
}
}, {
icon: 'checkretract',
text: 'Chat.Poll.Unvote',
onClick: this.onRetractVote,
verify: () => {
const poll = (this.message as any).media?.poll as Poll;
3 years ago
return poll && poll.chosenIndexes.length && !poll.pFlags.closed && !poll.pFlags.quiz;
}/* ,
cancelEvent: true */
}, {
icon: 'stop',
text: 'Chat.Poll.Stop',
onClick: this.onStopPoll,
verify: () => {
const poll = (this.message as any).media?.poll;
3 years ago
return this.appMessagesManager.canEditMessage(this.message, 'poll') && poll && !poll.pFlags.closed && !this.message.pFlags.is_outgoing;
}/* ,
cancelEvent: true */
}, {
icon: 'forward',
text: 'Forward',
onClick: this.onForwardClick, // let forward the message if it's outgoing but not ours (like a changelog)
verify: () => !this.noForwards && this.chat.type !== 'scheduled' && (!this.message.pFlags.is_outgoing || !this.message.pFlags.out) && this.message._ !== 'messageService'
3 years ago
}, {
icon: 'forward',
text: 'Message.Context.Selection.Forward',
onClick: this.onForwardClick,
verify: () => this.chat.selection.selectionForwardBtn &&
this.isSelected &&
3 years ago
!this.chat.selection.selectionForwardBtn.hasAttribute('disabled'),
notDirect: () => true,
withSelection: true
3 years ago
}, {
icon: 'flag',
text: 'ReportChat',
onClick: () => {
new PopupReportMessages(this.peerId, [this.mid]);
},
verify: () => !this.message.pFlags.out && this.message._ === 'message' && !this.message.pFlags.is_outgoing && this.appPeersManager.isChannel(this.peerId),
3 years ago
notDirect: () => true,
withSelection: true
3 years ago
}, {
icon: 'select',
text: 'Message.Context.Select',
onClick: this.onSelectClick,
verify: () => !(this.message as Message.messageService).action && !this.isSelected && this.isSelectable,
3 years ago
notDirect: () => true,
withSelection: true
}, {
icon: 'select',
text: 'Message.Context.Selection.Clear',
onClick: this.onClearSelectionClick,
verify: () => this.isSelected,
3 years ago
notDirect: () => true,
withSelection: true
}, {
icon: 'delete danger',
text: 'Delete',
onClick: this.onDeleteClick,
verify: () => this.appMessagesManager.canDeleteMessage(this.message)
}, {
icon: 'delete danger',
text: 'Message.Context.Selection.Delete',
onClick: this.onDeleteClick,
verify: () => this.isSelected && !this.chat.selection.selectionDeleteBtn.hasAttribute('disabled'),
3 years ago
notDirect: () => true,
withSelection: true
}, {
icon: 'info',
text: 'Chat.Message.Sponsored.What',
onClick: () => {
new PopupSponsored();
},
verify: () => false,
isSponsored: true
3 years ago
}];
3 years ago
}
3 years ago
3 years ago
private init() {
this.cleanup();
this.setButtons();
const filteredButtons = this.filterButtons(this.buttons);
const element = this.element = ButtonMenu(filteredButtons, this.listenerSetter);
element.id = 'bubble-contextmenu';
element.classList.add('contextmenu');
const reactionsMenu = this.reactionsMenu = new ChatReactionsMenu(this.appReactionsManager);
element.prepend(reactionsMenu.container);
this.chat.container.append(element);
return {
element,
cleanup: () => {
this.cleanup();
reactionsMenu.cleanup();
},
destroy: () => {
element.remove();
}
};
}
3 years ago
private onSendScheduledClick = () => {
if(this.chat.selection.isSelecting) {
simulateClickEvent(this.chat.selection.selectionSendNowBtn);
3 years ago
} else {
new PopupSendNow(this.peerId, this.chat.getMidsByMid(this.mid));
}
};
private onReplyClick = () => {
this.chat.input.initMessageReply(this.mid);
};
private onEditClick = () => {
this.chat.input.initMessageEditing(this.mid);
};
private onCopyClick = () => {
if(isSelectionEmpty()) {
const mids = this.chat.selection.isSelecting ?
[...this.chat.selection.selectedMids.get(this.peerId)].sort((a, b) => a - b) :
[this.mid];
3 years ago
const str = mids.reduce((acc, mid) => {
const message = this.chat.getMessage(mid);
return acc + (message?.message ? message.message + '\n' : '');
}, '').trim();
3 years ago
copyTextToClipboard(str);
} else {
document.execCommand('copy');
//cancelSelection();
}
};
private onCopyAnchorLinkClick = () => {
copyTextToClipboard((this.target as HTMLAnchorElement).href);
};
private onCopyLinkClick = () => {
let threadMessage: Message.message;
if(this.chat.type === 'discussion') {
threadMessage = this.appMessagesManager.getMessageByPeer(this.peerId, this.chat.threadId);
}
const username = this.appPeersManager.getPeerUsername(threadMessage ? threadMessage.fromId : this.peerId);
3 years ago
const msgId = this.appMessagesIdsManager.getServerMessageId(this.mid);
let url = 'https://t.me/';
let key: LangPackKey;
if(username) {
url += username + '/' + (threadMessage ? this.appMessagesIdsManager.getServerMessageId(threadMessage.fwd_from.channel_post) : msgId);
if(threadMessage) url += '?comment=' + msgId;
3 years ago
key = 'LinkCopied';
} else {
3 years ago
url += 'c/' + this.peerId.toChatId() + '/' + msgId;
if(threadMessage) url += '?thread=' + this.appMessagesIdsManager.getServerMessageId(threadMessage.mid);
3 years ago
key = 'LinkCopiedPrivateInfo';
}
toast(I18n.format(key, true));
copyTextToClipboard(url);
};
private onPinClick = () => {
new PopupPinMessage(this.peerId, this.mid);
};
private onUnpinClick = () => {
new PopupPinMessage(this.peerId, this.mid, true);
};
private onRetractVote = () => {
this.appPollsManager.sendVote(this.message, []);
};
private onStopPoll = () => {
this.appPollsManager.stopPoll(this.message);
};
private onForwardClick = () => {
if(this.chat.selection.isSelecting) {
simulateClickEvent(this.chat.selection.selectionForwardBtn);
3 years ago
} else {
const mids = this.isTargetAGroupedItem ? [this.mid] : this.chat.getMidsByMid(this.mid);
new PopupForward({
[this.peerId]: mids
});
3 years ago
}
};
private onSelectClick = () => {
this.chat.selection.toggleByElement(findUpClassName(this.target, 'grouped-item') || findUpClassName(this.target, 'bubble'));
3 years ago
};
private onClearSelectionClick = () => {
this.chat.selection.cancelSelection();
};
private onDeleteClick = () => {
if(this.chat.selection.isSelecting) {
simulateClickEvent(this.chat.selection.selectionDeleteBtn);
3 years ago
} else {
new PopupDeleteMessages(this.peerId, this.isTargetAGroupedItem ? [this.mid] : this.chat.getMidsByMid(this.mid), this.chat.type);
}
};
}