|
|
|
@ -55,7 +55,7 @@ import {CallType} from '../calls/types';
@@ -55,7 +55,7 @@ import {CallType} from '../calls/types';
|
|
|
|
|
import {Modify, SendMessageEmojiInteractionData} from '../../types'; |
|
|
|
|
import htmlToSpan from '../../helpers/dom/htmlToSpan'; |
|
|
|
|
import getVisibleRect from '../../helpers/dom/getVisibleRect'; |
|
|
|
|
import {simulateClickEvent} from '../../helpers/dom/clickEvent'; |
|
|
|
|
import {attachClickEvent, simulateClickEvent} from '../../helpers/dom/clickEvent'; |
|
|
|
|
import PopupCall from '../../components/call'; |
|
|
|
|
import copy from '../../helpers/object/copy'; |
|
|
|
|
import getObjectKeysAndSort from '../../helpers/object/getObjectKeysAndSort'; |
|
|
|
@ -92,6 +92,15 @@ import paymentsWrapCurrencyAmount from '../../helpers/paymentsWrapCurrencyAmount
@@ -92,6 +92,15 @@ import paymentsWrapCurrencyAmount from '../../helpers/paymentsWrapCurrencyAmount
|
|
|
|
|
import findUpClassName from '../../helpers/dom/findUpClassName'; |
|
|
|
|
import {CLICK_EVENT_NAME} from '../../helpers/dom/clickEvent'; |
|
|
|
|
import PopupPayment from '../../components/popups/payment'; |
|
|
|
|
import {getMiddleware} from '../../helpers/middleware'; |
|
|
|
|
import {wrapSticker} from '../../components/wrappers'; |
|
|
|
|
import windowSize from '../../helpers/windowSize'; |
|
|
|
|
import getStickerEffectThumb from './utils/stickers/getStickerEffectThumb'; |
|
|
|
|
import {makeMediaSize} from '../../helpers/mediaSize'; |
|
|
|
|
import RLottiePlayer from '../rlottie/rlottiePlayer'; |
|
|
|
|
import type {MyDocument} from './appDocsManager'; |
|
|
|
|
import deferredPromise from '../../helpers/cancellablePromise'; |
|
|
|
|
import {STICKER_EFFECT_MULTIPLIER} from '../../components/wrappers/sticker'; |
|
|
|
|
|
|
|
|
|
export const CHAT_ANIMATION_GROUP: AnimationItemGroup = 'chat'; |
|
|
|
|
|
|
|
|
@ -207,15 +216,17 @@ export class AppImManager extends EventListenerBase<{
@@ -207,15 +216,17 @@ export class AppImManager extends EventListenerBase<{
|
|
|
|
|
this.setSettings(); |
|
|
|
|
rootScope.addEventListener('settings_updated', this.setSettings); |
|
|
|
|
|
|
|
|
|
rootScope.addEventListener('premium_toggle', (isPremium) => { |
|
|
|
|
const onPremiumToggle = (isPremium: boolean) => { |
|
|
|
|
document.body.classList.toggle('is-premium', isPremium); |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
rootScope.addEventListener('premium_toggle', onPremiumToggle); |
|
|
|
|
onPremiumToggle(rootScope.premium); |
|
|
|
|
|
|
|
|
|
useHeavyAnimationCheck(() => { |
|
|
|
|
animationIntersector.setOnlyOnePlayableGroup('lock'); |
|
|
|
|
animationIntersector.checkAnimations(true); |
|
|
|
|
}, () => { |
|
|
|
|
animationIntersector.setOnlyOnePlayableGroup(''); |
|
|
|
|
animationIntersector.setOnlyOnePlayableGroup(); |
|
|
|
|
animationIntersector.checkAnimations(false); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
@ -404,6 +415,251 @@ export class AppImManager extends EventListenerBase<{
@@ -404,6 +415,251 @@ 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; |
|
|
|
|
|
|
|
|
|
const {ready, transformer} = await doThatSticker({ |
|
|
|
|
doc, |
|
|
|
|
mediaContainer, |
|
|
|
|
middleware, |
|
|
|
|
lockGroups: true |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
|
|
const {ready, transformer} = await doThatSticker({ |
|
|
|
|
doc, |
|
|
|
|
mediaContainer, |
|
|
|
|
middleware, |
|
|
|
|
isSwitching: true |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
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}); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
apiManagerProxy.addEventListener('notificationBuild', (options) => { |
|
|
|
|
if(this.chat.peerId === options.message.peerId && !idleController.isIdle) { |
|
|
|
|
return; |
|
|
|
|