/* * https://github.com/morethanwords/tweb * Copyright (C) 2019-2021 Eduard Kuzmenko * https://github.com/morethanwords/tweb/blob/master/LICENSE */ import PopupElement from '.'; import {Message, Reaction} from '../../layer'; import ReactionsElement from '../chat/reactions'; import {horizontalMenu} from '../horizontalMenu'; import Scrollable from '../scrollable'; import ScrollableLoader from '../../helpers/scrollableLoader'; import appDialogsManager from '../../lib/appManagers/appDialogsManager'; import replaceContent from '../../helpers/dom/replaceContent'; import wrapSticker from '../wrappers/sticker'; import ReactionElement from '../chat/reaction'; import getUserStatusString from '../wrappers/getUserStatusString'; import {makeMediaSize} from '../../helpers/mediaSize'; import wrapCustomEmoji from '../wrappers/customEmoji'; import SettingSection from '../settingSection'; import {formatFullSentTime} from '../../helpers/date'; export default class PopupReactedList extends PopupElement { constructor( private message: Message.message ) { super('popup-reacted-list', {closable: true, overlayClosable: true, body: true}); this.init(); } private async init() { const middleware = this.middlewareHelper.get(); const message = await this.managers.appMessagesManager.getGroupsFirstMessage(this.message); if(!middleware()) return; const canViewReadParticipants = await this.managers.appMessagesManager.canViewMessageReadParticipants(message); if(!middleware()) return; // this.body.append(generateDelimiter()); const reactionsElement = new ReactionsElement(); const newMessage: Message.message = { ...message, mid: 0, id: 0, reactions: { _: 'messageReactions', results: [], ...message.reactions, pFlags: {}, recent_reactions: [] } }; newMessage.reactions.results = newMessage.reactions.results.map((reactionCount) => { return { ...reactionCount, chosen_order: undefined, pFlags: {} }; }); reactionsElement.init(newMessage, 'block', this.middlewareHelper.get()); reactionsElement.render(); reactionsElement.classList.add('no-stripe'); reactionsElement.classList.remove('has-no-reactions'); reactionsElement.append(this.btnClose); this.header.append(reactionsElement); const tabsContainer = document.createElement('div'); tabsContainer.classList.add('tabs-container'); tabsContainer.dataset.animation = 'tabs'; const loaders: Map = new Map(); let hasAllReactions = false; if(newMessage.reactions.results.length) { const reaction = this.createFakeReaction('reactions', newMessage.reactions.results.reduce((acc, r) => acc + r.count, 0)); reactionsElement.prepend(reaction); newMessage.reactions.results.unshift(reaction.reactionCount); hasAllReactions = true; } let hasReadParticipants = false; if(canViewReadParticipants) { try { const readUserIds = await this.managers.appMessagesManager.getMessageReadParticipants(message.peerId, message.mid); if(!middleware()) return; if(!readUserIds.length) { throw ''; } const reaction = this.createFakeReaction('checks', readUserIds.length); reactionsElement.prepend(reaction); newMessage.reactions.results.unshift(reaction.reactionCount); hasReadParticipants = true; } catch(err) { } } newMessage.reactions.results.forEach((reactionCount) => { const scrollable = new Scrollable(undefined); scrollable.container.classList.add('tabs-tab'); const section = new SettingSection({ noShadow: true, noDelimiter: true }); const chatlist = appDialogsManager.createChatList({ dialogSize: 72 }); appDialogsManager.setListClickListener(chatlist, () => { this.hide(); }, undefined, false, true); section.content.append(chatlist); scrollable.container.append(section.container); const skipReadParticipants = (reactionCount.reaction as any) !== 'checks'; const skipReactionsList = (reactionCount.reaction as any) === 'checks'; if(['checks', 'reactions'].includes(reactionCount.reaction as any)) { reactionCount.reaction = undefined; } const size = 24; const mediaSize = makeMediaSize(size, size); let nextOffset: string; const loader = new ScrollableLoader({ scrollable, getPromise: async() => { const result = await this.managers.appMessagesManager.getMessageReactionsListAndReadParticipants(message, undefined, reactionCount.reaction, nextOffset, skipReadParticipants, skipReactionsList); nextOffset = result.nextOffset; await Promise.all(result.combined.map(async({peerId, reaction, date}) => { const {dom} = appDialogsManager.addDialogNew({ peerId: peerId, autonomous: true, container: chatlist, avatarSize: 'abitbigger', rippleEnabled: false, meAsSaved: false }); if(reaction) { const stickerContainer = document.createElement('div'); stickerContainer.classList.add('reacted-list-reaction-icon'); if(reaction._ === 'reactionEmoji') { const availableReaction = await this.managers.appReactionsManager.getReactionCached(reaction.emoticon); wrapSticker({ doc: availableReaction.static_icon, div: stickerContainer, width: 24, height: 24, middleware }); } else if(reaction._ === 'reactionCustomEmoji') { stickerContainer.append(wrapCustomEmoji({ docIds: [reaction.document_id], customEmojiSize: mediaSize, middleware })); } dom.listEl.append(stickerContainer); } if(date && message.pFlags.out) { const c = document.createElement('span'); dom.lastMessageSpan.style.cssText = `display: flex !important; align-items: center;`; const span = document.createElement('span'); span.classList.add(reaction ? 'tgico-reactions' : 'tgico-checks', 'reacted-list-checks'); const fragment = document.createDocumentFragment(); c.append(formatFullSentTime(date, false)); fragment.append(span, c); replaceContent(dom.lastMessageSpan, fragment); } else { const user = await this.managers.appUsersManager.getUser(peerId.toUserId()); replaceContent(dom.lastMessageSpan, getUserStatusString(user)); } })); return !nextOffset; } }); loaders.set(scrollable.container, loader); tabsContainer.append(scrollable.container); }); this.body.append(tabsContainer); const selectTab = horizontalMenu(reactionsElement, tabsContainer, (id, tabContent) => { if(id === (reactionsElement.childElementCount - 1)) { return false; } const reaction = reactionsElement.children[id] as ReactionElement; const prevId = selectTab.prevId(); if(prevId !== -1) { (reactionsElement.children[prevId] as ReactionElement).setIsChosen(false); } reaction.setIsChosen(true); const loader = loaders.get(tabContent); loader.load(); }, undefined, undefined, undefined, this.listenerSetter); // selectTab(hasAllReactions && hasReadParticipants ? 1 : 0, false); selectTab(0, false); this.show(); } private createFakeReaction(icon: string, count: number) { const reaction = new ReactionElement(); reaction.init('block', this.middlewareHelper.get()); reaction.reactionCount = { _: 'reactionCount', count: count, reaction: icon as any }; reaction.setCanRenderAvatars(false); reaction.renderCounter(); const allReactionsSticker = document.createElement('div'); allReactionsSticker.classList.add('reaction-counter', 'reaction-sticker-icon', 'tgico-' + icon); reaction.prepend(allReactionsSticker); return reaction; } }