Discussion read, handle reading update
Replies bot User subtitles
This commit is contained in:
parent
d44406fb7f
commit
3d81994cee
@ -38,7 +38,7 @@ import ListenerSetter from "../../helpers/listenerSetter";
|
|||||||
import PollElement from "../poll";
|
import PollElement from "../poll";
|
||||||
import AudioElement from "../audio";
|
import AudioElement from "../audio";
|
||||||
import { Message, MessageEntity, MessageReplies, MessageReplyHeader } from "../../layer";
|
import { Message, MessageEntity, MessageReplies, MessageReplyHeader } from "../../layer";
|
||||||
import { DEBUG, MOUNT_CLASS_TO } from "../../lib/mtproto/mtproto_config";
|
import { DEBUG, MOUNT_CLASS_TO, REPLIES_PEER_ID } from "../../lib/mtproto/mtproto_config";
|
||||||
|
|
||||||
const IGNORE_ACTIONS = ['messageActionHistoryClear'];
|
const IGNORE_ACTIONS = ['messageActionHistoryClear'];
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ export default class ChatBubbles {
|
|||||||
//public messagesCount: number = -1;
|
//public messagesCount: number = -1;
|
||||||
|
|
||||||
public unreadOut = new Set<number>();
|
public unreadOut = new Set<number>();
|
||||||
public needUpdate: {replyMid: number, mid: number}[] = []; // if need wrapSingleMessage
|
public needUpdate: {replyToPeerId: number, replyMid: number, mid: number}[] = []; // if need wrapSingleMessage
|
||||||
|
|
||||||
public bubbles: {[mid: string]: HTMLDivElement} = {};
|
public bubbles: {[mid: string]: HTMLDivElement} = {};
|
||||||
public dateMessages: {[timestamp: number]: {
|
public dateMessages: {[timestamp: number]: {
|
||||||
@ -277,17 +277,13 @@ export default class ChatBubbles {
|
|||||||
this.listenerSetter.add(rootScope, 'messages_downloaded', (e) => {
|
this.listenerSetter.add(rootScope, 'messages_downloaded', (e) => {
|
||||||
const {peerId, mids} = e.detail;
|
const {peerId, mids} = e.detail;
|
||||||
|
|
||||||
if(peerId !== this.peerId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
(mids as number[]).forEach(mid => {
|
(mids as number[]).forEach(mid => {
|
||||||
/* const promise = (this.scrollable.scrollLocked && this.scrollable.scrollLockedPromise) || Promise.resolve();
|
/* const promise = (this.scrollable.scrollLocked && this.scrollable.scrollLockedPromise) || Promise.resolve();
|
||||||
promise.then(() => {
|
promise.then(() => {
|
||||||
|
|
||||||
}); */
|
}); */
|
||||||
this.needUpdate.forEachReverse((obj, idx) => {
|
this.needUpdate.forEachReverse((obj, idx) => {
|
||||||
if(obj.replyMid == mid) {
|
if(obj.replyMid === mid, obj.replyToPeerId === peerId) {
|
||||||
const {mid, replyMid} = this.needUpdate.splice(idx, 1)[0];
|
const {mid, replyMid} = this.needUpdate.splice(idx, 1)[0];
|
||||||
|
|
||||||
//this.log('messages_downloaded', mid, replyMid, i, this.needUpdate, this.needUpdate.length, mids, this.bubbles[mid]);
|
//this.log('messages_downloaded', mid, replyMid, i, this.needUpdate, this.needUpdate.length, mids, this.bubbles[mid]);
|
||||||
@ -296,9 +292,9 @@ export default class ChatBubbles {
|
|||||||
|
|
||||||
const message = this.chat.getMessage(mid);
|
const message = this.chat.getMessage(mid);
|
||||||
|
|
||||||
const repliedMessage = this.chat.type === 'scheduled' ? this.appMessagesManager.getMessageByPeer(this.peerId, replyMid) : this.chat.getMessage(replyMid);
|
const repliedMessage = this.appMessagesManager.getMessageByPeer(obj.replyToPeerId, replyMid);
|
||||||
if(repliedMessage.deleted) { // чтобы не пыталось бесконечно загрузить удалённое сообщение
|
if(repliedMessage.deleted) { // ! чтобы не пыталось бесконечно загрузить удалённое сообщение
|
||||||
delete message.reply_to_mid; // WARNING!
|
delete message.reply_to_mid; // ! WARNING!
|
||||||
}
|
}
|
||||||
|
|
||||||
this.renderMessage(message, true, false, bubble, false);
|
this.renderMessage(message, true, false, bubble, false);
|
||||||
@ -429,9 +425,9 @@ export default class ChatBubbles {
|
|||||||
} */
|
} */
|
||||||
|
|
||||||
//appMessagesManager.readMessages(readed);
|
//appMessagesManager.readMessages(readed);
|
||||||
/* false && */ this.appMessagesManager.readHistory(this.peerId, max).catch((err: any) => {
|
/* false && */ this.appMessagesManager.readHistory(this.peerId, max, this.chat.threadId).catch((err: any) => {
|
||||||
this.log.error('readHistory err:', err);
|
this.log.error('readHistory err:', err);
|
||||||
this.appMessagesManager.readHistory(this.peerId, max);
|
this.appMessagesManager.readHistory(this.peerId, max, this.chat.threadId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -525,12 +521,23 @@ export default class ChatBubbles {
|
|||||||
const commentsDiv: HTMLElement = findUpClassName(target, 'replies');
|
const commentsDiv: HTMLElement = findUpClassName(target, 'replies');
|
||||||
if(commentsDiv) {
|
if(commentsDiv) {
|
||||||
const bubbleMid = +bubble.dataset.mid;
|
const bubbleMid = +bubble.dataset.mid;
|
||||||
const message = this.appMessagesManager.filterMessages(this.chat.getMessage(bubbleMid), message => !!(message as Message.message).replies)[0] as Message.message;
|
if(this.peerId === REPLIES_PEER_ID) {
|
||||||
const replies = message.replies;
|
const message = this.chat.getMessage(bubbleMid) as Message.message;
|
||||||
if(replies) {
|
const peerId = this.appPeersManager.getPeerId(message.reply_to.reply_to_peer_id);
|
||||||
this.appMessagesManager.getDiscussionMessage(this.peerId, message.mid).then(message => {
|
const threadId = message.reply_to.reply_to_top_id;
|
||||||
this.chat.appImManager.setInnerPeer(-replies.channel_id, (message as MyMessage).mid, 'discussion');
|
|
||||||
|
this.appMessagesManager.wrapSingleMessage(peerId, threadId).then(() => {
|
||||||
|
this.appMessagesManager.generateThreadServiceStartMessage(this.appMessagesManager.getMessageByPeer(peerId, threadId));
|
||||||
|
this.chat.appImManager.setInnerPeer(peerId, message.fwd_from.saved_from_msg_id, 'discussion', threadId);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
const message = this.appMessagesManager.filterMessages(this.chat.getMessage(bubbleMid), message => !!(message as Message.message).replies)[0] as Message.message;
|
||||||
|
const replies = message.replies;
|
||||||
|
if(replies) {
|
||||||
|
this.appMessagesManager.getDiscussionMessage(this.peerId, message.mid).then(message => {
|
||||||
|
this.chat.appImManager.setInnerPeer(-replies.channel_id, undefined, 'discussion', (message as MyMessage).mid);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -658,14 +665,21 @@ export default class ChatBubbles {
|
|||||||
} catch(err) {}
|
} catch(err) {}
|
||||||
|
|
||||||
if(isReplyClick && bubble.classList.contains('is-reply')/* || bubble.classList.contains('forwarded') */) {
|
if(isReplyClick && bubble.classList.contains('is-reply')/* || bubble.classList.contains('forwarded') */) {
|
||||||
this.replyFollowHistory.push(+bubble.dataset.mid);
|
const bubbleMid = +bubble.dataset.mid;
|
||||||
let originalMessageId = +bubble.getAttribute('data-original-mid');
|
this.replyFollowHistory.push(bubbleMid);
|
||||||
|
|
||||||
if(this.chat.type === 'discussion') {
|
const message = this.chat.getMessage(bubbleMid) as Message.message;
|
||||||
|
|
||||||
|
const replyToPeerId = message.reply_to.reply_to_peer_id ? this.appPeersManager.getPeerId(message.reply_to.reply_to_peer_id) : this.peerId;
|
||||||
|
const replyToMid = message.reply_to.reply_to_msg_id;
|
||||||
|
|
||||||
|
this.chat.appImManager.setInnerPeer(replyToPeerId, replyToMid, this.chat.type, this.chat.threadId);
|
||||||
|
|
||||||
|
/* if(this.chat.type === 'discussion') {
|
||||||
this.chat.appImManager.setPeer(this.peerId, originalMessageId);
|
this.chat.appImManager.setPeer(this.peerId, originalMessageId);
|
||||||
} else {
|
} else {
|
||||||
this.chat.appImManager.setInnerPeer(this.peerId, originalMessageId);
|
this.chat.appImManager.setInnerPeer(this.peerId, originalMessageId);
|
||||||
}
|
} */
|
||||||
//this.chat.setPeer(this.peerId, originalMessageId);
|
//this.chat.setPeer(this.peerId, originalMessageId);
|
||||||
}
|
}
|
||||||
} else if(target.tagName == 'IMG' && target.parentElement.tagName == "AVATAR-ELEMENT") {
|
} else if(target.tagName == 'IMG' && target.parentElement.tagName == "AVATAR-ELEMENT") {
|
||||||
@ -1114,6 +1128,11 @@ export default class ChatBubbles {
|
|||||||
let topMessage = this.chat.type === 'pinned' ? this.appMessagesManager.pinnedMessages[peerId].maxId : historyStorage.maxId ?? 0;
|
let topMessage = this.chat.type === 'pinned' ? this.appMessagesManager.pinnedMessages[peerId].maxId : historyStorage.maxId ?? 0;
|
||||||
const isTarget = lastMsgId !== undefined;
|
const isTarget = lastMsgId !== undefined;
|
||||||
|
|
||||||
|
// * this one will fix topMessage for null message in history (e.g. channel comments with only 1 comment and it is a topMessage)
|
||||||
|
if(this.chat.type !== 'pinned' && topMessage && !historyStorage.history.includes(topMessage)) {
|
||||||
|
topMessage = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if(!isTarget && topMessage) {
|
if(!isTarget && topMessage) {
|
||||||
const isUnread = this.appMessagesManager.isHistoryUnread(peerId, this.chat.threadId);
|
const isUnread = this.appMessagesManager.isHistoryUnread(peerId, this.chat.threadId);
|
||||||
if(/* dialog.unread_count */isUnread && !samePeer) {
|
if(/* dialog.unread_count */isUnread && !samePeer) {
|
||||||
@ -1124,7 +1143,7 @@ export default class ChatBubbles {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const isJump = lastMsgId != topMessage;
|
const isJump = lastMsgId !== topMessage;
|
||||||
|
|
||||||
if(samePeer) {
|
if(samePeer) {
|
||||||
const mounted = this.getMountedBubble(lastMsgId);
|
const mounted = this.getMountedBubble(lastMsgId);
|
||||||
@ -1230,7 +1249,7 @@ export default class ChatBubbles {
|
|||||||
this.lazyLoadQueue.unlock();
|
this.lazyLoadQueue.unlock();
|
||||||
|
|
||||||
//if(dialog && lastMsgID && lastMsgID != topMessage && (this.bubbles[lastMsgID] || this.firstUnreadBubble)) {
|
//if(dialog && lastMsgID && lastMsgID != topMessage && (this.bubbles[lastMsgID] || this.firstUnreadBubble)) {
|
||||||
if(topMessage && (isTarget || isJump)) {
|
if((topMessage && isJump) || isTarget) {
|
||||||
if(this.scrollable.scrollLocked) {
|
if(this.scrollable.scrollLocked) {
|
||||||
clearTimeout(this.scrollable.scrollLocked);
|
clearTimeout(this.scrollable.scrollLocked);
|
||||||
this.scrollable.scrollLocked = 0;
|
this.scrollable.scrollLocked = 0;
|
||||||
@ -1272,7 +1291,7 @@ export default class ChatBubbles {
|
|||||||
|
|
||||||
//if(!this.unreaded.length && dialog) { // lol
|
//if(!this.unreaded.length && dialog) { // lol
|
||||||
if(this.scrolledAllDown && topMessage) { // lol
|
if(this.scrolledAllDown && topMessage) { // lol
|
||||||
this.appMessagesManager.readHistory(peerId, topMessage);
|
this.appMessagesManager.readHistory(peerId, topMessage, this.chat.threadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.chat.type === 'chat') {
|
if(this.chat.type === 'chat') {
|
||||||
@ -1295,19 +1314,14 @@ export default class ChatBubbles {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public finishPeerChange() {
|
public finishPeerChange() {
|
||||||
let peerId = this.peerId;
|
const peerId = this.peerId;
|
||||||
|
|
||||||
//this.topbar.setPeer(peerId);
|
|
||||||
|
|
||||||
const isAnyGroup = this.appPeersManager.isAnyGroup(peerId);
|
|
||||||
const isChannel = this.appPeersManager.isChannel(peerId);
|
const isChannel = this.appPeersManager.isChannel(peerId);
|
||||||
|
|
||||||
const canWrite = this.appMessagesManager.canWriteToPeer(peerId);
|
const canWrite = this.appMessagesManager.canWriteToPeer(peerId);
|
||||||
|
|
||||||
this.chatInner.classList.toggle('has-rights', canWrite);
|
this.chatInner.classList.toggle('has-rights', canWrite);
|
||||||
this.bubblesContainer.classList.toggle('is-chat-input-hidden', !canWrite);
|
this.bubblesContainer.classList.toggle('is-chat-input-hidden', !canWrite);
|
||||||
|
|
||||||
this.chatInner.classList.toggle('is-chat', isAnyGroup || peerId == rootScope.myId);
|
this.chatInner.classList.toggle('is-chat', this.chat.isAnyGroup());
|
||||||
this.chatInner.classList.toggle('is-channel', isChannel);
|
this.chatInner.classList.toggle('is-channel', isChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1536,7 +1550,7 @@ export default class ChatBubbles {
|
|||||||
this.chat.selection.toggleBubbleCheckbox(bubble, true);
|
this.chat.selection.toggleBubbleCheckbox(bubble, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(message._ == 'messageService') {
|
if(message._ === 'messageService') {
|
||||||
let action = message.action;
|
let action = message.action;
|
||||||
let _ = action._;
|
let _ = action._;
|
||||||
if(IGNORE_ACTIONS.includes(_) || (langPack.hasOwnProperty(_) && !langPack[_])) {
|
if(IGNORE_ACTIONS.includes(_) || (langPack.hasOwnProperty(_) && !langPack[_])) {
|
||||||
@ -1564,7 +1578,7 @@ export default class ChatBubbles {
|
|||||||
messageMessage = t.message;
|
messageMessage = t.message;
|
||||||
//totalEntities = t.entities;
|
//totalEntities = t.entities;
|
||||||
totalEntities = t.totalEntities;
|
totalEntities = t.totalEntities;
|
||||||
} else if(messageMedia?.document?.type != 'sticker') {
|
} else if(messageMedia?.document?.type !== 'sticker') {
|
||||||
messageMessage = message.message;
|
messageMessage = message.message;
|
||||||
//totalEntities = message.entities;
|
//totalEntities = message.entities;
|
||||||
totalEntities = message.totalEntities;
|
totalEntities = message.totalEntities;
|
||||||
@ -1700,8 +1714,19 @@ export default class ChatBubbles {
|
|||||||
bubble.classList.add(status);
|
bubble.classList.add(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
let messageWithReplies: Message.message = this.appMessagesManager.filterMessages(message, message => !!(message as Message.message).replies)[0] as any;
|
let messageWithReplies: Message.message;
|
||||||
const withReplies = messageWithReplies && messageWithReplies.replies && messageWithReplies.replies.pFlags.comments && messageWithReplies.replies.channel_id !== 777;
|
let withReplies: boolean;
|
||||||
|
if(this.peerId === REPLIES_PEER_ID) {
|
||||||
|
messageWithReplies = message;
|
||||||
|
withReplies = true;
|
||||||
|
} else {
|
||||||
|
messageWithReplies = this.appMessagesManager.filterMessages(message, message => !!(message as Message.message).replies)[0] as any;
|
||||||
|
withReplies = messageWithReplies && messageWithReplies.replies && messageWithReplies.replies.pFlags.comments && messageWithReplies.replies.channel_id !== 777;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(withReplies) {
|
||||||
|
bubble.classList.add('with-replies');
|
||||||
|
}
|
||||||
|
|
||||||
const isOut = our && (!message.fwd_from || this.peerId != rootScope.myId);
|
const isOut = our && (!message.fwd_from || this.peerId != rootScope.myId);
|
||||||
let nameContainer = bubbleContainer;
|
let nameContainer = bubbleContainer;
|
||||||
@ -2163,7 +2188,7 @@ export default class ChatBubbles {
|
|||||||
nameDiv.classList.add('name');
|
nameDiv.classList.add('name');
|
||||||
nameDiv.dataset.peerId = message.fwdFromId;
|
nameDiv.dataset.peerId = message.fwdFromId;
|
||||||
|
|
||||||
if(this.peerId == rootScope.myId || isForwardFromChannel) {
|
if(this.peerId === rootScope.myId || this.peerId === REPLIES_PEER_ID || isForwardFromChannel) {
|
||||||
nameDiv.style.color = this.appPeersManager.getPeerColorById(message.fwdFromId, false);
|
nameDiv.style.color = this.appPeersManager.getPeerColorById(message.fwdFromId, false);
|
||||||
nameDiv.innerHTML = title;
|
nameDiv.innerHTML = title;
|
||||||
} else {
|
} else {
|
||||||
@ -2175,31 +2200,6 @@ export default class ChatBubbles {
|
|||||||
nameContainer.append(nameDiv);
|
nameContainer.append(nameDiv);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(message.reply_to_mid && message.reply_to_mid !== this.chat.threadId) {
|
|
||||||
let originalMessage = this.chat.type === 'scheduled' ? this.appMessagesManager.getMessageByPeer(this.peerId, message.reply_to_mid) : this.chat.getMessage(message.reply_to_mid);
|
|
||||||
let originalPeerTitle = this.appPeersManager.getPeerTitle(originalMessage.fromId || originalMessage.fwdFromId, true) || '';
|
|
||||||
|
|
||||||
/////////this.log('message to render reply', originalMessage, originalPeerTitle, bubble, message);
|
|
||||||
|
|
||||||
// need to download separately
|
|
||||||
if(originalMessage._ == 'messageEmpty') {
|
|
||||||
//////////this.log('message to render reply empty, need download', message, message.reply_to_mid);
|
|
||||||
this.appMessagesManager.wrapSingleMessage(this.peerId, message.reply_to_mid);
|
|
||||||
this.needUpdate.push({replyMid: message.reply_to_mid, mid: message.mid});
|
|
||||||
|
|
||||||
originalPeerTitle = 'Loading...';
|
|
||||||
}
|
|
||||||
|
|
||||||
if(originalMessage.mid) {
|
|
||||||
bubble.setAttribute('data-original-mid', originalMessage.mid);
|
|
||||||
} else {
|
|
||||||
bubble.setAttribute('data-original-mid', message.reply_to_mid);
|
|
||||||
}
|
|
||||||
|
|
||||||
bubbleContainer.append(wrapReply(originalPeerTitle, originalMessage.message || '', originalMessage));
|
|
||||||
bubble.classList.add('is-reply');
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!bubble.classList.contains('sticker') && needName) {
|
if(!bubble.classList.contains('sticker') && needName) {
|
||||||
let nameDiv = document.createElement('div');
|
let nameDiv = document.createElement('div');
|
||||||
nameDiv.classList.add('name');
|
nameDiv.classList.add('name');
|
||||||
@ -2215,9 +2215,34 @@ export default class ChatBubbles {
|
|||||||
bubble.classList.add('hide-name');
|
bubble.classList.add('hide-name');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(message.reply_to_mid && message.reply_to_mid !== this.chat.threadId) {
|
||||||
|
const replyToPeerId = message.reply_to.reply_to_peer_id ? this.appPeersManager.getPeerId(message.reply_to.reply_to_peer_id) : this.peerId;
|
||||||
|
|
||||||
|
let originalMessage = this.appMessagesManager.getMessageByPeer(replyToPeerId, message.reply_to_mid);
|
||||||
|
let originalPeerTitle: string;
|
||||||
|
|
||||||
|
/////////this.log('message to render reply', originalMessage, originalPeerTitle, bubble, message);
|
||||||
|
|
||||||
|
// need to download separately
|
||||||
|
if(originalMessage._ == 'messageEmpty') {
|
||||||
|
//////////this.log('message to render reply empty, need download', message, message.reply_to_mid);
|
||||||
|
this.appMessagesManager.wrapSingleMessage(replyToPeerId, message.reply_to_mid);
|
||||||
|
this.needUpdate.push({replyToPeerId, replyMid: message.reply_to_mid, mid: message.mid});
|
||||||
|
|
||||||
|
originalPeerTitle = 'Loading...';
|
||||||
|
} else {
|
||||||
|
originalPeerTitle = this.appPeersManager.getPeerTitle(originalMessage.fromId || originalMessage.fwdFromId, true) || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapped = wrapReply(originalPeerTitle, originalMessage.message || '', originalMessage);
|
||||||
|
bubbleContainer.append(wrapped);
|
||||||
|
//bubbleContainer.insertBefore(, nameContainer);
|
||||||
|
bubble.classList.add('is-reply');
|
||||||
|
}
|
||||||
|
|
||||||
if((!our && this.peerId < 0 && (!this.appPeersManager.isChannel(this.peerId) || this.appPeersManager.isMegagroup(this.peerId)))
|
const needAvatar = this.chat.isAnyGroup() && !isOut;
|
||||||
|| (this.peerId == rootScope.myId && !message.reply_to_mid)) {
|
if(needAvatar) {
|
||||||
let avatarElem = new AvatarElement();
|
let avatarElem = new AvatarElement();
|
||||||
//avatarElem.lazyLoadQueue = this.lazyLoadQueue;
|
//avatarElem.lazyLoadQueue = this.lazyLoadQueue;
|
||||||
avatarElem.classList.add('user-avatar', 'avatar-40');
|
avatarElem.classList.add('user-avatar', 'avatar-40');
|
||||||
@ -2226,7 +2251,7 @@ export default class ChatBubbles {
|
|||||||
avatarElem.setAttribute('peer-title', /* '🔥 FF 🔥' */message.fwd_from.from_name);
|
avatarElem.setAttribute('peer-title', /* '🔥 FF 🔥' */message.fwd_from.from_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
avatarElem.setAttribute('peer', '' + (((message.fwd_from && this.peerId == rootScope.myId) || isForwardFromChannel ? message.fwdFromId : message.fromId) || 0));
|
avatarElem.setAttribute('peer', '' + (((message.fwd_from && (this.peerId === rootScope.myId || this.peerId === REPLIES_PEER_ID)) || isForwardFromChannel ? message.fwdFromId : message.fromId) || 0));
|
||||||
avatarElem.update();
|
avatarElem.update();
|
||||||
|
|
||||||
//this.log('exec loadDialogPhoto', message);
|
//this.log('exec loadDialogPhoto', message);
|
||||||
@ -2245,7 +2270,7 @@ export default class ChatBubbles {
|
|||||||
bubble.classList.add('is-thread-starter');
|
bubble.classList.add('is-thread-starter');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(savedFrom) {
|
if(savedFrom && this.peerId !== REPLIES_PEER_ID) {
|
||||||
const goto = document.createElement('div');
|
const goto = document.createElement('div');
|
||||||
goto.classList.add('bubble-beside-button', 'goto-original', 'tgico-arrow-next');
|
goto.classList.add('bubble-beside-button', 'goto-original', 'tgico-arrow-next');
|
||||||
bubbleContainer.append(goto);
|
bubbleContainer.append(goto);
|
||||||
|
@ -20,6 +20,7 @@ import ChatContextMenu from "./contextMenu";
|
|||||||
import ChatInput from "./input";
|
import ChatInput from "./input";
|
||||||
import ChatSelection from "./selection";
|
import ChatSelection from "./selection";
|
||||||
import ChatTopbar from "./topbar";
|
import ChatTopbar from "./topbar";
|
||||||
|
import { REPLIES_PEER_ID } from "../../lib/mtproto/mtproto_config";
|
||||||
|
|
||||||
export type ChatType = 'chat' | 'pinned' | 'replies' | 'discussion' | 'scheduled';
|
export type ChatType = 'chat' | 'pinned' | 'replies' | 'discussion' | 'scheduled';
|
||||||
|
|
||||||
@ -140,11 +141,6 @@ export default class Chat extends EventListenerBase<{
|
|||||||
this.init = null;
|
this.init = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.type === 'discussion' && !this.threadId) {
|
|
||||||
this.threadId = lastMsgId;
|
|
||||||
lastMsgId = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
//console.time('appImManager setPeer');
|
//console.time('appImManager setPeer');
|
||||||
//console.time('appImManager setPeer pre promise');
|
//console.time('appImManager setPeer pre promise');
|
||||||
////console.time('appImManager: pre render start');
|
////console.time('appImManager: pre render start');
|
||||||
@ -228,4 +224,8 @@ export default class Chat extends EventListenerBase<{
|
|||||||
public getMidsByMid(mid: number) {
|
public getMidsByMid(mid: number) {
|
||||||
return this.appMessagesManager.getMidsByMessage(this.getMessage(mid));
|
return this.appMessagesManager.getMidsByMessage(this.getMessage(mid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public isAnyGroup() {
|
||||||
|
return this.peerId === rootScope.myId || this.peerId === REPLIES_PEER_ID || this.appPeersManager.isAnyGroup(this.peerId);
|
||||||
|
}
|
||||||
}
|
}
|
@ -1066,9 +1066,9 @@ export default class ChatInput {
|
|||||||
|
|
||||||
public onMessageSent(clearInput = true, clearReply?: boolean) {
|
public onMessageSent(clearInput = true, clearReply?: boolean) {
|
||||||
if(this.chat.type !== 'scheduled') {
|
if(this.chat.type !== 'scheduled') {
|
||||||
let dialog = this.appMessagesManager.getDialogByPeerId(this.chat.peerId)[0];
|
const historyStorage = this.appMessagesManager.getHistoryStorage(this.chat.peerId, this.chat.threadId);
|
||||||
if(dialog && dialog.top_message) {
|
if(historyStorage.maxId) {
|
||||||
this.appMessagesManager.readHistory(this.chat.peerId, dialog.top_message); // lol
|
this.appMessagesManager.readHistory(this.chat.peerId, historyStorage.maxId, this.chat.threadId); // lol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,9 +5,11 @@ import appPeersManager from "../../lib/appManagers/appPeersManager";
|
|||||||
import rootScope from "../../lib/rootScope";
|
import rootScope from "../../lib/rootScope";
|
||||||
import { ripple } from "../ripple";
|
import { ripple } from "../ripple";
|
||||||
|
|
||||||
|
const TAG_NAME = 'replies-element';
|
||||||
|
|
||||||
rootScope.on('replies_updated', (e) => {
|
rootScope.on('replies_updated', (e) => {
|
||||||
const message = e.detail;
|
const message = e.detail;
|
||||||
(Array.from(document.querySelectorAll(`replies-footer-element[data-post-key="${message.peerId}_${message.mid}"]`)) as RepliesElement[]).forEach(element => {
|
(Array.from(document.querySelectorAll(TAG_NAME + `[data-post-key="${message.peerId}_${message.mid}"]`)) as RepliesElement[]).forEach(element => {
|
||||||
element.message = message;
|
element.message = message;
|
||||||
element.render();
|
element.render();
|
||||||
});
|
});
|
||||||
@ -34,12 +36,12 @@ export default class RepliesElement extends HTMLElement {
|
|||||||
|
|
||||||
if(this.type === 'footer') {
|
if(this.type === 'footer') {
|
||||||
let leftHTML = '', lastStyle = '';
|
let leftHTML = '', lastStyle = '';
|
||||||
if(replies.recent_repliers) {
|
if(replies?.recent_repliers) {
|
||||||
leftHTML += '<div class="replies-footer-avatars">'
|
leftHTML += '<div class="replies-footer-avatars">'
|
||||||
let l: string[] = [];
|
let l: string[] = [];
|
||||||
replies.recent_repliers/* .slice().reverse() */.forEach((peer, idx) => {
|
replies.recent_repliers/* .slice().reverse() */.forEach((peer, idx) => {
|
||||||
lastStyle = idx == 0 ? '' : `style="transform: translateX(-${idx * 12}px);"`;
|
lastStyle = idx == 0 ? '' : `style="transform: translateX(-${idx * 14}px);"`;
|
||||||
l.push(`<avatar-element class="avatar-32" dialog="0" peer="${appPeersManager.getPeerId(peer)}" ${lastStyle}></avatar-element>`);
|
l.push(`<avatar-element class="avatar-34" dialog="0" peer="${appPeersManager.getPeerId(peer)}" ${lastStyle}></avatar-element>`);
|
||||||
});
|
});
|
||||||
leftHTML += l.reverse().join('') + '</div>';
|
leftHTML += l.reverse().join('') + '</div>';
|
||||||
} else {
|
} else {
|
||||||
@ -47,17 +49,21 @@ export default class RepliesElement extends HTMLElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let text: string;
|
let text: string;
|
||||||
if(replies.replies) {
|
if(replies) {
|
||||||
text = replies.replies + ' ' + (replies.replies > 1 ? 'Comments' : 'Comment');
|
if(replies.replies) {
|
||||||
|
text = replies.replies + ' ' + (replies.replies > 1 ? 'Comments' : 'Comment');
|
||||||
|
} else {
|
||||||
|
text = 'Leave a Comment';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
text = 'Leave a Comment';
|
text = 'View in chat';
|
||||||
}
|
}
|
||||||
|
|
||||||
const historyStorage = appMessagesManager.getHistoryStorage(-replies.channel_id);
|
if(replies) {
|
||||||
if(replies.read_max_id < replies.max_id && (!historyStorage.readMaxId || historyStorage.readMaxId < replies.max_id)) {
|
const historyStorage = appMessagesManager.getHistoryStorage(-replies.channel_id);
|
||||||
this.classList.add('is-unread');
|
this.classList.toggle('is-unread', replies.read_max_id < replies.max_id && (!historyStorage.readMaxId || historyStorage.readMaxId < replies.max_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.innerHTML = `${leftHTML}<span class="replies-footer-text" ${lastStyle}>${text}</span><span class="tgico-next"></span>`;
|
this.innerHTML = `${leftHTML}<span class="replies-footer-text" ${lastStyle}>${text}</span><span class="tgico-next"></span>`;
|
||||||
|
|
||||||
const rippleContainer = document.createElement('div');
|
const rippleContainer = document.createElement('div');
|
||||||
@ -65,10 +71,10 @@ export default class RepliesElement extends HTMLElement {
|
|||||||
ripple(rippleContainer);
|
ripple(rippleContainer);
|
||||||
} else {
|
} else {
|
||||||
this.classList.add('bubble-beside-button');
|
this.classList.add('bubble-beside-button');
|
||||||
this.innerHTML = `<span class="tgico-commentssticker"></span><span class="replies-beside-text">${replies.replies ? formatNumber(replies.replies, 0) : ''}</span>`;
|
this.innerHTML = `<span class="tgico-commentssticker"></span><span class="replies-beside-text">${replies?.replies ? formatNumber(replies.replies, 0) : ''}</span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this.updated) {
|
if(replies && !this.updated) {
|
||||||
appMessagesManager.subscribeRepliesThread(this.message.peerId, this.message.mid);
|
appMessagesManager.subscribeRepliesThread(this.message.peerId, this.message.mid);
|
||||||
appMessagesManager.updateMessage(this.message.peerId, this.message.mid, 'replies_updated');
|
appMessagesManager.updateMessage(this.message.peerId, this.message.mid, 'replies_updated');
|
||||||
this.updated = true;
|
this.updated = true;
|
||||||
@ -76,4 +82,4 @@ export default class RepliesElement extends HTMLElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define('replies-element', RepliesElement);
|
customElements.define(TAG_NAME, RepliesElement);
|
@ -195,12 +195,12 @@ export default class ChatTopbar {
|
|||||||
}];
|
}];
|
||||||
|
|
||||||
this.btnSearch = ButtonIcon('search');
|
this.btnSearch = ButtonIcon('search');
|
||||||
this.listenerSetter.add(this.btnSearch, 'click', (e) => {
|
attachClickEvent(this.btnSearch, (e) => {
|
||||||
cancelEvent(e);
|
cancelEvent(e);
|
||||||
if(this.peerId) {
|
if(this.peerId) {
|
||||||
this.appSidebarRight.searchTab.open(this.peerId, this.chat.threadId);
|
this.appSidebarRight.searchTab.open(this.peerId, this.chat.threadId);
|
||||||
}
|
}
|
||||||
});
|
}, {listenerSetter: this.listenerSetter});
|
||||||
}
|
}
|
||||||
|
|
||||||
public constructPeerHelpers() {
|
public constructPeerHelpers() {
|
||||||
@ -220,15 +220,15 @@ export default class ChatTopbar {
|
|||||||
this.btnPinned = ButtonIcon('pinlist');
|
this.btnPinned = ButtonIcon('pinlist');
|
||||||
this.btnMute = ButtonIcon('mute');
|
this.btnMute = ButtonIcon('mute');
|
||||||
|
|
||||||
this.listenerSetter.add(this.btnPinned, 'click', (e) => {
|
attachClickEvent(this.btnPinned, (e) => {
|
||||||
cancelEvent(e);
|
cancelEvent(e);
|
||||||
this.openPinned(true);
|
this.openPinned(true);
|
||||||
});
|
}, {listenerSetter: this.listenerSetter});
|
||||||
|
|
||||||
this.listenerSetter.add(this.btnMute, 'click', (e) => {
|
attachClickEvent(this.btnMute, (e) => {
|
||||||
cancelEvent(e);
|
cancelEvent(e);
|
||||||
this.appMessagesManager.mutePeer(this.peerId);
|
this.appMessagesManager.mutePeer(this.peerId);
|
||||||
});
|
}, {listenerSetter: this.listenerSetter});
|
||||||
|
|
||||||
attachClickEvent(this.btnJoin, (e) => {
|
attachClickEvent(this.btnJoin, (e) => {
|
||||||
cancelEvent(e);
|
cancelEvent(e);
|
||||||
|
@ -25,6 +25,8 @@ type UpdatesState = {
|
|||||||
lastPtsUpdateTime?: number
|
lastPtsUpdateTime?: number
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const SYNC_DELAY = 25;
|
||||||
|
|
||||||
export class ApiUpdatesManager {
|
export class ApiUpdatesManager {
|
||||||
public updatesState: UpdatesState = {
|
public updatesState: UpdatesState = {
|
||||||
pendingPtsUpdates: [],
|
pendingPtsUpdates: [],
|
||||||
@ -464,7 +466,7 @@ export class ApiUpdatesManager {
|
|||||||
} else {
|
} else {
|
||||||
this.getDifference();
|
this.getDifference();
|
||||||
}
|
}
|
||||||
}, 5000)
|
}, SYNC_DELAY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,7 +504,7 @@ export class ApiUpdatesManager {
|
|||||||
curState.syncPending = {
|
curState.syncPending = {
|
||||||
timeout: window.setTimeout(() => {
|
timeout: window.setTimeout(() => {
|
||||||
this.getDifference();
|
this.getDifference();
|
||||||
}, 5000)
|
}, SYNC_DELAY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -548,7 +548,7 @@ export class AppImManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public setInnerPeer(peerId: number, lastMsgId?: number, type: ChatType = 'chat') {
|
public setInnerPeer(peerId: number, lastMsgId?: number, type: ChatType = 'chat', threadId?: number) {
|
||||||
// * prevent opening already opened peer
|
// * prevent opening already opened peer
|
||||||
const existingIndex = this.chats.findIndex(chat => chat.peerId == peerId && chat.type == type);
|
const existingIndex = this.chats.findIndex(chat => chat.peerId == peerId && chat.type == type);
|
||||||
if(existingIndex !== -1) {
|
if(existingIndex !== -1) {
|
||||||
@ -560,6 +560,10 @@ export class AppImManager {
|
|||||||
|
|
||||||
if(type) {
|
if(type) {
|
||||||
this.chat.setType(type);
|
this.chat.setType(type);
|
||||||
|
|
||||||
|
if(threadId) {
|
||||||
|
this.chat.threadId = threadId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//this.chatsSelectTab(this.chat.container);
|
//this.chatsSelectTab(this.chat.container);
|
||||||
@ -593,7 +597,7 @@ export class AppImManager {
|
|||||||
|
|
||||||
return subtitle;
|
return subtitle;
|
||||||
//}
|
//}
|
||||||
} else if(!appUsersManager.isBot(peerId)) { // user
|
} else { // user
|
||||||
const user = appUsersManager.getUser(peerId);
|
const user = appUsersManager.getUser(peerId);
|
||||||
|
|
||||||
if(rootScope.myId == peerId) {
|
if(rootScope.myId == peerId) {
|
||||||
@ -601,17 +605,19 @@ export class AppImManager {
|
|||||||
} else if(user) {
|
} else if(user) {
|
||||||
subtitle = appUsersManager.getUserStatusString(user.id);
|
subtitle = appUsersManager.getUserStatusString(user.id);
|
||||||
|
|
||||||
const typings = appChatsManager.typingsInPeer[peerId];
|
if(!appUsersManager.isBot(peerId)) {
|
||||||
if(typings && typings.length) {
|
const typings = appChatsManager.typingsInPeer[peerId];
|
||||||
return '<span class="online">typing...</span>';
|
if(typings && typings.length) {
|
||||||
} else if(subtitle == 'online') {
|
return '<span class="online">typing...</span>';
|
||||||
return `<span class="online">${subtitle}</span>`;
|
} else if(subtitle == 'online') {
|
||||||
|
return `<span class="online">${subtitle}</span>`;
|
||||||
|
} else {
|
||||||
|
return subtitle;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return subtitle;
|
return subtitle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return 'bot';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,10 +41,9 @@ const APITIMEOUT = 0;
|
|||||||
export type HistoryStorage = {
|
export type HistoryStorage = {
|
||||||
count: number | null,
|
count: number | null,
|
||||||
history: number[],
|
history: number[],
|
||||||
pending: number[],
|
|
||||||
|
|
||||||
maxId?: number,
|
maxId?: number,
|
||||||
readPromise?: Promise<boolean>,
|
readPromise?: Promise<void>,
|
||||||
readMaxId?: number,
|
readMaxId?: number,
|
||||||
readOutboxMaxId?: number,
|
readOutboxMaxId?: number,
|
||||||
|
|
||||||
@ -262,7 +261,7 @@ export class AppMessagesManager {
|
|||||||
|
|
||||||
const processDialog = (dialog: MTDialog.dialog) => {
|
const processDialog = (dialog: MTDialog.dialog) => {
|
||||||
const historyStorage = this.getHistoryStorage(dialog.peerId);
|
const historyStorage = this.getHistoryStorage(dialog.peerId);
|
||||||
const history = [].concat(historyStorage.pending, historyStorage.history);
|
const history = [].concat(historyStorage.history);
|
||||||
dialog = copy(dialog);
|
dialog = copy(dialog);
|
||||||
let removeUnread = 0;
|
let removeUnread = 0;
|
||||||
for(const mid of history) {
|
for(const mid of history) {
|
||||||
@ -1287,7 +1286,6 @@ export class AppMessagesManager {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const historyStorage = this.getHistoryStorage(peerId);
|
const historyStorage = this.getHistoryStorage(peerId);
|
||||||
//historyStorage.pending.unshift(messageId);
|
|
||||||
historyStorage.history.unshift(messageId);
|
historyStorage.history.unshift(messageId);
|
||||||
|
|
||||||
if(!options.isGroupedItem) {
|
if(!options.isGroupedItem) {
|
||||||
@ -1377,7 +1375,7 @@ export class AppMessagesManager {
|
|||||||
if(pendingData) {
|
if(pendingData) {
|
||||||
const {peerId, tempId, storage} = pendingData;
|
const {peerId, tempId, storage} = pendingData;
|
||||||
const historyStorage = this.getHistoryStorage(peerId);
|
const historyStorage = this.getHistoryStorage(peerId);
|
||||||
const pos = historyStorage.pending.indexOf(tempId);
|
const pos = historyStorage.history.indexOf(tempId);
|
||||||
|
|
||||||
apiUpdatesManager.processUpdateMessage({
|
apiUpdatesManager.processUpdateMessage({
|
||||||
_: 'updateShort',
|
_: 'updateShort',
|
||||||
@ -1388,7 +1386,7 @@ export class AppMessagesManager {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if(pos !== -1) {
|
if(pos !== -1) {
|
||||||
historyStorage.pending.splice(pos, 1);
|
historyStorage.history.splice(pos, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete this.pendingByRandomId[randomId];
|
delete this.pendingByRandomId[randomId];
|
||||||
@ -2009,7 +2007,7 @@ export class AppMessagesManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const dialog = this.getDialogByPeerId(peerId)[0];
|
const dialog = this.getDialogByPeerId(peerId)[0];
|
||||||
if(dialog && mid > 0) {
|
if(dialog && mid) {
|
||||||
if(mid > dialog[message.pFlags.out
|
if(mid > dialog[message.pFlags.out
|
||||||
? 'read_outbox_max_id'
|
? 'read_outbox_max_id'
|
||||||
: 'read_inbox_max_id']) {
|
: 'read_inbox_max_id']) {
|
||||||
@ -2053,7 +2051,7 @@ export class AppMessagesManager {
|
|||||||
if(fwdHeader.saved_from_peer && fwdHeader.saved_from_msg_id) {
|
if(fwdHeader.saved_from_peer && fwdHeader.saved_from_msg_id) {
|
||||||
const savedFromPeerId = appPeersManager.getPeerId(fwdHeader.saved_from_peer);
|
const savedFromPeerId = appPeersManager.getPeerId(fwdHeader.saved_from_peer);
|
||||||
//const savedFromMid = fwdHeader.saved_from_msg_id;
|
//const savedFromMid = fwdHeader.saved_from_msg_id;
|
||||||
const savedFromMid = this.generateMessageId(fwdHeader.saved_from_msg_id);
|
const savedFromMid = fwdHeader.saved_from_msg_id = this.generateMessageId(fwdHeader.saved_from_msg_id);
|
||||||
message.savedFrom = savedFromPeerId + '_' + savedFromMid;
|
message.savedFrom = savedFromPeerId + '_' + savedFromMid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2664,22 +2662,22 @@ export class AppMessagesManager {
|
|||||||
dialog.peerId = peerId;
|
dialog.peerId = peerId;
|
||||||
|
|
||||||
// Because we saved message without dialog present
|
// Because we saved message without dialog present
|
||||||
if(mid > 0) {
|
if(message.pFlags.is_outgoing) {
|
||||||
if(mid > dialog[message.pFlags.out ? 'read_outbox_max_id' : 'read_inbox_max_id']) message.pFlags.unread = true;
|
if(mid > dialog[message.pFlags.out ? 'read_outbox_max_id' : 'read_inbox_max_id']) message.pFlags.unread = true;
|
||||||
else delete message.pFlags.unread;
|
else delete message.pFlags.unread;
|
||||||
}
|
}
|
||||||
|
|
||||||
let historyStorage = this.getHistoryStorage(peerId);
|
let historyStorage = this.getHistoryStorage(peerId);
|
||||||
if(historyStorage === undefined/* && !message.deleted */) { // warning
|
if(historyStorage === undefined/* && !message.deleted */) { // warning
|
||||||
historyStorage[mid > 0 ? 'history' : 'pending'].push(mid);
|
historyStorage.history.push(mid);
|
||||||
/* if(mid < 0 && message.pFlags.unread) {
|
/* if(mid < 0 && message.pFlags.unread) {
|
||||||
dialog.unread_count++;
|
dialog.unread_count++;
|
||||||
} */
|
} */
|
||||||
if(this.mergeReplyKeyboard(historyStorage, message)) {
|
if(this.mergeReplyKeyboard(historyStorage, message)) {
|
||||||
rootScope.broadcast('history_reply_markup', {peerId});
|
rootScope.broadcast('history_reply_markup', {peerId});
|
||||||
}
|
}
|
||||||
} else if(!historyStorage.history.length && !historyStorage.pending.length) {
|
} else if(!historyStorage.history.length) {
|
||||||
historyStorage[mid > 0 ? 'history' : 'pending'].push(mid);
|
historyStorage.history.push(mid);
|
||||||
}
|
}
|
||||||
|
|
||||||
historyStorage.maxId = mid;
|
historyStorage.maxId = mid;
|
||||||
@ -3056,6 +3054,27 @@ export class AppMessagesManager {
|
|||||||
this.getDiscussionMessage(peerId, mid);
|
this.getDiscussionMessage(peerId, mid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public generateThreadServiceStartMessage(message: Message.message) {
|
||||||
|
const threadKey = message.peerId + '_' + message.mid;
|
||||||
|
if(this.threadsServiceMessagesIdsStorage[threadKey]) return;
|
||||||
|
|
||||||
|
const serviceStartMessage: Message.messageService = {
|
||||||
|
_: 'messageService',
|
||||||
|
id: this.generateMessageId(message.id, true),
|
||||||
|
date: message.date,
|
||||||
|
from_id: message.from_id,
|
||||||
|
peer_id: message.peer_id,
|
||||||
|
action: {
|
||||||
|
_: 'messageActionCustomAction',
|
||||||
|
message: 'Discussion started'
|
||||||
|
},
|
||||||
|
reply_to: this.generateReplyHeader(message.id)
|
||||||
|
};
|
||||||
|
|
||||||
|
this.saveMessages([serviceStartMessage], {isOutgoing: true});
|
||||||
|
this.threadsServiceMessagesIdsStorage[threadKey] = serviceStartMessage.mid;
|
||||||
|
}
|
||||||
|
|
||||||
public getDiscussionMessage(peerId: number, mid: number) {
|
public getDiscussionMessage(peerId: number, mid: number) {
|
||||||
return apiManager.invokeApi('messages.getDiscussionMessage', {
|
return apiManager.invokeApi('messages.getDiscussionMessage', {
|
||||||
peer: appPeersManager.getInputPeerById(peerId),
|
peer: appPeersManager.getInputPeerById(peerId),
|
||||||
@ -3068,25 +3087,7 @@ export class AppMessagesManager {
|
|||||||
const message = this.filterMessages(result.messages[0], message => !!(message as Message.message).replies)[0] as Message.message;
|
const message = this.filterMessages(result.messages[0], message => !!(message as Message.message).replies)[0] as Message.message;
|
||||||
const threadKey = message.peerId + '_' + message.mid;
|
const threadKey = message.peerId + '_' + message.mid;
|
||||||
|
|
||||||
if(!this.threadsServiceMessagesIdsStorage[threadKey]) {
|
this.generateThreadServiceStartMessage(message);
|
||||||
(result.messages as Message.message[]).forEach(message => {
|
|
||||||
const serviceStartMessage: Message.messageService = {
|
|
||||||
_: 'messageService',
|
|
||||||
id: this.generateMessageId(message.id, true),
|
|
||||||
date: message.date,
|
|
||||||
from_id: message.from_id,
|
|
||||||
peer_id: message.peer_id,
|
|
||||||
action: {
|
|
||||||
_: 'messageActionCustomAction',
|
|
||||||
message: 'Discussion started'
|
|
||||||
},
|
|
||||||
reply_to: this.generateReplyHeader(message.id)
|
|
||||||
};
|
|
||||||
|
|
||||||
this.saveMessages([serviceStartMessage], {isOutgoing: true});
|
|
||||||
this.threadsServiceMessagesIdsStorage[threadKey] = serviceStartMessage.mid;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const historyStorage = this.getHistoryStorage(message.peerId, message.mid);
|
const historyStorage = this.getHistoryStorage(message.peerId, message.mid);
|
||||||
result.max_id = historyStorage.maxId = this.generateMessageId(result.max_id) || 0;
|
result.max_id = historyStorage.maxId = this.generateMessageId(result.max_id) || 0;
|
||||||
@ -3202,13 +3203,13 @@ export class AppMessagesManager {
|
|||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
public readHistory(peerId: number, maxId = 0) {
|
public readHistory(peerId: number, maxId = 0, threadId?: number) {
|
||||||
return Promise.resolve(true);
|
// return Promise.resolve();
|
||||||
// console.trace('start read')
|
// console.trace('start read')
|
||||||
if(!this.isHistoryUnread(peerId)) return Promise.resolve(true);
|
if(!this.isHistoryUnread(peerId, threadId)) return Promise.resolve();
|
||||||
|
|
||||||
const isChannel = appPeersManager.isChannel(peerId);
|
const isChannel = appPeersManager.isChannel(peerId);
|
||||||
const historyStorage = this.getHistoryStorage(peerId);
|
const historyStorage = this.getHistoryStorage(peerId, threadId);
|
||||||
|
|
||||||
if(!historyStorage.readMaxId || maxId > historyStorage.readMaxId) {
|
if(!historyStorage.readMaxId || maxId > historyStorage.readMaxId) {
|
||||||
historyStorage.readMaxId = maxId;
|
historyStorage.readMaxId = maxId;
|
||||||
@ -3218,8 +3219,24 @@ export class AppMessagesManager {
|
|||||||
return historyStorage.readPromise;
|
return historyStorage.readPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
let apiPromise: Promise<boolean>;
|
let apiPromise: Promise<void>;
|
||||||
if(isChannel) {
|
if(threadId) {
|
||||||
|
apiPromise = apiManager.invokeApi('messages.readDiscussion', {
|
||||||
|
peer: appPeersManager.getInputPeerById(peerId),
|
||||||
|
msg_id: this.getLocalMessageId(threadId),
|
||||||
|
read_max_id: this.getLocalMessageId(maxId)
|
||||||
|
}).then((res) => {
|
||||||
|
apiUpdatesManager.processUpdateMessage({
|
||||||
|
_: 'updateShort',
|
||||||
|
update: {
|
||||||
|
_: 'updateReadChannelDiscussionInbox',
|
||||||
|
channel_id: -peerId,
|
||||||
|
top_msg_id: threadId,
|
||||||
|
read_max_id: maxId
|
||||||
|
} as Update.updateReadChannelDiscussionInbox
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else if(isChannel) {
|
||||||
apiPromise = apiManager.invokeApi('channels.readHistory', {
|
apiPromise = apiManager.invokeApi('channels.readHistory', {
|
||||||
channel: appChatsManager.getChannelInput(-peerId),
|
channel: appChatsManager.getChannelInput(-peerId),
|
||||||
max_id: this.getLocalMessageId(maxId)
|
max_id: this.getLocalMessageId(maxId)
|
||||||
@ -3232,8 +3249,6 @@ export class AppMessagesManager {
|
|||||||
channel_id: -peerId
|
channel_id: -peerId
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return res;
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
apiPromise = apiManager.invokeApi('messages.readHistory', {
|
apiPromise = apiManager.invokeApi('messages.readHistory', {
|
||||||
@ -3257,8 +3272,6 @@ export class AppMessagesManager {
|
|||||||
peer: appPeersManager.getOutputPeer(peerId)
|
peer: appPeersManager.getOutputPeer(peerId)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3311,10 +3324,10 @@ export class AppMessagesManager {
|
|||||||
if(threadId) {
|
if(threadId) {
|
||||||
//threadId = this.getLocalMessageId(threadId);
|
//threadId = this.getLocalMessageId(threadId);
|
||||||
if(!this.threadsStorage[peerId]) this.threadsStorage[peerId] = {};
|
if(!this.threadsStorage[peerId]) this.threadsStorage[peerId] = {};
|
||||||
return this.threadsStorage[peerId][threadId] ?? (this.threadsStorage[peerId][threadId] = {count: null, history: [], pending: []});
|
return this.threadsStorage[peerId][threadId] ?? (this.threadsStorage[peerId][threadId] = {count: null, history: []});
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.historiesStorage[peerId] ?? (this.historiesStorage[peerId] = {count: null, history: [], pending: []});
|
return this.historiesStorage[peerId] ?? (this.historiesStorage[peerId] = {count: null, history: []});
|
||||||
}
|
}
|
||||||
|
|
||||||
public handleUpdate(update: Update) {
|
public handleUpdate(update: Update) {
|
||||||
@ -3331,9 +3344,9 @@ export class AppMessagesManager {
|
|||||||
const message = this.getMessageFromStorage(storage, mid);
|
const message = this.getMessageFromStorage(storage, mid);
|
||||||
if(!message.deleted) {
|
if(!message.deleted) {
|
||||||
const historyStorage = this.getHistoryStorage(peerId);
|
const historyStorage = this.getHistoryStorage(peerId);
|
||||||
const pos = historyStorage.pending.indexOf(tempId);
|
const pos = historyStorage.history.indexOf(tempId);
|
||||||
if(pos !== -1) {
|
if(pos !== -1) {
|
||||||
historyStorage.pending.splice(pos, 1);
|
historyStorage.history.splice(pos, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.finalizePendingMessageCallbacks(storage, tempId, mid);
|
this.finalizePendingMessageCallbacks(storage, tempId, mid);
|
||||||
@ -3376,19 +3389,19 @@ export class AppMessagesManager {
|
|||||||
const historyStorage = this.getHistoryStorage(peerId);
|
const historyStorage = this.getHistoryStorage(peerId);
|
||||||
this.updateMessageRepliesIfNeeded(message);
|
this.updateMessageRepliesIfNeeded(message);
|
||||||
|
|
||||||
const history = message.mid > 0 ? historyStorage.history : historyStorage.pending;
|
const history = historyStorage.history;
|
||||||
if(history.indexOf(message.mid) !== -1) {
|
if(history.indexOf(message.mid) !== -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const topMsgId = history[0];
|
const topMsgId = history[0];
|
||||||
history.unshift(message.mid);
|
history.unshift(message.mid);
|
||||||
if(message.mid > 0 && message.mid < topMsgId) {
|
if(message.mid < topMsgId) {
|
||||||
history.sort((a, b) => {
|
history.sort((a, b) => {
|
||||||
return b - a;
|
return b - a;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(message.mid > 0 && historyStorage.count !== null) {
|
if(historyStorage.count !== null) {
|
||||||
historyStorage.count++;
|
historyStorage.count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3655,6 +3668,14 @@ export class AppMessagesManager {
|
|||||||
appUsersManager.forceUserOnline(peerId);
|
appUsersManager.forceUserOnline(peerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(threadId) {
|
||||||
|
const repliesKey = this.threadsToReplies[peerId + '_' + threadId];
|
||||||
|
if(repliesKey) {
|
||||||
|
const [peerId, mid] = repliesKey.split('_').map(n => +n);
|
||||||
|
this.updateMessage(peerId, mid, 'replies_updated');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(let i = 0, length = history.length; i < length; i++) {
|
for(let i = 0, length = history.length; i < length; i++) {
|
||||||
const messageId = history[i];
|
const messageId = history[i];
|
||||||
if(messageId > maxId) {
|
if(messageId > maxId) {
|
||||||
@ -3713,6 +3734,17 @@ export class AppMessagesManager {
|
|||||||
if(foundAffected) {
|
if(foundAffected) {
|
||||||
rootScope.broadcast('messages_read');
|
rootScope.broadcast('messages_read');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!threadId && channelId) {
|
||||||
|
const threadKeyPart = peerId + '_';
|
||||||
|
for(const threadKey in this.threadsToReplies) {
|
||||||
|
if(threadKey.indexOf(threadKeyPart) === 0) {
|
||||||
|
const [peerId, mid] = this.threadsToReplies[threadKey].split('_').map(n => +n);
|
||||||
|
rootScope.broadcast('replies_updated', this.getMessageByPeer(peerId, mid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3764,7 +3796,6 @@ export class AppMessagesManager {
|
|||||||
const historyStorage = this.getHistoryStorage(peerId);
|
const historyStorage = this.getHistoryStorage(peerId);
|
||||||
//if(historyStorage !== undefined) {
|
//if(historyStorage !== undefined) {
|
||||||
const newHistory = historyStorage.history.filter(mid => !historyUpdated.msgs[mid]);
|
const newHistory = historyStorage.history.filter(mid => !historyUpdated.msgs[mid]);
|
||||||
const newPending = historyStorage.pending.filter(mid => !historyUpdated.msgs[mid]);
|
|
||||||
historyStorage.history = newHistory;
|
historyStorage.history = newHistory;
|
||||||
if(historyUpdated.count &&
|
if(historyUpdated.count &&
|
||||||
historyStorage.count !== null &&
|
historyStorage.count !== null &&
|
||||||
@ -3775,8 +3806,6 @@ export class AppMessagesManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
historyStorage.pending = newPending;
|
|
||||||
|
|
||||||
rootScope.broadcast('history_delete', {peerId, msgs: historyUpdated.msgs});
|
rootScope.broadcast('history_delete', {peerId, msgs: historyUpdated.msgs});
|
||||||
//}
|
//}
|
||||||
|
|
||||||
@ -4108,10 +4137,13 @@ export class AppMessagesManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public canWriteToPeer(peerId: number) {
|
public canWriteToPeer(peerId: number) {
|
||||||
const isChannel = appPeersManager.isChannel(peerId);
|
if(peerId < 0) {
|
||||||
const hasRights = isChannel && appChatsManager.hasRights(-peerId, 'send');
|
const isChannel = appPeersManager.isChannel(peerId);
|
||||||
|
const hasRights = isChannel && appChatsManager.hasRights(-peerId, 'send');
|
||||||
return (!isChannel || hasRights) && (peerId < 0 || appUsersManager.canSendToUser(peerId));
|
return !isChannel || hasRights;
|
||||||
|
} else {
|
||||||
|
return appUsersManager.canSendToUser(peerId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public finalizePendingMessage(randomId: string, finalMessage: any) {
|
public finalizePendingMessage(randomId: string, finalMessage: any) {
|
||||||
@ -4123,9 +4155,9 @@ export class AppMessagesManager {
|
|||||||
const historyStorage = this.getHistoryStorage(peerId);
|
const historyStorage = this.getHistoryStorage(peerId);
|
||||||
|
|
||||||
// this.log('pending', randomID, historyStorage.pending)
|
// this.log('pending', randomID, historyStorage.pending)
|
||||||
const pos = historyStorage.pending.indexOf(tempId);
|
const pos = historyStorage.history.indexOf(tempId);
|
||||||
if(pos !== -1) {
|
if(pos !== -1) {
|
||||||
historyStorage.pending.splice(pos, 1);
|
historyStorage.history.splice(pos, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = this.getMessageFromStorage(storage, tempId);
|
const message = this.getMessageFromStorage(storage, tempId);
|
||||||
|
@ -4,7 +4,7 @@ import { safeReplaceObject, isObject } from "../../helpers/object";
|
|||||||
import { InputUser, Update, User as MTUser, UserStatus } from "../../layer";
|
import { InputUser, Update, User as MTUser, UserStatus } from "../../layer";
|
||||||
//import apiManager from '../mtproto/apiManager';
|
//import apiManager from '../mtproto/apiManager';
|
||||||
import apiManager from '../mtproto/mtprotoworker';
|
import apiManager from '../mtproto/mtprotoworker';
|
||||||
import { MOUNT_CLASS_TO } from "../mtproto/mtproto_config";
|
import { MOUNT_CLASS_TO, REPLIES_PEER_ID } from "../mtproto/mtproto_config";
|
||||||
import serverTimeManager from "../mtproto/serverTimeManager";
|
import serverTimeManager from "../mtproto/serverTimeManager";
|
||||||
import { RichTextProcessor } from "../richtextprocessor";
|
import { RichTextProcessor } from "../richtextprocessor";
|
||||||
import rootScope from "../rootScope";
|
import rootScope from "../rootScope";
|
||||||
@ -343,6 +343,13 @@ export class AppUsersManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getUserStatusString(userId: number) {
|
public getUserStatusString(userId: number) {
|
||||||
|
switch(userId) {
|
||||||
|
case REPLIES_PEER_ID:
|
||||||
|
return 'reply notifications';
|
||||||
|
case 777000:
|
||||||
|
return 'service notifications';
|
||||||
|
}
|
||||||
|
|
||||||
if(this.isBot(userId)) {
|
if(this.isBot(userId)) {
|
||||||
return 'bot';
|
return 'bot';
|
||||||
}
|
}
|
||||||
@ -351,6 +358,10 @@ export class AppUsersManager {
|
|||||||
if(!user) {
|
if(!user) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(user.pFlags.support) {
|
||||||
|
return 'support';
|
||||||
|
}
|
||||||
|
|
||||||
let str = '';
|
let str = '';
|
||||||
switch(user.status?._) {
|
switch(user.status?._) {
|
||||||
@ -430,7 +441,7 @@ export class AppUsersManager {
|
|||||||
|
|
||||||
public canSendToUser(id: number) {
|
public canSendToUser(id: number) {
|
||||||
const user = this.getUser(id);
|
const user = this.getUser(id);
|
||||||
return !user.pFlags.deleted;
|
return !user.pFlags.deleted && user.username !== 'replies';
|
||||||
}
|
}
|
||||||
|
|
||||||
public getUserPhoto(id: number) {
|
public getUserPhoto(id: number) {
|
||||||
|
@ -1,14 +1,6 @@
|
|||||||
export type UserAuth = number;
|
export type UserAuth = number;
|
||||||
|
|
||||||
/*
|
export const REPLIES_PEER_ID = 1271266957;
|
||||||
|
|
||||||
IMPORTANT NOTICE
|
|
||||||
================
|
|
||||||
|
|
||||||
Do not publish your Webogram fork with my app credentials (below), or your application may be blocked.
|
|
||||||
You can get your own api_id, api_hash at https://my.telegram.org, see manual at https://core.telegram.org/api/obtaining_api_id.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const App = {
|
export const App = {
|
||||||
id: 1025907,
|
id: 1025907,
|
||||||
|
@ -15,7 +15,7 @@ avatar-element {
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
|
||||||
&.tgico-savedmessages:before {
|
&.tgico-savedmessages:before {
|
||||||
font-size: calc(26px / var(--multiplier));
|
font-size: calc(25px / var(--multiplier));
|
||||||
}
|
}
|
||||||
|
|
||||||
&.tgico-avatar_deletedaccount:before {
|
&.tgico-avatar_deletedaccount:before {
|
||||||
@ -103,6 +103,11 @@ avatar-element {
|
|||||||
--multiplier: 1.35;
|
--multiplier: 1.35;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.avatar-34 {
|
||||||
|
--size: 34px;
|
||||||
|
--multiplier: 1.588235;
|
||||||
|
}
|
||||||
|
|
||||||
&.avatar-32 {
|
&.avatar-32 {
|
||||||
--size: 32px;
|
--size: 32px;
|
||||||
--multiplier: 1.6875;
|
--multiplier: 1.6875;
|
||||||
|
@ -1005,6 +1005,10 @@ $bubble-margin: .25rem;
|
|||||||
position: relative !important;
|
position: relative !important;
|
||||||
height: 0px !important;
|
height: 0px !important;
|
||||||
visibility: hidden !important;
|
visibility: hidden !important;
|
||||||
|
|
||||||
|
.inner {
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-multiple-documents {
|
&.is-multiple-documents {
|
||||||
@ -1219,6 +1223,7 @@ $bubble-margin: .25rem;
|
|||||||
.time {
|
.time {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
visibility: visible;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 2.5px;
|
padding: 0 2.5px;
|
||||||
@ -1233,13 +1238,22 @@ $bubble-margin: .25rem;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.with-replies:not(.sticker) .message {
|
||||||
|
bottom: 55px;
|
||||||
|
}
|
||||||
|
|
||||||
&.sticker .message {
|
&.sticker .message {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.with-replies .attachment {
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.time {
|
.time {
|
||||||
color: transparent;
|
visibility: hidden; // * can't use color transparent here, because in name can be emoji
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
@ -1277,6 +1291,7 @@ $bubble-margin: .25rem;
|
|||||||
padding: inherit;
|
padding: inherit;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
height: 12px; // * as font-size
|
height: 12px; // * as font-size
|
||||||
|
visibility: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tgico-pinnedchat:before {
|
.tgico-pinnedchat:before {
|
||||||
@ -1349,6 +1364,7 @@ $bubble-margin: .25rem;
|
|||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
order: 1;
|
||||||
//width: max-content;
|
//width: max-content;
|
||||||
//white-space: nowrap;
|
//white-space: nowrap;
|
||||||
}
|
}
|
||||||
@ -1462,8 +1478,8 @@ $bubble-margin: .25rem;
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-footer {
|
&-footer {
|
||||||
height: 50px;
|
height: 51px;
|
||||||
border-top: 1px solid #dadce0;
|
border-top: 2px solid #e6e7ea;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -1479,9 +1495,11 @@ $bubble-margin: .25rem;
|
|||||||
|
|
||||||
&-text {
|
&-text {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin-left: 13px;
|
font-size: 15px;
|
||||||
|
margin-left: 9px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
color: #1f88e3;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-avatars {
|
&-avatars {
|
||||||
@ -1496,7 +1514,7 @@ $bubble-margin: .25rem;
|
|||||||
|
|
||||||
.tgico-next {
|
.tgico-next {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: .5rem;
|
right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-unread {
|
&.is-unread {
|
||||||
|
@ -211,4 +211,18 @@
|
|||||||
margin-bottom: .25rem;
|
margin-bottom: .25rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chat:not(.type-chat) & {
|
||||||
|
.content {
|
||||||
|
padding-left: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .user-title {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-close-button:before {
|
||||||
|
margin-top: 1px;
|
||||||
|
} */
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user