Browse Source

Larger reactions

master
Eduard Kuzmenko 3 years ago
parent
commit
513ed97988
  1. 23
      src/components/chat/reaction.ts
  2. 54
      src/components/wrappers.ts
  3. 7
      src/helpers/sequentialDom.ts
  4. 46
      src/scss/partials/_reaction.scss

23
src/components/chat/reaction.ts

@ -17,7 +17,7 @@ import { wrapSticker, wrapStickerAnimation } from "../wrappers";
const CLASS_NAME = 'reaction'; const CLASS_NAME = 'reaction';
const TAG_NAME = CLASS_NAME + '-element'; const TAG_NAME = CLASS_NAME + '-element';
const REACTION_INLINE_SIZE = 14; const REACTION_INLINE_SIZE = 14;
const REACTION_BLOCK_SIZE = 16; const REACTION_BLOCK_SIZE = 22;
export const REACTION_DISPLAY_INLINE_COUNTER_AT = 2; export const REACTION_DISPLAY_INLINE_COUNTER_AT = 2;
export const REACTION_DISPLAY_BLOCK_COUNTER_AT = 4; export const REACTION_DISPLAY_BLOCK_COUNTER_AT = 4;
@ -73,9 +73,10 @@ export default class ReactionElement extends HTMLElement {
const size = this.type === 'inline' ? REACTION_INLINE_SIZE : REACTION_BLOCK_SIZE; const size = this.type === 'inline' ? REACTION_INLINE_SIZE : REACTION_BLOCK_SIZE;
wrapSticker({ wrapSticker({
div: this.stickerContainer, div: this.stickerContainer,
doc: availableReaction.static_icon, doc: availableReaction.center_icon,
width: size, width: size,
height: size height: size,
static: true
}); });
}); });
} }
@ -120,7 +121,7 @@ export default class ReactionElement extends HTMLElement {
if(!this.stackedAvatars) { if(!this.stackedAvatars) {
this.stackedAvatars = new StackedAvatars({ this.stackedAvatars = new StackedAvatars({
avatarSize: 16 avatarSize: 24
}); });
this.append(this.stackedAvatars.container); this.append(this.stackedAvatars.container);
@ -139,7 +140,7 @@ export default class ReactionElement extends HTMLElement {
public fireAroundAnimation() { public fireAroundAnimation() {
callbackify(appReactionsManager.getReaction(this.reactionCount.reaction), (availableReaction) => { callbackify(appReactionsManager.getReaction(this.reactionCount.reaction), (availableReaction) => {
const size = (this.type === 'inline' ? REACTION_INLINE_SIZE : REACTION_BLOCK_SIZE) + 14; const size = this.type === 'inline' ? REACTION_INLINE_SIZE + 14 : REACTION_BLOCK_SIZE + 18;
const div = document.createElement('div'); const div = document.createElement('div');
div.classList.add(CLASS_NAME + '-sticker-activate'); div.classList.add(CLASS_NAME + '-sticker-activate');
@ -165,17 +166,17 @@ export default class ReactionElement extends HTMLElement {
skipRatio: 1, skipRatio: 1,
play: false play: false
}).stickerPromise }).stickerPromise
]).then(([activatePlayer, aroundPlayer]) => { ]).then(([iconPlayer, aroundPlayer]) => {
activatePlayer.addEventListener('enterFrame', (frameNo) => { iconPlayer.addEventListener('enterFrame', (frameNo) => {
if(frameNo === activatePlayer.maxFrame) { if(frameNo === iconPlayer.maxFrame) {
activatePlayer.remove(); iconPlayer.remove();
div.remove(); div.remove();
} }
}); });
activatePlayer.addEventListener('firstFrame', () => { iconPlayer.addEventListener('firstFrame', () => {
this.stickerContainer.prepend(div); this.stickerContainer.prepend(div);
activatePlayer.play(); iconPlayer.play();
aroundPlayer.play(); aroundPlayer.play();
}, {once: true}); }, {once: true});
}); });

54
src/components/wrappers.ts

@ -1222,7 +1222,7 @@ export function wrapStickerAnimation({
return {animationDiv, stickerPromise}; return {animationDiv, stickerPromise};
} }
export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, onlyThumb, emoji, width, height, withThumb, loop, loadPromises, needFadeIn, needUpscale, skipRatio}: { export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, onlyThumb, emoji, width, height, withThumb, loop, loadPromises, needFadeIn, needUpscale, skipRatio, static: asStatic}: {
doc: MyDocument, doc: MyDocument,
div: HTMLElement, div: HTMLElement,
middleware?: () => boolean, middleware?: () => boolean,
@ -1238,9 +1238,13 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
loadPromises?: Promise<any>[], loadPromises?: Promise<any>[],
needFadeIn?: boolean, needFadeIn?: boolean,
needUpscale?: boolean, needUpscale?: boolean,
skipRatio?: number skipRatio?: number,
static?: boolean
}): Promise<RLottiePlayer | void> { }): Promise<RLottiePlayer | void> {
const stickerType = doc.sticker; const stickerType = doc.sticker;
if(stickerType === 1) {
asStatic = true;
}
if(!width) { if(!width) {
width = !emoji ? 200 : undefined; width = !emoji ? 200 : undefined;
@ -1293,14 +1297,32 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
//console.log('wrap sticker', doc, div, onlyThumb); //console.log('wrap sticker', doc, div, onlyThumb);
const cacheContext = appDownloadManager.getCacheContext(doc); let cacheContext: ThumbCache;
if(asStatic && stickerType !== 1) {
const thumb = appPhotosManager.choosePhotoSize(doc, width, height, false) as PhotoSize.photoSize;
cacheContext = appDownloadManager.getCacheContext(doc, thumb.type);
} else {
cacheContext = appDownloadManager.getCacheContext(doc);
}
const toneIndex = emoji ? getEmojiToneIndex(emoji) : -1; const toneIndex = emoji ? getEmojiToneIndex(emoji) : -1;
const downloaded = cacheContext.downloaded && !needFadeIn; const downloaded = cacheContext.downloaded && !needFadeIn;
const isAnimated = !asStatic && (stickerType === 2 || stickerType === 3);
const isThumbNeededForType = isAnimated;
let loadThumbPromise = deferredPromise<void>(); let loadThumbPromise = deferredPromise<void>();
let haveThumbCached = false; let haveThumbCached = false;
if((doc.thumbs?.length || doc.stickerCachedThumbs) && !div.firstElementChild && (!downloaded || stickerType === 2 || stickerType === 3 || onlyThumb) && withThumb !== false/* && doc.thumbs[0]._ !== 'photoSizeEmpty' */) { if((
doc.thumbs?.length ||
doc.stickerCachedThumbs
) &&
!div.firstElementChild && (
!downloaded ||
isThumbNeededForType ||
onlyThumb
) && withThumb !== false/* && doc.thumbs[0]._ !== 'photoSizeEmpty' */
) {
let thumb = doc.stickerCachedThumbs && doc.stickerCachedThumbs[toneIndex] || doc.thumbs[0]; let thumb = doc.stickerCachedThumbs && doc.stickerCachedThumbs[toneIndex] || doc.thumbs[0];
//console.log('wrap sticker', thumb, div); //console.log('wrap sticker', thumb, div);
@ -1395,7 +1417,7 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
const load = async() => { const load = async() => {
if(middleware && !middleware()) return; if(middleware && !middleware()) return;
if(stickerType === 2) { if(stickerType === 2 && !asStatic) {
/* if(doc.id === '1860749763008266301') { /* if(doc.id === '1860749763008266301') {
console.log('loaded sticker:', doc, div); console.log('loaded sticker:', doc, div);
} */ } */
@ -1588,9 +1610,9 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
}); });
//console.timeEnd('render sticker' + doc.id); //console.timeEnd('render sticker' + doc.id);
} else if(stickerType === 1 || stickerType === 3) { } else if(asStatic || stickerType === 3) {
let media: HTMLElement; let media: HTMLElement;
if(stickerType === 1) { if(asStatic) {
media = new Image(); media = new Image();
} else { } else {
media = document.createElement('video'); media = document.createElement('video');
@ -1605,7 +1627,7 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
const thumbImage = div.firstElementChild !== media && div.firstElementChild; const thumbImage = div.firstElementChild !== media && div.firstElementChild;
if(needFadeIn !== false) { if(needFadeIn !== false) {
needFadeIn = (needFadeIn || !downloaded || (stickerType === 1 ? thumbImage : (!thumbImage || thumbImage.tagName === 'svg'))) && rootScope.settings.animationsEnabled; needFadeIn = (needFadeIn || !downloaded || (asStatic ? thumbImage : (!thumbImage || thumbImage.tagName === 'svg'))) && rootScope.settings.animationsEnabled;
} }
media.classList.add('media-sticker'); media.classList.add('media-sticker');
@ -1654,7 +1676,7 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
}); });
}; };
if(stickerType === 1) { if(asStatic) {
renderImageFromUrl(media, cacheContext.url, onLoad); renderImageFromUrl(media, cacheContext.url, onLoad);
} else { } else {
(media as HTMLVideoElement).src = cacheContext.url; (media as HTMLVideoElement).src = cacheContext.url;
@ -1664,17 +1686,25 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
if(cacheContext.url) r(); if(cacheContext.url) r();
else { else {
appDocsManager.downloadDoc(doc, /* undefined, */lazyLoadQueue?.queueId).then(r, resolve); let promise: Promise<any>;
if(stickerType === 2 && asStatic) {
const thumb = appPhotosManager.choosePhotoSize(doc, width, height, false) as PhotoSize.photoSize;
promise = appDocsManager.getThumbURL(doc, thumb).promise
} else {
promise = appDocsManager.downloadDoc(doc, /* undefined, */lazyLoadQueue?.queueId);
}
promise.then(r, resolve);
} }
}); });
} }
}; };
const loadPromise: Promise<RLottiePlayer | void> = lazyLoadQueue && (!downloaded || stickerType === 2 || stickerType === 3) ? const loadPromise: Promise<RLottiePlayer | void> = lazyLoadQueue && (!downloaded || isAnimated) ?
(lazyLoadQueue.push({div, load}), Promise.resolve()) : (lazyLoadQueue.push({div, load}), Promise.resolve()) :
load(); load();
if(downloaded && (stickerType === 1/* || stickerType === 3 */)) { if(downloaded && (asStatic/* || stickerType === 3 */)) {
loadThumbPromise = loadPromise as any; loadThumbPromise = loadPromise as any;
if(loadPromises) { if(loadPromises) {
loadPromises.push(loadThumbPromise); loadPromises.push(loadThumbPromise);

7
src/helpers/sequentialDom.ts

@ -45,11 +45,16 @@ class SequentialDom {
* @param callback * @param callback
*/ */
public mutateElement(element: HTMLElement, callback?: VoidFunction) { public mutateElement(element: HTMLElement, callback?: VoidFunction) {
const promise = isInDOM(element) ? this.mutate() : Promise.resolve(); const isConnected = isInDOM(element);
const promise = isConnected ? this.mutate() : Promise.resolve();
if(callback !== undefined) { if(callback !== undefined) {
if(isConnected) {
callback();
} else {
promise.then(() => callback()); promise.then(() => callback());
} }
}
return promise; return promise;
} }

46
src/scss/partials/_reaction.scss

@ -28,15 +28,16 @@
position: relative; position: relative;
width: var(--reaction-size); width: var(--reaction-size);
height: var(--reaction-size); height: var(--reaction-size);
display: flex;
align-items: center;
justify-content: center;
&-activate { &-activate {
--offset: -.4375rem;
// --offset: 0;
position: absolute; position: absolute;
top: var(--offset); top: var(--reaction-offset);
right: var(--offset); right: var(--reaction-offset);
bottom: var(--offset); bottom: var(--reaction-offset);
left: var(--offset); left: var(--reaction-offset);
// animation: reaction-activate 2s linear forwards; // animation: reaction-activate 2s linear forwards;
& + .media-sticker { & + .media-sticker {
@ -47,6 +48,7 @@
&-inline { &-inline {
--reaction-size: .875rem; --reaction-size: .875rem;
--reaction-offset: -.4375rem;
min-width: var(--reaction-size); min-width: var(--reaction-size);
min-height: var(--reaction-size); min-height: var(--reaction-size);
} }
@ -58,10 +60,12 @@
} }
&-block { &-block {
--additional-height: .625rem; --additional-height: .5rem;
--margin: .25rem; // --padding-horizontal: .5rem;
--margin: .375rem;
// --reaction-size: 1.0625rem; // --reaction-size: 1.0625rem;
--reaction-size: 1rem; --reaction-size: 1.375rem;
--reaction-offset: -.5625rem;
--background-color: var(--message-highlightning-color); --background-color: var(--message-highlightning-color);
--chosen-background-color: var(--message-primary-color); --chosen-background-color: var(--message-primary-color);
--counter-color: #fff; --counter-color: #fff;
@ -69,6 +73,8 @@
height: var(--reaction-total-size); height: var(--reaction-total-size);
border-radius: var(--reaction-total-size); border-radius: var(--reaction-total-size);
// padding: 0 .375rem 0 .625rem; // padding: 0 .375rem 0 .625rem;
// padding: 0 var(--padding-horizontal) 0 calc(var(--padding-horizontal) + var(--reaction-size));
// padding: 0 var(--padding-horizontal);
padding: 0 .5rem; padding: 0 .5rem;
background-color: var(--background-color); background-color: var(--background-color);
cursor: pointer; cursor: pointer;
@ -128,16 +134,30 @@
.stacked-avatars { .stacked-avatars {
--border-color: transparent; --border-color: transparent;
margin-left: .25rem; --border-size: .125rem;
--margin-right: -.875rem;
margin-left: .1875rem;
// margin-right: .0625rem; // margin-right: .0625rem;
} }
} }
&-block &-counter { &-block &-counter {
font-size: .875rem !important; font-size: .9375rem !important;
font-weight: 500; font-weight: 500;
margin: 0 .125rem 0 .375rem; margin: 0 .0625rem 0 .375rem;
line-height: 1; line-height: 1.125rem;
position: relative; position: relative;
} }
.media-sticker {
--size: calc(var(--reaction-size) + var(--reaction-offset) * -2);
width: var(--size) !important;
height: var(--size) !important;
max-width: var(--size);
max-height: var(--size);
top: auto;
right: auto;
bottom: auto;
left: auto;
}
} }

Loading…
Cancel
Save