some fixes
This commit is contained in:
parent
df814f2a68
commit
5aa64caecc
@ -112,6 +112,7 @@ import paymentsWrapCurrencyAmount from '../../helpers/paymentsWrapCurrencyAmount
|
||||
import PopupPayment from '../popups/payment';
|
||||
import isInDOM from '../../helpers/dom/isInDOM';
|
||||
import getStickerEffectThumb from '../../lib/appManagers/utils/stickers/getStickerEffectThumb';
|
||||
import attachStickerViewerListeners from '../stickerViewer';
|
||||
|
||||
const USE_MEDIA_TAILS = false;
|
||||
const IGNORE_ACTIONS: Set<Message.messageService['action']['_']> = new Set([
|
||||
@ -667,6 +668,7 @@ export default class ChatBubbles {
|
||||
});
|
||||
});
|
||||
|
||||
attachStickerViewerListeners({listenTo: this.scrollable.container, listenerSetter: this.listenerSetter});
|
||||
attachClickEvent(this.scrollable.container, this.onBubblesClick, {listenerSetter: this.listenerSetter});
|
||||
// this.listenerSetter.add(this.bubblesContainer)('click', this.onBubblesClick/* , {capture: true, passive: false} */);
|
||||
|
||||
@ -902,7 +904,7 @@ export default class ChatBubbles {
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope)('dialogs_multiupdate', (dialogs) => {
|
||||
if(dialogs[this.peerId]) {
|
||||
if(dialogs.has(this.peerId)) {
|
||||
this.chat.input.setUnreadCount();
|
||||
}
|
||||
});
|
||||
|
@ -735,7 +735,7 @@ export default class ChatInput {
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope)('dialogs_multiupdate', (dialogs) => {
|
||||
if(dialogs[this.chat.peerId]) {
|
||||
if(dialogs.has(this.chat.peerId)) {
|
||||
if(this.startParam === BOT_START_PARAM) {
|
||||
this.setStartParam();
|
||||
} else { // updateNewMessage comes earlier than dialog appers
|
||||
|
@ -105,6 +105,7 @@ export class ChatReactionsMenu {
|
||||
callbackify(result, (reactions) => {
|
||||
if(!middleware() || !reactions.length) return;
|
||||
reactions.forEach((reaction) => {
|
||||
if(reaction.pFlags.premium && !rootScope.premium) return;
|
||||
this.renderReaction(reaction);
|
||||
});
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import ListenerSetter from '../../helpers/listenerSetter';
|
||||
import mediaSizes from '../../helpers/mediaSizes';
|
||||
import preloadAnimatedEmojiSticker from '../../helpers/preloadAnimatedEmojiSticker';
|
||||
import {MyDocument} from '../../lib/appManagers/appDocsManager';
|
||||
@ -14,6 +15,7 @@ import {EmoticonsDropdown} from '../emoticonsDropdown';
|
||||
import {SuperStickerRenderer} from '../emoticonsDropdown/tabs/stickers';
|
||||
import LazyLoadQueue from '../lazyLoadQueue';
|
||||
import Scrollable from '../scrollable';
|
||||
import attachStickerViewerListeners from '../stickerViewer';
|
||||
import AutocompleteHelper from './autocompleteHelper';
|
||||
import AutocompleteHelperController from './autocompleteHelperController';
|
||||
|
||||
@ -22,6 +24,7 @@ export default class StickersHelper extends AutocompleteHelper {
|
||||
private superStickerRenderer: SuperStickerRenderer;
|
||||
private lazyLoadQueue: LazyLoadQueue;
|
||||
private onChangeScreen: () => void;
|
||||
private listenerSetter: ListenerSetter;
|
||||
|
||||
constructor(
|
||||
appendTo: HTMLElement,
|
||||
@ -52,6 +55,9 @@ export default class StickersHelper extends AutocompleteHelper {
|
||||
if(this.onChangeScreen) {
|
||||
mediaSizes.removeEventListener('changeScreen', this.onChangeScreen);
|
||||
this.onChangeScreen = undefined;
|
||||
|
||||
this.listenerSetter.removeAll();
|
||||
this.listenerSetter = undefined;
|
||||
}
|
||||
|
||||
rootScope.dispatchEvent('choosing_sticker', false);
|
||||
@ -105,6 +111,9 @@ export default class StickersHelper extends AutocompleteHelper {
|
||||
this.list.style.width = width + 'px';
|
||||
};
|
||||
mediaSizes.addEventListener('changeScreen', this.onChangeScreen);
|
||||
|
||||
this.listenerSetter = new ListenerSetter();
|
||||
attachStickerViewerListeners({listenTo: this.container, listenerSetter: this.listenerSetter});
|
||||
}
|
||||
|
||||
this.onChangeScreen();
|
||||
|
@ -32,6 +32,8 @@ import createStickersContextMenu from '../../../helpers/dom/createStickersContex
|
||||
import findUpAsChild from '../../../helpers/dom/findUpAsChild';
|
||||
import forEachReverse from '../../../helpers/array/forEachReverse';
|
||||
import {MTAppConfig} from '../../../lib/mtproto/appConfig';
|
||||
import attachStickerViewerListeners from '../../stickerViewer';
|
||||
import ListenerSetter from '../../../helpers/listenerSetter';
|
||||
|
||||
export class SuperStickerRenderer {
|
||||
public lazyLoadQueue: LazyLoadQueueRepeat;
|
||||
@ -567,6 +569,8 @@ export default class StickersTab implements EmoticonsTab {
|
||||
|
||||
emoticonsDropdown.addEventListener('opened', resizeCategories);
|
||||
|
||||
attachStickerViewerListeners({listenTo: this.content, listenerSetter: new ListenerSetter()});
|
||||
|
||||
createStickersContextMenu({
|
||||
listenTo: this.content,
|
||||
verifyRecent: (target) => !!findUpAsChild(target, this.categories['recent'].elements.items),
|
||||
|
@ -21,6 +21,7 @@ import {toastNew} from '../toast';
|
||||
import setInnerHTML from '../../helpers/dom/setInnerHTML';
|
||||
import wrapEmojiText from '../../lib/richTextProcessor/wrapEmojiText';
|
||||
import createStickersContextMenu from '../../helpers/dom/createStickersContextMenu';
|
||||
import attachStickerViewerListeners from '../stickerViewer';
|
||||
|
||||
const ANIMATION_GROUP: AnimationItemGroup = 'STICKERS-POPUP';
|
||||
|
||||
@ -64,6 +65,8 @@ export default class PopupStickers extends PopupElement {
|
||||
isStickerPack: true
|
||||
});
|
||||
|
||||
attachStickerViewerListeners({listenTo: this.stickersDiv, listenerSetter: this.listenerSetter});
|
||||
|
||||
this.loadStickerSet();
|
||||
}
|
||||
|
||||
|
@ -229,15 +229,16 @@ export default class ProgressivePreloader {
|
||||
this.attachPromise(promise);
|
||||
}
|
||||
|
||||
let useRafs = 0;
|
||||
if(this.detached || this.preloader.parentElement !== elem) {
|
||||
const useRafs = isInDOM(this.preloader) ? 1 : 2;
|
||||
useRafs = isInDOM(this.preloader) ? 1 : 2;
|
||||
if(this.preloader.parentElement !== elem) {
|
||||
elem[this.attachMethod](this.preloader);
|
||||
}
|
||||
|
||||
SetTransition(this.preloader, 'is-visible', true, TRANSITION_TIME, undefined, useRafs);
|
||||
}
|
||||
|
||||
SetTransition(this.preloader, 'is-visible', true, TRANSITION_TIME, undefined, useRafs);
|
||||
|
||||
if(this.cancelable && reset) {
|
||||
this.setProgress(0);
|
||||
}
|
||||
@ -253,7 +254,7 @@ export default class ProgressivePreloader {
|
||||
|
||||
// return;
|
||||
|
||||
if(this.preloader && this.preloader.parentElement) {
|
||||
if(this.preloader?.parentElement) {
|
||||
/* setTimeout(() => */// fastRaf(() => {
|
||||
/* if(!this.detached) return;
|
||||
this.detached = true; */
|
||||
|
@ -19,6 +19,7 @@ import {attachClickEvent} from '../../../helpers/dom/clickEvent';
|
||||
import forEachReverse from '../../../helpers/array/forEachReverse';
|
||||
import setInnerHTML from '../../../helpers/dom/setInnerHTML';
|
||||
import wrapEmojiText from '../../../lib/richTextProcessor/wrapEmojiText';
|
||||
import attachStickerViewerListeners from '../../stickerViewer';
|
||||
|
||||
export default class AppStickersTab extends SliderSuperTab {
|
||||
private inputSearch: InputSearch;
|
||||
@ -41,6 +42,8 @@ export default class AppStickersTab extends SliderSuperTab {
|
||||
this.setsDiv.classList.add('sticker-sets');
|
||||
this.scrollable.append(this.setsDiv);
|
||||
|
||||
attachStickerViewerListeners({listenTo: this.setsDiv, listenerSetter: this.listenerSetter});
|
||||
|
||||
attachClickEvent(this.setsDiv, (e) => {
|
||||
const sticker = findUpClassName(e.target, 'sticker-set-sticker');
|
||||
if(sticker) {
|
||||
|
303
src/components/stickerViewer.ts
Normal file
303
src/components/stickerViewer.ts
Normal file
@ -0,0 +1,303 @@
|
||||
/*
|
||||
* https://github.com/morethanwords/tweb
|
||||
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import IS_TOUCH_SUPPORTED from '../environment/touchSupport';
|
||||
import cancelEvent from '../helpers/dom/cancelEvent';
|
||||
import {simulateClickEvent, attachClickEvent} from '../helpers/dom/clickEvent';
|
||||
import findUpClassName from '../helpers/dom/findUpClassName';
|
||||
import getVisibleRect from '../helpers/dom/getVisibleRect';
|
||||
import ListenerSetter from '../helpers/listenerSetter';
|
||||
import {makeMediaSize} from '../helpers/mediaSize';
|
||||
import {getMiddleware} from '../helpers/middleware';
|
||||
import {doubleRaf} from '../helpers/schedulers';
|
||||
import pause from '../helpers/schedulers/pause';
|
||||
import windowSize from '../helpers/windowSize';
|
||||
import {MyDocument} from '../lib/appManagers/appDocsManager';
|
||||
import getStickerEffectThumb from '../lib/appManagers/utils/stickers/getStickerEffectThumb';
|
||||
import wrapEmojiText from '../lib/richTextProcessor/wrapEmojiText';
|
||||
import lottieLoader from '../lib/rlottie/lottieLoader';
|
||||
import RLottiePlayer from '../lib/rlottie/rlottiePlayer';
|
||||
import rootScope from '../lib/rootScope';
|
||||
import animationIntersector, {AnimationItemGroup} from './animationIntersector';
|
||||
import SetTransition from './singleTransition';
|
||||
import {wrapSticker} from './wrappers';
|
||||
import {STICKER_EFFECT_MULTIPLIER} from './wrappers/sticker';
|
||||
|
||||
let hasViewer = false;
|
||||
export default function attachStickerViewerListeners({listenTo, listenerSetter}: {
|
||||
listenerSetter: ListenerSetter,
|
||||
listenTo: HTMLElement
|
||||
}) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
return;
|
||||
}
|
||||
|
||||
const managers = rootScope.managers;
|
||||
const findClassName = 'media-sticker-wrapper';
|
||||
|
||||
listenerSetter.add(listenTo)('mousedown', (e) => {
|
||||
if(hasViewer || e.buttons > 1 || e.button !== 0) return;
|
||||
let mediaContainer = findUpClassName(e.target, findClassName);
|
||||
if(!mediaContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
// const img: HTMLImageElement = mediaContainer.querySelector('img.media-sticker');
|
||||
|
||||
const docId = mediaContainer.dataset.docId;
|
||||
if(!docId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const className = 'sticker-viewer';
|
||||
const group: AnimationItemGroup = 'STICKER-VIEWER';
|
||||
const openDuration = 200;
|
||||
const switchDuration = 200;
|
||||
const previousGroup = animationIntersector.getOnlyOnePlayableGroup();
|
||||
const _middleware = getMiddleware();
|
||||
let container: HTMLElement, previousTransformer: HTMLElement;
|
||||
|
||||
const doThatSticker = async({mediaContainer, doc, middleware, lockGroups, isSwitching}: {
|
||||
mediaContainer: HTMLElement,
|
||||
doc: MyDocument,
|
||||
middleware: () => boolean,
|
||||
lockGroups?: boolean,
|
||||
isSwitching?: boolean
|
||||
}) => {
|
||||
const effectThumb = getStickerEffectThumb(doc);
|
||||
const mediaRect: DOMRect = mediaContainer.getBoundingClientRect();
|
||||
const s = makeMediaSize(doc.w, doc.h);
|
||||
const size = effectThumb ? 280 : 360;
|
||||
const boxSize = makeMediaSize(size, size);
|
||||
const fitted = mediaRect.width === mediaRect.height ? boxSize : s.aspectFitted(boxSize);
|
||||
|
||||
const bubble = findUpClassName(mediaContainer, 'bubble');
|
||||
const isOut = bubble ? bubble.classList.contains('is-out') : true;
|
||||
|
||||
const transformer = document.createElement('div');
|
||||
transformer.classList.add(className + '-transformer');
|
||||
|
||||
const stickerContainer = document.createElement('div');
|
||||
stickerContainer.classList.add(className + '-sticker');
|
||||
/* transformer.style.width = */stickerContainer.style.width = fitted.width + 'px';
|
||||
/* transformer.style.height = */stickerContainer.style.height = fitted.height + 'px';
|
||||
|
||||
const stickerEmoji = document.createElement('div');
|
||||
stickerEmoji.classList.add(className + '-emoji');
|
||||
stickerEmoji.append(wrapEmojiText(doc.stickerEmojiRaw));
|
||||
|
||||
if(effectThumb) {
|
||||
const margin = (size * STICKER_EFFECT_MULTIPLIER - size) / 3 * (isOut ? 1 : -1);
|
||||
transformer.classList.add('has-effect');
|
||||
// const property = `--margin-${isOut ? 'right' : 'left'}`;
|
||||
// stickerContainer.style.setProperty(property, `${margin * 2}px`);
|
||||
transformer.style.setProperty('--translateX', `${margin}px`);
|
||||
stickerEmoji.style.setProperty('--translateX', `${-margin}px`);
|
||||
}
|
||||
|
||||
const overflowElement = findUpClassName(mediaContainer, 'scrollable');
|
||||
const visibleRect = getVisibleRect(mediaContainer, overflowElement, true, mediaRect);
|
||||
if(visibleRect.overflow.vertical || visibleRect.overflow.horizontal) {
|
||||
stickerContainer.classList.add('is-overflow');
|
||||
}
|
||||
|
||||
// if(img) {
|
||||
// const ratio = img.naturalWidth / img.naturalHeight;
|
||||
// if((mediaRect.width / mediaRect.height).toFixed(1) !== ratio.toFixed(1)) {
|
||||
|
||||
// mediaRect = mediaRect.toJSON();
|
||||
// }
|
||||
// }
|
||||
|
||||
const rect = mediaContainer.getBoundingClientRect();
|
||||
const scaleX = rect.width / fitted.width;
|
||||
const scaleY = rect.height / fitted.height;
|
||||
const transformX = rect.left - (windowSize.width - rect.width) / 2;
|
||||
const transformY = rect.top - (windowSize.height - rect.height) / 2;
|
||||
transformer.style.transform = `translate(${transformX}px, ${transformY}px) scale(${scaleX}, ${scaleY})`;
|
||||
if(isSwitching) transformer.classList.add('is-switching');
|
||||
transformer.append(stickerContainer, stickerEmoji);
|
||||
container.append(transformer);
|
||||
|
||||
const player = await wrapSticker({
|
||||
doc,
|
||||
div: stickerContainer,
|
||||
group,
|
||||
width: fitted.width,
|
||||
height: fitted.height,
|
||||
play: false,
|
||||
loop: true,
|
||||
middleware,
|
||||
managers,
|
||||
needFadeIn: false,
|
||||
isOut,
|
||||
withThumb: false,
|
||||
relativeEffect: true,
|
||||
loopEffect: true
|
||||
}).then(({render}) => render);
|
||||
if(!middleware()) return;
|
||||
|
||||
if(!container.parentElement) {
|
||||
document.body.append(container);
|
||||
}
|
||||
|
||||
const firstFramePromise = player instanceof RLottiePlayer ?
|
||||
new Promise<void>((resolve) => player.addEventListener('firstFrame', resolve, {once: true})) :
|
||||
Promise.resolve();
|
||||
await Promise.all([firstFramePromise, doubleRaf()]);
|
||||
await pause(0); // ! need it because firstFrame will be called just from the loop
|
||||
if(!middleware()) return;
|
||||
|
||||
if(lockGroups) {
|
||||
animationIntersector.setOnlyOnePlayableGroup(group);
|
||||
animationIntersector.checkAnimations(true);
|
||||
}
|
||||
|
||||
if(player instanceof RLottiePlayer) {
|
||||
const prevPlayer = lottieLoader.getAnimation(mediaContainer);
|
||||
player.curFrame = prevPlayer.curFrame;
|
||||
player.play();
|
||||
await new Promise<void>((resolve) => {
|
||||
let i = 0;
|
||||
const c = () => {
|
||||
if(++i === 2) {
|
||||
resolve();
|
||||
player.removeEventListener('enterFrame', c);
|
||||
}
|
||||
};
|
||||
|
||||
player.addEventListener('enterFrame', c);
|
||||
});
|
||||
player.pause();
|
||||
} else if(player instanceof HTMLVideoElement) {
|
||||
player.currentTime = (mediaContainer.querySelector('video') as HTMLVideoElement).currentTime;
|
||||
}
|
||||
|
||||
return {
|
||||
ready: () => {
|
||||
if(player instanceof RLottiePlayer || player instanceof HTMLVideoElement) {
|
||||
player.play();
|
||||
}
|
||||
|
||||
if(effectThumb) {
|
||||
simulateClickEvent(stickerContainer);
|
||||
}
|
||||
},
|
||||
transformer
|
||||
};
|
||||
};
|
||||
|
||||
const timeout = window.setTimeout(async() => {
|
||||
document.removeEventListener('mousemove', onMousePreMove);
|
||||
|
||||
container = document.createElement('div');
|
||||
container.classList.add(className);
|
||||
hasViewer = true;
|
||||
|
||||
const middleware = _middleware.get();
|
||||
const doc = await managers.appDocsManager.getDoc(docId);
|
||||
if(!middleware()) return;
|
||||
|
||||
let result: Awaited<ReturnType<typeof doThatSticker>>;
|
||||
try {
|
||||
result = await doThatSticker({
|
||||
doc,
|
||||
mediaContainer,
|
||||
middleware,
|
||||
lockGroups: true
|
||||
});
|
||||
if(!result) return;
|
||||
} catch(err) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {ready, transformer} = result;
|
||||
|
||||
previousTransformer = transformer;
|
||||
|
||||
SetTransition(container, 'is-visible', true, openDuration, () => {
|
||||
if(!middleware()) return;
|
||||
ready();
|
||||
});
|
||||
|
||||
document.addEventListener('mousemove', onMouseMove);
|
||||
}, 125);
|
||||
|
||||
const onMouseMove = async(e: MouseEvent) => {
|
||||
const newMediaContainer = findUpClassName(e.target, 'media-sticker-wrapper');
|
||||
if(!newMediaContainer || mediaContainer === newMediaContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const docId = newMediaContainer.dataset.docId;
|
||||
if(!docId) {
|
||||
return;
|
||||
}
|
||||
|
||||
mediaContainer = newMediaContainer;
|
||||
_middleware.clean();
|
||||
const middleware = _middleware.get();
|
||||
|
||||
const doc = await managers.appDocsManager.getDoc(docId);
|
||||
if(!middleware()) return;
|
||||
|
||||
let r: Awaited<ReturnType<typeof doThatSticker>>;
|
||||
try {
|
||||
r = await doThatSticker({
|
||||
doc,
|
||||
mediaContainer,
|
||||
middleware,
|
||||
isSwitching: true
|
||||
});
|
||||
if(!r) return;
|
||||
} catch(err) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {ready, transformer} = r;
|
||||
|
||||
const _previousTransformer = previousTransformer;
|
||||
SetTransition(_previousTransformer, 'is-switching', true, switchDuration, () => {
|
||||
_previousTransformer.remove();
|
||||
});
|
||||
|
||||
previousTransformer = transformer;
|
||||
|
||||
SetTransition(transformer, 'is-switching', false, switchDuration, () => {
|
||||
if(!middleware()) return;
|
||||
ready();
|
||||
});
|
||||
};
|
||||
|
||||
const onMousePreMove = (e: MouseEvent) => {
|
||||
if(!findUpClassName(e.target, findClassName)) {
|
||||
onMouseUp();
|
||||
}
|
||||
};
|
||||
|
||||
const onMouseUp = () => {
|
||||
clearTimeout(timeout);
|
||||
_middleware.clean();
|
||||
|
||||
if(container) {
|
||||
SetTransition(container, 'is-visible', false, openDuration, () => {
|
||||
container.remove();
|
||||
animationIntersector.setOnlyOnePlayableGroup(previousGroup);
|
||||
animationIntersector.checkAnimations(false);
|
||||
hasViewer = false;
|
||||
});
|
||||
|
||||
attachClickEvent(document.body, cancelEvent, {capture: true, once: true});
|
||||
}
|
||||
|
||||
document.removeEventListener('mousemove', onMousePreMove);
|
||||
document.removeEventListener('mousemove', onMouseMove);
|
||||
};
|
||||
|
||||
document.addEventListener('mousemove', onMousePreMove);
|
||||
document.addEventListener('mouseup', onMouseUp, {once: true});
|
||||
});
|
||||
}
|
@ -199,12 +199,20 @@ export default async function wrapDocument({message, withTime, fontWeight, voice
|
||||
|
||||
let downloadDiv: HTMLElement, preloader: ProgressivePreloader = null;
|
||||
const onLoad = () => {
|
||||
docDiv.classList.remove('downloading');
|
||||
|
||||
if(/* !hasThumb || */(doc.size > MAX_FILE_SAVE_SIZE && !uploadFileName)) {
|
||||
preloader.setManual();
|
||||
preloader.attach(downloadDiv);
|
||||
preloader.preloader.classList.add('manual');
|
||||
preloader.setDownloadFunction(load);
|
||||
return;
|
||||
}
|
||||
|
||||
if(doc.size <= MAX_FILE_SAVE_SIZE) {
|
||||
docDiv.classList.add('downloaded');
|
||||
}
|
||||
|
||||
docDiv.classList.remove('downloading');
|
||||
|
||||
if(downloadDiv) {
|
||||
if(downloadDiv !== icoDiv) {
|
||||
const _downloadDiv = downloadDiv;
|
||||
|
@ -518,8 +518,7 @@ export class AppDialogsManager {
|
||||
});
|
||||
|
||||
rootScope.addEventListener('dialogs_multiupdate', (dialogs) => {
|
||||
for(const peerId in dialogs) {
|
||||
const dialog = dialogs[peerId];
|
||||
for(const [peerId, dialog] of dialogs) {
|
||||
this.updateDialog(dialog);
|
||||
|
||||
if(this.processContact) {
|
||||
|
@ -415,267 +415,6 @@ export class AppImManager extends EventListenerBase<{
|
||||
}, useRafs);
|
||||
};
|
||||
|
||||
let hasViewer = false;
|
||||
!IS_TOUCH_SUPPORTED && document.addEventListener('mousedown', (e) => {
|
||||
if(hasViewer || e.buttons > 1 || e.button !== 0) return;
|
||||
let mediaContainer = findUpClassName(e.target, 'media-sticker-wrapper');
|
||||
if(!mediaContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
// const img: HTMLImageElement = mediaContainer.querySelector('img.media-sticker');
|
||||
|
||||
const docId = mediaContainer.dataset.docId;
|
||||
if(!docId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const className = 'sticker-viewer';
|
||||
const group: AnimationItemGroup = 'STICKER-VIEWER';
|
||||
const openDuration = 200;
|
||||
const switchDuration = 200;
|
||||
const previousGroup = animationIntersector.getOnlyOnePlayableGroup();
|
||||
const _middleware = getMiddleware();
|
||||
let container: HTMLElement, previousTransformer: HTMLElement;
|
||||
|
||||
const doThatSticker = async({mediaContainer, doc, middleware, lockGroups, isSwitching}: {
|
||||
mediaContainer: HTMLElement,
|
||||
doc: MyDocument,
|
||||
middleware: () => boolean,
|
||||
lockGroups?: boolean,
|
||||
isSwitching?: boolean
|
||||
}) => {
|
||||
const effectThumb = getStickerEffectThumb(doc);
|
||||
const mediaRect: DOMRect = mediaContainer.getBoundingClientRect();
|
||||
const s = makeMediaSize(doc.w, doc.h);
|
||||
const size = effectThumb ? 280 : 360;
|
||||
const boxSize = makeMediaSize(size, size);
|
||||
const fitted = mediaRect.width === mediaRect.height ? boxSize : s.aspectFitted(boxSize);
|
||||
|
||||
const bubble = findUpClassName(mediaContainer, 'bubble');
|
||||
const isOut = bubble ? bubble.classList.contains('is-out') : true;
|
||||
|
||||
const transformer = document.createElement('div');
|
||||
transformer.classList.add(className + '-transformer');
|
||||
|
||||
const stickerContainer = document.createElement('div');
|
||||
stickerContainer.classList.add(className + '-sticker');
|
||||
/* transformer.style.width = */stickerContainer.style.width = fitted.width + 'px';
|
||||
/* transformer.style.height = */stickerContainer.style.height = fitted.height + 'px';
|
||||
|
||||
const stickerEmoji = document.createElement('div');
|
||||
stickerEmoji.classList.add(className + '-emoji');
|
||||
stickerEmoji.append(wrapEmojiText(doc.stickerEmojiRaw));
|
||||
|
||||
if(effectThumb) {
|
||||
const margin = (size * STICKER_EFFECT_MULTIPLIER - size) / 3 * (isOut ? 1 : -1);
|
||||
transformer.classList.add('has-effect');
|
||||
// const property = `--margin-${isOut ? 'right' : 'left'}`;
|
||||
// stickerContainer.style.setProperty(property, `${margin * 2}px`);
|
||||
transformer.style.setProperty('--translateX', `${margin}px`);
|
||||
stickerEmoji.style.setProperty('--translateX', `${-margin}px`);
|
||||
}
|
||||
|
||||
const overflowElement = findUpClassName(mediaContainer, 'scrollable');
|
||||
const visibleRect = getVisibleRect(mediaContainer, overflowElement, true, mediaRect);
|
||||
if(visibleRect.overflow.vertical || visibleRect.overflow.horizontal) {
|
||||
stickerContainer.classList.add('is-overflow');
|
||||
}
|
||||
|
||||
// if(img) {
|
||||
// const ratio = img.naturalWidth / img.naturalHeight;
|
||||
// if((mediaRect.width / mediaRect.height).toFixed(1) !== ratio.toFixed(1)) {
|
||||
|
||||
// mediaRect = mediaRect.toJSON();
|
||||
// }
|
||||
// }
|
||||
|
||||
const rect = mediaContainer.getBoundingClientRect();
|
||||
const scaleX = rect.width / fitted.width;
|
||||
const scaleY = rect.height / fitted.height;
|
||||
const transformX = rect.left - (windowSize.width - rect.width) / 2;
|
||||
const transformY = rect.top - (windowSize.height - rect.height) / 2;
|
||||
transformer.style.transform = `translate(${transformX}px, ${transformY}px) scale(${scaleX}, ${scaleY})`;
|
||||
if(isSwitching) transformer.classList.add('is-switching');
|
||||
transformer.append(stickerContainer, stickerEmoji);
|
||||
container.append(transformer);
|
||||
|
||||
const player = await wrapSticker({
|
||||
doc,
|
||||
div: stickerContainer,
|
||||
group,
|
||||
width: fitted.width,
|
||||
height: fitted.height,
|
||||
play: false,
|
||||
loop: true,
|
||||
middleware,
|
||||
managers: this.managers,
|
||||
needFadeIn: false,
|
||||
isOut,
|
||||
withThumb: false,
|
||||
relativeEffect: true,
|
||||
loopEffect: true
|
||||
}).then(({render}) => render);
|
||||
if(!middleware()) return;
|
||||
|
||||
if(!container.parentElement) {
|
||||
document.body.append(container);
|
||||
}
|
||||
|
||||
const firstFramePromise = player instanceof RLottiePlayer ?
|
||||
new Promise<void>((resolve) => player.addEventListener('firstFrame', resolve, {once: true})) :
|
||||
Promise.resolve();
|
||||
await Promise.all([firstFramePromise, doubleRaf()]);
|
||||
await pause(0); // ! need it because firstFrame will be called just from the loop
|
||||
if(!middleware()) return;
|
||||
|
||||
if(lockGroups) {
|
||||
animationIntersector.setOnlyOnePlayableGroup(group);
|
||||
animationIntersector.checkAnimations(true);
|
||||
}
|
||||
|
||||
if(player instanceof RLottiePlayer) {
|
||||
const prevPlayer = lottieLoader.getAnimation(mediaContainer);
|
||||
player.curFrame = prevPlayer.curFrame;
|
||||
player.play();
|
||||
await new Promise<void>((resolve) => {
|
||||
let i = 0;
|
||||
const c = () => {
|
||||
if(++i === 2) {
|
||||
resolve();
|
||||
player.removeEventListener('enterFrame', c);
|
||||
}
|
||||
};
|
||||
|
||||
player.addEventListener('enterFrame', c);
|
||||
});
|
||||
player.pause();
|
||||
} else if(player instanceof HTMLVideoElement) {
|
||||
player.currentTime = (mediaContainer.querySelector('video') as HTMLVideoElement).currentTime;
|
||||
}
|
||||
|
||||
return {
|
||||
ready: () => {
|
||||
if(player instanceof RLottiePlayer || player instanceof HTMLVideoElement) {
|
||||
player.play();
|
||||
}
|
||||
|
||||
if(effectThumb) {
|
||||
simulateClickEvent(stickerContainer);
|
||||
}
|
||||
},
|
||||
transformer
|
||||
};
|
||||
};
|
||||
|
||||
const timeout = window.setTimeout(async() => {
|
||||
document.removeEventListener('mousemove', onMousePreMove);
|
||||
|
||||
container = document.createElement('div');
|
||||
container.classList.add(className);
|
||||
hasViewer = true;
|
||||
|
||||
const middleware = _middleware.get();
|
||||
const doc = await this.managers.appDocsManager.getDoc(docId);
|
||||
if(!middleware()) return;
|
||||
|
||||
let result: Awaited<ReturnType<typeof doThatSticker>>;
|
||||
try {
|
||||
result = await doThatSticker({
|
||||
doc,
|
||||
mediaContainer,
|
||||
middleware,
|
||||
lockGroups: true
|
||||
});
|
||||
if(!result) return;
|
||||
} catch(err) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {ready, transformer} = result;
|
||||
|
||||
previousTransformer = transformer;
|
||||
|
||||
SetTransition(container, 'is-visible', true, openDuration, () => {
|
||||
if(!middleware()) return;
|
||||
ready();
|
||||
});
|
||||
|
||||
document.addEventListener('mousemove', onMouseMove);
|
||||
}, 100);
|
||||
|
||||
const onMouseMove = async(e: MouseEvent) => {
|
||||
const newMediaContainer = findUpClassName(e.target, 'media-sticker-wrapper');
|
||||
if(!newMediaContainer || mediaContainer === newMediaContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const docId = newMediaContainer.dataset.docId;
|
||||
if(!docId) {
|
||||
return;
|
||||
}
|
||||
|
||||
mediaContainer = newMediaContainer;
|
||||
_middleware.clean();
|
||||
const middleware = _middleware.get();
|
||||
|
||||
const doc = await this.managers.appDocsManager.getDoc(docId);
|
||||
if(!middleware()) return;
|
||||
|
||||
let r: Awaited<ReturnType<typeof doThatSticker>>;
|
||||
try {
|
||||
r = await doThatSticker({
|
||||
doc,
|
||||
mediaContainer,
|
||||
middleware,
|
||||
isSwitching: true
|
||||
});
|
||||
if(!r) return;
|
||||
} catch(err) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {ready, transformer} = r;
|
||||
|
||||
const _previousTransformer = previousTransformer;
|
||||
SetTransition(_previousTransformer, 'is-switching', true, switchDuration, () => {
|
||||
_previousTransformer.remove();
|
||||
});
|
||||
|
||||
previousTransformer = transformer;
|
||||
|
||||
SetTransition(transformer, 'is-switching', false, switchDuration, () => {
|
||||
if(!middleware()) return;
|
||||
ready();
|
||||
});
|
||||
};
|
||||
|
||||
const onMousePreMove = () => {
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
|
||||
const onMouseUp = () => {
|
||||
clearTimeout(timeout);
|
||||
_middleware.clean();
|
||||
|
||||
if(container) {
|
||||
SetTransition(container, 'is-visible', false, openDuration, () => {
|
||||
container.remove();
|
||||
animationIntersector.setOnlyOnePlayableGroup(previousGroup);
|
||||
animationIntersector.checkAnimations(false);
|
||||
hasViewer = false;
|
||||
});
|
||||
|
||||
attachClickEvent(document.body, cancelEvent, {capture: true, once: true});
|
||||
}
|
||||
|
||||
document.removeEventListener('mousemove', onMouseMove);
|
||||
};
|
||||
|
||||
document.addEventListener('mousemove', onMousePreMove, {once: true});
|
||||
document.addEventListener('mouseup', onMouseUp, {once: true});
|
||||
});
|
||||
|
||||
rootScope.addEventListener('sticker_updated', ({type, faved}) => {
|
||||
if(type === 'faved') {
|
||||
toastNew({
|
||||
|
@ -196,7 +196,7 @@ export class AppMessagesManager extends AppManager {
|
||||
public migratedToFrom: {[peerId: PeerId]: PeerId} = {};
|
||||
|
||||
private newDialogsHandlePromise: Promise<any>;
|
||||
private newDialogsToHandle: {[peerId: PeerId]: Dialog} = {};
|
||||
private newDialogsToHandle: Map<PeerId, Dialog> = new Map();
|
||||
public newUpdatesAfterReloadToHandle: {[peerId: PeerId]: Set<Update>} = {};
|
||||
|
||||
private notificationsHandlePromise = 0;
|
||||
@ -1907,7 +1907,7 @@ export class AppMessagesManager extends AppManager {
|
||||
|
||||
let maxSeenIdIncremented = offsetDate ? true : false;
|
||||
let hasPrepend = false;
|
||||
const noIdsDialogs: {[peerId: PeerId]: Dialog} = {};
|
||||
const noIdsDialogs: Map<PeerId, Dialog> = new Map();
|
||||
const setFolderId: REAL_FOLDER_ID = folderId === GLOBAL_FOLDER_ID ? FOLDER_ID_ALL : folderId;
|
||||
const saveGlobalOffset = folderId === GLOBAL_FOLDER_ID;
|
||||
forEachReverse((dialogsResult.dialogs as Dialog[]), (dialog) => {
|
||||
@ -1941,16 +1941,15 @@ export class AppMessagesManager extends AppManager {
|
||||
// ! это может случиться, если запрос идёт не по папке 0, а по 1. почему-то read'ов нет
|
||||
// ! в итоге, чтобы получить 1 диалог, делается первый запрос по папке 0, потом запрос для архивных по папке 1, и потом ещё перезагрузка архивного диалога
|
||||
if(!getServerMessageId(dialog.read_inbox_max_id) && !getServerMessageId(dialog.read_outbox_max_id)) {
|
||||
noIdsDialogs[dialog.peerId] = dialog;
|
||||
noIdsDialogs.set(dialog.peerId, dialog);
|
||||
|
||||
this.log.error('noIdsDialogs', dialog, params);
|
||||
}
|
||||
});
|
||||
|
||||
const keys = Object.keys(noIdsDialogs);
|
||||
if(keys.length) {
|
||||
if(noIdsDialogs.size) {
|
||||
// setTimeout(() => { // test bad situation
|
||||
const peerIds = keys.map((key) => key.toPeerId());
|
||||
const peerIds = [...noIdsDialogs.keys()];
|
||||
const promises = peerIds.map((peerId) => this.reloadConversation(peerId));
|
||||
Promise.all(promises).then(() => {
|
||||
this.rootScope.dispatchEvent('dialogs_multiupdate', noIdsDialogs);
|
||||
@ -1988,7 +1987,7 @@ export class AppMessagesManager extends AppManager {
|
||||
if(hasPrepend) {
|
||||
this.scheduleHandleNewDialogs();
|
||||
} else {
|
||||
this.rootScope.dispatchEvent('dialogs_multiupdate', {});
|
||||
this.rootScope.dispatchEvent('dialogs_multiupdate', new Map());
|
||||
}
|
||||
|
||||
const dialogs = (dialogsResult as MessagesDialogs.messagesDialogsSlice).dialogs;
|
||||
@ -2402,31 +2401,7 @@ export class AppMessagesManager extends AppManager {
|
||||
}
|
||||
|
||||
return this.doFlushHistory(this.appPeersManager.getInputPeerById(peerId), justClear, revoke).then(() => {
|
||||
[
|
||||
this.historiesStorage,
|
||||
this.threadsStorage,
|
||||
this.searchesStorage,
|
||||
this.pinnedMessages,
|
||||
this.pendingAfterMsgs,
|
||||
this.pendingTopMsgs
|
||||
].forEach((s) => {
|
||||
delete s[peerId];
|
||||
});
|
||||
|
||||
const m = this.needSingleMessages.get(peerId);
|
||||
if(m) {
|
||||
m.clear();
|
||||
}
|
||||
|
||||
[
|
||||
this.messagesStorageByPeerId,
|
||||
this.scheduledMessagesStorage
|
||||
].forEach((s) => {
|
||||
const ss = s[peerId];
|
||||
if(ss) {
|
||||
ss.clear();
|
||||
}
|
||||
});
|
||||
this.flushStoragesByPeerId(peerId);
|
||||
|
||||
if(justClear) {
|
||||
this.rootScope.dispatchEvent('dialog_flush', {peerId, dialog: this.getDialogOnly(peerId)});
|
||||
@ -2445,6 +2420,38 @@ export class AppMessagesManager extends AppManager {
|
||||
});
|
||||
}
|
||||
|
||||
private flushStoragesByPeerId(peerId: PeerId) {
|
||||
[
|
||||
this.historiesStorage,
|
||||
this.threadsStorage,
|
||||
this.searchesStorage,
|
||||
this.pinnedMessages,
|
||||
this.pendingAfterMsgs,
|
||||
this.pendingTopMsgs
|
||||
].forEach((s) => {
|
||||
delete s[peerId];
|
||||
});
|
||||
|
||||
const needSingleMessages = this.needSingleMessages.get(peerId);
|
||||
if(needSingleMessages) {
|
||||
for(const [mid, promise] of needSingleMessages) {
|
||||
promise.resolve(this.generateEmptyMessage(mid));
|
||||
}
|
||||
|
||||
needSingleMessages.clear();
|
||||
}
|
||||
|
||||
[
|
||||
this.messagesStorageByPeerId,
|
||||
this.scheduledMessagesStorage
|
||||
].forEach((s) => {
|
||||
const ss = s[peerId];
|
||||
if(ss) {
|
||||
ss.clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public hidePinnedMessages(peerId: PeerId) {
|
||||
return Promise.all([
|
||||
this.appStateManager.getState(),
|
||||
@ -3558,12 +3565,11 @@ export class AppMessagesManager extends AppManager {
|
||||
|
||||
private handleNewDialogs = () => {
|
||||
let newMaxSeenId = 0;
|
||||
const obj = this.newDialogsToHandle;
|
||||
for(const peerId in obj) {
|
||||
const dialog = obj[peerId];
|
||||
const map = this.newDialogsToHandle;
|
||||
for(const [peerId, dialog] of map) {
|
||||
if(!dialog) {
|
||||
this.reloadConversation(peerId.toPeerId());
|
||||
delete obj[peerId];
|
||||
map.delete(peerId);
|
||||
} else {
|
||||
this.dialogsStorage.pushDialog(dialog);
|
||||
if(!this.appPeersManager.isChannel(peerId.toPeerId())) {
|
||||
@ -3578,13 +3584,13 @@ export class AppMessagesManager extends AppManager {
|
||||
this.incrementMaxSeenId(newMaxSeenId);
|
||||
}
|
||||
|
||||
this.rootScope.dispatchEvent('dialogs_multiupdate', obj);
|
||||
this.newDialogsToHandle = {};
|
||||
this.rootScope.dispatchEvent('dialogs_multiupdate', map);
|
||||
this.newDialogsToHandle.clear();
|
||||
};
|
||||
|
||||
public scheduleHandleNewDialogs(peerId?: PeerId, dialog?: Dialog) {
|
||||
if(peerId !== undefined) {
|
||||
this.newDialogsToHandle[peerId] = dialog;
|
||||
this.newDialogsToHandle.set(peerId, dialog);
|
||||
}
|
||||
|
||||
if(this.newDialogsHandlePromise) return this.newDialogsHandlePromise;
|
||||
@ -4263,7 +4269,7 @@ export class AppMessagesManager extends AppManager {
|
||||
|
||||
releaseUnreadCount();
|
||||
this.dialogsStorage.setDialogToState(dialog);
|
||||
this.rootScope.dispatchEvent('dialogs_multiupdate', {[peerId]: dialog});
|
||||
this.rootScope.dispatchEvent('dialogs_multiupdate', new Map([[peerId, dialog]]));
|
||||
}
|
||||
};
|
||||
|
||||
@ -4321,10 +4327,8 @@ export class AppMessagesManager extends AppManager {
|
||||
});
|
||||
|
||||
if(isTopMessage || (message as Message.message).grouped_id) {
|
||||
const updatedDialogs: {[peerId: PeerId]: Dialog} = {};
|
||||
updatedDialogs[peerId] = dialog;
|
||||
this.dialogsStorage.setDialogToState(dialog);
|
||||
this.rootScope.dispatchEvent('dialogs_multiupdate', updatedDialogs);
|
||||
this.rootScope.dispatchEvent('dialogs_multiupdate', new Map([[peerId, dialog]]));
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -4599,9 +4603,7 @@ export class AppMessagesManager extends AppManager {
|
||||
private onUpdateChannelReload = (update: Update.updateChannelReload) => {
|
||||
const peerId = update.channel_id.toPeerId(true);
|
||||
|
||||
this.dialogsStorage.dropDialog(peerId);
|
||||
|
||||
delete this.historiesStorage[peerId];
|
||||
this.flushStoragesByPeerId(peerId);
|
||||
this.reloadConversation(peerId).then(() => {
|
||||
this.rootScope.dispatchEvent('history_reload', peerId);
|
||||
});
|
||||
@ -5651,9 +5653,7 @@ export class AppMessagesManager extends AppManager {
|
||||
});
|
||||
|
||||
if(this.isMessageIsTopMessage(message)) {
|
||||
this.rootScope.dispatchEvent('dialogs_multiupdate', {
|
||||
[peerId]: this.getDialogOnly(peerId)
|
||||
});
|
||||
this.rootScope.dispatchEvent('dialogs_multiupdate', new Map([[peerId, this.getDialogOnly(peerId)]]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ import fixEmoji from '../richTextProcessor/fixEmoji';
|
||||
import ctx from '../../environment/ctx';
|
||||
import {getEnvironment} from '../../environment/utils';
|
||||
import getDocumentInput from './utils/docs/getDocumentInput';
|
||||
import getStickerEffectThumb from './utils/stickers/getStickerEffectThumb';
|
||||
|
||||
const CACHE_TIME = 3600e3;
|
||||
|
||||
@ -673,7 +674,8 @@ export class AppStickersManager extends AppManager {
|
||||
const stickers = [...new Set(cachedStickersAnimated.concat(cachedStickersStatic, foundStickers))]/* .filter((doc) => !doc.animated) */;
|
||||
|
||||
forEachReverse(stickers, (sticker, idx, arr) => {
|
||||
if(sticker.sticker === 3 && !getEnvironment().IS_WEBM_SUPPORTED) {
|
||||
if((sticker.sticker === 3 && !getEnvironment().IS_WEBM_SUPPORTED) ||
|
||||
(!this.rootScope.premium && getStickerEffectThumb(sticker))) {
|
||||
arr.splice(idx, 1);
|
||||
}
|
||||
});
|
||||
|
@ -58,7 +58,7 @@ export type BroadcastEvents = {
|
||||
// 'dialog_top': Dialog,
|
||||
'dialog_notify_settings': Dialog,
|
||||
// 'dialog_order': {dialog: Dialog, pos: number},
|
||||
'dialogs_multiupdate': {[peerId: PeerId]: Dialog},
|
||||
'dialogs_multiupdate': Map<PeerId, Dialog>,
|
||||
|
||||
'history_append': {storageKey: MessagesStorageKey, message: Message.message},
|
||||
'history_update': {storageKey: MessagesStorageKey, message: MyMessage, sequential?: boolean},
|
||||
|
@ -26,6 +26,8 @@ const downloadMap: Map<string, DownloadItem> = new Map();
|
||||
const DOWNLOAD_ERROR = makeError('UNKNOWN');
|
||||
const DOWNLOAD_TEST = false;
|
||||
|
||||
(self as any).downloadMap = downloadMap;
|
||||
|
||||
type A = Parameters<ServiceMessagePort<false>['addMultipleEventsListeners']>[0];
|
||||
|
||||
const events: A = {
|
||||
|
@ -20,7 +20,7 @@ import {getWindowClients} from '../../helpers/context';
|
||||
import {MessageSendPort} from '../mtproto/superMessagePort';
|
||||
import handleDownload from './download';
|
||||
|
||||
export const log = logger('SW', LogTypes.Error | LogTypes.Debug | LogTypes.Log | LogTypes.Warn);
|
||||
export const log = logger('SW', LogTypes.Error | LogTypes.Debug | LogTypes.Log | LogTypes.Warn, true);
|
||||
const ctx = self as any as ServiceWorkerGlobalScope;
|
||||
|
||||
// #if !MTPROTO_SW
|
||||
|
@ -18,7 +18,7 @@ const deferredPromises: Map<MessagePort, {[taskId: string]: CancellablePromise<M
|
||||
const cacheStorage = new CacheStorageController('cachedStreamChunks');
|
||||
const CHUNK_TTL = 86400;
|
||||
const CHUNK_CACHED_TIME_HEADER = 'Time-Cached';
|
||||
const USE_CACHE = false;
|
||||
const USE_CACHE = true;
|
||||
|
||||
const clearOldChunks = () => {
|
||||
return cacheStorage.timeoutOperation((cache) => {
|
||||
|
@ -361,16 +361,18 @@ export default class DialogsStorage extends AppManager {
|
||||
private setDialogIndexInFilter(dialog: Dialog, indexKey: ReturnType<typeof getDialogIndexKey>, filter: MyDialogFilter) {
|
||||
let index: number;
|
||||
|
||||
if(REAL_FOLDERS.has(filter.id)) {
|
||||
index = getDialogIndex(dialog, indexKey);
|
||||
} else if(this.filtersStorage.testDialogForFilter(dialog, filter)) {
|
||||
const isRealFolder = REAL_FOLDERS.has(filter.id);
|
||||
/* if(isRealFolder) {
|
||||
// index = getDialogIndex(dialog, indexKey);
|
||||
index = this.generateIndexForDialog(dialog, true);
|
||||
} else */if(this.filtersStorage.testDialogForFilter(dialog, filter)) {
|
||||
const pinnedIndex = filter.pinnedPeerIds.indexOf(dialog.peerId);
|
||||
if(pinnedIndex !== -1) {
|
||||
index = this.generateDialogIndex(this.generateDialogPinnedDateByIndex(filter.pinnedPeerIds.length - 1 - pinnedIndex), true);
|
||||
} else if(dialog.pFlags?.pinned) {
|
||||
index = this.generateIndexForDialog(dialog, true);
|
||||
} else if(dialog.pFlags?.pinned || isRealFolder) {
|
||||
index = this.generateIndexForDialog(dialog, true, undefined, !isRealFolder);
|
||||
} else {
|
||||
index = getDialogIndex(dialog);
|
||||
index = getDialogIndex(dialog) ?? this.generateIndexForDialog(dialog, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -541,13 +543,13 @@ export default class DialogsStorage extends AppManager {
|
||||
}
|
||||
}
|
||||
|
||||
public generateIndexForDialog(dialog: Dialog, justReturn = false, message?: MyMessage) {
|
||||
// if(!justReturn) {
|
||||
// return;
|
||||
// }
|
||||
public generateIndexForDialog(dialog: Dialog, justReturn?: boolean, message?: MyMessage, noPinnedOrderUpdate?: boolean) {
|
||||
if(!justReturn) {
|
||||
return;
|
||||
}
|
||||
|
||||
let topDate = 0, isPinned: boolean;
|
||||
if(dialog.pFlags.pinned && !justReturn) {
|
||||
if(dialog.pFlags.pinned && !noPinnedOrderUpdate) {
|
||||
topDate = this.generateDialogPinnedDate(dialog);
|
||||
isPinned = true;
|
||||
} else {
|
||||
@ -784,7 +786,7 @@ export default class DialogsStorage extends AppManager {
|
||||
|
||||
// this.appMessagesManager.log('applyConversation', dialogsResult);
|
||||
|
||||
const updatedDialogs: {[peerId: PeerId]: Dialog} = {};
|
||||
const updatedDialogs: Map<PeerId, Dialog> = new Map();
|
||||
(dialogsResult.dialogs as Dialog[]).forEach((dialog) => {
|
||||
const peerId = this.appPeersManager.getPeerId(dialog.peer);
|
||||
let topMessage = dialog.top_message;
|
||||
@ -805,7 +807,7 @@ export default class DialogsStorage extends AppManager {
|
||||
|
||||
if(topMessage || dialog.draft?._ === 'draftMessage') {
|
||||
this.saveDialog(dialog);
|
||||
updatedDialogs[peerId] = dialog;
|
||||
updatedDialogs.set(peerId, dialog);
|
||||
} else {
|
||||
this.dropDialogWithEvent(peerId);
|
||||
}
|
||||
@ -823,7 +825,7 @@ export default class DialogsStorage extends AppManager {
|
||||
}
|
||||
});
|
||||
|
||||
if(Object.keys(updatedDialogs).length) {
|
||||
if(updatedDialogs.size) {
|
||||
this.rootScope.dispatchEvent('dialogs_multiupdate', updatedDialogs);
|
||||
}
|
||||
}
|
||||
@ -1158,6 +1160,8 @@ export default class DialogsStorage extends AppManager {
|
||||
|
||||
const handleOrder = (order: PeerId[]) => {
|
||||
this.resetPinnedOrder(folderId);
|
||||
this.pinnedOrders[folderId].push(...order);
|
||||
this.savePinnedOrders();
|
||||
order.reverse(); // index must be higher
|
||||
order.forEach((peerId) => {
|
||||
newPinned[peerId] = true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user