Performance fix
This commit is contained in:
parent
4ab2c8036d
commit
3763ef768e
@ -959,7 +959,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
||||
img = new Image();
|
||||
img.src = cacheContext.url;
|
||||
} else {
|
||||
const gotThumb = appPhotosManager.getStrippedThumbIfNeeded(media);
|
||||
const gotThumb = appPhotosManager.getStrippedThumbIfNeeded(media, true);
|
||||
if(gotThumb) {
|
||||
thumbPromise = gotThumb.loadPromise;
|
||||
img = gotThumb.image;
|
||||
|
@ -291,9 +291,9 @@ export default class AppSearchSuper {
|
||||
// Jolly Cobra's // Workaround for scrollable content flickering during animation.
|
||||
const container = this.scrollable.container;
|
||||
if(container.style.overflowY !== 'hidden') {
|
||||
const scrollBarWidth = container.offsetWidth - container.clientWidth;
|
||||
// const scrollBarWidth = container.offsetWidth - container.clientWidth;
|
||||
container.style.overflowY = 'hidden';
|
||||
container.style.paddingRight = `${scrollBarWidth}px`;
|
||||
// container.style.paddingRight = `${scrollBarWidth}px`;
|
||||
this.container.classList.add('sliding');
|
||||
}
|
||||
};
|
||||
@ -313,7 +313,7 @@ export default class AppSearchSuper {
|
||||
container.style.display = '';
|
||||
}
|
||||
|
||||
container.style.paddingRight = '0';
|
||||
// container.style.paddingRight = '0';
|
||||
this.container.classList.remove('sliding');
|
||||
};
|
||||
|
||||
@ -478,7 +478,8 @@ export default class AppSearchSuper {
|
||||
boxHeight: 0,
|
||||
lazyLoadQueue: this.lazyLoadQueue,
|
||||
middleware,
|
||||
withoutPreloader: true
|
||||
withoutPreloader: true,
|
||||
noBlur: true
|
||||
});
|
||||
}
|
||||
|
||||
@ -586,7 +587,8 @@ export default class AppSearchSuper {
|
||||
lazyLoadQueue: this.lazyLoadQueue,
|
||||
middleware,
|
||||
size: appPhotosManager.choosePhotoSize(webpage.photo, 60, 60, false),
|
||||
loadPromises: promises
|
||||
loadPromises: promises,
|
||||
noBlur: true
|
||||
});
|
||||
} else {
|
||||
previewDiv.classList.add('empty');
|
||||
|
@ -15,7 +15,7 @@ import type { AppPeersManager } from "../../lib/appManagers/appPeersManager";
|
||||
import type sessionStorage from '../../lib/sessionStorage';
|
||||
import type Chat from "./chat";
|
||||
import { CHAT_ANIMATION_GROUP } from "../../lib/appManagers/appImManager";
|
||||
import { cancelEvent, whichChild, getElementByPoint, attachClickEvent, positionElementByIndex, reflowScrollableElement } from "../../helpers/dom";
|
||||
import { cancelEvent, whichChild, attachClickEvent, positionElementByIndex, reflowScrollableElement, replaceContent } from "../../helpers/dom";
|
||||
import { getObjectKeysAndSort } from "../../helpers/object";
|
||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||
import { logger } from "../../lib/logger";
|
||||
@ -58,6 +58,7 @@ import { forEachReverse } from "../../helpers/array";
|
||||
import findUpClassName from "../../helpers/dom/findUpClassName";
|
||||
import findUpTag from "../../helpers/dom/findUpTag";
|
||||
import { toast } from "../toast";
|
||||
import { getElementByPoint } from "../../helpers/dom/getElementByPoint";
|
||||
|
||||
const USE_MEDIA_TAILS = false;
|
||||
const IGNORE_ACTIONS: Message.messageService['action']['_'][] = [/* 'messageActionHistoryClear' */];
|
||||
@ -71,7 +72,6 @@ export default class ChatBubbles {
|
||||
bubblesContainer: HTMLDivElement;
|
||||
chatInner: HTMLDivElement;
|
||||
scrollable: Scrollable;
|
||||
scroll: HTMLElement;
|
||||
|
||||
private getHistoryTopPromise: Promise<boolean>;
|
||||
private getHistoryBottomPromise: Promise<boolean>;
|
||||
@ -140,10 +140,10 @@ export default class ChatBubbles {
|
||||
this.chatInner = document.createElement('div');
|
||||
this.chatInner.classList.add('bubbles-inner');
|
||||
|
||||
this.bubblesContainer.append(this.chatInner);
|
||||
|
||||
this.setScroll();
|
||||
|
||||
this.bubblesContainer.append(this.scrollable.container);
|
||||
|
||||
// * constructor end
|
||||
|
||||
this.log = this.chat.log;
|
||||
@ -1067,10 +1067,12 @@ export default class ChatBubbles {
|
||||
};
|
||||
|
||||
public setScroll() {
|
||||
this.scrollable = new Scrollable(this.bubblesContainer/* .firstElementChild */ as HTMLElement, 'IM', /* 10300 */300);
|
||||
this.scrollable = new Scrollable(null, 'IM', /* 10300 */300);
|
||||
this.scrollable.loadedAll.top = false;
|
||||
this.scrollable.loadedAll.bottom = false;
|
||||
|
||||
this.scrollable.container.append(this.chatInner);
|
||||
|
||||
/* const getScrollOffset = () => {
|
||||
//return Math.round(Math.max(300, appPhotosManager.windowH / 1.5));
|
||||
return 300;
|
||||
@ -1081,17 +1083,14 @@ export default class ChatBubbles {
|
||||
});
|
||||
|
||||
this.scrollable = new Scrollable(this.bubblesContainer, 'y', 'IM', this.chatInner, getScrollOffset()); */
|
||||
this.scroll = this.scrollable.container;
|
||||
|
||||
this.scrollable.onAdditionalScroll = this.onScroll;
|
||||
this.scrollable.onScrolledTop = () => this.loadMoreHistory(true);
|
||||
this.scrollable.onScrolledBottom = () => this.loadMoreHistory(false);
|
||||
//this.scrollable.attachSentinels(undefined, 300);
|
||||
|
||||
this.bubblesContainer.classList.add('scrolled-down');
|
||||
|
||||
if(isTouchSupported) {
|
||||
this.scroll.addEventListener('touchmove', () => {
|
||||
this.scrollable.container.addEventListener('touchmove', () => {
|
||||
if(this.isScrollingTimeout) {
|
||||
clearTimeout(this.isScrollingTimeout);
|
||||
} else if(!this.chatInner.classList.contains('is-scrolling')) {
|
||||
@ -1099,7 +1098,7 @@ export default class ChatBubbles {
|
||||
}
|
||||
}, {passive: true});
|
||||
|
||||
this.scroll.addEventListener('touchend', () => {
|
||||
this.scrollable.container.addEventListener('touchend', () => {
|
||||
if(!this.chatInner.classList.contains('is-scrolling')) {
|
||||
return;
|
||||
}
|
||||
@ -1447,7 +1446,7 @@ export default class ChatBubbles {
|
||||
this.chat.dispatchEvent('setPeer', lastMsgId, false);
|
||||
} else if(topMessage && !isJump) {
|
||||
//this.log('will scroll down', this.scroll.scrollTop, this.scroll.scrollHeight);
|
||||
this.scroll.scrollTop = this.scroll.scrollHeight;
|
||||
this.scrollable.scrollTop = this.scrollable.scrollHeight;
|
||||
this.chat.dispatchEvent('setPeer', lastMsgId, true);
|
||||
}
|
||||
|
||||
@ -1493,9 +1492,8 @@ export default class ChatBubbles {
|
||||
|
||||
const oldChatInner = this.chatInner;
|
||||
this.cleanup();
|
||||
this.chatInner = document.createElement('div');
|
||||
this.chatInner.className = oldChatInner.className;
|
||||
this.chatInner.classList.add('disable-hover', 'is-scrolling');
|
||||
this.chatInner = oldChatInner.cloneNode() as HTMLDivElement;
|
||||
this.chatInner.classList.remove('disable-hover', 'is-scrolling');
|
||||
|
||||
this.lazyLoadQueue.lock();
|
||||
|
||||
@ -1516,7 +1514,7 @@ export default class ChatBubbles {
|
||||
// clear
|
||||
if(!cached) {
|
||||
if(!samePeer) {
|
||||
this.scrollable.container.innerHTML = '';
|
||||
this.scrollable.container.textContent = '';
|
||||
//oldChatInner.remove();
|
||||
this.chat.finishPeerChange(isTarget, isJump, lastMsgId);
|
||||
this.preloader.attach(this.bubblesContainer);
|
||||
@ -1529,9 +1527,6 @@ export default class ChatBubbles {
|
||||
const setPeerPromise = promise.then(() => {
|
||||
////this.log('setPeer removing preloader');
|
||||
|
||||
this.scrollable.container.innerHTML = '';
|
||||
//oldChatInner.remove();
|
||||
|
||||
if(cached) {
|
||||
if(!samePeer) {
|
||||
this.chat.finishPeerChange(isTarget, isJump, lastMsgId); // * костыль
|
||||
@ -1540,11 +1535,14 @@ export default class ChatBubbles {
|
||||
this.preloader.detach();
|
||||
}
|
||||
|
||||
this.scrollable.container.append(this.chatInner);
|
||||
replaceContent(this.scrollable.container, this.chatInner);
|
||||
|
||||
animationIntersector.unlockGroup(CHAT_ANIMATION_GROUP);
|
||||
animationIntersector.checkAnimations(false, CHAT_ANIMATION_GROUP/* , true */);
|
||||
|
||||
this.lazyLoadQueue.unlock();
|
||||
fastRaf(() => {
|
||||
this.lazyLoadQueue.unlock();
|
||||
});
|
||||
|
||||
//if(dialog && lastMsgID && lastMsgID !== topMessage && (this.bubbles[lastMsgID] || this.firstUnreadBubble)) {
|
||||
if(savedPosition) {
|
||||
@ -1564,7 +1562,7 @@ export default class ChatBubbles {
|
||||
const fromUp = maxBubbleId > 0 && (maxBubbleId < lastMsgId || lastMsgId < 0);
|
||||
const followingUnread = readMaxId === lastMsgId && !isTarget;
|
||||
if(!fromUp && samePeer) {
|
||||
this.scrollable.scrollTop = this.scrollable.scrollHeight;
|
||||
this.scrollable.scrollTop = 99999;
|
||||
} else if(fromUp/* && (samePeer || forwardingUnread) */) {
|
||||
this.scrollable.scrollTop = 0;
|
||||
}
|
||||
@ -1583,7 +1581,7 @@ export default class ChatBubbles {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.scrollable.scrollTop = this.scrollable.scrollHeight;
|
||||
this.scrollable.scrollTop = 99999;
|
||||
}
|
||||
|
||||
this.chat.dispatchEvent('setPeer', lastMsgId, !isJump);
|
||||
@ -1613,8 +1611,11 @@ export default class ChatBubbles {
|
||||
}
|
||||
}
|
||||
|
||||
this.chatInner.classList.remove('disable-hover', 'is-scrolling'); // warning, performance!
|
||||
//this.chatInner.classList.remove('disable-hover', 'is-scrolling'); // warning, performance!
|
||||
|
||||
/* if(!document.body.classList.contains(RIGHT_COLUMN_ACTIVE_CLASSNAME)) {
|
||||
return new Promise<void>((resolve) => fastRaf(resolve));
|
||||
} */
|
||||
//console.timeEnd('appImManager setPeer');
|
||||
}).catch(err => {
|
||||
this.log.error('getHistory promise error:', err);
|
||||
@ -2729,9 +2730,9 @@ export default class ChatBubbles {
|
||||
const peerId = this.peerId;
|
||||
|
||||
//console.time('appImManager call getHistory');
|
||||
const pageCount = this.appPhotosManager.windowH / 38/* * 1.25 */ | 0;
|
||||
const pageCount = Math.min(30, this.appPhotosManager.windowH / 38/* * 1.25 */ | 0);
|
||||
//const loadCount = Object.keys(this.bubbles).length > 0 ? 50 : pageCount;
|
||||
const realLoadCount = Object.keys(this.bubbles).length > 0 || additionMsgId ? Math.max(40, pageCount) : pageCount;//const realLoadCount = 50;
|
||||
const realLoadCount = Object.keys(this.bubbles).length > 0/* || additionMsgId */ ? Math.max(40, pageCount) : pageCount;//const realLoadCount = 50;
|
||||
//const realLoadCount = pageCount;//const realLoadCount = 50;
|
||||
let loadCount = realLoadCount;
|
||||
|
||||
|
@ -148,4 +148,4 @@ export default class RepliesElement extends HTMLElement {
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(TAG_NAME, RepliesElement);
|
||||
customElements.define(TAG_NAME, RepliesElement);
|
||||
|
@ -4,7 +4,7 @@
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import { debounce } from "../helpers/schedulers";
|
||||
import { throttle } from "../helpers/schedulers";
|
||||
import { logger, LogLevels } from "../lib/logger";
|
||||
import VisibilityIntersector, { OnVisibilityChange } from "./visibilityIntersector";
|
||||
import { findAndSpliceAll } from "../helpers/array";
|
||||
@ -33,7 +33,7 @@ export class LazyLoadQueueBase {
|
||||
protected processQueue: () => void;
|
||||
|
||||
constructor(protected parallelLimit = PARALLEL_LIMIT) {
|
||||
this.processQueue = debounce(() => this._processQueue(), 20, false, true);
|
||||
this.processQueue = throttle(() => this._processQueue(), 20, false);
|
||||
}
|
||||
|
||||
public clear() {
|
||||
@ -117,6 +117,8 @@ export class LazyLoadQueueBase {
|
||||
protected _processQueue(item?: LazyLoadElementBase) {
|
||||
if(!this.queue.length || this.lockPromise || (this.parallelLimit > 0 && this.inProcess.size >= this.parallelLimit)) return;
|
||||
|
||||
//console.log('_processQueue start');
|
||||
let added = 0;
|
||||
do {
|
||||
if(item) {
|
||||
this.queue.findAndSplice(i => i === item);
|
||||
@ -131,7 +133,9 @@ export class LazyLoadQueueBase {
|
||||
}
|
||||
|
||||
item = null;
|
||||
++added;
|
||||
} while(this.inProcess.size < this.parallelLimit && this.queue.length);
|
||||
//console.log('_processQueue end, added', added, this.queue.length);
|
||||
}
|
||||
|
||||
public push(el: LazyLoadElementBase) {
|
||||
|
@ -21,7 +21,7 @@ import SetTransition from "./singleTransition";
|
||||
import findUpClassName from "../helpers/dom/findUpClassName";
|
||||
|
||||
let lineTotalLength = 0;
|
||||
const tailLength = 9;
|
||||
//const tailLength = 9;
|
||||
const times = 10;
|
||||
const fullTime = 340;
|
||||
const oneTime = fullTime / times;
|
||||
@ -163,8 +163,9 @@ export default class PollElement extends HTMLElement {
|
||||
private votersCountDiv: HTMLDivElement;
|
||||
|
||||
private maxOffset = -46.5;
|
||||
private maxLength: number;
|
||||
private maxLengths: number[];
|
||||
//private maxLength: number;
|
||||
//private maxLengths: number[];
|
||||
private maxPercents: number[];
|
||||
|
||||
public isClosed = false;
|
||||
private isQuiz = false;
|
||||
@ -393,21 +394,17 @@ export default class PollElement extends HTMLElement {
|
||||
footerDiv.append(this.sendVoteBtn);
|
||||
}
|
||||
|
||||
const width = this.getBoundingClientRect().width;
|
||||
this.maxLength = width + tailLength + this.maxOffset + -13.7; // 13 - position left
|
||||
//const width = this.getBoundingClientRect().width;
|
||||
//this.maxLength = width + tailLength + this.maxOffset + -13.7; // 13 - position left
|
||||
|
||||
if(poll.chosenIndexes.length || this.isClosed) {
|
||||
this.performResults(results, poll.chosenIndexes);
|
||||
this.performResults(results, poll.chosenIndexes, false);
|
||||
} else if(!this.isClosed) {
|
||||
this.setVotersCount(results);
|
||||
attachClickEvent(this, this.clickHandler);
|
||||
}
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.render();
|
||||
}
|
||||
|
||||
initQuizHint(results: PollResults) {
|
||||
if(results.solution && results.solution_entities) {
|
||||
const toggleHint = document.createElement('div');
|
||||
@ -486,7 +483,11 @@ export default class PollElement extends HTMLElement {
|
||||
});
|
||||
}
|
||||
|
||||
performResults(results: PollResults, chosenIndexes: number[]) {
|
||||
performResults(results: PollResults, chosenIndexes: number[], animate = true) {
|
||||
if(!rootScope.settings.animationsEnabled) {
|
||||
animate = false;
|
||||
}
|
||||
|
||||
if(this.isQuiz && (results.results?.length || this.isClosed)) {
|
||||
this.answerDivs.forEach((el, idx) => {
|
||||
el.classList.toggle('is-correct', !!results.results[idx].pFlags.correct);
|
||||
@ -533,9 +534,13 @@ export default class PollElement extends HTMLElement {
|
||||
if(this.chosenIndexes.length || this.isRetracted || this.isClosed) {
|
||||
const percents = results.results.map(v => results.total_voters ? v.voters / results.total_voters * 100 : 0);
|
||||
|
||||
SetTransition(this, '', !this.isRetracted, 340);
|
||||
this.classList.toggle('no-transition', !animate);
|
||||
if(animate) {
|
||||
SetTransition(this, '', !this.isRetracted, 340);
|
||||
}
|
||||
|
||||
fastRaf(() => {
|
||||
this.setResults(this.isRetracted ? this.percents : percents, this.chosenIndexes);
|
||||
this.setResults(this.isRetracted ? this.percents : percents, this.chosenIndexes, animate);
|
||||
this.percents = percents;
|
||||
this.isRetracted = false;
|
||||
});
|
||||
@ -576,7 +581,7 @@ export default class PollElement extends HTMLElement {
|
||||
}
|
||||
}
|
||||
|
||||
setResults(percents: number[], chosenIndexes: number[]) {
|
||||
setResults(percents: number[], chosenIndexes: number[], animate: boolean) {
|
||||
this.svgLines.forEach(svg => svg.style.display = '');
|
||||
|
||||
this.answerDivs.forEach((el, idx) => {
|
||||
@ -584,7 +589,8 @@ export default class PollElement extends HTMLElement {
|
||||
});
|
||||
|
||||
const maxValue = Math.max(...percents);
|
||||
this.maxLengths = percents.map(p => p / maxValue * this.maxLength);
|
||||
//this.maxLengths = percents.map(p => p / maxValue * this.maxLength);
|
||||
this.maxPercents = percents.map(p => p / maxValue);
|
||||
|
||||
// line
|
||||
if(this.isRetracted) {
|
||||
@ -592,42 +598,70 @@ export default class PollElement extends HTMLElement {
|
||||
this.setLineProgress(idx, -1);
|
||||
});
|
||||
} else {
|
||||
this.svgLines.forEach((svg, idx) => {
|
||||
void svg.getBoundingClientRect(); // reflow
|
||||
this.setLineProgress(idx, 1);
|
||||
});
|
||||
const cb = () => {
|
||||
this.svgLines.forEach((svg, idx) => {
|
||||
//void svg.getBoundingClientRect(); // reflow
|
||||
this.setLineProgress(idx, 1);
|
||||
});
|
||||
};
|
||||
|
||||
animate ? fastRaf(cb) : cb();
|
||||
}
|
||||
|
||||
percents = percents.slice();
|
||||
roundPercents(percents);
|
||||
let getPercentValue: (percents: number, index: number) => number;
|
||||
const iterate = (i: number) => {
|
||||
percents.forEach((percents, idx) => {
|
||||
const value = getPercentValue(percents, i);
|
||||
this.numberDivs[idx].innerText = value + '%';
|
||||
});
|
||||
};
|
||||
// numbers
|
||||
if(this.isRetracted) {
|
||||
for(let i = (times - 1), k = 0; i >= 0; --i, ++k) {
|
||||
setTimeout(() => {
|
||||
percents.forEach((percents, idx) => {
|
||||
const value = Math.round(percents / times * i);
|
||||
this.numberDivs[idx].innerText = value + '%';
|
||||
});
|
||||
}, oneTime * k);
|
||||
getPercentValue = (percents, index) => Math.round(percents / times * index);
|
||||
|
||||
if(animate) {
|
||||
for(let i = (times - 1), k = 0; i >= 0; --i, ++k) {
|
||||
setTimeout(() => {
|
||||
iterate(i);
|
||||
}, oneTime * k);
|
||||
}
|
||||
} else {
|
||||
iterate(0);
|
||||
}
|
||||
} else {
|
||||
for(let i = 0; i < times; ++i) {
|
||||
setTimeout(() => {
|
||||
percents.forEach((percents, idx) => {
|
||||
const value = Math.round(percents / times * (i + 1));
|
||||
this.numberDivs[idx].innerText = value + '%';
|
||||
});
|
||||
}, oneTime * i);
|
||||
getPercentValue = (percents, index) => Math.round(percents / times * (index + 1));
|
||||
|
||||
if(animate) {
|
||||
for(let i = 0; i < times; ++i) {
|
||||
setTimeout(() => {
|
||||
iterate(i);
|
||||
}, oneTime * i);
|
||||
}
|
||||
} else {
|
||||
iterate(times - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if(this.isRetracted) {
|
||||
this.classList.add('is-retracting');
|
||||
if(animate) {
|
||||
this.classList.add('is-retracting');
|
||||
}
|
||||
|
||||
this.classList.remove('is-voted');
|
||||
setTimeout(() => {
|
||||
this.classList.remove('is-retracting');
|
||||
const cb = () => {
|
||||
this.svgLines.forEach(svg => svg.style.display = 'none');
|
||||
}, fullTime);
|
||||
};
|
||||
|
||||
if(animate) {
|
||||
setTimeout(() => {
|
||||
this.classList.remove('is-retracting');
|
||||
cb();
|
||||
}, fullTime);
|
||||
} else {
|
||||
cb();
|
||||
}
|
||||
} else {
|
||||
this.classList.add('is-voted');
|
||||
}
|
||||
@ -647,15 +681,16 @@ export default class PollElement extends HTMLElement {
|
||||
replaceContent(this.votersCountDiv, i18n(key, args));
|
||||
}
|
||||
|
||||
setLineProgress(index: number, percents: number) {
|
||||
setLineProgress(index: number, multiplier: number) {
|
||||
const svg = this.svgLines[index];
|
||||
|
||||
if(percents === -1) {
|
||||
if(multiplier === -1) {
|
||||
svg.style.strokeDasharray = '';
|
||||
svg.style.strokeDashoffset = '';
|
||||
} else {
|
||||
svg.style.strokeDasharray = (percents * this.maxLengths[index]) + ', 485.9';
|
||||
svg.style.strokeDashoffset = '' + percents * this.maxOffset;
|
||||
//svg.style.strokeDasharray = (percents * this.maxLengths[index]) + ', 485.9';
|
||||
svg.style.strokeDasharray = (multiplier * this.maxPercents[index] * 100) + '%, 485.9';
|
||||
svg.style.strokeDashoffset = '' + multiplier * this.maxOffset;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
import findUpClassName from "../helpers/dom/findUpClassName";
|
||||
import sequentialDom from "../helpers/sequentialDom";
|
||||
import {isTouchSupported} from "../helpers/touchSupport";
|
||||
import rootScope from "../lib/rootScope";
|
||||
|
||||
@ -44,22 +45,22 @@ export function ripple(elem: HTMLElement, callback: (id: number) => Promise<bool
|
||||
//const duration = isSquare || mediaSizes.isMobile ? 200 : 700;
|
||||
//return;
|
||||
let elapsedTime = Date.now() - startTime;
|
||||
const cb = () => {
|
||||
//console.log('ripple elapsedTime total pre-remove:', Date.now() - startTime);
|
||||
sequentialDom.mutate(() => {
|
||||
elem.remove();
|
||||
});
|
||||
|
||||
if(onEnd) onEnd(clickId);
|
||||
};
|
||||
if(elapsedTime < duration) {
|
||||
let delay = Math.max(duration - elapsedTime, duration / 2);
|
||||
setTimeout(() => elem.classList.add('hiding'), Math.max(delay - duration / 2, 0));
|
||||
|
||||
setTimeout(() => {
|
||||
//console.log('ripple elapsedTime total pre-remove:', Date.now() - startTime);
|
||||
elem.remove();
|
||||
if(onEnd) onEnd(clickId);
|
||||
}, delay);
|
||||
setTimeout(cb, delay);
|
||||
} else {
|
||||
elem.classList.add('hiding');
|
||||
setTimeout(() => {
|
||||
//console.log('ripple elapsedTime total pre-remove:', Date.now() - startTime);
|
||||
elem.remove();
|
||||
if(onEnd) onEnd(clickId);
|
||||
}, duration / 2);
|
||||
setTimeout(cb, duration / 2);
|
||||
}
|
||||
|
||||
if(!isTouchSupported) {
|
||||
|
@ -108,6 +108,7 @@ export class ScrollableBase {
|
||||
forceDuration?: number,
|
||||
axis?: 'x' | 'y'
|
||||
) {
|
||||
//return Promise.resolve();
|
||||
return fastSmoothScroll(this.container, element, position, margin, maxDistance, forceDirection, forceDuration, axis);
|
||||
}
|
||||
}
|
||||
|
@ -120,4 +120,4 @@ export default class VisibilityIntersector {
|
||||
public lock() {
|
||||
this.locked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -579,7 +579,7 @@ function wrapMediaWithTail(photo: MyPhoto | MyDocument, message: {mid: number, m
|
||||
|
||||
const foreignObject = document.createElementNS("http://www.w3.org/2000/svg", 'foreignObject');
|
||||
|
||||
const gotThumb = appPhotosManager.getStrippedThumbIfNeeded(photo);
|
||||
const gotThumb = appPhotosManager.getStrippedThumbIfNeeded(photo, true);
|
||||
if(gotThumb) {
|
||||
foreignObject.append(gotThumb.image);
|
||||
}
|
||||
@ -632,7 +632,7 @@ function wrapMediaWithTail(photo: MyPhoto | MyDocument, message: {mid: number, m
|
||||
return img;
|
||||
}
|
||||
|
||||
export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withTail, isOut, lazyLoadQueue, middleware, size, withoutPreloader, loadPromises, noAutoDownload}: {
|
||||
export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withTail, isOut, lazyLoadQueue, middleware, size, withoutPreloader, loadPromises, noAutoDownload, noBlur}: {
|
||||
photo: MyPhoto | MyDocument,
|
||||
message: any,
|
||||
container: HTMLElement,
|
||||
@ -646,6 +646,7 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT
|
||||
withoutPreloader?: boolean,
|
||||
loadPromises?: Promise<any>[],
|
||||
noAutoDownload?: boolean,
|
||||
noBlur?: boolean,
|
||||
}) {
|
||||
if(!((photo as MyPhoto).sizes || (photo as MyDocument).thumbs)) {
|
||||
if(boxWidth && boxHeight && photo._ === 'document') {
|
||||
@ -680,7 +681,7 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT
|
||||
size = appPhotosManager.setAttachmentSize(photo, container, boxWidth, boxHeight, undefined, message && message.message);
|
||||
}
|
||||
|
||||
const gotThumb = appPhotosManager.getStrippedThumbIfNeeded(photo);
|
||||
const gotThumb = appPhotosManager.getStrippedThumbIfNeeded(photo, !noBlur);
|
||||
if(gotThumb) {
|
||||
loadThumbPromise = gotThumb.loadPromise;
|
||||
thumbImage = gotThumb.image;
|
||||
@ -1307,6 +1308,6 @@ export function wrapPoll(message: any) {
|
||||
elem.setAttribute('peer-id', '' + message.peerId);
|
||||
elem.setAttribute('poll-id', message.media.poll.id);
|
||||
elem.setAttribute('message-id', '' + message.mid);
|
||||
//elem.render();
|
||||
elem.render();
|
||||
return elem;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
const App = {
|
||||
id: 1025907,
|
||||
hash: '452b0359b988148995f22ff0f4229750',
|
||||
version: '0.4.0',
|
||||
version: '0.4.1',
|
||||
langPackVersion: '0.1.3',
|
||||
langPack: 'macos',
|
||||
langPackCode: 'en',
|
||||
|
@ -46,8 +46,11 @@ function processBlur(dataUri: string, radius: number, iterations: number) {
|
||||
});
|
||||
}
|
||||
|
||||
const blurPromises: {[dataUri: string]: Promise<string>} = {};
|
||||
|
||||
export default function blur(dataUri: string, radius: number = RADIUS, iterations: number = ITERATIONS) {
|
||||
return new Promise<string>((resolve) => {
|
||||
if(blurPromises[dataUri]) return blurPromises[dataUri];
|
||||
return blurPromises[dataUri] = new Promise<string>((resolve) => {
|
||||
//return resolve(dataUri);
|
||||
pushHeavyTask({
|
||||
items: [[dataUri, radius, iterations]],
|
||||
|
@ -529,7 +529,7 @@ export const getSelectedNodes = () => {
|
||||
return nodes.filter(node => !!node);
|
||||
};
|
||||
|
||||
export const isSelectionSingle = (input: Element = document.activeElement) => {
|
||||
/* export const isSelectionSingle = (input: Element = document.activeElement) => {
|
||||
const nodes = getSelectedNodes();
|
||||
const parents = [...new Set(nodes.map(node => node.parentNode))];
|
||||
const differentParents = parents.length > 1;
|
||||
@ -545,7 +545,7 @@ export const isSelectionSingle = (input: Element = document.activeElement) => {
|
||||
}
|
||||
|
||||
return single;
|
||||
};
|
||||
}; */
|
||||
|
||||
export const handleScrollSideEvent = (elem: HTMLElement, side: 'top' | 'bottom', callback: () => void, listenerSetter: ListenerSetter) => {
|
||||
if(isTouchSupported) {
|
||||
@ -587,81 +587,6 @@ export const handleScrollSideEvent = (elem: HTMLElement, side: 'top' | 'bottom',
|
||||
}
|
||||
};
|
||||
|
||||
export const getElementByPoint = (container: HTMLElement, verticalSide: 'top' | 'bottom', horizontalSide: 'center' | 'left'): HTMLElement => {
|
||||
const rect = container.getBoundingClientRect();
|
||||
const x = horizontalSide === 'center' ? Math.ceil(rect.left + ((rect.right - rect.left) / 2) + 1) : Math.ceil(rect.left + 1);
|
||||
const y = verticalSide === 'bottom' ? Math.floor(rect.top + rect.height - 1) : Math.ceil(rect.top + 1);
|
||||
return document.elementFromPoint(x, y) as any;
|
||||
};
|
||||
|
||||
MOUNT_CLASS_TO.getElementByPoint = getElementByPoint;
|
||||
|
||||
export async function getFilesFromEvent(e: ClipboardEvent | DragEvent, onlyTypes = false): Promise<any[]> {
|
||||
const files: any[] = [];
|
||||
|
||||
const scanFiles = async(entry: any, item: DataTransferItem) => {
|
||||
if(entry.isDirectory) {
|
||||
const directoryReader = entry.createReader();
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
directoryReader.readEntries(async(entries: any) => {
|
||||
for(const entry of entries) {
|
||||
await scanFiles(entry, item);
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
} else if(entry) {
|
||||
if(onlyTypes) {
|
||||
files.push(entry.type);
|
||||
} else {
|
||||
const itemFile = item.getAsFile(); // * Safari can't handle entry.file with pasting
|
||||
const file = entry instanceof File ?
|
||||
entry :
|
||||
(
|
||||
entry instanceof DataTransferItem ?
|
||||
entry.getAsFile() :
|
||||
await new Promise((resolve, reject) => entry.file(resolve, (err: any) => resolve(itemFile)))
|
||||
);
|
||||
|
||||
/* if(!onlyTypes) {
|
||||
console.log('getFilesFromEvent: got file', item, file);
|
||||
} */
|
||||
|
||||
if(!file) return;
|
||||
files.push(file);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if(e instanceof DragEvent && e.dataTransfer.files && !e.dataTransfer.items) {
|
||||
for(let i = 0; i < e.dataTransfer.files.length; i++) {
|
||||
const file = e.dataTransfer.files[i];
|
||||
files.push(onlyTypes ? file.type : file);
|
||||
}
|
||||
} else {
|
||||
// @ts-ignore
|
||||
const items = (e.dataTransfer || e.clipboardData || e.originalEvent.clipboardData).items;
|
||||
|
||||
const promises: Promise<any>[] = [];
|
||||
for(let i = 0; i < items.length; ++i) {
|
||||
const item: DataTransferItem = items[i];
|
||||
if(item.kind === 'file') {
|
||||
const entry = (onlyTypes ? item : item.webkitGetAsEntry()) || item.getAsFile();
|
||||
promises.push(scanFiles(entry, item));
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
/* if(!onlyTypes) {
|
||||
console.log('getFilesFromEvent: got files:', e, files);
|
||||
} */
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
/* export function radiosHandleChange(inputs: HTMLInputElement[], onChange: (value: string) => void) {
|
||||
inputs.forEach(input => {
|
||||
input.addEventListener('change', () => {
|
||||
@ -756,11 +681,13 @@ export function htmlToSpan(html: string) {
|
||||
}
|
||||
|
||||
export function replaceContent(elem: HTMLElement, node: string | Node) {
|
||||
if(elem.children.length === 1) {
|
||||
elem.firstChild.remove();
|
||||
// * children.length doesn't count text nodes
|
||||
if(elem.children.length) {
|
||||
elem.firstChild.replaceWith(node);
|
||||
} else if(!elem.firstChild) {
|
||||
elem.append(node);
|
||||
} else {
|
||||
elem.textContent = '';
|
||||
elem.append(node);
|
||||
}
|
||||
|
||||
elem.append(node);
|
||||
}
|
||||
|
17
src/helpers/dom/getElementByPoint.ts
Normal file
17
src/helpers/dom/getElementByPoint.ts
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* https://github.com/morethanwords/tweb
|
||||
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import { MOUNT_CLASS_TO } from "../../config/debug";
|
||||
|
||||
export function getElementByPoint(container: HTMLElement, verticalSide: 'top' | 'bottom', horizontalSide: 'center' | 'left'): HTMLElement {
|
||||
//return null;
|
||||
const rect = container.getBoundingClientRect();
|
||||
const x = horizontalSide === 'center' ? Math.ceil(rect.left + ((rect.right - rect.left) / 2) + 1) : Math.ceil(rect.left + 1);
|
||||
const y = verticalSide === 'bottom' ? Math.floor(rect.top + rect.height - 1) : Math.ceil(rect.top + 1);
|
||||
return document.elementFromPoint(x, y) as any;
|
||||
};
|
||||
|
||||
MOUNT_CLASS_TO.getElementByPoint = getElementByPoint;
|
@ -53,4 +53,70 @@ export function onVideoLoad(video: HTMLVideoElement) {
|
||||
|
||||
video.addEventListener(isAppleMobile ? 'loadeddata' : 'canplay', () => resolve(), {once: true});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function getFilesFromEvent(e: ClipboardEvent | DragEvent, onlyTypes = false): Promise<any[]> {
|
||||
const files: any[] = [];
|
||||
|
||||
const scanFiles = async(entry: any, item: DataTransferItem) => {
|
||||
if(entry.isDirectory) {
|
||||
const directoryReader = entry.createReader();
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
directoryReader.readEntries(async(entries: any) => {
|
||||
for(const entry of entries) {
|
||||
await scanFiles(entry, item);
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
} else if(entry) {
|
||||
if(onlyTypes) {
|
||||
files.push(entry.type);
|
||||
} else {
|
||||
const itemFile = item.getAsFile(); // * Safari can't handle entry.file with pasting
|
||||
const file = entry instanceof File ?
|
||||
entry :
|
||||
(
|
||||
entry instanceof DataTransferItem ?
|
||||
entry.getAsFile() :
|
||||
await new Promise((resolve, reject) => entry.file(resolve, (err: any) => resolve(itemFile)))
|
||||
);
|
||||
|
||||
/* if(!onlyTypes) {
|
||||
console.log('getFilesFromEvent: got file', item, file);
|
||||
} */
|
||||
|
||||
if(!file) return;
|
||||
files.push(file);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if(e instanceof DragEvent && e.dataTransfer.files && !e.dataTransfer.items) {
|
||||
for(let i = 0; i < e.dataTransfer.files.length; i++) {
|
||||
const file = e.dataTransfer.files[i];
|
||||
files.push(onlyTypes ? file.type : file);
|
||||
}
|
||||
} else {
|
||||
// @ts-ignore
|
||||
const items = (e.dataTransfer || e.clipboardData || e.originalEvent.clipboardData).items;
|
||||
|
||||
const promises: Promise<any>[] = [];
|
||||
for(let i = 0; i < items.length; ++i) {
|
||||
const item: DataTransferItem = items[i];
|
||||
if(item.kind === 'file') {
|
||||
const entry = (onlyTypes ? item : item.webkitGetAsEntry()) || item.getAsFile();
|
||||
promises.push(scanFiles(entry, item));
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
/* if(!onlyTypes) {
|
||||
console.log('getFilesFromEvent: got files:', e, files);
|
||||
} */
|
||||
|
||||
return files;
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ export function debounce<F extends AnyToVoidFunction>(
|
||||
};
|
||||
}
|
||||
|
||||
/* export function throttle<F extends AnyToVoidFunction>(
|
||||
export function throttle<F extends AnyToVoidFunction>(
|
||||
fn: F,
|
||||
ms: number,
|
||||
shouldRunFirst = true,
|
||||
@ -70,7 +70,7 @@ export function debounce<F extends AnyToVoidFunction>(
|
||||
}, ms);
|
||||
}
|
||||
};
|
||||
} */
|
||||
}
|
||||
|
||||
/* export function throttleWithRaf<F extends AnyToVoidFunction>(fn: F) {
|
||||
return throttleWith(fastRaf, fn);
|
||||
@ -131,7 +131,7 @@ export function fastRaf(callback: NoneToVoidFunction) {
|
||||
}
|
||||
|
||||
export function doubleRaf() {
|
||||
return new Promise((resolve) => {
|
||||
return new Promise<void>((resolve) => {
|
||||
fastRaf(() => {
|
||||
fastRaf(resolve);
|
||||
});
|
||||
|
@ -58,9 +58,16 @@ console.timeEnd('get storage1'); */
|
||||
// @ts-ignore
|
||||
const w = window.visualViewport || window; // * handle iOS keyboard
|
||||
let setViewportVH = false;
|
||||
let lastVH: number;
|
||||
const setVH = () => {
|
||||
// @ts-ignore
|
||||
const vh = (setViewportVH && !rootScope.default.overlayIsActive ? w.height || w.innerHeight : window.innerHeight) * 0.01;
|
||||
if(lastVH === vh) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastVH = vh;
|
||||
|
||||
//const vh = document.documentElement.scrollHeight * 0.01;
|
||||
document.documentElement.style.setProperty('--vh', `${vh}px`);
|
||||
|
||||
|
@ -24,7 +24,7 @@ import appPhotosManager from './appPhotosManager';
|
||||
import appProfileManager from './appProfileManager';
|
||||
import appStickersManager from './appStickersManager';
|
||||
import appWebPagesManager from './appWebPagesManager';
|
||||
import { blurActiveElement, cancelEvent, disableTransition, getFilesFromEvent, placeCaretAtEnd, whichChild } from '../../helpers/dom';
|
||||
import { blurActiveElement, cancelEvent, disableTransition, placeCaretAtEnd, whichChild } from '../../helpers/dom';
|
||||
import PopupNewMedia from '../../components/popups/newMedia';
|
||||
import MarkupTooltip from '../../components/chat/markupTooltip';
|
||||
import { isTouchSupported } from '../../helpers/touchSupport';
|
||||
@ -47,6 +47,7 @@ import { i18n } from '../langPack';
|
||||
import { SendMessageAction } from '../../layer';
|
||||
import { highlightningColor } from '../../helpers/color';
|
||||
import { getObjectKeysAndSort } from '../../helpers/object';
|
||||
import { getFilesFromEvent } from '../../helpers/files';
|
||||
|
||||
//console.log('appImManager included33!');
|
||||
|
||||
|
@ -67,6 +67,7 @@ export type HistoryStorage = {
|
||||
readPromise?: Promise<void>,
|
||||
readMaxId?: number,
|
||||
readOutboxMaxId?: number,
|
||||
triedToReadMaxId?: number,
|
||||
|
||||
maxOutId?: number,
|
||||
reply_markup?: any
|
||||
@ -3433,7 +3434,7 @@ export class AppMessagesManager {
|
||||
if((message.totalEntities as MessageEntity[]).find(e => goodEntities.includes(e._)) || RichTextProcessor.matchUrl(message.message)) {
|
||||
found = true;
|
||||
}
|
||||
} else if(neededContents['avatar'] && message.action && ['messageActionChannelEditPhoto', 'messageActionChatEditPhoto'].includes(message.action._)) {
|
||||
} else if(neededContents['avatar'] && message.action && ['messageActionChannelEditPhoto', 'messageActionChatEditPhoto', 'messageActionChannelEditVideo', 'messageActionChatEditVideo'].includes(message.action._)) {
|
||||
found = true;
|
||||
}/* else if(neededFlags.find(flag => message.pFlags[flag])) {
|
||||
found = true;
|
||||
@ -3471,9 +3472,12 @@ export class AppMessagesManager {
|
||||
});
|
||||
}
|
||||
|
||||
const canCache = (['inputMessagesFilterChatPhotos', 'inputMessagesFilterPinned'] as MyInputMessagesFilter[]).includes(inputFilter._);
|
||||
const method = (canCache ? apiManager.invokeApiCacheable : apiManager.invokeApi).bind(apiManager);
|
||||
|
||||
let apiPromise: Promise<any>;
|
||||
if(peerId && !nextRate && folderId === undefined/* || !query */) {
|
||||
apiPromise = apiManager.invokeApi('messages.search', {
|
||||
apiPromise = method('messages.search', {
|
||||
peer: appPeersManager.getInputPeerById(peerId),
|
||||
q: query || '',
|
||||
filter: inputFilter as any as MessagesFilter,
|
||||
@ -3502,7 +3506,7 @@ export class AppMessagesManager {
|
||||
offsetPeerId = this.getMessagePeer(offsetMessage);
|
||||
}
|
||||
|
||||
apiPromise = apiManager.invokeApi('messages.searchGlobal', {
|
||||
apiPromise = method('messages.searchGlobal', {
|
||||
q: query,
|
||||
filter: inputFilter as any as MessagesFilter,
|
||||
min_date: minDate,
|
||||
@ -3721,7 +3725,7 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
public readHistory(peerId: number, maxId = 0, threadId?: number, force = false) {
|
||||
// return Promise.resolve();
|
||||
//return Promise.resolve();
|
||||
// console.trace('start read')
|
||||
this.log('readHistory:', peerId, maxId, threadId);
|
||||
if(!this.getReadMaxIdIfUnread(peerId, threadId) && !force) {
|
||||
@ -3729,9 +3733,12 @@ export class AppMessagesManager {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const isChannel = appPeersManager.isChannel(peerId);
|
||||
const historyStorage = this.getHistoryStorage(peerId, threadId);
|
||||
|
||||
if(historyStorage.triedToReadMaxId >= maxId) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
let apiPromise: Promise<any>;
|
||||
if(threadId) {
|
||||
if(!historyStorage.readPromise) {
|
||||
@ -3751,7 +3758,7 @@ export class AppMessagesManager {
|
||||
read_max_id: maxId
|
||||
} as Update.updateReadChannelDiscussionInbox
|
||||
});
|
||||
} else if(isChannel) {
|
||||
} else if(appPeersManager.isChannel(peerId)) {
|
||||
if(!historyStorage.readPromise) {
|
||||
apiPromise = apiManager.invokeApi('channels.readHistory', {
|
||||
channel: appChatsManager.getChannelInput(-peerId),
|
||||
@ -3811,6 +3818,8 @@ export class AppMessagesManager {
|
||||
return historyStorage.readPromise;
|
||||
}
|
||||
|
||||
historyStorage.triedToReadMaxId = maxId;
|
||||
|
||||
apiPromise.finally(() => {
|
||||
delete historyStorage.readPromise;
|
||||
|
||||
|
@ -133,7 +133,7 @@ export class AppPhotosManager {
|
||||
|
||||
public getUserPhotos(userId: number, maxId: string = '0', limit: number = 20) {
|
||||
const inputUser = appUsersManager.getUserInput(userId);
|
||||
return apiManager.invokeApi('photos.getUserPhotos', {
|
||||
return apiManager.invokeApiCacheable('photos.getUserPhotos', {
|
||||
user_id: inputUser,
|
||||
offset: 0,
|
||||
limit,
|
||||
@ -204,13 +204,13 @@ export class AppPhotosManager {
|
||||
return thumb.url ?? (defineNotNumerableProperties(thumb, ['url']), thumb.url = this.getPreviewURLFromBytes(thumb.bytes, isSticker));
|
||||
}
|
||||
|
||||
public getImageFromStrippedThumb(thumb: PhotoSize.photoCachedSize | PhotoSize.photoStrippedSize) {
|
||||
public getImageFromStrippedThumb(thumb: PhotoSize.photoCachedSize | PhotoSize.photoStrippedSize, useBlur: boolean) {
|
||||
const url = this.getPreviewURLFromThumb(thumb, false);
|
||||
|
||||
const image = new Image();
|
||||
image.classList.add('thumbnail');
|
||||
|
||||
const loadPromise = blur(url).then(url => {
|
||||
const loadPromise = (useBlur ? blur(url) : Promise.resolve(url)).then(url => {
|
||||
return new Promise<any>((resolve) => {
|
||||
renderImageFromUrl(image, url, resolve);
|
||||
});
|
||||
@ -252,7 +252,7 @@ export class AppPhotosManager {
|
||||
return photoSize;
|
||||
}
|
||||
|
||||
public getStrippedThumbIfNeeded(photo: MyPhoto | MyDocument): ReturnType<AppPhotosManager['getImageFromStrippedThumb']> {
|
||||
public getStrippedThumbIfNeeded(photo: MyPhoto | MyDocument, useBlur: boolean): ReturnType<AppPhotosManager['getImageFromStrippedThumb']> {
|
||||
if(!photo.downloaded || (photo as MyDocument).type === 'video' || (photo as MyDocument).type === 'gif') {
|
||||
if(photo._ === 'document') {
|
||||
const cacheContext = this.getCacheContext(photo);
|
||||
@ -264,7 +264,7 @@ export class AppPhotosManager {
|
||||
const sizes = (photo as MyPhoto).sizes || (photo as MyDocument).thumbs;
|
||||
const thumb = sizes?.length ? sizes.find(size => size._ === 'photoStrippedSize') : null;
|
||||
if(thumb && ('bytes' in thumb)) {
|
||||
return appPhotosManager.getImageFromStrippedThumb(thumb as any);
|
||||
return appPhotosManager.getImageFromStrippedThumb(thumb as any, useBlur);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,9 @@
|
||||
|
||||
import { MOUNT_CLASS_TO } from "../../config/debug";
|
||||
import { tsNow } from "../../helpers/date";
|
||||
import { replaceContent } from "../../helpers/dom";
|
||||
import renderImageFromUrl from "../../helpers/dom/renderImageFromUrl";
|
||||
import sequentialDom from "../../helpers/sequentialDom";
|
||||
import { ChannelParticipantsFilter, ChannelsChannelParticipants, ChatFull, ChatParticipants, ChatPhoto, ExportedChatInvite, InputChannel, InputFile, InputFileLocation, PhotoSize, UserFull, UserProfilePhoto } from "../../layer";
|
||||
//import apiManager from '../mtproto/apiManager';
|
||||
import apiManager from '../mtproto/mtprotoworker';
|
||||
@ -504,8 +506,7 @@ export class AppProfileManager {
|
||||
if(!needFadeIn) {
|
||||
// смотри в misc.ts: renderImageFromUrl
|
||||
callback = () => {
|
||||
div.innerHTML = '';
|
||||
div.append(img);
|
||||
replaceContent(div, img);
|
||||
div.dataset.color = '';
|
||||
};
|
||||
} else {
|
||||
@ -515,15 +516,16 @@ export class AppProfileManager {
|
||||
}
|
||||
|
||||
callback = () => {
|
||||
div.innerHTML = '';
|
||||
div.append(img);
|
||||
replaceContent(div, img);
|
||||
|
||||
setTimeout(() => {
|
||||
if(div.childElementCount) {
|
||||
div.dataset.color = '';
|
||||
|
||||
if(animate) {
|
||||
img.classList.remove('fade-in');
|
||||
sequentialDom.mutateElement(img, () => {
|
||||
img.classList.remove('fade-in');
|
||||
});
|
||||
}
|
||||
}
|
||||
}, animate ? 200 : 0);
|
||||
@ -554,7 +556,7 @@ export class AppProfileManager {
|
||||
|
||||
//console.log('loadDialogPhoto location:', location, inputPeer);
|
||||
if(peerId === myId && isDialog) {
|
||||
div.innerHTML = '';
|
||||
div.innerText = '';
|
||||
div.dataset.color = '';
|
||||
div.classList.add('tgico-saved');
|
||||
div.classList.remove('tgico-deletedaccount');
|
||||
@ -564,7 +566,7 @@ export class AppProfileManager {
|
||||
if(peerId > 0) {
|
||||
const user = appUsersManager.getUser(peerId);
|
||||
if(user && user.pFlags && user.pFlags.deleted) {
|
||||
div.innerHTML = '';
|
||||
div.innerText = '';
|
||||
div.dataset.color = appPeersManager.getPeerColorById(peerId);
|
||||
div.classList.add('tgico-deletedaccount');
|
||||
div.classList.remove('tgico-saved');
|
||||
@ -578,7 +580,7 @@ export class AppProfileManager {
|
||||
color = appPeersManager.getPeerColorById(peerId);
|
||||
}
|
||||
|
||||
div.innerHTML = '';
|
||||
div.innerText = '';
|
||||
div.classList.remove('tgico-saved', 'tgico-deletedaccount');
|
||||
div.dataset.color = color;
|
||||
|
||||
|
@ -170,9 +170,9 @@ export class AppStateManager extends EventListenerBase<{
|
||||
|
||||
const time = Date.now();
|
||||
if(state) {
|
||||
if(state.version !== STATE_VERSION) {
|
||||
/* if(state.version !== STATE_VERSION) {
|
||||
state = copy(STATE_INIT);
|
||||
} else if((state.stateCreatedTime + REFRESH_EVERY) < time/* || true *//* && false */) {
|
||||
} else */if((state.stateCreatedTime + REFRESH_EVERY) < time/* || true *//* && false */) {
|
||||
if(DEBUG) {
|
||||
this.log('will refresh state', state.stateCreatedTime, time);
|
||||
}
|
||||
|
@ -2017,11 +2017,13 @@ $bubble-margin: .25rem;
|
||||
|
||||
&-answer-selected {
|
||||
background-color: var(--message-out-primary-color);
|
||||
color: var(--message-out-background-color);
|
||||
}
|
||||
|
||||
html.no-touch &-answer:hover {
|
||||
.animation-ring {
|
||||
background-color: rgba(79, 174, 78, .08);
|
||||
background-color: var(--message-out-primary-color);
|
||||
opacity: .08;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,10 +55,9 @@ poll-element {
|
||||
color: var(--primary-color);
|
||||
cursor: pointer;
|
||||
transform: scale(1);
|
||||
transition: transform .2s ease;
|
||||
|
||||
body.animation-level-0 & {
|
||||
transition: none;
|
||||
|
||||
@include animation-level(2) {
|
||||
transition: transform .2s ease;
|
||||
}
|
||||
|
||||
// @include respond-to(handhelds) {
|
||||
@ -100,7 +99,6 @@ poll-element {
|
||||
font-weight: 500;
|
||||
margin-top: 7px;
|
||||
font-size: 14px;
|
||||
transition: .34s opacity;
|
||||
margin-left: -9px;
|
||||
text-align: right;
|
||||
width: 40px;
|
||||
@ -117,10 +115,7 @@ poll-element {
|
||||
width: 16px;
|
||||
font-weight: bold;
|
||||
font-size: .75rem;
|
||||
opacity: 0;
|
||||
animation: fade-in-opacity .1s ease forwards;
|
||||
animation-direction: reverse;
|
||||
animation-delay: .24s;
|
||||
opacity: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@ -148,14 +143,16 @@ poll-element {
|
||||
|
||||
&:not(.is-correct):not(.is-chosen) {
|
||||
.poll-answer-selected {
|
||||
display: none;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Multiple answers
|
||||
&.is-chosing {
|
||||
.poll-answer-selected {
|
||||
opacity: 1;
|
||||
.circle-hover {
|
||||
.poll-answer-selected {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
& ~ .poll-footer {
|
||||
@ -238,11 +235,11 @@ poll-element {
|
||||
&-answer {
|
||||
&.is-chosen:not(.is-correct) {
|
||||
use {
|
||||
stroke: #DF3F40;
|
||||
stroke: var(--danger-color);
|
||||
}
|
||||
|
||||
.poll-answer-selected {
|
||||
background: #DF3F40;
|
||||
background: var(--danger-color);
|
||||
//line-height: 16px;
|
||||
|
||||
&:before {
|
||||
@ -278,7 +275,6 @@ poll-element {
|
||||
left: -1px;
|
||||
top: -1px;
|
||||
transform: scale(1);
|
||||
transition: .1s transform;
|
||||
|
||||
.poll-answer-selected {
|
||||
display: flex!important;
|
||||
@ -300,10 +296,13 @@ poll-element {
|
||||
border-radius: 50%;
|
||||
height: 34px;
|
||||
width: 34px;
|
||||
transition: transform .12s;
|
||||
background-color: #f4f4f4;
|
||||
background-color: var(--light-secondary-text-color);
|
||||
transform: scale(.1);
|
||||
visibility: hidden;
|
||||
|
||||
@include animation-level(2) {
|
||||
transition: transform .12s ease;
|
||||
}
|
||||
}
|
||||
|
||||
.progress-ring {
|
||||
@ -315,12 +314,11 @@ poll-element {
|
||||
&__circle {
|
||||
transform-origin: center;
|
||||
transform: rotate(-90deg);
|
||||
transition: stroke-dashoffset .15s;
|
||||
stroke-dasharray: 56.5487, 56.5487;
|
||||
stroke-dashoffset: 0;
|
||||
stroke-opacity: 1;
|
||||
stroke-width: 2;
|
||||
stroke: var(--border-color);
|
||||
stroke: var(--poll-circle-color);
|
||||
fill: transparent;
|
||||
}
|
||||
}
|
||||
@ -333,10 +331,6 @@ poll-element {
|
||||
.poll-answer-percents {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.poll-answer-selected {
|
||||
animation-direction: normal;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-retracting {
|
||||
@ -353,6 +347,29 @@ poll-element {
|
||||
.poll-line {
|
||||
transition: stroke-dashoffset .34s linear, stroke-dasharray .34s linear;
|
||||
}
|
||||
|
||||
.poll-answer-selected {
|
||||
transition-delay: .24s;
|
||||
transition: opacity .1s ease forwards;
|
||||
}
|
||||
|
||||
&.is-retracting {
|
||||
.poll-answer-selected {
|
||||
transition-delay: 0s;
|
||||
}
|
||||
}
|
||||
|
||||
.poll-answer-percents {
|
||||
transition: .34s opacity;
|
||||
}
|
||||
|
||||
.progress-ring__circle {
|
||||
transition: stroke-dashoffset .15s;
|
||||
}
|
||||
|
||||
.circle-hover {
|
||||
transition: .1s transform;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,8 +42,8 @@ $chat-padding-handhelds: .5rem;
|
||||
--hover-alpha: #{$hover-alpha};
|
||||
|
||||
--transition-standard-easing: cubic-bezier(.4, .0, .2, 1);
|
||||
--transition-standard-in-time: .25s;
|
||||
--transition-standard-out-time: .2s;
|
||||
--transition-standard-in-time: .3s;
|
||||
--transition-standard-out-time: .25s;
|
||||
--transition-standard-in: var(--transition-standard-in-time) var(--transition-standard-easing);
|
||||
--transition-standard-out: var(--transition-standard-out-time) var(--transition-standard-easing);
|
||||
|
||||
@ -149,6 +149,7 @@ $chat-padding-handhelds: .5rem;
|
||||
--badge-text-color: #fff;
|
||||
--link-color: #00488f;
|
||||
--ripple-color: rgba(0, 0, 0, .08);
|
||||
--poll-circle-color: var(--border-color);
|
||||
|
||||
--message-background-color: var(--surface-color);
|
||||
--message-checkbox-color: #61c642;
|
||||
@ -192,6 +193,7 @@ html.night {
|
||||
--badge-text-color: #fff;
|
||||
--link-color: var(--primary-color);
|
||||
--ripple-color: rgba(255, 255, 255, .08);
|
||||
--poll-circle-color: #fff;
|
||||
|
||||
--message-background-color: var(--surface-color);
|
||||
--message-checkbox-color: var(--primary-color);
|
||||
|
Loading…
x
Reference in New Issue
Block a user