Fix group call styles

This commit is contained in:
Eduard Kuzmenko 2023-02-01 12:53:35 +04:00
parent d8e739261f
commit 90120ac76d
8 changed files with 161 additions and 124 deletions

View File

@ -4,12 +4,12 @@
* https://github.com/morethanwords/tweb/blob/master/LICENSE
*/
import type {MyDocument} from '../lib/appManagers/appDocsManager';
import type {MyPhoto} from '../lib/appManagers/appPhotosManager';
import deferredPromise from '../helpers/cancellablePromise';
import mediaSizes from '../helpers/mediaSizes';
import IS_TOUCH_SUPPORTED from '../environment/touchSupport';
import {IS_MOBILE, IS_MOBILE_SAFARI, IS_SAFARI} from '../environment/userAgent';
import type {MyDocument} from '../lib/appManagers/appDocsManager';
import type {MyPhoto} from '../lib/appManagers/appPhotosManager';
import {logger} from '../lib/logger';
import VideoPlayer from '../lib/mediaPlayer';
import rootScope from '../lib/rootScope';
@ -48,7 +48,6 @@ import setAttachmentSize from '../helpers/setAttachmentSize';
import wrapEmojiText from '../lib/richTextProcessor/wrapEmojiText';
import LazyLoadQueueBase from './lazyLoadQueueBase';
import overlayCounter from '../helpers/overlayCounter';
import {ThumbCache} from '../lib/storages/thumbs';
import appDownloadManager from '../lib/appManagers/appDownloadManager';
import wrapPeerTitle from './wrappers/peerTitle';
import {toastNew} from './toast';
@ -329,10 +328,11 @@ export default class AppMediaViewerBase<
return false;
},
verifyTouchTarget: (evt) => {
console.log('verify');
verifyTouchTarget: (e) => {
// * Fix for seek input
if((evt.target as HTMLElement).tagName === 'INPUT' || findUpClassName(evt.target, 'media-viewer-caption')) {
if(findUpClassName(e.target, 'ckin__controls') ||
findUpClassName(e.target, 'media-viewer-caption') ||
findUpClassName(e.target, 'media-viewer-topbar')) {
return false;
}

View File

@ -267,7 +267,7 @@ export default class AppGeneralSettingsTab extends SliderSuperTabEventable {
managers: this.managers,
loadPromises,
middleware: this.middlewareHelper.get(),
play: rootScope.settings.animationsEnabled
play: false
}).then(({render}) => render).then((player) => {
k.player = player as RLottiePlayer;
});

View File

@ -54,6 +54,16 @@ const locksUrls: {[docId: string]: string} = {};
export const videosCache: {[key: string]: Promise<any>} = {};
const onAnimationEnd = (element: HTMLElement, onAnimationEnd: () => void, timeout: number) => {
const onEnd = () => {
element.removeEventListener('animationend', onEnd);
onAnimationEnd();
clearTimeout(_timeout);
};
element.addEventListener('animationend', onEnd);
const _timeout = setTimeout(onEnd, timeout);
};
export default async function wrapSticker({doc, div, middleware, loadStickerMiddleware, lazyLoadQueue, exportLoad, group, play, onlyThumb, emoji, width, height, withThumb, loop, loadPromises, needFadeIn, needUpscale, skipRatio, static: asStatic, managers = rootScope.managers, fullThumb, isOut, noPremium, withLock, relativeEffect, loopEffect, isCustomEmoji, syncedVideo}: {
doc: MyDocument,
div: HTMLElement | HTMLElement[],
@ -200,10 +210,12 @@ export default async function wrapSticker({doc, div, middleware, loadStickerMidd
const afterRender = (div: HTMLElement, thumbImage: HTMLElement) => {
if(!div.childElementCount) {
thumbImage.classList.add('media-sticker', 'thumbnail');
sequentialDom.mutateElement(div, () => {
div.append(thumbImage);
if(!div.childElementCount) {
thumbImage.classList.add('media-sticker', 'thumbnail');
div.append(thumbImage);
}
loadThumbPromise.resolve();
});
} else {
@ -364,94 +376,92 @@ export default async function wrapSticker({doc, div, middleware, loadStickerMidd
}
if(stickerType === 2 && !asStatic) {
return appDownloadManager.downloadMedia({media: doc, queueId: lazyLoadQueue?.queueId, thumb: fullThumb})
.then(async(blob) => {
if(middleware && !middleware()) {
throw middlewareError;
const blob = await appDownloadManager.downloadMedia({media: doc, queueId: lazyLoadQueue?.queueId, thumb: fullThumb});
if(middleware && !middleware()) {
throw middlewareError;
}
const animation = await lottieLoader.loadAnimationWorker({
container: (div as HTMLElement[])[0],
loop: !!(!emoji || isCustomEmoji) && loop,
autoplay: play,
animationData: blob,
width,
height,
name: 'doc' + doc.id,
needUpscale,
skipRatio,
toneIndex,
sync: isCustomEmoji,
middleware: loadStickerMiddleware ?? middleware,
group
});
// const deferred = deferredPromise<void>();
const setLockColor = willHaveLock ? () => {
const lockUrl = locksUrls[doc.id] ??= computeLockColor(animation.canvas[0]);
(div as HTMLElement[]).forEach((div) => div.style.setProperty('--lock-url', `url(${lockUrl})`));
} : undefined;
const onFirstFrame = (container: HTMLElement, canvas: HTMLCanvasElement) => {
const element = container.firstElementChild !== canvas && container.firstElementChild as HTMLElement;
if(needFadeIn !== false) {
needFadeIn = (needFadeIn || !element || element.tagName === 'svg') && rootScope.settings.animationsEnabled;
}
const animation = await lottieLoader.loadAnimationWorker({
container: (div as HTMLElement[])[0],
loop: !!(!emoji || isCustomEmoji) && loop,
autoplay: play,
animationData: blob,
width,
height,
name: 'doc' + doc.id,
needUpscale,
skipRatio,
toneIndex,
sync: isCustomEmoji,
middleware: loadStickerMiddleware ?? middleware,
group
});
// const deferred = deferredPromise<void>();
const setLockColor = willHaveLock ? () => {
const lockUrl = locksUrls[doc.id] ??= computeLockColor(animation.canvas[0]);
(div as HTMLElement[]).forEach((div) => div.style.setProperty('--lock-url', `url(${lockUrl})`));
} : undefined;
const onFirstFrame = (container: HTMLElement, canvas: HTMLCanvasElement) => {
const element = container.firstElementChild;
if(needFadeIn !== false) {
needFadeIn = (needFadeIn || !element || element.tagName === 'svg') && rootScope.settings.animationsEnabled;
}
const cb = () => {
if(element && element !== canvas && element.tagName !== 'DIV') {
element.remove();
}
};
if(!needFadeIn) {
if(element) {
sequentialDom.mutate(cb);
}
} else {
sequentialDom.mutate(() => {
canvas && canvas.classList.add('fade-in');
if(element) {
element.classList.add('fade-out');
}
(canvas || element).addEventListener('animationend', () => {
sequentialDom.mutate(() => {
canvas && canvas.classList.remove('fade-in');
cb();
});
}, {once: true});
});
const cb = () => {
if(element && element !== canvas && element.tagName !== 'DIV') {
element.remove();
}
};
animation.addEventListener('firstFrame', () => {
const canvas = animation.canvas[0];
if(withThumb !== false || isCustomEmoji) {
saveLottiePreview(doc, canvas, toneIndex);
if(!needFadeIn) {
if(element) {
sequentialDom.mutate(cb);
}
} else {
sequentialDom.mutate(() => {
canvas && canvas.classList.add('fade-in');
if(element) {
element.classList.add('fade-out');
}
if(willHaveLock) {
setLockColor();
}
onAnimationEnd(canvas || element, () => {
sequentialDom.mutate(() => {
canvas && canvas.classList.remove('fade-in');
cb();
});
}, 400);
});
}
};
if(!isCustomEmoji) {
(div as HTMLElement[]).forEach((container, idx) => {
onFirstFrame(container, animation.canvas[idx]);
});
}
}, {once: true});
if(emoji) {
managers.appStickersManager.preloadAnimatedEmojiStickerAnimation(emoji);
animation.addEventListener('firstFrame', () => {
const canvas = animation.canvas[0];
if(withThumb !== false || isCustomEmoji) {
saveLottiePreview(doc, canvas, toneIndex);
}
return animation;
if(willHaveLock) {
setLockColor();
}
// return deferred;
// await new Promise((resolve) => setTimeout(resolve, 5e3));
});
if(!isCustomEmoji) {
(div as HTMLElement[]).forEach((container, idx) => {
onFirstFrame(container, animation.canvas[idx]);
});
}
}, {once: true});
if(emoji) {
managers.appStickersManager.preloadAnimatedEmojiStickerAnimation(emoji);
}
return animation;
// return deferred;
// await new Promise((resolve) => setTimeout(resolve, 5e3));
} else if(asStatic || stickerType === 3) {
const isSingleVideo = isAnimated && syncedVideo;
const cacheName = isSingleVideo ? framesCache.generateName('' + doc.id, 0, 0, undefined, undefined) : undefined;
@ -550,10 +560,10 @@ export default async function wrapSticker({doc, div, middleware, loadStickerMidd
if(needFadeIn) {
thumbImage && thumbImage.classList.add('fade-out');
media.addEventListener('animationend', () => {
onAnimationEnd(media, () => {
media.classList.remove('fade-in');
thumbImage?.remove();
}, {once: true});
}, 400);
} else {
thumbImage?.remove();
}

View File

@ -25,9 +25,9 @@ export default async function wrapStickerEmoji(options: Modify<Parameters<typeof
}
return wrapSticker({
...options,
doc,
play: true,
loop: false,
play: true
...options
});
}

View File

@ -10,6 +10,7 @@ import type AppBackgroundTab from '../components/sidebarLeft/tabs/background';
import IS_TOUCH_SUPPORTED from '../environment/touchSupport';
import rootScope from '../lib/rootScope';
import {changeColorAccent, ColorRgb, getAccentColor, getAverageColor, getHexColorFromTelegramColor, getRgbColorFromTelegramColor, hexToRgb, hslaStringToHex, hsvToRgb, mixColors, rgbaToHexa, rgbaToHsla, rgbToHsv} from './color';
import {MOUNT_CLASS_TO} from '../config/debug';
type AppColorName = 'primary-color' | 'message-out-primary-color' |
'surface-color' | 'danger-color' | 'primary-text-color' |
@ -89,6 +90,7 @@ export class ThemeController {
private themeColor: string;
private _themeColorElem: Element;
private systemTheme: AppTheme['name'];
private styleElement: HTMLStyleElement;
public AppBackgroundTab: typeof AppBackgroundTab;
constructor() {
@ -147,7 +149,7 @@ export class ThemeController {
public applyHighlightningColor() {
let hsla: string;
const theme = themeController.getTheme();
const theme = this.getTheme();
if(theme.settings?.highlightningColor) {
hsla = theme.settings.highlightningColor;
document.documentElement.style.setProperty('--message-highlightning-color', hsla);
@ -156,7 +158,7 @@ export class ThemeController {
}
if(!IS_TOUCH_SUPPORTED && hsla) {
themeController.themeColor = hslaStringToHex(hsla);
this.themeColor = hslaStringToHex(hsla);
}
}
@ -169,7 +171,19 @@ export class ThemeController {
document.documentElement.classList.toggle('night', isNight);
this.setThemeColor();
this.applyTheme(this.getTheme());
const theme = this.getTheme();
this.applyTheme(theme);
let style = this.styleElement;
if(!style) {
style = this.styleElement = document.createElement('style');
document.head.append(style);
}
const e = document.createElement('div');
this.applyTheme(rootScope.settings.themes.find((theme) => theme.name === 'night'), e);
console.log(e.style.cssText);
style.textContent = `.night {${e.style.cssText}}`;
this.applyHighlightningColor();
}
@ -188,7 +202,7 @@ export class ThemeController {
}
// theme applier
private bindColorApplier(options: Pick<Parameters<ThemeController['applyAppColor']>[0], 'element'>) {
private bindColorApplier(options: Pick<Parameters<ThemeController['applyAppColor']>[0], 'element' | 'isNight'>) {
const appliedColors: Set<AppColorName> = new Set();
return {
applyAppColor: (_options: Omit<Parameters<ThemeController['applyAppColor']>[0], keyof typeof options>) => {
@ -196,12 +210,13 @@ export class ThemeController {
return this.applyAppColor({..._options, ...options});
},
finalize: () => {
const isNight = this.isNight();
const isNight = options.isNight;
for(const name in appColorMap) {
if(!appliedColors.has(name as AppColorName)) {
this.applyAppColor({
name: name as AppColorName,
hex: colorMap[isNight ? 'night' : 'day'][name as AppColorName]
hex: colorMap[isNight ? 'night' : 'day'][name as AppColorName],
...options
});
}
}
@ -212,23 +227,25 @@ export class ThemeController {
private applyAppColor({
name,
hex,
element = document.documentElement,
element,
lightenAlpha = 0.08,
darkenAlpha = lightenAlpha,
mixColor
mixColor,
isNight
}: {
name: AppColorName,
hex: string,
element?: HTMLElement,
element: HTMLElement,
lightenAlpha?: number
darkenAlpha?: number,
mixColor?: ColorRgb
mixColor?: ColorRgb,
isNight?: boolean
}) {
const appColor = appColorMap[name];
const rgb = hexToRgb(hex);
const hsla = rgbaToHsla(...rgb);
mixColor ??= hexToRgb(colorMap[themeController.isNight() ? 'night' : 'day']['surface-color']);
mixColor ??= hexToRgb(colorMap[isNight ? 'night' : 'day']['surface-color']);
const lightenedRgb = mixColors(rgb, mixColor, lightenAlpha);
const darkenedHsla: typeof hsla = {
@ -236,16 +253,22 @@ export class ThemeController {
l: hsla.l - darkenAlpha * 100
};
element.style.setProperty('--' + name, hex);
appColor.rgb && element.style.setProperty('--' + name + '-rgb', rgb.join(','));
appColor.light && element.style.setProperty('--light-' + name, `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, ${lightenAlpha})`);
appColor.lightFilled && element.style.setProperty('--light-filled-' + name, rgbaToHexa(lightenedRgb));
appColor.dark && element.style.setProperty('--dark-' + name, `hsl(${darkenedHsla.h}, ${darkenedHsla.s}%, ${darkenedHsla.l}%)`);
// appColor.darkFilled && element.style.setProperty('--dark-' + name, `hsl(${darkenedHsla.h}, ${darkenedHsla.s}%, ${darkenedHsla.l}%)`);
const properties: [string, string][] = [
[name, hex],
appColor.rgb && [name + '-rgb', rgb.join(',')],
appColor.light && ['light-' + name, `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, ${lightenAlpha})`],
appColor.lightFilled && ['light-filled-' + name, rgbaToHexa(lightenedRgb)],
appColor.dark && ['dark-' + name, `hsl(${darkenedHsla.h}, ${darkenedHsla.s}%, ${darkenedHsla.l}%)`]
// appColor.darkFilled && ['dark-' + name, `hsl(${darkenedHsla.h}, ${darkenedHsla.s}%, ${darkenedHsla.l}%)`]
];
properties.filter(Boolean).forEach(([name, value]) => {
element.style.setProperty('--' + name, value);
});
}
public async applyNewTheme(theme: Theme) {
const isNight = this.isNight();
const isNight = this.isNightTheme(theme);
const currentTheme = this.getTheme();
const themes = rootScope.settings.themes;
const themeSettings = theme.settings.find((themeSettings) => themeSettings.base_theme._ === (isNight ? 'baseThemeNight' : 'baseThemeClassic'));
@ -264,8 +287,12 @@ export class ThemeController {
rootScope.dispatchEvent('theme_change');
}
public async applyTheme(theme: Theme | AppTheme, element = document.documentElement) {
const isNight = themeController.isNight();
private isNightTheme(theme: Theme | AppTheme) {
return (theme as AppTheme).name === 'night' || this.isNight();
}
public applyTheme(theme: Theme | AppTheme, element = document.documentElement) {
const isNight = this.isNightTheme(theme);
const themeSettings = Array.isArray(theme.settings) ?
theme.settings.find((settings) => settings.base_theme._ === (isNight ? 'baseThemeNight' : 'baseThemeClassic')) :
theme.settings;
@ -282,7 +309,7 @@ export class ThemeController {
);
const newAccentHex = rgbaToHexa(newAccentRgb);
const {applyAppColor, finalize} = this.bindColorApplier({element});
const {applyAppColor, finalize} = this.bindColorApplier({element, isNight});
applyAppColor({
name: 'primary-color',
@ -295,7 +322,7 @@ export class ThemeController {
hex: newAccentHex,
lightenAlpha: 0.64,
mixColor: [255, 255, 255]
})
});
if(!themeSettings.message_colors?.length) {
return;
@ -357,4 +384,5 @@ export class ThemeController {
}
const themeController = new ThemeController();
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.themeController = themeController);
export default themeController;

View File

@ -327,16 +327,15 @@ export class UiNotificationsManager {
notification.image = url;
} else {
const WIDTH = 54, HEIGHT = WIDTH;
let {avatarCanvas, avatarContext} = this;
if(!this.avatarCanvas) {
avatarCanvas = this.avatarCanvas = document.createElement('canvas');
avatarContext = this.avatarContext = avatarCanvas.getContext('2d');
const dpr = window.devicePixelRatio;
const SIZE = 54;
const dpr = 1;
avatarCanvas.dpr = dpr;
avatarCanvas.width = 54 * dpr;
avatarCanvas.height = 54 * dpr;
avatarCanvas.width = avatarCanvas.height = SIZE * dpr;
this.avatarGradients = {};
} else {
@ -346,7 +345,7 @@ export class UiNotificationsManager {
const color = getPeerColorById(peerId, true);
let gradient = this.avatarGradients[color];
if(!gradient) {
gradient = this.avatarGradients[color] = avatarContext.createLinearGradient(WIDTH / 2, 0, WIDTH / 2, HEIGHT);
gradient = this.avatarGradients[color] = avatarContext.createLinearGradient(avatarCanvas.width / 2, 0, avatarCanvas.width / 2, avatarCanvas.height);
const colorTop = customProperties.getProperty(`peer-avatar-${color}-top`);
const colorBottom = customProperties.getProperty(`peer-avatar-${color}-bottom`);
@ -356,10 +355,10 @@ export class UiNotificationsManager {
avatarContext.fillStyle = gradient;
drawCircle(avatarContext, WIDTH / 2, HEIGHT / 2, WIDTH / 2);
drawCircle(avatarContext, avatarCanvas.width / 2, avatarCanvas.height / 2, avatarCanvas.width / 2);
avatarContext.fill();
const fontSize = 20 * window.devicePixelRatio;
const fontSize = 20 * avatarCanvas.dpr;
const abbreviation = getAbbreviation(peerTitle);
avatarContext.font = `700 ${fontSize}px ${FontFamily}`;

View File

@ -863,9 +863,9 @@ $btn-menu-z-index: 4;
transition: background-color var(--transition-standard-in), opacity var(--transition-standard-in);
}
& + &,
&-container + &-container {
margin-inline-start: var(--call-button-margin);
&,
&-container {
margin: 0 var(--call-button-margin);
}
}

View File

@ -37,7 +37,7 @@
}
.group-call {
--call-button-margin: 1.25rem;
--call-button-margin: .625rem;
width: 100%;
height: 100%;
padding: 0 .5rem;