|
|
@ -38,6 +38,7 @@ import contextMenuController from "../../helpers/contextMenuController"; |
|
|
|
import { attachContextMenuListener } from "../../helpers/dom/attachContextMenuListener"; |
|
|
|
import { attachContextMenuListener } from "../../helpers/dom/attachContextMenuListener"; |
|
|
|
import filterAsync from "../../helpers/array/filterAsync"; |
|
|
|
import filterAsync from "../../helpers/array/filterAsync"; |
|
|
|
import appDownloadManager from "../../lib/appManagers/appDownloadManager"; |
|
|
|
import appDownloadManager from "../../lib/appManagers/appDownloadManager"; |
|
|
|
|
|
|
|
import { SERVICE_PEER_ID } from "../../lib/mtproto/mtproto_config"; |
|
|
|
|
|
|
|
|
|
|
|
export default class ChatContextMenu { |
|
|
|
export default class ChatContextMenu { |
|
|
|
private buttons: (ButtonMenuItemOptions & {verify: () => boolean | Promise<boolean>, notDirect?: () => boolean, withSelection?: true, isSponsored?: true})[]; |
|
|
|
private buttons: (ButtonMenuItemOptions & {verify: () => boolean | Promise<boolean>, notDirect?: () => boolean, withSelection?: true, isSponsored?: true})[]; |
|
|
@ -178,6 +179,10 @@ export default class ChatContextMenu { |
|
|
|
this.canOpenReactedList = undefined; |
|
|
|
this.canOpenReactedList = undefined; |
|
|
|
|
|
|
|
|
|
|
|
const initResult = await this.init(); |
|
|
|
const initResult = await this.init(); |
|
|
|
|
|
|
|
if(!initResult) { |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
element = initResult.element; |
|
|
|
element = initResult.element; |
|
|
|
const {cleanup, destroy, menuPadding, reactionsMenu, reactionsMenuPosition} = initResult; |
|
|
|
const {cleanup, destroy, menuPadding, reactionsMenu, reactionsMenuPosition} = initResult; |
|
|
|
let isReactionsMenuVisible = false; |
|
|
|
let isReactionsMenuVisible = false; |
|
|
@ -214,7 +219,7 @@ export default class ChatContextMenu { |
|
|
|
if(isReactionsMenuVisible) void reactionsMenu.container.offsetLeft; // reflow
|
|
|
|
if(isReactionsMenuVisible) void reactionsMenu.container.offsetLeft; // reflow
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
openBtnMenu(element, () => { |
|
|
|
contextMenuController.openBtnMenu(element, () => { |
|
|
|
if(reactionsMenu) { |
|
|
|
if(reactionsMenu) { |
|
|
|
reactionsMenu.container.classList.remove('is-visible'); |
|
|
|
reactionsMenu.container.classList.remove('is-visible'); |
|
|
|
} |
|
|
|
} |
|
|
@ -224,6 +229,7 @@ export default class ChatContextMenu { |
|
|
|
this.target = null; |
|
|
|
this.target = null; |
|
|
|
this.viewerPeerId = undefined; |
|
|
|
this.viewerPeerId = undefined; |
|
|
|
this.canOpenReactedList = undefined; |
|
|
|
this.canOpenReactedList = undefined; |
|
|
|
|
|
|
|
cleanup(); |
|
|
|
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
|
setTimeout(() => { |
|
|
|
destroy(); |
|
|
|
destroy(); |
|
|
@ -235,6 +241,9 @@ export default class ChatContextMenu { |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
r(); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
public cleanup() { |
|
|
|
public cleanup() { |
|
|
|
this.listenerSetter.removeAll(); |
|
|
|
this.listenerSetter.removeAll(); |
|
|
|
this.reactionsMenu && this.reactionsMenu.cleanup(); |
|
|
|
this.reactionsMenu && this.reactionsMenu.cleanup(); |
|
|
@ -425,7 +434,7 @@ export default class ChatContextMenu { |
|
|
|
icon: 'forward', |
|
|
|
icon: 'forward', |
|
|
|
text: 'Forward', |
|
|
|
text: 'Forward', |
|
|
|
onClick: this.onForwardClick, // let forward the message if it's outgoing but not ours (like a changelog)
|
|
|
|
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' |
|
|
|
verify: () => !this.noForwards && this.chat.type !== 'scheduled' && (!this.message.pFlags.is_outgoing || this.message.fromId === SERVICE_PEER_ID) && this.message._ !== 'messageService' |
|
|
|
}, { |
|
|
|
}, { |
|
|
|
icon: 'forward', |
|
|
|
icon: 'forward', |
|
|
|
text: 'Message.Context.Selection.Forward', |
|
|
|
text: 'Message.Context.Selection.Forward', |
|
|
@ -500,6 +509,10 @@ export default class ChatContextMenu { |
|
|
|
this.setButtons(); |
|
|
|
this.setButtons(); |
|
|
|
|
|
|
|
|
|
|
|
const filteredButtons = await this.filterButtons(this.buttons); |
|
|
|
const filteredButtons = await this.filterButtons(this.buttons); |
|
|
|
|
|
|
|
if(!filteredButtons.length) { |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const element = this.element = ButtonMenu(filteredButtons, this.listenerSetter); |
|
|
|
const element = this.element = ButtonMenu(filteredButtons, this.listenerSetter); |
|
|
|
element.id = 'bubble-contextmenu'; |
|
|
|
element.id = 'bubble-contextmenu'; |
|
|
|
element.classList.add('contextmenu'); |
|
|
|
element.classList.add('contextmenu'); |
|
|
@ -540,8 +553,9 @@ export default class ChatContextMenu { |
|
|
|
fakeText.classList.add('btn-menu-item-text-fake'); |
|
|
|
fakeText.classList.add('btn-menu-item-text-fake'); |
|
|
|
viewsButton.element.append(fakeText); |
|
|
|
viewsButton.element.append(fakeText); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const AVATAR_SIZE = 22; |
|
|
|
const MAX_AVATARS = 3; |
|
|
|
const MAX_AVATARS = 3; |
|
|
|
const PADDING_PER_AVATAR = .875; |
|
|
|
const PADDING_PER_AVATAR = 1.125; |
|
|
|
i18nElem.element.style.visibility = 'hidden'; |
|
|
|
i18nElem.element.style.visibility = 'hidden'; |
|
|
|
i18nElem.element.style.paddingRight = isViewingReactions ? PADDING_PER_AVATAR * Math.min(MAX_AVATARS, recentReactions.length) + 'rem' : '1rem'; |
|
|
|
i18nElem.element.style.paddingRight = isViewingReactions ? PADDING_PER_AVATAR * Math.min(MAX_AVATARS, recentReactions.length) + 'rem' : '1rem'; |
|
|
|
const middleware = this.middleware.get(); |
|
|
|
const middleware = this.middleware.get(); |
|
|
@ -595,7 +609,7 @@ export default class ChatContextMenu { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(reactions.length) { |
|
|
|
if(reactions.length) { |
|
|
|
const avatars = new StackedAvatars({avatarSize: 24}); |
|
|
|
const avatars = new StackedAvatars({avatarSize: AVATAR_SIZE}); |
|
|
|
avatars.render(recentReactions ? recentReactions.map((r) => getPeerId(r.peer_id)) : reactions.map((reaction) => reaction.peerId)); |
|
|
|
avatars.render(recentReactions ? recentReactions.map((r) => getPeerId(r.peer_id)) : reactions.map((reaction) => reaction.peerId)); |
|
|
|
viewsButton.element.append(avatars.container); |
|
|
|
viewsButton.element.append(avatars.container); |
|
|
|
|
|
|
|
|
|
|
@ -645,7 +659,7 @@ export default class ChatContextMenu { |
|
|
|
}, |
|
|
|
}, |
|
|
|
destroy: () => { |
|
|
|
destroy: () => { |
|
|
|
element.remove(); |
|
|
|
element.remove(); |
|
|
|
reactionsMenu.widthContainer.remove(); |
|
|
|
reactionsMenu && reactionsMenu.widthContainer.remove(); |
|
|
|
}, |
|
|
|
}, |
|
|
|
menuPadding, |
|
|
|
menuPadding, |
|
|
|
reactionsMenu, |
|
|
|
reactionsMenu, |
|
|
|