/* * https://github.com/morethanwords/tweb * Copyright (C) 2019-2021 Eduard Kuzmenko * https://github.com/morethanwords/tweb/blob/master/LICENSE */ import { formatTime, getFullDate } from "../../helpers/date"; import setInnerHTML from "../../helpers/dom/setInnerHTML"; import formatNumber from "../../helpers/number/formatNumber"; import { Message } from "../../layer"; import getPeerId from "../../lib/appManagers/utils/peers/getPeerId"; import { i18n, _i18n } from "../../lib/langPack"; import wrapEmojiText from "../../lib/richTextProcessor/wrapEmojiText"; import rootScope from "../../lib/rootScope"; import type LazyLoadQueue from "../lazyLoadQueue"; import PeerTitle from "../peerTitle"; import { wrapReply } from "../wrappers"; import Chat, { ChatType } from "./chat"; import ReactionsElement from "./reactions"; import RepliesElement from "./replies"; const NBSP = ' '; const makeEdited = () => { const edited = document.createElement('i'); edited.classList.add('edited'); _i18n(edited, 'EditedMessage'); return edited; }; const makeSponsored = () => i18n('SponsoredMessage'); export namespace MessageRender { /* export const setText = () => { }; */ export const setTime = (options: { chatType: ChatType, message: Message.message | Message.messageService, reactionsMessage?: Message.message }) => { const {chatType, message} = options; const date = new Date(message.date * 1000); const args: (HTMLElement | string)[] = []; let editedSpan: HTMLElement, sponsoredSpan: HTMLElement, reactionsElement: ReactionsElement, reactionsMessage: Message.message; const isSponsored = !!(message as Message.message).pFlags.sponsored; const isMessage = !('action' in message) && !isSponsored; let hasReactions: boolean; let time: HTMLElement = isSponsored ? undefined : formatTime(date); if(isMessage) { if(message.views) { const postAuthor = message.post_author || message.fwd_from?.post_author; const postViewsSpan = document.createElement('span'); postViewsSpan.classList.add('post-views'); postViewsSpan.innerHTML = formatNumber(message.views, 1); const channelViews = document.createElement('i'); channelViews.classList.add('tgico-channelviews', 'time-icon'); args.push(postViewsSpan, channelViews); if(postAuthor) { const span = document.createElement('span'); setInnerHTML(span, wrapEmojiText(postAuthor)); span.insertAdjacentHTML('beforeend', ',' + NBSP) args.push(span); } } if(message.edit_date && chatType !== 'scheduled' && !message.pFlags.edit_hide) { args.unshift(editedSpan = makeEdited()); } if(chatType !== 'pinned' && message.pFlags.pinned) { const i = document.createElement('i'); i.classList.add('tgico-pinnedchat', 'time-icon'); args.unshift(i); } if(message.peer_id._ === 'peerUser'/* && message.reactions?.results?.length */) { hasReactions = true; reactionsMessage = options.reactionsMessage; reactionsElement = new ReactionsElement(); reactionsElement.init(reactionsMessage, 'inline', true); reactionsElement.render(); args.unshift(reactionsElement); } } else if(isSponsored) { args.push(sponsoredSpan = makeSponsored()); } if(time) { args.push(time); } let title = isSponsored ? undefined : getFullDate(date); if(isMessage) { title += (message.edit_date && !message.pFlags.edit_hide ? `\nEdited: ${getFullDate(new Date(message.edit_date * 1000))}` : '') + (message.fwd_from ? `\nOriginal: ${getFullDate(new Date(message.fwd_from.date * 1000))}` : ''); } const timeSpan = document.createElement('span'); timeSpan.classList.add('time', 'tgico'); // if(title) timeSpan.title = title; timeSpan.append(...args); const inner = document.createElement('div'); inner.classList.add('inner', 'tgico'); if(title) inner.title = title; let clonedArgs = args; if(editedSpan) { clonedArgs[clonedArgs.indexOf(editedSpan)] = makeEdited(); } if(sponsoredSpan) { clonedArgs[clonedArgs.indexOf(sponsoredSpan)] = makeSponsored(); } if(reactionsElement) { const _reactionsElement = clonedArgs[clonedArgs.indexOf(reactionsElement)] = new ReactionsElement(); _reactionsElement.init(reactionsMessage, 'inline'); _reactionsElement.render(); } clonedArgs = clonedArgs.map((a) => a instanceof HTMLElement && !a.classList.contains('i18n') && !a.classList.contains('reactions') ? a.cloneNode(true) as HTMLElement : a); if(time) { clonedArgs[clonedArgs.length - 1] = formatTime(date); // clone time } inner.append(...clonedArgs); timeSpan.append(inner); return timeSpan; }; export const renderReplies = ({bubble, bubbleContainer, message, messageDiv, loadPromises, lazyLoadQueue}: { bubble: HTMLElement, bubbleContainer: HTMLElement, message: Message.message, messageDiv: HTMLElement, loadPromises?: Promise[], lazyLoadQueue?: LazyLoadQueue }) => { const isFooter = !bubble.classList.contains('sticker') && !bubble.classList.contains('emoji-big') && !bubble.classList.contains('round'); const repliesFooter = new RepliesElement(); repliesFooter.message = message; repliesFooter.type = isFooter ? 'footer' : 'beside'; repliesFooter.loadPromises = loadPromises; repliesFooter.lazyLoadQueue = lazyLoadQueue; repliesFooter.init(); bubbleContainer.prepend(repliesFooter); return isFooter; }; export const setReply = async({chat, bubble, bubbleContainer, message}: { chat: Chat, bubble: HTMLElement, bubbleContainer?: HTMLElement, message: Message.message }) => { const isReplacing = !bubbleContainer; if(isReplacing) { bubbleContainer = bubble.querySelector('.bubble-content'); } const currentReplyDiv = isReplacing ? bubbleContainer.querySelector('.reply') : null; if(!message.reply_to_mid) { if(currentReplyDiv) { currentReplyDiv.remove(); } bubble.classList.remove('is-reply'); return; } const replyToPeerId = message.reply_to.reply_to_peer_id ? getPeerId(message.reply_to.reply_to_peer_id) : chat.peerId; let originalMessage = await rootScope.managers.appMessagesManager.getMessageByPeer(replyToPeerId, message.reply_to_mid); let originalPeerTitle: string | HTMLElement; /////////this.log('message to render reply', originalMessage, originalPeerTitle, bubble, message); let titlePeerId: PeerId; // need to download separately if(!originalMessage) { //////////this.log('message to render reply empty, need download', message, message.reply_to_mid); rootScope.managers.appMessagesManager.fetchMessageReplyTo(message); chat.bubbles.needUpdate.push({replyToPeerId, replyMid: message.reply_to_mid, mid: message.mid}); originalPeerTitle = i18n('Loading'); } else { const originalMessageFwdFromId = (originalMessage as Message.message).fwdFromId; titlePeerId = message.fwdFromId && message.fwdFromId === originalMessageFwdFromId ? message.fwdFromId : originalMessage.fromId || originalMessageFwdFromId; originalPeerTitle = new PeerTitle({ peerId: titlePeerId, dialog: false, onlyFirstName: false, plainText: false }).element; } const {container, fillPromise} = wrapReply(originalPeerTitle, undefined, originalMessage, chat.isAnyGroup ? titlePeerId : undefined); await fillPromise; if(currentReplyDiv) { currentReplyDiv.replaceWith(container); } else { bubbleContainer.append(container); } //bubbleContainer.insertBefore(, nameContainer); bubble.classList.add('is-reply'); }; }