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

54
src/components/wrappers.ts

@ -1222,7 +1222,7 @@ export function wrapStickerAnimation({ @@ -1222,7 +1222,7 @@ export function wrapStickerAnimation({
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,
div: HTMLElement,
middleware?: () => boolean,
@ -1238,9 +1238,13 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o @@ -1238,9 +1238,13 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
loadPromises?: Promise<any>[],
needFadeIn?: boolean,
needUpscale?: boolean,
skipRatio?: number
skipRatio?: number,
static?: boolean
}): Promise<RLottiePlayer | void> {
const stickerType = doc.sticker;
if(stickerType === 1) {
asStatic = true;
}
if(!width) {
width = !emoji ? 200 : undefined;
@ -1293,14 +1297,32 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o @@ -1293,14 +1297,32 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
//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 downloaded = cacheContext.downloaded && !needFadeIn;
const isAnimated = !asStatic && (stickerType === 2 || stickerType === 3);
const isThumbNeededForType = isAnimated;
let loadThumbPromise = deferredPromise<void>();
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];
//console.log('wrap sticker', thumb, div);
@ -1395,7 +1417,7 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o @@ -1395,7 +1417,7 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
const load = async() => {
if(middleware && !middleware()) return;
if(stickerType === 2) {
if(stickerType === 2 && !asStatic) {
/* if(doc.id === '1860749763008266301') {
console.log('loaded sticker:', doc, div);
} */
@ -1588,9 +1610,9 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o @@ -1588,9 +1610,9 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
});
//console.timeEnd('render sticker' + doc.id);
} else if(stickerType === 1 || stickerType === 3) {
} else if(asStatic || stickerType === 3) {
let media: HTMLElement;
if(stickerType === 1) {
if(asStatic) {
media = new Image();
} else {
media = document.createElement('video');
@ -1605,7 +1627,7 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o @@ -1605,7 +1627,7 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
const thumbImage = div.firstElementChild !== media && div.firstElementChild;
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');
@ -1654,7 +1676,7 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o @@ -1654,7 +1676,7 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
});
};
if(stickerType === 1) {
if(asStatic) {
renderImageFromUrl(media, cacheContext.url, onLoad);
} else {
(media as HTMLVideoElement).src = cacheContext.url;
@ -1664,17 +1686,25 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o @@ -1664,17 +1686,25 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
if(cacheContext.url) r();
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()) :
load();
if(downloaded && (stickerType === 1/* || stickerType === 3 */)) {
if(downloaded && (asStatic/* || stickerType === 3 */)) {
loadThumbPromise = loadPromise as any;
if(loadPromises) {
loadPromises.push(loadThumbPromise);

9
src/helpers/sequentialDom.ts

@ -45,10 +45,15 @@ class SequentialDom { @@ -45,10 +45,15 @@ class SequentialDom {
* @param callback
*/
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) {
promise.then(() => callback());
if(isConnected) {
callback();
} else {
promise.then(() => callback());
}
}
return promise;

46
src/scss/partials/_reaction.scss

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