Browse Source

Fix rendering bugged webpages

Fix rendering search results from hidden sender
master
morethanwords 3 years ago
parent
commit
8d7dd98df8
  1. 7
      src/components/appMediaViewer.ts
  2. 26
      src/components/appSearch.ts
  3. 460
      src/components/appSearchSuper..ts
  4. 29
      src/components/chat/bubbles.ts
  5. 7
      src/components/chat/chat.ts
  6. 2
      src/components/chat/input.ts
  7. 26
      src/components/chat/topbar.ts
  8. 17
      src/components/peerTitle.ts
  9. 2
      src/components/popups/forward.ts
  10. 4
      src/components/sidebarLeft/index.ts
  11. 51
      src/lib/appManagers/appDialogsManager.ts
  12. 107
      src/lib/appManagers/appImManager.ts
  13. 20
      src/lib/appManagers/appMessagesManager.ts
  14. 3
      src/lib/appManagers/internalLink.ts

7
src/components/appMediaViewer.ts

@ -205,7 +205,12 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet
} }
} }
appImManager.setInnerPeer(message.peerId, mid, threadId ? 'discussion' : undefined, threadId); appImManager.setInnerPeer({
peerId: message.peerId,
lastMsgId: mid,
type: threadId ? 'discussion' : undefined,
threadId
});
}); });
} }
}; };

26
src/components/appSearch.ts

