Render first message and load rest with animation
Fix video unload in chrome
This commit is contained in:
parent
c3b9cd8cf1
commit
9c5c9741b2
@ -2,6 +2,7 @@ import { isInDOM } from "../lib/utils";
|
||||
import { RLottiePlayer } from "../lib/lottieLoader";
|
||||
import { MOUNT_CLASS_TO } from "../lib/mtproto/mtproto_config";
|
||||
import $rootScope from "../lib/rootScope";
|
||||
import { isSafari } from "../helpers/userAgent";
|
||||
|
||||
export interface AnimationItem {
|
||||
el: HTMLElement,
|
||||
@ -71,9 +72,11 @@ export class AnimationIntersector {
|
||||
const {el, animation} = player;
|
||||
animation.remove();
|
||||
|
||||
if(animation instanceof HTMLVideoElement) {
|
||||
animation.src = '';
|
||||
animation.load();
|
||||
if(animation instanceof HTMLVideoElement && isSafari) {
|
||||
setTimeout(() => { // TODO: очистка по очереди, а не все вместе с этим таймаутом
|
||||
animation.src = '';
|
||||
animation.load();
|
||||
}, 1e3);
|
||||
}
|
||||
|
||||
for(const group in this.byGroups) {
|
||||
|
@ -118,6 +118,8 @@ export default class ChatContextMenu {
|
||||
onClick: this.onPinClick,
|
||||
verify: () => {
|
||||
const message = appMessagesManager.getMessage(this.msgID);
|
||||
// for new layer
|
||||
// return this.msgID > 0 && message._ != 'messageService' && appImManager.pinnedMsgID != this.msgID && (this.peerID > 0 || appChatsManager.hasRights(-this.peerID, 'pin'));
|
||||
return this.msgID > 0 && message._ != 'messageService' && appImManager.pinnedMsgID != this.msgID && (this.peerID == $rootScope.myID || (this.peerID < 0 && appChatsManager.hasRights(-this.peerID, 'pin')));
|
||||
}
|
||||
}, {
|
||||
|
@ -44,7 +44,7 @@ import appChatsManager, { Channel, Chat } from "./appChatsManager";
|
||||
import appDialogsManager from "./appDialogsManager";
|
||||
import appDocsManager from './appDocsManager';
|
||||
import appInlineBotsManager from './AppInlineBotsManager';
|
||||
import appMessagesManager, { Dialog } from "./appMessagesManager";
|
||||
import appMessagesManager, { AppMessagesManager, Dialog, HistoryResult } from "./appMessagesManager";
|
||||
import appPeersManager from "./appPeersManager";
|
||||
import appPhotosManager from "./appPhotosManager";
|
||||
import appPollsManager from './appPollsManager';
|
||||
@ -57,7 +57,8 @@ import appUsersManager from "./appUsersManager";
|
||||
|
||||
appSidebarLeft; // just to include
|
||||
|
||||
const TEST_SCROLL = false;
|
||||
const TEST_SCROLL_TIMES: number = undefined;
|
||||
let TEST_SCROLL = TEST_SCROLL_TIMES;
|
||||
|
||||
const LEFT_COLUMN_ACTIVE_CLASSNAME = 'is-left-column-shown';
|
||||
|
||||
@ -843,7 +844,7 @@ export class AppImManager {
|
||||
|
||||
public loadMoreHistory(top: boolean, justLoad = false) {
|
||||
//this.log('loadMoreHistory', top);
|
||||
if(!this.peerID || TEST_SCROLL || this.setPeerPromise || (top && this.getHistoryTopPromise) || (!top && this.getHistoryBottomPromise)) return;
|
||||
if(!this.peerID || /* TEST_SCROLL || */ this.setPeerPromise || (top && this.getHistoryTopPromise) || (!top && this.getHistoryBottomPromise)) return;
|
||||
|
||||
// warning, если иды только отрицательные то вниз не попадёт (хотя мб и так не попадёт)
|
||||
let history = Object.keys(this.bubbles).map(id => +id).filter(id => id > 0).sort((a, b) => a - b);
|
||||
@ -1027,6 +1028,10 @@ export class AppImManager {
|
||||
this.scrolledAll = false;
|
||||
this.scrolledAllDown = false;
|
||||
|
||||
if(TEST_SCROLL !== undefined) {
|
||||
TEST_SCROLL = TEST_SCROLL_TIMES;
|
||||
}
|
||||
|
||||
this.bubbles = {};
|
||||
this.dateMessages = {};
|
||||
this.bubbleGroups.cleanup();
|
||||
@ -2338,7 +2343,7 @@ export class AppImManager {
|
||||
return bubble;
|
||||
}
|
||||
|
||||
public performHistoryResult(history: number[], reverse: boolean, isBackLimit: boolean, additionMsgID: number) {
|
||||
public performHistoryResult(history: number[], reverse: boolean, isBackLimit: boolean, additionMsgID?: number) {
|
||||
// commented bot getProfile in getHistory!
|
||||
if(!history/* .filter((id: number) => id > 0) */.length) {
|
||||
if(!isBackLimit) {
|
||||
@ -2382,13 +2387,17 @@ export class AppImManager {
|
||||
|
||||
const method = (reverse ? history.shift : history.pop).bind(history);
|
||||
|
||||
//const padding = 99999;
|
||||
const realLength = this.scrollable.length;
|
||||
let previousScrollHeightMinusTop: number;
|
||||
let previousScrollHeightMinusTop: number/* , previousScrollHeight: number */;
|
||||
if(realLength > 0 && (reverse || isSafari)) { // for safari need set when scrolling bottom too
|
||||
this.messagesQueueOnRender = () => {
|
||||
const {scrollTop, scrollHeight} = this.scrollable;
|
||||
|
||||
//previousScrollHeight = scrollHeight + padding;
|
||||
previousScrollHeightMinusTop = reverse ? scrollHeight - scrollTop : scrollTop;
|
||||
|
||||
//this.chatInner.style.paddingTop = padding + 'px';
|
||||
/* if(reverse) {
|
||||
previousScrollHeightMinusTop = this.scrollable.scrollHeight - scrollTop;
|
||||
} else {
|
||||
@ -2409,8 +2418,18 @@ export class AppImManager {
|
||||
//.then(() => new Promise(resolve => setTimeout(resolve, 100)))
|
||||
.then(() => {
|
||||
if(previousScrollHeightMinusTop !== undefined) {
|
||||
/* const scrollHeight = this.scrollable.scrollHeight;
|
||||
const addedHeight = scrollHeight - previousScrollHeight;
|
||||
|
||||
this.chatInner.style.paddingTop = (padding - addedHeight) + 'px';
|
||||
|
||||
//const newScrollTop = reverse ? scrollHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop;
|
||||
const newScrollTop = reverse ? scrollHeight - addedHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop;
|
||||
this.log('performHistoryResult: will set scrollTop',
|
||||
previousScrollHeightMinusTop, this.scrollable.scrollHeight,
|
||||
newScrollTop, this.scrollable.container.clientHeight); */
|
||||
//const newScrollTop = reverse ? scrollHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop;
|
||||
const newScrollTop = reverse ? this.scrollable.scrollHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop;
|
||||
//this.log('performHistoryResult: will set scrollTop', this.scrollable.scrollHeight, newScrollTop, this.scrollable.container.clientHeight);
|
||||
|
||||
// touchSupport for safari iOS
|
||||
isTouchSupported && isApple && (this.scrollable.container.style.overflow = 'hidden');
|
||||
@ -2444,13 +2463,22 @@ export class AppImManager {
|
||||
//console.time('appImManager call getHistory');
|
||||
const pageCount = appPhotosManager.windowH / 38/* * 1.25 */ | 0;
|
||||
//const loadCount = Object.keys(this.bubbles).length > 0 ? 50 : pageCount;
|
||||
const realLoadCount = Object.keys(this.bubbles).length > 0 ? 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;
|
||||
let loadCount = realLoadCount;
|
||||
|
||||
if(TEST_SCROLL) {
|
||||
/* if(TEST_SCROLL) {
|
||||
//loadCount = 1;
|
||||
if(Object.keys(this.bubbles).length > 0)
|
||||
return {cached: false, promise: Promise.resolve(true)};
|
||||
} */
|
||||
if(TEST_SCROLL !== undefined) {
|
||||
if(TEST_SCROLL) {
|
||||
if(Object.keys(this.bubbles).length > 0) {
|
||||
--TEST_SCROLL;
|
||||
}
|
||||
} else {
|
||||
return {cached: false, promise: Promise.resolve(true)};
|
||||
}
|
||||
}
|
||||
|
||||
////console.time('render history total');
|
||||
@ -2465,12 +2493,21 @@ export class AppImManager {
|
||||
}
|
||||
}
|
||||
|
||||
const result = appMessagesManager.getHistory(this.peerID, maxID, loadCount, backLimit);
|
||||
/* const result = additionMsgID ?
|
||||
{history: [additionMsgID]} :
|
||||
appMessagesManager.getHistory(this.peerID, maxID, loadCount, backLimit); */
|
||||
let result: ReturnType<AppMessagesManager['getHistory']> | {history: number[]} = appMessagesManager.getHistory(this.peerID, maxID, loadCount, backLimit);
|
||||
let resultPromise: Promise<any>;
|
||||
|
||||
let promise: Promise<boolean>, cached: boolean;
|
||||
if(result instanceof Promise) {
|
||||
cached = false;
|
||||
promise = result.then((result) => {
|
||||
const isFirstMessageRender = !!additionMsgID && result instanceof Promise && !appMessagesManager.getMessage(additionMsgID).grouped_id;
|
||||
if(isFirstMessageRender) {
|
||||
resultPromise = result as Promise<any>;
|
||||
result = {history: [additionMsgID]};
|
||||
//additionMsgID = 0;
|
||||
}
|
||||
|
||||
const processPromise = (result: Promise<HistoryResult>) => {
|
||||
const promise = result.then((result) => {
|
||||
this.log('getHistory not cached result by maxID:', maxID, reverse, isBackLimit, result, peerID, justLoad);
|
||||
|
||||
if(justLoad) {
|
||||
@ -2487,24 +2524,55 @@ export class AppImManager {
|
||||
|
||||
////console.timeEnd('render history total');
|
||||
|
||||
return this.performHistoryResult(result.history || [], reverse, isBackLimit, additionMsgID);
|
||||
return this.performHistoryResult(result.history || [], reverse, isBackLimit, !isFirstMessageRender && additionMsgID);
|
||||
}, (err) => {
|
||||
this.log.error('getHistory error:', err);
|
||||
return false;
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
let promise: Promise<boolean>, cached: boolean;
|
||||
if(result instanceof Promise) {
|
||||
cached = false;
|
||||
promise = processPromise(result);
|
||||
} else if(justLoad) {
|
||||
return null;
|
||||
} else {
|
||||
cached = true;
|
||||
this.log('getHistory cached result by maxID:', maxID, reverse, isBackLimit, result, peerID, justLoad);
|
||||
promise = this.performHistoryResult(result.history || [], reverse, isBackLimit, additionMsgID);
|
||||
promise = this.performHistoryResult(result.history || [], reverse, isBackLimit, !isFirstMessageRender && additionMsgID);
|
||||
//return (reverse ? this.getHistoryTopPromise = promise : this.getHistoryBottomPromise = promise);
|
||||
//return this.performHistoryResult(result.history || [], reverse, isBackLimit, additionMsgID, true);
|
||||
}
|
||||
|
||||
(reverse ? this.getHistoryTopPromise = promise : this.getHistoryBottomPromise = promise);
|
||||
const waitPromise = isFirstMessageRender ? processPromise(resultPromise) : promise;
|
||||
|
||||
promise.finally(() => {
|
||||
if(isFirstMessageRender) {
|
||||
waitPromise.then(() => {
|
||||
const mids = getObjectKeysAndSort(this.bubbles, 'desc');
|
||||
mids.findAndSplice(mid => mid == additionMsgID);
|
||||
mids.forEach((mid, idx) => {
|
||||
const bubble = this.bubbles[mid];
|
||||
|
||||
//if(idx || isSafari) {
|
||||
// ! 0.1 = 1ms задержка для Safari, без этого первое сообщение над самым нижним может появиться позже другого с animation-delay, LOL !
|
||||
bubble.style.animationDelay = ((idx || 0.1) * 10) + 'ms';
|
||||
//}
|
||||
|
||||
bubble.classList.add('zoom-fade');
|
||||
bubble.addEventListener('animationend', () => {
|
||||
bubble.style.animationDelay = '';
|
||||
bubble.classList.remove('zoom-fade');
|
||||
}, {once: true});
|
||||
//this.log('supa', bubble);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
(reverse ? this.getHistoryTopPromise = waitPromise : this.getHistoryBottomPromise = waitPromise);
|
||||
waitPromise.finally(() => {
|
||||
(reverse ? this.getHistoryTopPromise = undefined : this.getHistoryBottomPromise = undefined);
|
||||
});
|
||||
|
||||
@ -2512,7 +2580,7 @@ export class AppImManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* false && */promise.then(() => {
|
||||
/* false && */!isFirstMessageRender && promise.then(() => {
|
||||
if(reverse) {
|
||||
this.loadedTopTimes++;
|
||||
this.loadedBottomTimes = Math.max(0, --this.loadedBottomTimes);
|
||||
@ -2537,7 +2605,7 @@ export class AppImManager {
|
||||
this.scrolledAllDown = false;
|
||||
|
||||
this.log('getHistory: slice bottom messages:', ids.length, loadCount);
|
||||
this.getHistoryBottomPromise = undefined; // !WARNING, это нужно для обратной загрузки истории, если запрос словил флуд
|
||||
//this.getHistoryBottomPromise = undefined; // !WARNING, это нужно для обратной загрузки истории, если запрос словил флуд
|
||||
} else {
|
||||
//ids = ids.slice(0, removeCount);
|
||||
//ids = ids.slice(0, ids.length - (removeCount * 2));
|
||||
@ -2545,7 +2613,7 @@ export class AppImManager {
|
||||
this.scrolledAll = false;
|
||||
|
||||
this.log('getHistory: slice up messages:', ids.length, loadCount);
|
||||
this.getHistoryTopPromise = undefined; // !WARNING, это нужно для обратной загрузки истории, если запрос словил флуд
|
||||
//this.getHistoryTopPromise = undefined; // !WARNING, это нужно для обратной загрузки истории, если запрос словил флуд
|
||||
}
|
||||
|
||||
this.log('getHistory: will slice ids:', ids, reverse);
|
||||
@ -2556,10 +2624,12 @@ export class AppImManager {
|
||||
this.setUnreadDelimiter(); // не нашёл места лучше
|
||||
|
||||
// preload more
|
||||
setTimeout(() => {
|
||||
this.loadMoreHistory(true, true);
|
||||
this.loadMoreHistory(false, true);
|
||||
}, 0);
|
||||
//if(!isFirstMessageRender) {
|
||||
setTimeout(() => {
|
||||
this.loadMoreHistory(true, true);
|
||||
this.loadMoreHistory(false, true);
|
||||
}, 0);
|
||||
//}
|
||||
});
|
||||
|
||||
return {cached, promise};
|
||||
|
@ -4186,7 +4186,7 @@ export class AppMessagesManager {
|
||||
limit += backLimit;
|
||||
}
|
||||
|
||||
return this.requestHistory(reqPeerID, maxID, limit, offset).then((historyResult: any) => {
|
||||
return this.requestHistory(reqPeerID, maxID, limit, offset).then((historyResult) => {
|
||||
historyStorage.count = historyResult.count || historyResult.messages.length;
|
||||
if(isMigrated) {
|
||||
historyStorage.count++;
|
||||
@ -4331,7 +4331,7 @@ export class AppMessagesManager {
|
||||
//timeout: APITIMEOUT,
|
||||
noErrorBox: true
|
||||
}).then((historyResult) => {
|
||||
this.log('requestHistory result:', historyResult, maxID, limit, offset);
|
||||
this.log('requestHistory result:', peerID, historyResult, maxID, limit, offset);
|
||||
|
||||
if(historyResult._ == 'messages.messagesNotModified') {
|
||||
return historyResult;
|
||||
|
@ -14,6 +14,24 @@ $bubble-margin: .25rem;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* zoom-fade-opacity
|
||||
*/
|
||||
@keyframes zoom-opacity-fade-in {
|
||||
0% {
|
||||
//transform: scale(.8) translateZ(0);
|
||||
transform: scale3d(.8, .8, 1);
|
||||
//transform: scale(.8);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
//transform: scale(1) translateZ(0);
|
||||
transform: scale3d(1, 1, 1);
|
||||
//transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.bubbles-date-group {
|
||||
position: relative;
|
||||
|
||||
@ -156,6 +174,16 @@ $bubble-margin: .25rem;
|
||||
}
|
||||
}
|
||||
|
||||
&.zoom-fade /* .bubble__container */ {
|
||||
//transform: scale(.8) translateZ(0);
|
||||
transform: scale3d(.8, .8, 1);
|
||||
//transform: scale(.8);
|
||||
opacity: 0;
|
||||
transform-origin: center;
|
||||
animation: zoom-opacity-fade-in .2s linear forwards;
|
||||
animation-delay: 0;
|
||||
}
|
||||
|
||||
&-select-checkbox {
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
|
Loading…
x
Reference in New Issue
Block a user