Merge branch 'bg-fixes'
This commit is contained in:
commit
82488dda32
@ -85,6 +85,7 @@ export default class Chat extends EventListenerBase<{
|
||||
public patternCanvas: HTMLCanvasElement;
|
||||
public backgroundTempId: number;
|
||||
public setBackgroundPromise: Promise<void>;
|
||||
// public renderDarkPattern: () => Promise<void>;
|
||||
|
||||
constructor(
|
||||
public appImManager: AppImManager,
|
||||
@ -159,6 +160,7 @@ export default class Chat extends EventListenerBase<{
|
||||
this.patternRenderer =
|
||||
this.gradientCanvas =
|
||||
this.patternCanvas =
|
||||
// this.renderDarkPattern =
|
||||
undefined;
|
||||
|
||||
const intensity = theme.background.intensity && theme.background.intensity / 100;
|
||||
@ -179,11 +181,28 @@ export default class Chat extends EventListenerBase<{
|
||||
patternRenderer = this.patternRenderer = ChatBackgroundPatternRenderer.getInstance({
|
||||
url,
|
||||
width: rect.width,
|
||||
height: rect.height
|
||||
height: rect.height,
|
||||
mask: isDarkPattern
|
||||
});
|
||||
|
||||
patternCanvas = this.patternCanvas = patternRenderer.createCanvas();
|
||||
patternCanvas.classList.add('chat-background-item-canvas', 'chat-background-item-pattern-canvas');
|
||||
|
||||
if(isDarkPattern) {
|
||||
item.classList.add('is-dark');
|
||||
}
|
||||
|
||||
// if(isDarkPattern) {
|
||||
// this.renderDarkPattern = () => {
|
||||
// return patternRenderer.exportCanvasPatternToImage(patternCanvas).then(url => {
|
||||
// if(this.backgroundTempId !== tempId) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// gradientCanvas.style.webkitMaskImage = `url(${url})`;
|
||||
// });
|
||||
// };
|
||||
// }
|
||||
} else if(theme.background.slug) {
|
||||
item.classList.add('is-image');
|
||||
}
|
||||
@ -236,7 +255,11 @@ export default class Chat extends EventListenerBase<{
|
||||
return;
|
||||
}
|
||||
|
||||
const append = [gradientCanvas, isDarkPattern ? undefined : patternCanvas].filter(Boolean);
|
||||
const append = [
|
||||
gradientCanvas,
|
||||
// isDarkPattern && this.renderDarkPattern ? undefined : patternCanvas
|
||||
patternCanvas
|
||||
].filter(Boolean);
|
||||
if(append.length) {
|
||||
item.append(...append);
|
||||
}
|
||||
@ -261,18 +284,16 @@ export default class Chat extends EventListenerBase<{
|
||||
if(patternRenderer) {
|
||||
const renderPatternPromise = patternRenderer.renderToCanvas(patternCanvas);
|
||||
renderPatternPromise.then(() => {
|
||||
let promise: Promise<any>;
|
||||
if(isDarkPattern) {
|
||||
promise = patternRenderer.exportCanvasPatternToImage(patternCanvas).then(url => {
|
||||
if(this.backgroundTempId !== tempId) {
|
||||
return;
|
||||
}
|
||||
|
||||
gradientCanvas.style.webkitMaskImage = `url(${url})`;
|
||||
});
|
||||
} else {
|
||||
promise = Promise.resolve();
|
||||
if(this.backgroundTempId !== tempId) {
|
||||
return;
|
||||
}
|
||||
|
||||
let promise: Promise<any>;
|
||||
// if(isDarkPattern && this.renderDarkPattern) {
|
||||
// promise = this.renderDarkPattern();
|
||||
// } else {
|
||||
promise = Promise.resolve();
|
||||
// }
|
||||
|
||||
promise.then(cb);
|
||||
});
|
||||
|
@ -4,27 +4,29 @@
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import { IS_SAFARI } from "../../environment/userAgent";
|
||||
import indexOfAndSplice from "../../helpers/array/indexOfAndSplice";
|
||||
import { renderImageFromUrlPromise } from "../../helpers/dom/renderImageFromUrl";
|
||||
import deepEqual from "../../helpers/object/deepEqual";
|
||||
import { renderImageFromUrlPromise } from "../../helpers/dom/renderImageFromUrl";
|
||||
import mediaSizes, { ScreenSize } from "../../helpers/mediaSizes";
|
||||
|
||||
type ChatBackgroundPatternRendererInitOptions = {
|
||||
url: string,
|
||||
width: number,
|
||||
height: number
|
||||
height: number,
|
||||
mask?: boolean
|
||||
};
|
||||
|
||||
export default class ChatBackgroundPatternRenderer {
|
||||
private static INSTANCES: ChatBackgroundPatternRenderer[] = [];
|
||||
|
||||
private pattern: CanvasPattern;
|
||||
// private pattern: CanvasPattern;
|
||||
private objectUrl: string;
|
||||
private options: ChatBackgroundPatternRendererInitOptions;
|
||||
private canvases: Set<HTMLCanvasElement>;
|
||||
private createCanvasPatternPromise: Promise<void>;
|
||||
private exportCanvasPatternToImagePromise: Promise<string>;
|
||||
// private img: HTMLImageElement;
|
||||
// private createCanvasPatternPromise: Promise<CanvasPattern>;
|
||||
// private exportCanvasPatternToImagePromise: Promise<string>;
|
||||
private renderImageFromUrlPromise: Promise<HTMLImageElement>;
|
||||
private img: HTMLImageElement;
|
||||
|
||||
constructor() {
|
||||
this.canvases = new Set();
|
||||
@ -45,36 +47,54 @@ export default class ChatBackgroundPatternRenderer {
|
||||
}
|
||||
|
||||
public init(options: ChatBackgroundPatternRendererInitOptions) {
|
||||
// if(this.options) {
|
||||
// if(this.options.width !== options.width || this.options.height !== options.height) {
|
||||
// this.createCanvasPatternPromise =
|
||||
// this.pattern =
|
||||
// this.exportCanvasPatternToImagePromise =
|
||||
// undefined;
|
||||
// }
|
||||
// }
|
||||
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public renderToCanvas(canvas: HTMLCanvasElement) {
|
||||
return this.createCanvasPattern(canvas).then(() => {
|
||||
// return this.createCanvasPattern(canvas).then(() => {
|
||||
// return this.fillCanvas(canvas);
|
||||
// });
|
||||
|
||||
return this.renderImageFromUrl(this.options.url).then(() => {
|
||||
return this.fillCanvas(canvas);
|
||||
});
|
||||
}
|
||||
|
||||
private createCanvasPattern(canvas: HTMLCanvasElement) {
|
||||
private renderImageFromUrl(url: string) {
|
||||
if(this.renderImageFromUrlPromise) return this.renderImageFromUrlPromise;
|
||||
const img = this.img = document.createElement('img');
|
||||
img.crossOrigin = 'anonymous';
|
||||
return this.renderImageFromUrlPromise = renderImageFromUrlPromise(img, url, false).then(() => img);
|
||||
}
|
||||
|
||||
/* private createCanvasPattern(canvas: HTMLCanvasElement) {
|
||||
if(this.createCanvasPatternPromise) return this.createCanvasPatternPromise;
|
||||
return this.createCanvasPatternPromise = new Promise((resolve) => {
|
||||
const img = document.createElement('img');
|
||||
img.crossOrigin = 'anonymous';
|
||||
renderImageFromUrlPromise(img, this.options.url, false).then(() => {
|
||||
let createPatternFrom: HTMLImageElement | HTMLCanvasElement;
|
||||
if(IS_SAFARI) {
|
||||
const canvas = createPatternFrom = document.createElement('canvas');
|
||||
canvas.width = img.naturalWidth;
|
||||
canvas.height = img.naturalHeight;
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
||||
} else {
|
||||
createPatternFrom = img;
|
||||
}
|
||||
|
||||
// this.img = img;
|
||||
this.pattern = canvas.getContext('2d').createPattern(createPatternFrom, 'repeat-x');
|
||||
resolve();
|
||||
});
|
||||
return this.createCanvasPatternPromise = this.renderImageFromUrl(this.options.url).then((img) => {
|
||||
let createPatternFrom: HTMLImageElement | HTMLCanvasElement;
|
||||
if(IS_SAFARI) {
|
||||
const canvas = createPatternFrom = document.createElement('canvas');
|
||||
canvas.width = img.naturalWidth;
|
||||
canvas.height = img.naturalHeight;
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
||||
} else {
|
||||
createPatternFrom = img;
|
||||
}
|
||||
|
||||
const perf = performance.now();
|
||||
this.pattern = canvas.getContext('2d').createPattern(createPatternFrom, 'repeat-x');
|
||||
console.warn('creating pattern time:', performance.now() - perf);
|
||||
|
||||
return this.pattern;
|
||||
});
|
||||
}
|
||||
|
||||
@ -86,7 +106,7 @@ export default class ChatBackgroundPatternRenderer {
|
||||
resolve(newUrl);
|
||||
}, 'image/png');
|
||||
});
|
||||
}
|
||||
} */
|
||||
|
||||
public cleanup(canvas: HTMLCanvasElement) {
|
||||
this.canvases.delete(canvas);
|
||||
@ -102,14 +122,42 @@ export default class ChatBackgroundPatternRenderer {
|
||||
|
||||
public fillCanvas(canvas: HTMLCanvasElement) {
|
||||
const context = canvas.getContext('2d');
|
||||
context.fillStyle = this.pattern;
|
||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||
// context.drawImage(this.img, 0, 0, canvas.width, canvas.height);
|
||||
if(context.fillStyle instanceof CanvasPattern) {
|
||||
context.clearRect(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
|
||||
// const perf = performance.now();
|
||||
const img = this.img;
|
||||
|
||||
let imageWidth = img.width, imageHeight = img.height;
|
||||
// if(imageHeight < canvas.height) {
|
||||
const ratio = canvas.height / imageHeight;
|
||||
imageWidth *= ratio;
|
||||
imageHeight = canvas.height;
|
||||
// }
|
||||
|
||||
if(this.options.mask) {
|
||||
context.fillStyle = '#000';
|
||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||
context.globalCompositeOperation = 'destination-out';
|
||||
} else {
|
||||
context.globalCompositeOperation = 'source-over';
|
||||
}
|
||||
|
||||
for(let x = 0; x < canvas.width; x += imageWidth) {
|
||||
for(let y = 0; y < canvas.height; y += imageHeight) {
|
||||
context.drawImage(img, x, y, imageWidth, imageHeight);
|
||||
}
|
||||
}
|
||||
// context.fillStyle = this.pattern;
|
||||
// context.fillRect(0, 0, canvas.width, canvas.height);
|
||||
// console.warn('fill canvas time', performance.now() - perf);
|
||||
}
|
||||
|
||||
public setCanvasDimensions(canvas: HTMLCanvasElement) {
|
||||
canvas.width = this.options.width * window.devicePixelRatio;
|
||||
canvas.height = this.options.height * window.devicePixelRatio * 1.5;
|
||||
const devicePixelRatio = Math.min(2, window.devicePixelRatio);
|
||||
canvas.width = this.options.width * devicePixelRatio;
|
||||
canvas.height = this.options.height * devicePixelRatio * (mediaSizes.activeScreen === ScreenSize.large ? 1.5 : 1);
|
||||
}
|
||||
|
||||
public createCanvas() {
|
||||
@ -118,4 +166,34 @@ export default class ChatBackgroundPatternRenderer {
|
||||
this.setCanvasDimensions(canvas);
|
||||
return canvas;
|
||||
}
|
||||
|
||||
public resize(width: number, height: number) {
|
||||
this.init({
|
||||
...this.options,
|
||||
width,
|
||||
height
|
||||
});
|
||||
|
||||
const promises: Promise<any>[] = [];
|
||||
for(const canvas of this.canvases) {
|
||||
this.setCanvasDimensions(canvas);
|
||||
promises.push(this.renderToCanvas(canvas));
|
||||
}
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
public static resizeInstances(width: number, height: number) {
|
||||
return Promise.all(this.INSTANCES.map(instance => instance.resize(width, height)));
|
||||
}
|
||||
|
||||
/* public setResizeMode(resizing: boolean) {
|
||||
const canvases = Array.from(this.canvases);
|
||||
const canvas = canvases[canvases.length - 1];
|
||||
canvas.style.display = resizing ? 'none' : '';
|
||||
const img = this.img;
|
||||
img.style.display = resizing ? '' : 'none';
|
||||
|
||||
return {img, canvas};
|
||||
} */
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ export default function renderImageFromUrl(
|
||||
}
|
||||
|
||||
export function renderImageFromUrlPromise(elem: Parameters<typeof renderImageFromUrl>[0], url: string, useCache?: boolean) {
|
||||
return new Promise((resolve) => {
|
||||
return new Promise<Event>((resolve) => {
|
||||
renderImageFromUrl(elem, url, resolve, useCache);
|
||||
});
|
||||
}
|
||||
|
@ -89,6 +89,7 @@ import getObjectKeysAndSort from '../../helpers/object/getObjectKeysAndSort';
|
||||
import type GroupCallInstance from '../calls/groupCallInstance';
|
||||
import type CallInstance from '../calls/callInstance';
|
||||
import numberThousandSplitter from '../../helpers/number/numberThousandSplitter';
|
||||
import ChatBackgroundPatternRenderer from '../../components/chat/patternRenderer';
|
||||
|
||||
//console.log('appImManager included33!');
|
||||
|
||||
@ -234,11 +235,17 @@ export class AppImManager {
|
||||
this.appendEmojiAnimationContainer(to);
|
||||
});
|
||||
|
||||
const resizeBackgroundDebounced = debounce(() => {
|
||||
this.setBackground(this.lastBackgroundUrl, false);
|
||||
}, 200, false, true);
|
||||
mediaSizes.addEventListener('resize', () => {
|
||||
resizeBackgroundDebounced();
|
||||
// const perf = performance.now();
|
||||
const rect = this.chatsContainer.getBoundingClientRect();
|
||||
ChatBackgroundPatternRenderer.resizeInstances(rect.width, rect.height).then(() => {
|
||||
// this.log.warn('resize bg time:', performance.now() - perf);
|
||||
// for(const chat of this.chats) {
|
||||
// if(chat.renderDarkPattern) {
|
||||
// chat.renderDarkPattern();
|
||||
// }
|
||||
// }
|
||||
});
|
||||
});
|
||||
|
||||
rootScope.addEventListener('history_focus', (e) => {
|
||||
|
@ -691,8 +691,11 @@ $background-transition-total-time: #{$input-transition-time - $background-transi
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
// mix-blend-mode: overlay;
|
||||
height: 150%;
|
||||
top: -25%;
|
||||
|
||||
@include respond-to(medium-screens) {
|
||||
height: 150%;
|
||||
top: -25%;
|
||||
}
|
||||
}
|
||||
|
||||
@include animation-level(2) {
|
||||
@ -727,7 +730,7 @@ $background-transition-total-time: #{$input-transition-time - $background-transi
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-pattern-canvas {
|
||||
&:not(.is-dark) &-pattern-canvas {
|
||||
mix-blend-mode: overlay;
|
||||
// height: 100%;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user