@ -184,20 +184,20 @@ export default class AppSearch {
const searchGroup = this.searchGroups.messages; const searchGroup = this.searchGroups.messages;
history.forEach((message) => { history.forEach((message) => {
const peerId = this.peerId ? message.fromId : message.peerId; try {
const {dialog, dom} = appDialogsManager.addDialogNew({ const peerId = this.peerId ? message.fromId : message.peerId;
dialog: peerId, appDialogsManager.addDialogAndSetLastMessage({
container: this.scrollable/* searchGroup.list */, peerId,
drawStatus: false, container: this.scrollable/* searchGroup.list */,
avatarSize: 54, drawStatus: false,
meAsSaved: false avatarSize: 54,
}); meAsSaved: false,
message,
if(message.peerId !== peerId) { query
dom.listEl.dataset.peerId = '' + message.peerId; });
} catch(err) {
console.error('[appSearch] render search result', err);
} }
appDialogsManager.setLastMessage(dialog, message, dom, query);
}); });
searchGroup.toggle(); searchGroup.toggle();

460
src/components/appSearchSuper..ts

@ -28,7 +28,7 @@ import I18n, { LangPackKey, i18n } from "../lib/langPack";
import findUpClassName from "../helpers/dom/findUpClassName"; import findUpClassName from "../helpers/dom/findUpClassName";
import { getMiddleware } from "../helpers/middleware"; import { getMiddleware } from "../helpers/middleware";
import appProfileManager from "../lib/appManagers/appProfileManager"; import appProfileManager from "../lib/appManagers/appProfileManager";
import { ChannelParticipant, ChatFull, ChatParticipant, ChatParticipants } from "../layer"; import { ChannelParticipant, ChatFull, ChatParticipant, ChatParticipants, Message, MessageMedia, Photo, WebPage } from "../layer";
import SortedUserList from "./sortedUserList"; import SortedUserList from "./sortedUserList";
import findUpTag from "../helpers/dom/findUpTag"; import findUpTag from "../helpers/dom/findUpTag";
import appSidebarRight from "./sidebarRight"; import appSidebarRight from "./sidebarRight";
@ -222,6 +222,15 @@ class SearchContextMenu {
}; };
} }
export type ProcessSearchSuperResult = {
message: Message.message,
middleware: () => boolean,
promises: Promise<any>[],
elemsToAppend: {element: HTMLElement, message: any}[],
inputFilter: MyInputMessagesFilter,
searchGroup?: SearchGroup
};
export default class AppSearchSuper { export default class AppSearchSuper {
public tabs: {[t in SearchSuperType]: HTMLDivElement} = {} as any; public tabs: {[t in SearchSuperType]: HTMLDivElement} = {} as any;
@ -656,250 +665,268 @@ export default class AppSearchSuper {
return filtered; return filtered;
} }
public async performSearchResult(messages: any[], mediaTab: SearchSuperMediaTab, append = true) { private processEmptyFilter({message, searchGroup}: ProcessSearchSuperResult) {
const elemsToAppend: {element: HTMLElement, message: any}[] = []; const {dialog, dom} = appDialogsManager.addDialogNew({
const sharedMediaDiv: HTMLElement = mediaTab.contentTab; dialog: message.peerId,
const promises: Promise<any>[] = []; container: searchGroup.list,
const middleware = this.middleware.get(); drawStatus: false,
let inputFilter = mediaTab.inputFilter; avatarSize: 54
});
await getHeavyAnimationPromise(); appDialogsManager.setLastMessage(dialog, message, dom, this.searchContext.query);
}
let searchGroup: SearchGroup; private processPhotoVideoFilter({message, promises, middleware, elemsToAppend}: ProcessSearchSuperResult) {
if(inputFilter === 'inputMessagesFilterPhotoVideo' && !!this.searchContext.query.trim()) { const media = appMessagesManager.getMediaFromMessage(message);
inputFilter = 'inputMessagesFilterEmpty';
searchGroup = this.searchGroupMedia; const div = document.createElement('div');
sharedMediaDiv.append(searchGroup.container); div.classList.add('grid-item');
} else if(inputFilter === 'inputMessagesFilterEmpty') { //this.log(message, photo);
searchGroup = this.searchGroups.messages;
let wrapped: ReturnType<typeof wrapPhoto>;
const size = appPhotosManager.choosePhotoSize(media, 200, 200);
if(media._ !== 'photo') {
wrapped = wrapVideo({
doc: media,
message,
container: div,
boxWidth: 0,
boxHeight: 0,
lazyLoadQueue: this.lazyLoadQueue,
middleware,
onlyPreview: true,
withoutPreloader: true,
noPlayButton: true,
size
}).thumb;
} else {
wrapped = wrapPhoto({
photo: media,
message,
container: div,
boxWidth: 0,
boxHeight: 0,
lazyLoadQueue: this.lazyLoadQueue,
middleware,
withoutPreloader: true,
noBlur: true,
size
});
} }
// https://core.telegram.org/type/MessagesFilter [wrapped.images.thumb, wrapped.images.full].filter(Boolean).forEach(image => {
switch(inputFilter) { image.classList.add('grid-item-media');
case 'inputMessagesFilterEmpty': { });
for(const message of messages) {
const {dialog, dom} = appDialogsManager.addDialogNew({
dialog: message.peerId,
container: searchGroup.list,
drawStatus: false,
avatarSize: 54
});
appDialogsManager.setLastMessage(dialog, message, dom, this.searchContext.query);
}
if(searchGroup.list.childElementCount) { promises.push(wrapped.loadPromises.thumb);
searchGroup.setActive();
}
break;
}
case 'inputMessagesFilterPhotoVideo': { elemsToAppend.push({element: div, message});
for(const message of messages) { }
const media = message.media.photo || message.media.document || (message.media.webpage && message.media.webpage.document);
const div = document.createElement('div');
div.classList.add('grid-item');
//this.log(message, photo);
let wrapped: ReturnType<typeof wrapPhoto>;
const size = appPhotosManager.choosePhotoSize(media, 200, 200);
if(media._ !== 'photo') {
wrapped = wrapVideo({
doc: media,
message,
container: div,
boxWidth: 0,
boxHeight: 0,
lazyLoadQueue: this.lazyLoadQueue,
middleware,
onlyPreview: true,
withoutPreloader: true,
noPlayButton: true,
size
}).thumb;
} else {
wrapped = wrapPhoto({
photo: media,
message,
container: div,
boxWidth: 0,
boxHeight: 0,
lazyLoadQueue: this.lazyLoadQueue,
middleware,
withoutPreloader: true,
noBlur: true,
size
});
}
[wrapped.images.thumb, wrapped.images.full].filter(Boolean).forEach(image => { private processDocumentFilter({message, elemsToAppend, inputFilter}: ProcessSearchSuperResult) {
image.classList.add('grid-item-media'); const document = appMessagesManager.getMediaFromMessage(message);
}); const showSender = this.showSender || (['voice', 'round'] as MyDocument['type'][]).includes(document.type);
const div = wrapDocument({
message,
withTime: !showSender,
fontWeight: 400,
voiceAsMusic: true,
showSender,
searchContext: this.copySearchContext(inputFilter),
lazyLoadQueue: this.lazyLoadQueue,
noAutoDownload: true
});
if((['audio', 'voice', 'round'] as MyDocument['type'][]).includes(document.type)) {
div.classList.add('audio-48');
}
elemsToAppend.push({element: div, message});
}
private processUrlFilter({message, promises, middleware, elemsToAppend}: ProcessSearchSuperResult) {
let webpage = (message.media as MessageMedia.messageMediaWebPage)?.webpage as WebPage.webPage;
promises.push(wrapped.loadPromises.thumb); if(!webpage) {
const entity = message.totalEntities ? message.totalEntities.find((e: any) => e._ === 'messageEntityUrl' || e._ === 'messageEntityTextUrl') : null;
let url: string, display_url: string, sliced: string;
elemsToAppend.push({element: div, message}); if(!entity) {
//this.log.error('NO ENTITY:', message);
const match = RichTextProcessor.matchUrl(message.message);
if(!match) {
//this.log.error('NO ENTITY AND NO MATCH:', message);
return;
} }
break; url = match[0];
} else {
sliced = message.message.slice(entity.offset, entity.offset + entity.length);
} }
case 'inputMessagesFilterVoice': if(entity?._ === 'messageEntityTextUrl') {
case 'inputMessagesFilterRoundVoice': url = entity.url;
case 'inputMessagesFilterMusic': //display_url = sliced;
case 'inputMessagesFilterDocument': { } else {
for(const message of messages) { url = url || sliced;
const showSender = this.showSender || (['voice', 'round'] as MyDocument['type'][]).includes(message.media.document.type); }
const div = wrapDocument({
message,
withTime: !showSender,
fontWeight: 400,
voiceAsMusic: true,
showSender,
searchContext: this.copySearchContext(inputFilter),
lazyLoadQueue: this.lazyLoadQueue,
noAutoDownload: true
});
if((['audio', 'voice', 'round'] as MyDocument['type'][]).includes(message.media.document.type)) { display_url = url;
div.classList.add('audio-48');
}
elemsToAppend.push({element: div, message}); const same = message.message === url;
} if(!url.match(/^(ftp|http|https):\/\//)) {
break; display_url = 'https://' + url;
url = url.includes('@') ? url : 'https://' + url;
} }
case 'inputMessagesFilterUrl': { display_url = new URL(display_url).hostname;
for(let message of messages) {
let webpage: any;
if(message.media?.webpage && message.media.webpage._ !== 'webPageEmpty') { webpage = {
webpage = message.media.webpage; _: 'webPage',
} else { url,
const entity = message.totalEntities ? message.totalEntities.find((e: any) => e._ === 'messageEntityUrl' || e._ === 'messageEntityTextUrl') : null; display_url,
let url: string, display_url: string, sliced: string; id: '',
hash: 0
if(!entity) { };
//this.log.error('NO ENTITY:', message);
const match = RichTextProcessor.matchUrl(message.message);
if(!match) {
//this.log.error('NO ENTITY AND NO MATCH:', message);
continue;
}
url = match[0]; if(!same) {
} else { webpage.description = message.message;
sliced = message.message.slice(entity.offset, entity.offset + entity.length); webpage.rDescription = RichTextProcessor.wrapRichText(limitSymbols(message.message, 150, 180));
} }
}
if(entity?._ === 'messageEntityTextUrl') { let previewDiv = document.createElement('div');
url = entity.url; previewDiv.classList.add('preview', 'row-media');
//display_url = sliced;
} else { //this.log('wrapping webpage', webpage);
url = url || sliced;
} if(webpage.photo) {
const res = wrapPhoto({
container: previewDiv,
message: null,
photo: webpage.photo as Photo.photo,
boxWidth: 0,
boxHeight: 0,
withoutPreloader: true,
lazyLoadQueue: this.lazyLoadQueue,
middleware,
size: appPhotosManager.choosePhotoSize(webpage.photo as Photo.photo, 60, 60, false),
loadPromises: promises,
noBlur: true
});
} else {
previewDiv.classList.add('empty');
previewDiv.innerHTML = RichTextProcessor.getAbbreviation(webpage.title || webpage.display_url || webpage.description || webpage.url, true);
}
display_url = url; let title = webpage.rTitle || '';
let subtitle = webpage.rDescription || '';
const same = message.message === url; const subtitleFragment = htmlToDocumentFragment(subtitle);
if(!url.match(/^(ftp|http|https):\/\//)) { const aFragment = htmlToDocumentFragment(RichTextProcessor.wrapRichText(webpage.url || ''));
display_url = 'https://' + url; const a = aFragment.firstElementChild;
url = url.includes('@') ? url : 'https://' + url; if(a instanceof HTMLAnchorElement) {
} try { // can have 'URIError: URI malformed'
a.innerText = decodeURIComponent(a.href);
} catch(err) {
display_url = new URL(display_url).hostname; }
}
webpage = { if(subtitleFragment.firstChild) {
url, subtitleFragment.append('\n');
display_url }
};
if(!same) { subtitleFragment.append(a);
webpage.description = message.message;
webpage.rDescription = RichTextProcessor.wrapRichText(limitSymbols(message.message, 150, 180));
}
}
let div = document.createElement('div'); if(this.showSender) {
subtitleFragment.append('\n', appMessagesManager.wrapSenderToPeer(message));
let previewDiv = document.createElement('div'); }
previewDiv.classList.add('preview', 'row-media');
//this.log('wrapping webpage', webpage);
if(webpage.photo) {
const res = wrapPhoto({
container: previewDiv,
message: null,
photo: webpage.photo,
boxWidth: 0,
boxHeight: 0,
withoutPreloader: true,
lazyLoadQueue: this.lazyLoadQueue,
middleware,
size: appPhotosManager.choosePhotoSize(webpage.photo, 60, 60, false),
loadPromises: promises,
noBlur: true
});
} else {
previewDiv.classList.add('empty');
previewDiv.innerHTML = RichTextProcessor.getAbbreviation(webpage.title || webpage.display_url || webpage.description || webpage.url, true);
}
let title = webpage.rTitle || ''; if(!title) {
let subtitle = webpage.rDescription || ''; //title = new URL(webpage.url).hostname;
title = RichTextProcessor.wrapPlainText(webpage.display_url.split('/', 1)[0]);
}
const subtitleFragment = htmlToDocumentFragment(subtitle); const row = new Row({
const aFragment = htmlToDocumentFragment(RichTextProcessor.wrapRichText(webpage.url || '')); title,
const a = aFragment.firstElementChild; titleRight: appMessagesManager.wrapSentTime(message),
if(a instanceof HTMLAnchorElement) { subtitle: subtitleFragment,
a.innerText = decodeURIComponent(a.href); havePadding: true,
} clickable: true,
noRipple: true
});
if(subtitleFragment.firstChild) { /* const mediaDiv = document.createElement('div');
subtitleFragment.append('\n'); mediaDiv.classList.add('row-media'); */
}
subtitleFragment.append(a); row.container.append(previewDiv);
if(this.showSender) { /* ripple(div);
subtitleFragment.append('\n', appMessagesManager.wrapSenderToPeer(message)); div.append(previewDiv);
} div.insertAdjacentHTML('beforeend', `
<div class="title">${title}${titleAdditionHTML}</div>
<div class="subtitle">${subtitle}</div>
<div class="url">${url}</div>
${sender}
`); */
if(!title) { if(row.container.innerText.trim().length) {
//title = new URL(webpage.url).hostname; elemsToAppend.push({element: row.container, message});
title = RichTextProcessor.wrapPlainText(webpage.display_url.split('/', 1)[0]); }
} }
const row = new Row({ public async performSearchResult(messages: any[], mediaTab: SearchSuperMediaTab, append = true) {
title, const elemsToAppend: {element: HTMLElement, message: any}[] = [];
titleRight: appMessagesManager.wrapSentTime(message), const sharedMediaDiv: HTMLElement = mediaTab.contentTab;
subtitle: subtitleFragment, const promises: Promise<any>[] = [];
havePadding: true, const middleware = this.middleware.get();
clickable: true, let inputFilter = mediaTab.inputFilter;
noRipple: true
});
/* const mediaDiv = document.createElement('div'); await getHeavyAnimationPromise();
mediaDiv.classList.add('row-media'); */
row.container.append(previewDiv); let searchGroup: SearchGroup;
if(inputFilter === 'inputMessagesFilterPhotoVideo' && !!this.searchContext.query.trim()) {
inputFilter = 'inputMessagesFilterEmpty';
searchGroup = this.searchGroupMedia;
sharedMediaDiv.append(searchGroup.container);
} else if(inputFilter === 'inputMessagesFilterEmpty') {
searchGroup = this.searchGroups.messages;
}
/* ripple(div); const options: ProcessSearchSuperResult = {
div.append(previewDiv); elemsToAppend,
div.insertAdjacentHTML('beforeend', ` inputFilter,
<div class="title">${title}${titleAdditionHTML}</div> message: undefined,
<div class="subtitle">${subtitle}</div> middleware,
<div class="url">${url}</div> promises,
${sender} searchGroup
`); */ };
if(row.container.innerText.trim().length) { let processCallback: (options: ProcessSearchSuperResult) => any;
elemsToAppend.push({element: row.container, message});
} // https://core.telegram.org/type/MessagesFilter
} switch(inputFilter) {
case 'inputMessagesFilterEmpty': {
processCallback = this.processEmptyFilter;
break;
}
case 'inputMessagesFilterPhotoVideo': {
processCallback = this.processPhotoVideoFilter;
break;
}
case 'inputMessagesFilterVoice':
case 'inputMessagesFilterRoundVoice':
case 'inputMessagesFilterMusic':
case 'inputMessagesFilterDocument': {
processCallback = this.processDocumentFilter;
break;
}
case 'inputMessagesFilterUrl': {
processCallback = this.processUrlFilter;
break; break;
} }
@ -908,6 +935,23 @@ export default class AppSearchSuper {
break; break;
} }
if(processCallback) {
processCallback = processCallback.bind(this);
for(const message of messages) {
try {
options.message = message;
processCallback(options);
} catch(err) {
this.log.error('error rendering filter', inputFilter, options, message, err);
}
}
}
if(searchGroup && searchGroup.list.childElementCount) {
searchGroup.setActive();
}
if(this.loadMutex) { if(this.loadMutex) {
promises.push(this.loadMutex); promises.push(this.loadMutex);
} }
@ -1163,7 +1207,7 @@ export default class AppSearchSuper {
} }
promise.then(() => { promise.then(() => {
appImManager.setInnerPeer(peerId); appImManager.setInnerPeer({peerId});
}); });
}); });
mediaTab.contentTab.append(this.membersList.list); mediaTab.contentTab.append(this.membersList.list);

