Resize patterns
Optimize dark patterns
This commit is contained in:
parent
da5f6a87c8
commit
45b5cedeb7
@ -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,7 +4,6 @@
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import { IS_SAFARI } from "../../environment/userAgent";
|
||||
import { indexOfAndSplice } from "../../helpers/array";
|
||||
import { renderImageFromUrlPromise } from "../../helpers/dom/renderImageFromUrl";
|
||||
import { deepEqual } from "../../helpers/object";
|
||||
@ -12,19 +11,21 @@ import { deepEqual } from "../../helpers/object";
|
||||
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 +46,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 +105,7 @@ export default class ChatBackgroundPatternRenderer {
|
||||
resolve(newUrl);
|
||||
}, 'image/png');
|
||||
});
|
||||
}
|
||||
} */
|
||||
|
||||
public cleanup(canvas: HTMLCanvasElement) {
|
||||
this.canvases.delete(canvas);
|
||||
@ -102,9 +121,34 @@ 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) {
|
||||
context.drawImage(img, x, 0);
|
||||
}
|
||||
// context.fillStyle = this.pattern;
|
||||
// context.fillRect(0, 0, canvas.width, canvas.height);
|
||||
// console.warn('fill canvas time', performance.now() - perf);
|
||||
}
|
||||
|
||||
public setCanvasDimensions(canvas: HTMLCanvasElement) {
|
||||
@ -118,4 +162,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);
|
||||
});
|
||||
}
|
||||
|
@ -84,6 +84,7 @@ import htmlToSpan from '../../helpers/dom/htmlToSpan';
|
||||
import getVisibleRect from '../../helpers/dom/getVisibleRect';
|
||||
import { simulateClickEvent } from '../../helpers/dom/clickEvent';
|
||||
import appReactionsManager from './appReactionsManager';
|
||||
import ChatBackgroundPatternRenderer from '../../components/chat/patternRenderer';
|
||||
|
||||
//console.log('appImManager included33!');
|
||||
|
||||
@ -229,11 +230,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) => {
|
||||
|
@ -722,7 +722,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