Fix jumping scroll again
This commit is contained in:
parent
a7f5bae92a
commit
97d645f1ea
@ -40,20 +40,31 @@ for(const name of Object.keys(nets)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const useHttp = false;
|
const useHttp = false;
|
||||||
const server = useHttp ? http : https;
|
const transport = useHttp ? http : https;
|
||||||
let options = {};
|
let options = {};
|
||||||
if(!useHttp) {
|
if(!useHttp) {
|
||||||
options.key = fs.readFileSync(__dirname + '/certs/server-key.pem');
|
options.key = fs.readFileSync(__dirname + '/certs/server-key.pem');
|
||||||
options.cert = fs.readFileSync(__dirname + '/certs/server-cert.pem');
|
options.cert = fs.readFileSync(__dirname + '/certs/server-cert.pem');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(results);
|
||||||
|
|
||||||
const port = 3000;
|
const port = 3000;
|
||||||
const protocol = useHttp ? 'http' : 'https';
|
const protocol = useHttp ? 'http' : 'https';
|
||||||
console.log('Listening port:', port);
|
console.log('Listening port:', port);
|
||||||
function createServer(host) {
|
function createServer(host) {
|
||||||
server.createServer(options, app).listen(port, host, () => {
|
const server = transport.createServer(options, app);
|
||||||
|
server.listen(port, host, () => {
|
||||||
console.log('Host:', `${protocol}://${host || 'localhost'}:${port}/`);
|
console.log('Host:', `${protocol}://${host || 'localhost'}:${port}/`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.on('error', (e) => {
|
||||||
|
// @ts-ignore
|
||||||
|
if(e.code === 'EADDRINUSE') {
|
||||||
|
console.log('Address in use:', host);
|
||||||
|
server.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const name in results) {
|
for(const name in results) {
|
||||||
|
@ -47,14 +47,24 @@ export class AnimationIntersector {
|
|||||||
if(entry.isIntersecting) {
|
if(entry.isIntersecting) {
|
||||||
this.visible.add(player);
|
this.visible.add(player);
|
||||||
this.checkAnimation(player, false);
|
this.checkAnimation(player, false);
|
||||||
|
|
||||||
|
/* if(animation instanceof HTMLVideoElement && animation.dataset.src) {
|
||||||
|
animation.src = animation.dataset.src;
|
||||||
|
animation.load();
|
||||||
|
} */
|
||||||
} else {
|
} else {
|
||||||
this.visible.delete(player);
|
this.visible.delete(player);
|
||||||
this.checkAnimation(player, true);
|
this.checkAnimation(player, true);
|
||||||
|
|
||||||
if(player.animation instanceof RLottiePlayer/* && player.animation.cachingDelta === 2 */) {
|
const animation = player.animation;
|
||||||
|
if(animation instanceof RLottiePlayer/* && animation.cachingDelta === 2 */) {
|
||||||
//console.warn('will clear cache', player);
|
//console.warn('will clear cache', player);
|
||||||
player.animation.clearCache();
|
animation.clearCache();
|
||||||
}
|
}/* else if(animation instanceof HTMLVideoElement && animation.src) {
|
||||||
|
animation.dataset.src = animation.src;
|
||||||
|
animation.src = '';
|
||||||
|
animation.load();
|
||||||
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -208,8 +208,6 @@ export default class ChatBubbles {
|
|||||||
private hoverBubble: HTMLElement;
|
private hoverBubble: HTMLElement;
|
||||||
private hoverReaction: HTMLElement;
|
private hoverReaction: HTMLElement;
|
||||||
|
|
||||||
private onUpdateScrollSaver: ScrollSaver;
|
|
||||||
|
|
||||||
// private reactions: Map<number, ReactionsElement>;
|
// private reactions: Map<number, ReactionsElement>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -431,8 +429,10 @@ export default class ChatBubbles {
|
|||||||
|
|
||||||
const updatePosition = this.chat.type === 'scheduled';
|
const updatePosition = this.chat.type === 'scheduled';
|
||||||
|
|
||||||
this.saveOnUpdateScroll();
|
const scrollSaver = new ScrollSaver(this.scrollable, true);
|
||||||
|
scrollSaver.save();
|
||||||
this.safeRenderMessage(mounted.message, true, false, mounted.bubble, updatePosition);
|
this.safeRenderMessage(mounted.message, true, false, mounted.bubble, updatePosition);
|
||||||
|
scrollSaver.restore();
|
||||||
|
|
||||||
if(updatePosition) {
|
if(updatePosition) {
|
||||||
(this.messagesQueuePromise || Promise.resolve()).then(() => {
|
(this.messagesQueuePromise || Promise.resolve()).then(() => {
|
||||||
@ -461,43 +461,41 @@ export default class ChatBubbles {
|
|||||||
this.appendReactionsElementToBubble(bubble, message, changedResults);
|
this.appendReactionsElementToBubble(bubble, message, changedResults);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.listenerSetter.add(rootScope)('message_reactions', ({message, changedResults}) => {
|
this.listenerSetter.add(rootScope)('messages_reactions', (arr) => {
|
||||||
if(this.peerId !== message.peerId) {
|
let scrollSaver: ScrollSaver;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bubble = this.getBubbleByMessage(message);
|
for(const {message, changedResults} of arr) {
|
||||||
if(!bubble) {
|
if(this.peerId !== message.peerId) {
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
this.saveOnUpdateScroll();
|
|
||||||
|
|
||||||
const key = message.peerId + '_' + message.mid;
|
|
||||||
const set = REACTIONS_ELEMENTS.get(key);
|
|
||||||
if(set) {
|
|
||||||
for(const element of set) {
|
|
||||||
element.update(message, changedResults);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
rootScope.dispatchEvent('missed_reactions_element', {message, changedResults});
|
const bubble = this.getBubbleByMessage(message);
|
||||||
|
if(!bubble) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!scrollSaver) {
|
||||||
|
scrollSaver = new ScrollSaver(this.scrollable, true);
|
||||||
|
scrollSaver.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
const key = message.peerId + '_' + message.mid;
|
||||||
|
const set = REACTIONS_ELEMENTS.get(key);
|
||||||
|
if(set) {
|
||||||
|
for(const element of set) {
|
||||||
|
element.update(message, changedResults);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rootScope.dispatchEvent('missed_reactions_element', {message, changedResults});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(scrollSaver) {
|
||||||
|
scrollSaver.restore();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this.listenerSetter.add(rootScope)('message_reactions', ({peerId, mid}) => {
|
|
||||||
if(this.peerId !== peerId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const reactionsElement = this.reactions.get(mid);
|
|
||||||
if(!reactionsElement) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}); */
|
|
||||||
|
|
||||||
this.listenerSetter.add(rootScope)('album_edit', ({peerId, groupId, deletedMids}) => {
|
this.listenerSetter.add(rootScope)('album_edit', ({peerId, groupId, deletedMids}) => {
|
||||||
//fastRaf(() => { // ! can't use delayed smth here, need original bubble to be edited
|
//fastRaf(() => { // ! can't use delayed smth here, need original bubble to be edited
|
||||||
if(peerId !== this.peerId) return;
|
if(peerId !== this.peerId) return;
|
||||||
@ -767,24 +765,35 @@ export default class ChatBubbles {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.listenerSetter.add(rootScope)('message_views', ({peerId, views, mid}) => {
|
this.listenerSetter.add(rootScope)('messages_views', (arr) => {
|
||||||
if(this.peerId !== peerId) return;
|
|
||||||
|
|
||||||
fastRaf(() => {
|
fastRaf(() => {
|
||||||
const bubble = this.bubbles[mid];
|
let scrollSaver: ScrollSaver;
|
||||||
if(!bubble) return;
|
for(const {peerId, views, mid} of arr) {
|
||||||
|
if(this.peerId !== peerId) return;
|
||||||
|
|
||||||
const postViewsElements = Array.from(bubble.querySelectorAll('.post-views')) as HTMLElement[];
|
const bubble = this.bubbles[mid];
|
||||||
if(postViewsElements.length) {
|
if(!bubble) return;
|
||||||
const str = formatNumber(views, 1);
|
|
||||||
let different = false;
|
const postViewsElements = Array.from(bubble.querySelectorAll('.post-views')) as HTMLElement[];
|
||||||
postViewsElements.forEach(postViews => {
|
if(postViewsElements.length) {
|
||||||
if(different || postViews.innerHTML !== str) {
|
const str = formatNumber(views, 1);
|
||||||
this.saveOnUpdateScroll();
|
let different = false;
|
||||||
different = true;
|
postViewsElements.forEach(postViews => {
|
||||||
postViews.innerHTML = str;
|
if(different || postViews.innerHTML !== str) {
|
||||||
}
|
if(!scrollSaver) {
|
||||||
});
|
scrollSaver = new ScrollSaver(this.scrollable, true);
|
||||||
|
scrollSaver.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
different = true;
|
||||||
|
postViews.innerHTML = str;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(scrollSaver) {
|
||||||
|
scrollSaver.restore();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -928,18 +937,6 @@ export default class ChatBubbles {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private saveOnUpdateScroll() {
|
|
||||||
if(!this.onUpdateScrollSaver) {
|
|
||||||
this.onUpdateScrollSaver = new ScrollSaver(this.scrollable, true);
|
|
||||||
setTimeout(() => {
|
|
||||||
this.onUpdateScrollSaver.restore();
|
|
||||||
this.onUpdateScrollSaver = undefined;
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
this.onUpdateScrollSaver.save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private onBubblesMouseMove = (e: MouseEvent) => {
|
private onBubblesMouseMove = (e: MouseEvent) => {
|
||||||
const content = findUpClassName(e.target, 'bubble-content');
|
const content = findUpClassName(e.target, 'bubble-content');
|
||||||
if(content && !this.chat.selection.isSelecting) {
|
if(content && !this.chat.selection.isSelecting) {
|
||||||
@ -1048,6 +1045,8 @@ export default class ChatBubbles {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public setStickyDateManually() {
|
public setStickyDateManually() {
|
||||||
|
// return;
|
||||||
|
|
||||||
const timestamps = Object.keys(this.dateMessages).map(k => +k).sort((a, b) => b - a);
|
const timestamps = Object.keys(this.dateMessages).map(k => +k).sort((a, b) => b - a);
|
||||||
let lastVisible: HTMLElement;
|
let lastVisible: HTMLElement;
|
||||||
|
|
||||||
@ -1716,7 +1715,7 @@ export default class ChatBubbles {
|
|||||||
//lottieLoader.checkAnimations(false, 'chat');
|
//lottieLoader.checkAnimations(false, 'chat');
|
||||||
|
|
||||||
const distanceToEnd = this.scrollable.getDistanceToEnd();
|
const distanceToEnd = this.scrollable.getDistanceToEnd();
|
||||||
if(!IS_TOUCH_SUPPORTED && this.scrollable.lastScrollDirection !== 0 && distanceToEnd > 0) {
|
if(/* !IS_TOUCH_SUPPORTED && */this.scrollable.lastScrollDirection !== 0 && distanceToEnd > 0) {
|
||||||
if(this.isScrollingTimeout) {
|
if(this.isScrollingTimeout) {
|
||||||
clearTimeout(this.isScrollingTimeout);
|
clearTimeout(this.isScrollingTimeout);
|
||||||
} else if(!this.chatInner.classList.contains('is-scrolling')) {
|
} else if(!this.chatInner.classList.contains('is-scrolling')) {
|
||||||
@ -1767,7 +1766,7 @@ export default class ChatBubbles {
|
|||||||
this.scrollable.onScrolledBottom = () => this.loadMoreHistory(false);
|
this.scrollable.onScrolledBottom = () => this.loadMoreHistory(false);
|
||||||
//this.scrollable.attachSentinels(undefined, 300);
|
//this.scrollable.attachSentinels(undefined, 300);
|
||||||
|
|
||||||
if(IS_TOUCH_SUPPORTED) {
|
if(IS_TOUCH_SUPPORTED && false) {
|
||||||
this.scrollable.container.addEventListener('touchmove', () => {
|
this.scrollable.container.addEventListener('touchmove', () => {
|
||||||
if(this.isScrollingTimeout) {
|
if(this.isScrollingTimeout) {
|
||||||
clearTimeout(this.isScrollingTimeout);
|
clearTimeout(this.isScrollingTimeout);
|
||||||
@ -3782,7 +3781,7 @@ export default class ChatBubbles {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private appendReactionsElementToBubble(bubble: HTMLElement, message: Message.message, changedResults?: ReactionCount[]) {
|
private appendReactionsElementToBubble(bubble: HTMLElement, message: Message.message, changedResults?: ReactionCount[]) {
|
||||||
if(this.peerId.isUser()) {
|
if(this.peerId.isUser()/* || true */) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,7 +343,7 @@ export default class ChatPinnedMessage {
|
|||||||
|
|
||||||
public setCorrectIndex(lastScrollDirection?: number) {
|
public setCorrectIndex(lastScrollDirection?: number) {
|
||||||
if(this.isStatic) return;
|
if(this.isStatic) return;
|
||||||
//return;
|
// return;
|
||||||
|
|
||||||
if(this.locked || this.hidden/* || this.chat.setPeerPromise || this.chat.bubbles.messagesQueuePromise */) {
|
if(this.locked || this.hidden/* || this.chat.setPeerPromise || this.chat.bubbles.messagesQueuePromise */) {
|
||||||
return;
|
return;
|
||||||
|
@ -451,13 +451,23 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
|||||||
});
|
});
|
||||||
|
|
||||||
if(doc.type === 'video') {
|
if(doc.type === 'video') {
|
||||||
video.addEventListener('timeupdate', () => {
|
const onTimeUpdate = () => {
|
||||||
|
if(!video.videoWidth) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
spanTime.innerText = toHHMMSS(video.duration - video.currentTime, false);
|
spanTime.innerText = toHHMMSS(video.duration - video.currentTime, false);
|
||||||
});
|
};
|
||||||
|
|
||||||
|
const throttledTimeUpdate = throttleWithRaf(onTimeUpdate);
|
||||||
|
|
||||||
|
video.addEventListener('timeupdate', throttledTimeUpdate);
|
||||||
|
|
||||||
if(spanPlay) {
|
if(spanPlay) {
|
||||||
video.addEventListener('timeupdate', () => {
|
video.addEventListener('timeupdate', () => {
|
||||||
spanPlay.remove();
|
sequentialDom.mutateElement(spanPlay, () => {
|
||||||
|
spanPlay.remove();
|
||||||
|
});
|
||||||
}, {once: true});
|
}, {once: true});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { MOUNT_CLASS_TO } from "../../config/debug";
|
||||||
import { renderImageFromUrlPromise } from "../../helpers/dom/renderImageFromUrl";
|
import { renderImageFromUrlPromise } from "../../helpers/dom/renderImageFromUrl";
|
||||||
import replaceContent from "../../helpers/dom/replaceContent";
|
import replaceContent from "../../helpers/dom/replaceContent";
|
||||||
import sequentialDom from "../../helpers/sequentialDom";
|
import sequentialDom from "../../helpers/sequentialDom";
|
||||||
@ -220,4 +221,5 @@ export class AppAvatarsManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const appAvatarsManager = new AppAvatarsManager();
|
const appAvatarsManager = new AppAvatarsManager();
|
||||||
|
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.appAvatarsManager = appAvatarsManager);
|
||||||
export default appAvatarsManager;
|
export default appAvatarsManager;
|
||||||
|
@ -15,8 +15,8 @@ import { CancellablePromise, deferredPromise } from "../../helpers/cancellablePr
|
|||||||
import { formatDateAccordingToTodayNew, formatTime, tsNow } from "../../helpers/date";
|
import { formatDateAccordingToTodayNew, formatTime, tsNow } from "../../helpers/date";
|
||||||
import { createPosterForVideo } from "../../helpers/files";
|
import { createPosterForVideo } from "../../helpers/files";
|
||||||
import { randomLong } from "../../helpers/random";
|
import { randomLong } from "../../helpers/random";
|
||||||
import { Chat, ChatFull, Dialog as MTDialog, DialogPeer, DocumentAttribute, InputMedia, InputMessage, InputPeerNotifySettings, InputSingleMedia, Message, MessageAction, MessageEntity, MessageFwdHeader, MessageMedia, MessageReplies, MessageReplyHeader, MessagesDialogs, MessagesFilter, MessagesMessages, MethodDeclMap, NotifyPeer, PeerNotifySettings, PhotoSize, SendMessageAction, Update, Photo, Updates, ReplyMarkup, InputPeer, InputPhoto, InputDocument, InputGeoPoint, WebPage, GeoPoint, ReportReason, MessagesGetDialogs, InputChannel, InputDialogPeer, ReactionCount, MessagePeerReaction, MessagesSearchCounter, Peer } from "../../layer";
|
import { Chat, ChatFull, Dialog as MTDialog, DialogPeer, DocumentAttribute, InputMedia, InputMessage, InputPeerNotifySettings, InputSingleMedia, Message, MessageAction, MessageEntity, MessageFwdHeader, MessageMedia, MessageReplies, MessageReplyHeader, MessagesDialogs, MessagesFilter, MessagesMessages, MethodDeclMap, NotifyPeer, PeerNotifySettings, PhotoSize, SendMessageAction, Update, Photo, Updates, ReplyMarkup, InputPeer, InputPhoto, InputDocument, InputGeoPoint, WebPage, GeoPoint, ReportReason, MessagesGetDialogs, InputChannel, InputDialogPeer, ReactionCount, MessagePeerReaction, MessagesSearchCounter, Peer, MessageReactions } from "../../layer";
|
||||||
import { InvokeApiOptions } from "../../types";
|
import { ArgumentTypes, InvokeApiOptions } from "../../types";
|
||||||
import I18n, { FormatterArguments, i18n, join, langPack, LangPackKey, UNSUPPORTED_LANG_PACK_KEY, _i18n } from "../langPack";
|
import I18n, { FormatterArguments, i18n, join, langPack, LangPackKey, UNSUPPORTED_LANG_PACK_KEY, _i18n } from "../langPack";
|
||||||
import { logger, LogTypes } from "../logger";
|
import { logger, LogTypes } from "../logger";
|
||||||
import type { ApiFileManager } from '../mtproto/apiFileManager';
|
import type { ApiFileManager } from '../mtproto/apiFileManager';
|
||||||
@ -70,6 +70,7 @@ import deepEqual from "../../helpers/object/deepEqual";
|
|||||||
import escapeRegExp from "../../helpers/string/escapeRegExp";
|
import escapeRegExp from "../../helpers/string/escapeRegExp";
|
||||||
import limitSymbols from "../../helpers/string/limitSymbols";
|
import limitSymbols from "../../helpers/string/limitSymbols";
|
||||||
import splitStringByLength from "../../helpers/string/splitStringByLength";
|
import splitStringByLength from "../../helpers/string/splitStringByLength";
|
||||||
|
import debounce from "../../helpers/schedulers/debounce";
|
||||||
|
|
||||||
//console.trace('include');
|
//console.trace('include');
|
||||||
// TODO: если удалить диалог находясь в папке, то он не удалится из папки и будет виден в настройках
|
// TODO: если удалить диалог находясь в папке, то он не удалится из папки и будет виден в настройках
|
||||||
@ -128,6 +129,13 @@ type PendingAfterMsg = Partial<InvokeApiOptions & {
|
|||||||
messageId: string
|
messageId: string
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
type MapValueType<A> = A extends Map<any, infer V> ? V : never;
|
||||||
|
|
||||||
|
export type BatchUpdates = {
|
||||||
|
'messages_reactions': AppMessagesManager['batchUpdateReactions'],
|
||||||
|
'messages_views': AppMessagesManager['batchUpdateViews']
|
||||||
|
};
|
||||||
|
|
||||||
export class AppMessagesManager {
|
export class AppMessagesManager {
|
||||||
private messagesStorageByPeerId: {[peerId: string]: MessagesStorage};
|
private messagesStorageByPeerId: {[peerId: string]: MessagesStorage};
|
||||||
public groupedMessagesStorage: {[groupId: string]: MessagesStorage}; // will be used for albums
|
public groupedMessagesStorage: {[groupId: string]: MessagesStorage}; // will be used for albums
|
||||||
@ -214,6 +222,14 @@ export class AppMessagesManager {
|
|||||||
|
|
||||||
private unreadMentions: {[peerId: PeerId]: SlicedArray} = {};
|
private unreadMentions: {[peerId: PeerId]: SlicedArray} = {};
|
||||||
private goToNextMentionPromises: {[peerId: PeerId]: Promise<any>} = {};
|
private goToNextMentionPromises: {[peerId: PeerId]: Promise<any>} = {};
|
||||||
|
|
||||||
|
private batchUpdates: {
|
||||||
|
[k in keyof BatchUpdates]?: {
|
||||||
|
callback: BatchUpdates[k],
|
||||||
|
batch: ArgumentTypes<BatchUpdates[k]>[0]
|
||||||
|
}
|
||||||
|
} = {};
|
||||||
|
private batchUpdatesDebounced: () => Promise<void>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.clear();
|
this.clear();
|
||||||
@ -345,6 +361,20 @@ export class AppMessagesManager {
|
|||||||
this.maxSeenId = state.maxSeenMsgId;
|
this.maxSeenId = state.maxSeenMsgId;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.batchUpdatesDebounced = debounce(() => {
|
||||||
|
for(const event in this.batchUpdates) {
|
||||||
|
const details = this.batchUpdates[event as keyof BatchUpdates];
|
||||||
|
delete this.batchUpdates[event as keyof BatchUpdates];
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
const result = details.callback(details.batch);
|
||||||
|
if(result && (!(result instanceof Array) || result.length)) {
|
||||||
|
// @ts-ignore
|
||||||
|
rootScope.dispatchEvent(event as keyof BatchUpdates, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 33, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public clear() {
|
public clear() {
|
||||||
@ -4700,26 +4730,10 @@ export class AppMessagesManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const results = reactions?.results ?? [];
|
|
||||||
const previousResults = message.reactions?.results ?? [];
|
|
||||||
const changedResults = results.filter(reactionCount => {
|
|
||||||
const previousReactionCount = previousResults.find(_reactionCount => _reactionCount.reaction === reactionCount.reaction);
|
|
||||||
return (
|
|
||||||
message.pFlags.out && (
|
|
||||||
!previousReactionCount ||
|
|
||||||
reactionCount.count > previousReactionCount.count
|
|
||||||
)
|
|
||||||
) || (
|
|
||||||
reactionCount.pFlags.chosen && (
|
|
||||||
!previousReactionCount ||
|
|
||||||
!previousReactionCount.pFlags.chosen
|
|
||||||
)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
message.reactions = reactions;
|
message.reactions = reactions;
|
||||||
|
|
||||||
rootScope.dispatchEvent('message_reactions', {message, changedResults});
|
const key = message.peerId + '_' + message.mid;
|
||||||
|
this.pushBatchUpdate('messages_reactions', this.batchUpdateReactions, key, () => copy(message.reactions));
|
||||||
|
|
||||||
if(!update.local) {
|
if(!update.local) {
|
||||||
this.setDialogToStateIfMessageIsTop(message);
|
this.setDialogToStateIfMessageIsTop(message);
|
||||||
@ -5094,7 +5108,7 @@ export class AppMessagesManager {
|
|||||||
const message: Message.message = this.getMessageByPeer(peerId, mid);
|
const message: Message.message = this.getMessageByPeer(peerId, mid);
|
||||||
if(!message.deleted && message.views !== undefined && message.views < views) {
|
if(!message.deleted && message.views !== undefined && message.views < views) {
|
||||||
message.views = views;
|
message.views = views;
|
||||||
rootScope.dispatchEvent('message_views', {peerId, mid, views});
|
this.pushBatchUpdate('messages_views', this.batchUpdateViews, message.peerId + '_' + message.mid);
|
||||||
this.setDialogToStateIfMessageIsTop(message);
|
this.setDialogToStateIfMessageIsTop(message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -6283,6 +6297,86 @@ export class AppMessagesManager {
|
|||||||
public canForward(message: Message.message | Message.messageService) {
|
public canForward(message: Message.message | Message.messageService) {
|
||||||
return !(message as Message.message).pFlags.noforwards && !appPeersManager.noForwards(message.peerId);
|
return !(message as Message.message).pFlags.noforwards && !appPeersManager.noForwards(message.peerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private pushBatchUpdate<E extends keyof BatchUpdates, C extends BatchUpdates[E]>(
|
||||||
|
event: E,
|
||||||
|
callback: C,
|
||||||
|
key: string,
|
||||||
|
getElementCallback?: () => MapValueType<ArgumentTypes<C>[0]>
|
||||||
|
) {
|
||||||
|
let details = this.batchUpdates[event];
|
||||||
|
if(!details) {
|
||||||
|
// @ts-ignore
|
||||||
|
details = this.batchUpdates[event] = {
|
||||||
|
callback,
|
||||||
|
batch: new Map()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!details.batch.has(key)) {
|
||||||
|
// @ts-ignore
|
||||||
|
details.batch.set(key, getElementCallback ? getElementCallback() : undefined);
|
||||||
|
this.batchUpdatesDebounced();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getMessagesFromMap<T extends Map<any, any>>(map: T) {
|
||||||
|
const newMap: Map<Message.message, MapValueType<T>> = new Map();
|
||||||
|
for(const [key, value] of map) {
|
||||||
|
const [peerIdStr, mid] = key.split('_');
|
||||||
|
const message: Message.message | Message.messageEmpty = this.getMessageByPeer(peerIdStr.toPeerId(), +mid);
|
||||||
|
if(message._ === 'messageEmpty') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
newMap.set(message, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private batchUpdateViews = (batch: Map<string, undefined>) => {
|
||||||
|
const toDispatch: {peerId: PeerId, mid: number, views: number}[] = [];
|
||||||
|
|
||||||
|
const map = this.getMessagesFromMap(batch);
|
||||||
|
for(const [message] of map) {
|
||||||
|
toDispatch.push({
|
||||||
|
peerId: message.peerId,
|
||||||
|
mid: message.mid,
|
||||||
|
views: message.views
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return toDispatch;
|
||||||
|
};
|
||||||
|
|
||||||
|
private batchUpdateReactions = (batch: Map<string, MessageReactions>) => {
|
||||||
|
const toDispatch: {message: Message.message, changedResults: ReactionCount.reactionCount[]}[] = [];
|
||||||
|
|
||||||
|
const map = this.getMessagesFromMap(batch);
|
||||||
|
for(const [message, reactions] of map) {
|
||||||
|
const results = reactions?.results ?? [];
|
||||||
|
const previousResults = message.reactions?.results ?? [];
|
||||||
|
const changedResults = results.filter(reactionCount => {
|
||||||
|
const previousReactionCount = previousResults.find(_reactionCount => _reactionCount.reaction === reactionCount.reaction);
|
||||||
|
return (
|
||||||
|
message.pFlags.out && (
|
||||||
|
!previousReactionCount ||
|
||||||
|
reactionCount.count > previousReactionCount.count
|
||||||
|
)
|
||||||
|
) || (
|
||||||
|
reactionCount.pFlags.chosen && (
|
||||||
|
!previousReactionCount ||
|
||||||
|
!previousReactionCount.pFlags.chosen
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
toDispatch.push({message, changedResults});
|
||||||
|
}
|
||||||
|
|
||||||
|
return toDispatch;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const appMessagesManager = new AppMessagesManager();
|
const appMessagesManager = new AppMessagesManager();
|
||||||
|
@ -320,7 +320,7 @@ export class AppReactionsManager {
|
|||||||
|
|
||||||
if(onlyLocal) {
|
if(onlyLocal) {
|
||||||
message.reactions = reactions;
|
message.reactions = reactions;
|
||||||
rootScope.dispatchEvent('message_reactions', {message, changedResults: []});
|
rootScope.dispatchEvent('messages_reactions', [{message, changedResults: []}]);
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,9 +76,9 @@ export type BroadcastEvents = {
|
|||||||
//'history_request': void,
|
//'history_request': void,
|
||||||
|
|
||||||
'message_edit': {storage: MessagesStorage, peerId: PeerId, mid: number},
|
'message_edit': {storage: MessagesStorage, peerId: PeerId, mid: number},
|
||||||
'message_views': {peerId: PeerId, mid: number, views: number},
|
|
||||||
'message_sent': {storage: MessagesStorage, tempId: number, tempMessage: any, mid: number, message: MyMessage},
|
'message_sent': {storage: MessagesStorage, tempId: number, tempMessage: any, mid: number, message: MyMessage},
|
||||||
'message_reactions': {message: Message.message, changedResults: ReactionCount[]},
|
'messages_views': {peerId: PeerId, mid: number, views: number}[],
|
||||||
|
'messages_reactions': {message: Message.message, changedResults: ReactionCount[]}[],
|
||||||
'messages_pending': void,
|
'messages_pending': void,
|
||||||
'messages_read': void,
|
'messages_read': void,
|
||||||
'messages_downloaded': {peerId: PeerId, mids: number[]},
|
'messages_downloaded': {peerId: PeerId, mids: number[]},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user