29
src/components/chat/bubbles.ts

@ -1011,7 +1011,9 @@ export default class ChatBubbles {
const contactDiv: HTMLElement = findUpClassName(target, 'contact'); const contactDiv: HTMLElement = findUpClassName(target, 'contact');
if(contactDiv) { if(contactDiv) {
this.chat.appImManager.setInnerPeer(contactDiv.dataset.peerId.toPeerId()); this.chat.appImManager.setInnerPeer({
peerId: contactDiv.dataset.peerId.toPeerId()
});
return; return;
} }
@ -1035,7 +1037,11 @@ export default class ChatBubbles {
const replies = message.replies; const replies = message.replies;
if(replies) { if(replies) {
this.appMessagesManager.getDiscussionMessage(this.peerId, message.mid).then(message => { this.appMessagesManager.getDiscussionMessage(this.peerId, message.mid).then(message => {
this.chat.appImManager.setInnerPeer(replies.channel_id.toPeerId(true), undefined, 'discussion', (message as MyMessage).mid); this.chat.appImManager.setInnerPeer({
peerId: replies.channel_id.toPeerId(true),
type: 'discussion',
threadId: (message as MyMessage).mid
});
}); });
} }
} }
@ -1064,11 +1070,14 @@ export default class ChatBubbles {
if(savedFrom) { if(savedFrom) {
const [peerId, mid] = savedFrom.split('_'); const [peerId, mid] = savedFrom.split('_');
this.chat.appImManager.setInnerPeer(peerId.toPeerId(), +mid); this.chat.appImManager.setInnerPeer({
peerId: peerId.toPeerId(),
lastMsgId: +mid
});
} else { } else {
const peerId = peerIdStr.toPeerId(); const peerId = peerIdStr.toPeerId();
if(peerId !== NULL_PEER_ID) { if(peerId !== NULL_PEER_ID) {
this.chat.appImManager.setInnerPeer(peerId); this.chat.appImManager.setInnerPeer({peerId});
} else { } else {
toast(I18n.format('HidAccount', true)); toast(I18n.format('HidAccount', true));
} }
@ -1213,7 +1222,10 @@ export default class ChatBubbles {
const savedFrom = bubble.dataset.savedFrom; const savedFrom = bubble.dataset.savedFrom;
const [peerId, mid] = savedFrom.split('_'); const [peerId, mid] = savedFrom.split('_');
////this.log('savedFrom', peerId, msgID); ////this.log('savedFrom', peerId, msgID);
this.chat.appImManager.setInnerPeer(peerId.toPeerId(), +mid); this.chat.appImManager.setInnerPeer({
peerId: peerId.toPeerId(),
lastMsgId: +mid
});
return; return;
} else if(target.classList.contains('forward')) { } else if(target.classList.contains('forward')) {
const mid = +bubble.dataset.mid; const mid = +bubble.dataset.mid;
@ -1240,7 +1252,12 @@ export default class ChatBubbles {
const replyToPeerId = message.reply_to.reply_to_peer_id ? this.appPeersManager.getPeerId(message.reply_to.reply_to_peer_id) : this.peerId; 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; const replyToMid = message.reply_to.reply_to_msg_id;
this.chat.appImManager.setInnerPeer(replyToPeerId, replyToMid, this.chat.type, this.chat.threadId); this.chat.appImManager.setInnerPeer({
peerId: replyToPeerId,
lastMsgId: replyToMid,
type: this.chat.type,
threadId: this.chat.threadId
});
/* if(this.chat.type === 'discussion') { /* if(this.chat.type === 'discussion') {
this.chat.appImManager.setMessageId(, originalMessageId); this.chat.appImManager.setMessageId(, originalMessageId);

7
src/components/chat/chat.ts

@ -223,7 +223,7 @@ export default class Chat extends EventListenerBase<{
this.bubbles.listenerSetter.add(rootScope)('dialog_drop', (e) => { this.bubbles.listenerSetter.add(rootScope)('dialog_drop', (e) => {
if(e.peerId === this.peerId) { if(e.peerId === this.peerId) {
this.appImManager.setPeer(NULL_PEER_ID); this.appImManager.setPeer();
} }
}); });
} }
@ -271,8 +271,6 @@ export default class Chat extends EventListenerBase<{
if(!samePeer) { if(!samePeer) {
rootScope.dispatchEvent('peer_changing', this); rootScope.dispatchEvent('peer_changing', this);
this.peerId = peerId; this.peerId = peerId;
this.noForwards = this.appPeersManager.noForwards(peerId);
this.container.classList.toggle('no-forwards', this.noForwards);
} else if(this.setPeerPromise) { } else if(this.setPeerPromise) {
return; return;
} }
@ -297,6 +295,9 @@ export default class Chat extends EventListenerBase<{
searchTab.close(); searchTab.close();
} }
this.noForwards = this.appPeersManager.noForwards(peerId);
this.container.classList.toggle('no-forwards', this.noForwards);
appSidebarRight.sharedMediaTab.setPeer(peerId, this.threadId); appSidebarRight.sharedMediaTab.setPeer(peerId, this.threadId);
this.input.clearHelper(); // костыль this.input.clearHelper(); // костыль
this.selection.cleanup(); // TODO: REFACTOR !!!!!! this.selection.cleanup(); // TODO: REFACTOR !!!!!!

2
src/components/chat/input.ts

@ -805,7 +805,7 @@ export default class ChatInput {
const peerId = this.chat.peerId; const peerId = this.chat.peerId;
new PopupPinMessage(peerId, 0, true, () => { new PopupPinMessage(peerId, 0, true, () => {
this.chat.appImManager.setPeer(NULL_PEER_ID); // * close tab this.chat.appImManager.setPeer(); // * close tab
// ! костыль, это скроет закреплённые сообщения сразу, вместо того, чтобы ждать пока анимация перехода закончится // ! костыль, это скроет закреплённые сообщения сразу, вместо того, чтобы ждать пока анимация перехода закончится
const originalChat = this.chat.appImManager.chat; const originalChat = this.chat.appImManager.chat;

26
src/components/chat/topbar.ts

@ -202,12 +202,12 @@ export default class ChatTopbar {
} else { } else {
const peerId = container.dataset.peerId.toPeerId(); const peerId = container.dataset.peerId.toPeerId();
const searchContext = appMediaPlaybackController.getSearchContext(); const searchContext = appMediaPlaybackController.getSearchContext();
this.chat.appImManager.setInnerPeer( this.chat.appImManager.setInnerPeer({
peerId, peerId,
mid, lastMsgId: mid,
searchContext.isScheduled ? 'scheduled' : (searchContext.threadId ? 'discussion' : undefined), type: searchContext.isScheduled ? 'scheduled' : (searchContext.threadId ? 'discussion' : undefined),
searchContext.threadId threadId: searchContext.threadId
); });
} }
} else { } else {
if(mediaSizes.activeScreen === ScreenSize.medium && document.body.classList.contains(LEFT_COLUMN_ACTIVE_CLASSNAME)) { if(mediaSizes.activeScreen === ScreenSize.medium && document.body.classList.contains(LEFT_COLUMN_ACTIVE_CLASSNAME)) {
@ -228,7 +228,7 @@ export default class ChatTopbar {
//const item = appNavigationController.findItemByType('chat'); //const item = appNavigationController.findItemByType('chat');
// * return manually to chat by arrow, since can't get back to // * return manually to chat by arrow, since can't get back to
if(mediaSizes.activeScreen === ScreenSize.medium && document.body.classList.contains(LEFT_COLUMN_ACTIVE_CLASSNAME)) { if(mediaSizes.activeScreen === ScreenSize.medium && document.body.classList.contains(LEFT_COLUMN_ACTIVE_CLASSNAME)) {
this.chat.appImManager.setPeer(this.peerId); this.chat.appImManager.setPeer({peerId: this.peerId});
} else { } else {
const isFirstChat = this.chat.appImManager.chats.indexOf(this.chat) === 0; const isFirstChat = this.chat.appImManager.chats.indexOf(this.chat) === 0;
appNavigationController.back(isFirstChat ? 'im' : 'chat'); appNavigationController.back(isFirstChat ? 'im' : 'chat');
@ -337,7 +337,9 @@ export default class ChatTopbar {
const middleware = this.chat.bubbles.getMiddleware(); const middleware = this.chat.bubbles.getMiddleware();
this.appProfileManager.getChannelFull(this.peerId.toChatId()).then(channelFull => { this.appProfileManager.getChannelFull(this.peerId.toChatId()).then(channelFull => {
if(middleware() && channelFull.linked_chat_id) { if(middleware() && channelFull.linked_chat_id) {
this.chat.appImManager.setInnerPeer(channelFull.linked_chat_id.toPeerId(true)); this.chat.appImManager.setInnerPeer({
peerId: channelFull.linked_chat_id.toPeerId(true)
});
} }
}); });
}, },
@ -426,7 +428,7 @@ export default class ChatTopbar {
resolve(); resolve();
this.appMessagesManager.sendOther(peerId, this.appUsersManager.getContactMediaInput(contactPeerId)); this.appMessagesManager.sendOther(peerId, this.appUsersManager.getContactMediaInput(contactPeerId));
this.chat.appImManager.setInnerPeer(peerId); this.chat.appImManager.setInnerPeer({peerId});
} }
}, { }, {
langKey: 'Cancel', langKey: 'Cancel',
@ -640,7 +642,11 @@ export default class ChatTopbar {
} }
public openPinned(byCurrent: boolean) { public openPinned(byCurrent: boolean) {
this.chat.appImManager.setInnerPeer(this.peerId, byCurrent ? +this.pinnedMessage.pinnedMessageContainer.divAndCaption.container.dataset.mid : 0, 'pinned'); this.chat.appImManager.setInnerPeer({
peerId: this.peerId,
lastMsgId: byCurrent ? +this.pinnedMessage.pinnedMessageContainer.divAndCaption.container.dataset.mid : 0,
type: 'pinned'
});
} }
private onResize = () => { private onResize = () => {
@ -748,7 +754,7 @@ export default class ChatTopbar {
// ! костыль х2, это нужно делать в другом месте // ! костыль х2, это нужно делать в другом месте
if(!count) { if(!count) {
this.chat.appImManager.setPeer(NULL_PEER_ID); // * close tab this.chat.appImManager.setPeer(); // * close tab
// ! костыль, это скроет закреплённые сообщения сразу, вместо того, чтобы ждать пока анимация перехода закончится // ! костыль, это скроет закреплённые сообщения сразу, вместо того, чтобы ждать пока анимация перехода закончится
const originalChat = this.chat.appImManager.chat; const originalChat = this.chat.appImManager.chat;

17
src/components/peerTitle.ts

@ -10,9 +10,12 @@ import rootScope from "../lib/rootScope";
import { i18n } from "../lib/langPack"; import { i18n } from "../lib/langPack";
import replaceContent from "../helpers/dom/replaceContent"; import replaceContent from "../helpers/dom/replaceContent";
import appUsersManager from "../lib/appManagers/appUsersManager"; import appUsersManager from "../lib/appManagers/appUsersManager";
import RichTextProcessor from "../lib/richtextprocessor";
import { NULL_PEER_ID } from "../lib/mtproto/mtproto_config";
export type PeerTitleOptions = { export type PeerTitleOptions = {
peerId: PeerId, peerId?: PeerId,
fromName?: string,
plainText?: boolean, plainText?: boolean,
onlyFirstName?: boolean, onlyFirstName?: boolean,
dialog?: boolean dialog?: boolean
@ -37,6 +40,7 @@ rootScope.addEventListener('peer_title_edit', (peerId) => {
export default class PeerTitle { export default class PeerTitle {
public element: HTMLElement; public element: HTMLElement;
public peerId: PeerId; public peerId: PeerId;
public fromName: string;
public plainText = false; public plainText = false;
public onlyFirstName = false; public onlyFirstName = false;
public dialog = false; public dialog = false;
@ -54,12 +58,21 @@ export default class PeerTitle {
if(options) { if(options) {
for(let i in options) { for(let i in options) {
// @ts-ignore // @ts-ignore
this.element.dataset[i] = options[i] ? '' + (typeof(options[i]) === 'boolean' ? +options[i] : options[i]) : '0'; // this.element.dataset[i] = options[i] ? '' + (typeof(options[i]) === 'boolean' ? +options[i] : options[i]) : '0';
// @ts-ignore // @ts-ignore
this[i] = options[i]; this[i] = options[i];
} }
} }
if(this.fromName !== undefined) {
this.element.innerHTML = RichTextProcessor.wrapEmojiText(this.fromName);
return;
}
if(this.peerId === undefined) {
this.peerId = NULL_PEER_ID;
}
if(this.peerId !== rootScope.myId || !this.dialog) { if(this.peerId !== rootScope.myId || !this.dialog) {
if(this.peerId.isUser() && appUsersManager.getUser(this.peerId).pFlags.deleted) { if(this.peerId.isUser() && appUsersManager.getUser(this.peerId).pFlags.deleted) {
replaceContent(this.element, i18n(this.onlyFirstName ? 'Deleted' : 'HiddenName')); replaceContent(this.element, i18n(this.onlyFirstName ? 'Deleted' : 'HiddenName'));

2
src/components/popups/forward.ts

@ -23,7 +23,7 @@ export default class PopupForward extends PopupPickUser {
} }
} }
appImManager.setInnerPeer(peerId); appImManager.setInnerPeer({peerId});
appImManager.chat.input.initMessagesForward(peerIdMids); appImManager.chat.input.initMessagesForward(peerIdMids);
}, },
placeholder: 'ShareModal.Search.ForwardPlaceholder', placeholder: 'ShareModal.Search.ForwardPlaceholder',

4
src/components/sidebarLeft/index.ts

@ -122,7 +122,9 @@ export class AppSidebarLeft extends SidebarSlider {
text: 'SavedMessages', text: 'SavedMessages',
onClick: () => { onClick: () => {
setTimeout(() => { // menu doesn't close if no timeout (lol) setTimeout(() => { // menu doesn't close if no timeout (lol)
appImManager.setPeer(appImManager.myId); appImManager.setPeer({
peerId: appImManager.myId
});
}, 0); }, 0);
} }
}, btnArchive, { }, btnArchive, {

51
src/lib/appManagers/appDialogsManager.ts

@ -1358,9 +1358,11 @@ export class AppDialogsManager {
const peerId = elem.dataset.peerId.toPeerId(); const peerId = elem.dataset.peerId.toPeerId();
const lastMsgId = +elem.dataset.mid || undefined; const lastMsgId = +elem.dataset.mid || undefined;
setPeerFunc(peerId, lastMsgId); setPeerFunc({
peerId, lastMsgId
});
} else { } else {
setPeerFunc(NULL_PEER_ID); setPeerFunc();
} }
}, {capture: true}); }, {capture: true});
@ -1641,12 +1643,13 @@ export class AppDialogsManager {
} }
private getDialog(dialog: Dialog | PeerId): Dialog { private getDialog(dialog: Dialog | PeerId): Dialog {
if(typeof(dialog) !== 'object' && dialog) { if(typeof(dialog) !== 'object') {
const originalDialog = appMessagesManager.getDialogOnly(dialog); const originalDialog = appMessagesManager.getDialogOnly(dialog);
if(!originalDialog) { if(!originalDialog) {
const peerId = dialog || NULL_PEER_ID;
return { return {
peerId: dialog, peerId,
peer: appPeersManager.getOutputPeer(dialog), peer: appPeersManager.getOutputPeer(peerId),
pFlags: {} pFlags: {}
} as any; } as any;
} }
@ -1712,6 +1715,30 @@ export class AppDialogsManager {
this.setCallStatus(dom, !!(chat.pFlags.call_active && chat.pFlags.call_not_empty)); this.setCallStatus(dom, !!(chat.pFlags.call_active && chat.pFlags.call_not_empty));
} }
/**
* use for rendering search result
*/
public addDialogAndSetLastMessage(options: Omit<Parameters<AppDialogsManager['addDialogNew']>[0], 'dialog'> & {
message: MyMessage,
peerId: PeerId,
query?: string
}) {
const {peerId, message, query} = options;
const ret = appDialogsManager.addDialogNew({
...options,
...appMessagesManager.getMessageSenderPeerIdOrName(message),
dialog: this.getDialog(peerId),
});
this.setLastMessage(ret.dialog, message, ret.dom, query);
if(message.peerId !== peerId) {
ret.dom.listEl.dataset.peerId = '' + message.peerId;
}
return ret;
}
public addDialogNew(options: { public addDialogNew(options: {
dialog: Parameters<AppDialogsManager['addDialog']>[0], dialog: Parameters<AppDialogsManager['addDialog']>[0],
container?: Parameters<AppDialogsManager['addDialog']>[1], container?: Parameters<AppDialogsManager['addDialog']>[1],
@ -1723,12 +1750,14 @@ export class AppDialogsManager {
avatarSize?: number, avatarSize?: number,
autonomous?: boolean, autonomous?: boolean,
lazyLoadQueue?: LazyLoadQueueIntersector, lazyLoadQueue?: LazyLoadQueueIntersector,
loadPromises?: Promise<any>[] loadPromises?: Promise<any>[],
fromName?: string
}) { }) {
return this.addDialog(options.dialog, options.container, options.drawStatus, options.rippleEnabled, options.onlyFirstName, options.meAsSaved, options.append, options.avatarSize, options.autonomous, options.lazyLoadQueue, options.loadPromises); return this.addDialog(options.dialog, options.container, options.drawStatus, options.rippleEnabled, options.onlyFirstName, options.meAsSaved, options.append, options.avatarSize, options.autonomous, options.lazyLoadQueue, options.loadPromises, options.fromName);
} }
public addDialog(_dialog: Parameters<AppDialogsManager['getDialog']>[0], public addDialog(
_dialog: Parameters<AppDialogsManager['getDialog']>[0],
container?: HTMLElement | Scrollable | DocumentFragment | false, container?: HTMLElement | Scrollable | DocumentFragment | false,
drawStatus = true, drawStatus = true,
rippleEnabled = true, rippleEnabled = true,
@ -1738,7 +1767,9 @@ export class AppDialogsManager {
avatarSize = 54, avatarSize = 54,
autonomous = !!container, autonomous = !!container,
lazyLoadQueue?: LazyLoadQueueIntersector, lazyLoadQueue?: LazyLoadQueueIntersector,
loadPromises?: Promise<any>[]) { loadPromises?: Promise<any>[],
fromName?: string
) {
const dialog = this.getDialog(_dialog); const dialog = this.getDialog(_dialog);
const peerId = dialog.peerId; const peerId = dialog.peerId;
@ -1746,6 +1777,7 @@ export class AppDialogsManager {
avatarEl.loadPromises = loadPromises; avatarEl.loadPromises = loadPromises;
avatarEl.lazyLoadQueue = lazyLoadQueue; avatarEl.lazyLoadQueue = lazyLoadQueue;
avatarEl.setAttribute('dialog', meAsSaved ? '1' : '0'); avatarEl.setAttribute('dialog', meAsSaved ? '1' : '0');
if(fromName !== undefined) avatarEl.setAttribute('peer-title', fromName);
avatarEl.setAttribute('peer', '' + peerId); avatarEl.setAttribute('peer', '' + peerId);
avatarEl.classList.add('dialog-avatar', 'avatar-' + avatarSize); avatarEl.classList.add('dialog-avatar', 'avatar-' + avatarSize);
@ -1764,6 +1796,7 @@ export class AppDialogsManager {
const peerTitle = new PeerTitle({ const peerTitle = new PeerTitle({
peerId, peerId,
fromName,
dialog: meAsSaved, dialog: meAsSaved,
onlyFirstName, onlyFirstName,
plainText: false plainText: false

107
src/lib/appManagers/appImManager.ts

@ -43,7 +43,7 @@ import appNavigationController from '../../components/appNavigationController';
import appNotificationsManager from './appNotificationsManager'; import appNotificationsManager from './appNotificationsManager';
import AppPrivateSearchTab from '../../components/sidebarRight/tabs/search'; import AppPrivateSearchTab from '../../components/sidebarRight/tabs/search';
import I18n, { i18n, join, LangPackKey } from '../langPack'; import I18n, { i18n, join, LangPackKey } from '../langPack';
import { ChatInvite, Dialog, SendMessageAction } from '../../layer'; import { ChatInvite, Dialog, Message, SendMessageAction } from '../../layer';
import { hslaStringToHex } from '../../helpers/color'; import { hslaStringToHex } from '../../helpers/color';
import { copy, getObjectKeysAndSort } from '../../helpers/object'; import { copy, getObjectKeysAndSort } from '../../helpers/object';
import { getFilesFromEvent } from '../../helpers/files'; import { getFilesFromEvent } from '../../helpers/files';
@ -79,6 +79,7 @@ import IS_GROUP_CALL_SUPPORTED from '../../environment/groupCallSupport';
import appAvatarsManager from './appAvatarsManager'; import appAvatarsManager from './appAvatarsManager';
import IS_CALL_SUPPORTED from '../../environment/callSupport'; import IS_CALL_SUPPORTED from '../../environment/callSupport';
import { CallType } from '../calls/types'; import { CallType } from '../calls/types';
import { Modify } from '../../types';
//console.log('appImManager included33!'); //console.log('appImManager included33!');
@ -92,6 +93,19 @@ export type ChatSavedPosition = {
top: number top: number
}; };
export type ChatSetPeerOptions = {
peerId?: PeerId,
lastMsgId?: number,
threadId?: number,
startParam?: string
};
export type ChatSetInnerPeerOptions = Modify<ChatSetPeerOptions, {
peerId: PeerId
}> & {
type?: ChatType
};
export class AppImManager { export class AppImManager {
public columnEl = document.getElementById('column-center') as HTMLDivElement; public columnEl = document.getElementById('column-center') as HTMLDivElement;
public chatsContainer: HTMLElement; public chatsContainer: HTMLElement;
@ -197,7 +211,12 @@ export class AppImManager {
if(threadId) threadId = appMessagesIdsManager.generateMessageId(threadId); if(threadId) threadId = appMessagesIdsManager.generateMessageId(threadId);
if(mid) mid = appMessagesIdsManager.generateMessageId(mid); // because mid can come from notification, i.e. server message id if(mid) mid = appMessagesIdsManager.generateMessageId(mid); // because mid can come from notification, i.e. server message id
this.setInnerPeer(peerId, mid, threadId ? 'discussion' : undefined, threadId); this.setInnerPeer({
peerId,
lastMsgId: mid,
type: threadId ? 'discussion' : undefined,
threadId
});
}); });
rootScope.addEventListener('peer_changing', (chat) => { rootScope.addEventListener('peer_changing', (chat) => {
@ -374,7 +393,7 @@ export class AppImManager {
// pathnameParams: [string, string?], // pathnameParams: [string, string?],
// uriParams: {comment?: number} // uriParams: {comment?: number}
pathnameParams: ['c', string, string] | [string, string?], pathnameParams: ['c', string, string] | [string, string?],
uriParams: {thread?: string, comment?: string} | {comment?: string} uriParams: {thread?: string, comment?: string} | {comment?: string, start?: string}
}>({ }>({
name: 'im', name: 'im',
callback: async({pathnameParams, uriParams}) => { callback: async({pathnameParams, uriParams}) => {
@ -384,7 +403,7 @@ export class AppImManager {
_: INTERNAL_LINK_TYPE.PRIVATE_POST, _: INTERNAL_LINK_TYPE.PRIVATE_POST,
channel: pathnameParams[1], channel: pathnameParams[1],
post: pathnameParams[2], post: pathnameParams[2],
thread: 'thread' in uriParams ? uriParams.thread : undefined, thread: 'thread' in uriParams && uriParams.thread,
comment: uriParams.comment comment: uriParams.comment
}; };
} else { } else {
@ -392,7 +411,8 @@ export class AppImManager {
_: INTERNAL_LINK_TYPE.MESSAGE, _: INTERNAL_LINK_TYPE.MESSAGE,
domain: pathnameParams[0], domain: pathnameParams[0],
post: pathnameParams[1], post: pathnameParams[1],
comment: uriParams.comment comment: uriParams.comment,
start: 'start' in uriParams && uriParams.start
}; };
} }
@ -514,7 +534,7 @@ export class AppImManager {
} }
if(nextDialog) { if(nextDialog) {
this.setPeer(nextDialog.peerId); this.setPeer({peerId: nextDialog.peerId});
} }
} else if(key === 'ArrowUp') { } else if(key === 'ArrowUp') {
if(!chat.input.editMsgId && chat.input.isInputEmpty()) { if(!chat.input.editMsgId && chat.input.isInputEmpty()) {
@ -606,7 +626,11 @@ export class AppImManager {
const threadId = link.thread ? appMessagesIdsManager.generateMessageId(+link.thread) : undefined; const threadId = link.thread ? appMessagesIdsManager.generateMessageId(+link.thread) : undefined;
if(threadId) this.openThread(peerId, postId, threadId); if(threadId) this.openThread(peerId, postId, threadId);
else this.setInnerPeer(peerId, postId); else this.setInnerPeer({
peerId,
lastMsgId: postId,
threadId
});
break; break;
} }
@ -627,7 +651,9 @@ export class AppImManager {
if(chatInvite._ === 'chatInviteAlready' || if(chatInvite._ === 'chatInviteAlready' ||
chatInvite._ === 'chatInvitePeek'/* && chatInvite.expires > tsNow(true) */) { chatInvite._ === 'chatInvitePeek'/* && chatInvite.expires > tsNow(true) */) {
this.setInnerPeer(chatInvite.chat.id.toPeerId(true)); this.setInnerPeer({
peerId: chatInvite.chat.id.toPeerId(true)
});
return; return;
} }
@ -719,7 +745,10 @@ export class AppImManager {
} }
default: { // peerId default: { // peerId
this.setInnerPeer(postId ? p.toPeerId(true) : p.toPeerId(), postId); this.setInnerPeer({
peerId: postId ? p.toPeerId(true) : p.toPeerId(),
lastMsgId: postId
});
break; break;
} }
} }
@ -730,14 +759,21 @@ export class AppImManager {
//location.hash = ''; //location.hash = '';
}; };
public openUsername(username: string, msgId?: number, threadId?: number, commentId?: number) { public openUsername(username: string, lastMsgId?: number, threadId?: number, commentId?: number) {
return appUsersManager.resolveUsername(username).then(peer => { return appUsersManager.resolveUsername(username).then(peer => {
const isUser = peer._ === 'user'; const isUser = peer._ === 'user';
const peerId = isUser ? peer.id.toPeerId() : peer.id.toPeerId(true); const peerId = peer.id.toPeerId(!isUser);
if(threadId) {
return this.openThread(peerId, lastMsgId, threadId);
} else if(commentId) {
return this.openComment(peerId, lastMsgId, commentId);
}
if(threadId) return this.openThread(peerId, msgId, threadId); return this.setInnerPeer({
else if(commentId) return this.openComment(peerId, msgId, commentId); peerId,
else return this.setInnerPeer(peerId, msgId); lastMsgId
});
}, (err) => { }, (err) => {
if(err.type === 'USERNAME_NOT_OCCUPIED') { if(err.type === 'USERNAME_NOT_OCCUPIED') {
toastNew({langPackKey: 'NoUsernameFound'}); toastNew({langPackKey: 'NoUsernameFound'});
@ -752,10 +788,19 @@ export class AppImManager {
*/ */
public openThread(peerId: PeerId, lastMsgId: number, threadId: number) { public openThread(peerId: PeerId, lastMsgId: number, threadId: number) {
return appMessagesManager.wrapSingleMessage(peerId, threadId).then(() => { return appMessagesManager.wrapSingleMessage(peerId, threadId).then(() => {
const message = appMessagesManager.getMessageByPeer(peerId, threadId); const message: Message = appMessagesManager.getMessageByPeer(peerId, threadId);
appMessagesManager.generateThreadServiceStartMessage(message); if(message._ === 'messageEmpty') {
lastMsgId = undefined;
} else {
appMessagesManager.generateThreadServiceStartMessage(message);
}
return this.setInnerPeer(peerId, lastMsgId, 'discussion', threadId); return this.setInnerPeer({
peerId,
lastMsgId,
threadId,
type: 'discussion'
});
}); });
} }
@ -1044,7 +1089,7 @@ export class AppImManager {
appNavigationController.pushItem({ appNavigationController.pushItem({
type: 'chat', type: 'chat',
onPop: (canAnimate) => { onPop: (canAnimate) => {
this.setPeer(NULL_PEER_ID, undefined, canAnimate); this.setPeer({}, canAnimate);
blurActiveElement(); blurActiveElement();
} }
}); });
@ -1270,7 +1315,7 @@ export class AppImManager {
type: 'im', type: 'im',
onPop: (canAnimate) => { onPop: (canAnimate) => {
//this.selectTab(prevTabId, !isSafari); //this.selectTab(prevTabId, !isSafari);
this.setPeer(NULL_PEER_ID, undefined, canAnimate); this.setPeer({}, canAnimate);
} }
}); });
} }
@ -1382,12 +1427,14 @@ export class AppImManager {
}, 250 + 100); }, 250 + 100);
} }
public setPeer(peerId: PeerId, lastMsgId?: number, animate?: boolean): boolean { public setPeer(options: ChatSetPeerOptions = {}, animate?: boolean): boolean {
if(this.init) { if(this.init) {
this.init(); this.init();
this.init = null; this.init = null;
} }
const {peerId, lastMsgId} = options;
const chat = this.chat; const chat = this.chat;
const chatIndex = this.chats.indexOf(chat); const chatIndex = this.chats.indexOf(chat);
@ -1411,7 +1458,7 @@ export class AppImManager {
this.spliceChats(0, true, true, spliced); this.spliceChats(0, true, true, spliced);
return; return;
} else { } else {
const ret = this.setPeer(peerId, lastMsgId); const ret = this.setPeer(options);
this.spliceChats(0, false, false, spliced); this.spliceChats(0, false, false, spliced);
return ret; return ret;
} }
@ -1452,16 +1499,19 @@ export class AppImManager {
} }
} }
public setInnerPeer(peerId: PeerId, lastMsgId?: number, type: ChatType = 'chat', threadId?: number) { public setInnerPeer(options: ChatSetInnerPeerOptions) {
const {peerId} = options;
if(peerId === NULL_PEER_ID || !peerId) { if(peerId === NULL_PEER_ID || !peerId) {
return; return;
} }
const type = options.type ??= 'chat';
// * 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) {
this.spliceChats(existingIndex + 1); this.spliceChats(existingIndex + 1);
return this.setPeer(peerId, lastMsgId); return this.setPeer(options);
} }
const oldChat = this.chat; const oldChat = this.chat;
@ -1473,8 +1523,8 @@ export class AppImManager {
if(type) { if(type) {
chat.setType(type); chat.setType(type);
if(threadId) { if(options.threadId) {
chat.threadId = threadId; chat.threadId = options.threadId;
} }
} }
@ -1482,11 +1532,14 @@ export class AppImManager {
//this.chatsSelectTab(chat.container); //this.chatsSelectTab(chat.container);
return this.setPeer(peerId, lastMsgId); return this.setPeer(options);
} }
public openScheduled(peerId: PeerId) { public openScheduled(peerId: PeerId) {
this.setInnerPeer(peerId, undefined, 'scheduled'); this.setInnerPeer({
peerId,
type: 'scheduled'
});
} }
private getTypingElement(action: SendMessageAction) { private getTypingElement(action: SendMessageAction) {

20
src/lib/appManagers/appMessagesManager.ts

@ -2357,8 +2357,8 @@ export class AppMessagesManager {
//return Object.keys(this.groupedMessagesStorage[grouped_id]).map(id => +id).sort((a, b) => a - b); //return Object.keys(this.groupedMessagesStorage[grouped_id]).map(id => +id).sort((a, b) => a - b);
} }
public getMidsByMessage(message: Message.message) { public getMidsByMessage(message: Message) {
if(message?.grouped_id) return this.getMidsByAlbum(message.grouped_id); if((message as Message.message)?.grouped_id) return this.getMidsByAlbum((message as Message.message).grouped_id);
else return [message.mid]; else return [message.mid];
} }
@ -2949,7 +2949,7 @@ export class AppMessagesManager {
fromMe ? fromMe ?
i18n('FromYou') : i18n('FromYou') :
new PeerTitle({ new PeerTitle({
peerId: message.fromId, ...this.getMessageSenderPeerIdOrName(message),
dialog: message.peerId === rootScope.myId dialog: message.peerId === rootScope.myId
}).element }).element
); );
@ -2962,6 +2962,18 @@ export class AppMessagesManager {
return senderTitle; return senderTitle;
} }
public getMessageSenderPeerIdOrName(message: MyMessage) {
if(message.fromId) {
return {
peerId: message.fromId
};
} else {
return {
fromName: (message as Message.message).fwd_from?.from_name
};
}
}
public wrapSentTime(message: MyMessage) { public wrapSentTime(message: MyMessage) {
const el: HTMLElement = document.createElement('span'); const el: HTMLElement = document.createElement('span');
el.classList.add('sent-time'); el.classList.add('sent-time');
@ -3844,7 +3856,7 @@ export class AppMessagesManager {
this.getDiscussionMessage(peerId, mid); this.getDiscussionMessage(peerId, mid);
} }
public generateThreadServiceStartMessage(message: Message.message) { public generateThreadServiceStartMessage(message: Message.message | Message.messageService) {
const threadKey = message.peerId + '_' + message.mid; const threadKey = message.peerId + '_' + message.mid;
if(this.threadsServiceMessagesIdsStorage[threadKey]) return; if(this.threadsServiceMessagesIdsStorage[threadKey]) return;

3
src/lib/appManagers/internalLink.ts

@ -19,7 +19,8 @@ export namespace InternalLink {
_: INTERNAL_LINK_TYPE.MESSAGE, _: INTERNAL_LINK_TYPE.MESSAGE,
domain: string, domain: string,
post?: string, post?: string,
comment?: string comment?: string,
start?: string
} }
export interface InternalLinkPrivatePost { export interface InternalLinkPrivatePost {

Loading…
Cancel
Save