Wrap pinned photo
Video render photo, no video Fix iOS Safari scroll Stickers sizes for devicePixelRatio
This commit is contained in:
parent
6356b9152c
commit
cd4b8db2d1
@ -92,7 +92,8 @@ export class ChatInput {
|
||||
encoderSampleRate: 48000,
|
||||
monitorGain: 0,
|
||||
numberOfChannels: 1,
|
||||
recordingGain: 1
|
||||
recordingGain: 1,
|
||||
reuseWorker: true
|
||||
});
|
||||
} catch(err) {
|
||||
this.btnSend.classList.remove('tgico-microphone2');
|
||||
|
@ -345,7 +345,7 @@ const initEmoticonsDropdown = (pageEl: HTMLDivElement,
|
||||
let prevCategoryIndex = 0;
|
||||
let stickersScroll = new Scrollable(contentStickersDiv, 'y', 'STICKERS', undefined, undefined, 2);
|
||||
stickersScroll.container.addEventListener('scroll', (e) => {
|
||||
lottieLoader.checkAnimations();
|
||||
lottieLoader.checkAnimations(false, EMOTICONSSTICKERGROUP);
|
||||
|
||||
prevCategoryIndex = emoticonsContentOnScroll(menu, heights, prevCategoryIndex, stickersScroll.container, menuScroll);
|
||||
});
|
||||
|
@ -13,7 +13,7 @@ export default class LazyLoadQueue {
|
||||
private unlockResolve: () => void = null;
|
||||
|
||||
private log = console.log.bind(console, '[LL]:');
|
||||
private debug = true;
|
||||
private debug = false;
|
||||
|
||||
private observer: IntersectionObserver;
|
||||
|
||||
|
@ -61,7 +61,7 @@ export default class ProgressivePreloader {
|
||||
promise.notify = (details: {done: number, total: number}) => {
|
||||
if(tempID != this.tempID) return;
|
||||
|
||||
console.log('preloader download', promise, details);
|
||||
//console.log('preloader download', promise, details);
|
||||
let percents = details.done / details.total * 100;
|
||||
this.setProgress(percents);
|
||||
};
|
||||
@ -116,7 +116,7 @@ export default class ProgressivePreloader {
|
||||
}
|
||||
|
||||
let totalLength = this.circle.getTotalLength();
|
||||
console.log('setProgress', (percents / 100 * totalLength));
|
||||
//console.log('setProgress', (percents / 100 * totalLength));
|
||||
this.circle.style.strokeDasharray = '' + Math.max(5, percents / 100 * totalLength) + ', 200';
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,10 @@ import appPhotosManager from '../lib/appManagers/appPhotosManager';
|
||||
//import CryptoWorker from '../lib/crypto/cryptoworker';
|
||||
import apiManager from '../lib/mtproto/mtprotoworker';
|
||||
import LottieLoader from '../lib/lottieLoader';
|
||||
import appStickersManager from "../lib/appManagers/appStickersManager";
|
||||
import appDocsManager from "../lib/appManagers/appDocsManager";
|
||||
import { formatBytes, getEmojiToneIndex } from "../lib/utils";
|
||||
import ProgressivePreloader from './preloader';
|
||||
import LazyLoadQueue from './lazyLoadQueue';
|
||||
import apiFileManager from '../lib/mtproto/apiFileManager';
|
||||
import VideoPlayer, { MediaProgressLine } from '../lib/mediaPlayer';
|
||||
import { RichTextProcessor } from '../lib/richtextprocessor';
|
||||
import { CancellablePromise } from '../lib/polyfill';
|
||||
@ -30,6 +28,10 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
||||
middleware: () => boolean,
|
||||
lazyLoadQueue: LazyLoadQueue
|
||||
}) {
|
||||
if(doc.type == 'video') {
|
||||
return wrapPhoto(doc, message, container, boxWidth, boxHeight, withTail, isOut, lazyLoadQueue, middleware);
|
||||
}
|
||||
|
||||
let img: HTMLImageElement;
|
||||
if(withTail) {
|
||||
img = wrapMediaWithTail(doc, message, container, boxWidth, boxHeight, isOut);
|
||||
@ -49,7 +51,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
||||
if(!img || img.tagName != 'IMG') {
|
||||
container.append(img = new Image());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let video = document.createElement('video');
|
||||
let source = document.createElement('source');
|
||||
@ -95,17 +97,19 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('loaded doc:', doc, doc.url, container);
|
||||
//console.log('loaded doc:', doc, doc.url, container);
|
||||
|
||||
renderImageFromUrl(source, doc.url);
|
||||
source.type = doc.mime_type;
|
||||
video.append(source);
|
||||
video.setAttribute('playsinline', '');
|
||||
|
||||
if(img && img.parentElement) {
|
||||
img.remove();
|
||||
}
|
||||
|
||||
if(doc.type == 'gif') {
|
||||
video.muted = true;
|
||||
video.autoplay = true;
|
||||
video.loop = true;
|
||||
video.play();
|
||||
@ -687,7 +691,7 @@ function wrapMediaWithTail(photo: any, message: {mid: number, message: string},
|
||||
return img;
|
||||
}
|
||||
|
||||
export function wrapPhoto(photoID: string, message: any, container: HTMLDivElement, boxWidth = mediaSizes.active.regular.width, boxHeight = mediaSizes.active.regular.height, withTail = true, isOut = false, lazyLoadQueue: LazyLoadQueue, middleware: () => boolean, size: MTPhotoSize = null) {
|
||||
export function wrapPhoto(photoID: any, message: any, container: HTMLDivElement, boxWidth = mediaSizes.active.regular.width, boxHeight = mediaSizes.active.regular.height, withTail = true, isOut = false, lazyLoadQueue: LazyLoadQueue, middleware: () => boolean, size: MTPhotoSize = null) {
|
||||
let photo = appPhotosManager.getPhoto(photoID);
|
||||
|
||||
let image: HTMLImageElement;
|
||||
@ -734,7 +738,7 @@ export function wrapPhoto(photoID: string, message: any, container: HTMLDivEleme
|
||||
return promise.then(() => {
|
||||
if(middleware && !middleware()) return;
|
||||
|
||||
renderImageFromUrl(image || container, photo.url);
|
||||
renderImageFromUrl(image || container, photo._ == 'photo' ? photo.url : appPhotosManager.getDocumentCachedThumb(photo.id).url);
|
||||
});
|
||||
};
|
||||
|
||||
@ -865,8 +869,8 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
|
||||
loop: !emoji,
|
||||
autoplay: true,
|
||||
animationData: JSON.parse(json),
|
||||
width: !emoji ? 200 : 140,
|
||||
height: !emoji ? 200 : 140
|
||||
width: !emoji ? 200 : undefined,
|
||||
height: !emoji ? 200 : undefined
|
||||
}, group, toneIndex);
|
||||
|
||||
animation.addListener('ready', () => {
|
||||
@ -932,31 +936,34 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
|
||||
return lazyLoadQueue && (!doc.downloaded || stickerType == 2) ? (lazyLoadQueue.push({div, load, wasSeen: group == 'chat' && stickerType != 2}), Promise.resolve()) : load();
|
||||
}
|
||||
|
||||
export function wrapReply(title: string, subtitle: string, message?: any) {
|
||||
let div = document.createElement('div');
|
||||
div.classList.add('reply');
|
||||
export function wrapReply(title: string, subtitle: string, message?: any, isPinned?: boolean) {
|
||||
const prefix = isPinned ? 'pinned-message' : 'reply';
|
||||
const div = document.createElement('div');
|
||||
div.classList.add(prefix);
|
||||
|
||||
let replyBorder = document.createElement('div');
|
||||
replyBorder.classList.add('reply-border');
|
||||
const replyBorder = document.createElement('div');
|
||||
replyBorder.classList.add(prefix + '-border');
|
||||
|
||||
let replyContent = document.createElement('div');
|
||||
replyContent.classList.add('reply-content');
|
||||
const replyContent = document.createElement('div');
|
||||
replyContent.classList.add(prefix + '-content');
|
||||
|
||||
let replyTitle = document.createElement('div');
|
||||
replyTitle.classList.add('reply-title');
|
||||
const replyTitle = document.createElement('div');
|
||||
replyTitle.classList.add(prefix + '-title');
|
||||
|
||||
let replySubtitle = document.createElement('div');
|
||||
replySubtitle.classList.add('reply-subtitle');
|
||||
const replySubtitle = document.createElement('div');
|
||||
replySubtitle.classList.add(prefix + '-subtitle');
|
||||
|
||||
replyTitle.innerHTML = title ? RichTextProcessor.wrapEmojiText(title) : '';
|
||||
|
||||
let media = message && message.media;
|
||||
const media = message && message.media;
|
||||
if(media) {
|
||||
replySubtitle.innerHTML = message.rReply;
|
||||
|
||||
console.log('wrap reply', media);
|
||||
|
||||
if(media.photo || (media.document && ['video'].indexOf(media.document.type) !== -1)) {
|
||||
let replyMedia = document.createElement('div');
|
||||
replyMedia.classList.add('reply-media');
|
||||
replyMedia.classList.add(prefix + '-media');
|
||||
|
||||
let photo = media.photo || media.document;
|
||||
|
||||
@ -971,7 +978,7 @@ export function wrapReply(title: string, subtitle: string, message?: any) {
|
||||
});
|
||||
|
||||
replyContent.append(replyMedia);
|
||||
div.classList.add('is-reply-media');
|
||||
div.classList.add('is-media');
|
||||
}
|
||||
} else {
|
||||
replySubtitle.innerHTML = subtitle ? RichTextProcessor.wrapEmojiText(subtitle) : '';
|
||||
|
@ -394,13 +394,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pinned-message">
|
||||
<div class="pinned-message-border"></div>
|
||||
<div class="pinned-message-content">
|
||||
<div class="pinned-message-title">Pinned Message</div>
|
||||
<div class="pinned-message-subtitle"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-icon rp chat-mute-button" style="display: none;"></div>
|
||||
<div class="btn-icon rp tgico-search chat-search-button"></div>
|
||||
<div class="btn-icon btn-menu-toggle rp tgico-more chat-more-button">
|
||||
|
@ -5,6 +5,7 @@ import { dT, $rootScope, tsNow } from "../utils";
|
||||
import appPeersManager from "./appPeersManager";
|
||||
import appUsersManager from "./appUsersManager";
|
||||
import appChatsManager from "./appChatsManager";
|
||||
import { logger, LogLevels } from '../polyfill';
|
||||
|
||||
export class ApiUpdatesManager {
|
||||
public updatesState: {
|
||||
@ -25,6 +26,8 @@ export class ApiUpdatesManager {
|
||||
|
||||
public channelStates: any = {};
|
||||
private attached = false;
|
||||
|
||||
private log = logger('UPDATES', LogLevels.error);
|
||||
|
||||
public popPendingSeqUpdate() {
|
||||
var nextSeq = this.updatesState.seq + 1;
|
||||
@ -67,7 +70,7 @@ export class ApiUpdatesManager {
|
||||
curState.pendingPtsUpdates.sort((a: any, b: any) => {
|
||||
return a.pts - b.pts;
|
||||
});
|
||||
// console.log(dT(), 'pop update', channelID, curState.pendingPtsUpdates)
|
||||
// this.log(dT(), 'pop update', channelID, curState.pendingPtsUpdates)
|
||||
|
||||
var curPts = curState.pts;
|
||||
var goodPts = false;
|
||||
@ -86,7 +89,7 @@ export class ApiUpdatesManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log(dT(), 'pop pending pts updates', goodPts, curState.pendingPtsUpdates.slice(0, goodIndex + 1));
|
||||
this.log(dT(), 'pop pending pts updates', goodPts, curState.pendingPtsUpdates.slice(0, goodIndex + 1));
|
||||
|
||||
curState.pts = goodPts;
|
||||
for(i = 0; i <= goodIndex; i++) {
|
||||
@ -170,12 +173,12 @@ export class ApiUpdatesManager {
|
||||
break;
|
||||
|
||||
default:
|
||||
console.warn(dT(), 'Unknown update message', updateMessage);
|
||||
this.log.warn(dT(), 'Unknown update message', updateMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public getDifference() {
|
||||
// console.trace(dT(), 'Get full diff')
|
||||
// this.trace(dT(), 'Get full diff')
|
||||
const updatesState = this.updatesState;
|
||||
if(!updatesState.syncLoading) {
|
||||
updatesState.syncLoading = true;
|
||||
@ -196,7 +199,7 @@ export class ApiUpdatesManager {
|
||||
timeout: 0x7fffffff
|
||||
}).then((differenceResult: any) => {
|
||||
if(differenceResult._ == 'updates.differenceEmpty') {
|
||||
console.log(dT(), 'apply empty diff', differenceResult.seq);
|
||||
this.log(dT(), 'apply empty diff', differenceResult.seq);
|
||||
updatesState.date = differenceResult.date;
|
||||
updatesState.seq = differenceResult.seq;
|
||||
updatesState.syncLoading = false;
|
||||
@ -208,7 +211,7 @@ export class ApiUpdatesManager {
|
||||
appChatsManager.saveApiChats(differenceResult.chats);
|
||||
|
||||
// Should be first because of updateMessageID
|
||||
// console.log(dT(), 'applying', differenceResult.other_updates.length, 'other updates')
|
||||
// this.log(dT(), 'applying', differenceResult.other_updates.length, 'other updates')
|
||||
|
||||
differenceResult.other_updates.forEach((update: any) => {
|
||||
switch(update._) {
|
||||
@ -222,7 +225,7 @@ export class ApiUpdatesManager {
|
||||
this.saveUpdate(update);
|
||||
});
|
||||
|
||||
// console.log(dT(), 'applying', differenceResult.new_messages.length, 'new messages')
|
||||
// this.log(dT(), 'applying', differenceResult.new_messages.length, 'new messages')
|
||||
differenceResult.new_messages.forEach((apiMessage: any) => {
|
||||
this.saveUpdate({
|
||||
_: 'updateNewMessage',
|
||||
@ -237,12 +240,12 @@ export class ApiUpdatesManager {
|
||||
updatesState.pts = nextState.pts;
|
||||
updatesState.date = nextState.date;
|
||||
|
||||
// console.log(dT(), 'apply diff', updatesState.seq, updatesState.pts)
|
||||
// this.log(dT(), 'apply diff', updatesState.seq, updatesState.pts)
|
||||
|
||||
if(differenceResult._ == 'updates.differenceSlice') {
|
||||
this.getDifference();
|
||||
} else {
|
||||
// console.log(dT(), 'finished get diff')
|
||||
// this.log(dT(), 'finished get diff')
|
||||
$rootScope.$broadcast('stateSynchronized');
|
||||
updatesState.syncLoading = false;
|
||||
}
|
||||
@ -261,25 +264,25 @@ export class ApiUpdatesManager {
|
||||
clearTimeout(channelState.syncPending.timeout);
|
||||
channelState.syncPending = false;
|
||||
}
|
||||
// console.log(dT(), 'Get channel diff', appChatsManager.getChat(channelID), channelState.pts)
|
||||
// this.log(dT(), 'Get channel diff', appChatsManager.getChat(channelID), channelState.pts)
|
||||
apiManager.invokeApi('updates.getChannelDifference', {
|
||||
channel: appChatsManager.getChannelInput(channelID),
|
||||
filter: {_: 'channelMessagesFilterEmpty'},
|
||||
pts: channelState.pts,
|
||||
limit: 30
|
||||
}, {timeout: 0x7fffffff}).then((differenceResult: any) => {
|
||||
// console.log(dT(), 'channel diff result', differenceResult)
|
||||
// this.log(dT(), 'channel diff result', differenceResult)
|
||||
channelState.pts = differenceResult.pts;
|
||||
|
||||
if (differenceResult._ == 'updates.channelDifferenceEmpty') {
|
||||
console.log(dT(), 'apply channel empty diff', differenceResult);
|
||||
this.log(dT(), 'apply channel empty diff', differenceResult);
|
||||
channelState.syncLoading = false;
|
||||
$rootScope.$broadcast('stateSynchronized');
|
||||
return false;
|
||||
}
|
||||
|
||||
if(differenceResult._ == 'updates.channelDifferenceTooLong') {
|
||||
console.log(dT(), 'channel diff too long', differenceResult);
|
||||
this.log(dT(), 'channel diff too long', differenceResult);
|
||||
channelState.syncLoading = false;
|
||||
delete this.channelStates[channelID];
|
||||
this.saveUpdate({_: 'updateChannelReload', channel_id: channelID});
|
||||
@ -290,12 +293,12 @@ export class ApiUpdatesManager {
|
||||
appChatsManager.saveApiChats(differenceResult.chats);
|
||||
|
||||
// Should be first because of updateMessageID
|
||||
console.log(dT(), 'applying', differenceResult.other_updates.length, 'channel other updates')
|
||||
this.log(dT(), 'applying', differenceResult.other_updates.length, 'channel other updates')
|
||||
differenceResult.other_updates.forEach((update: any) => {
|
||||
this.saveUpdate(update);
|
||||
});
|
||||
|
||||
console.log(dT(), 'applying', differenceResult.new_messages.length, 'channel new messages')
|
||||
this.log(dT(), 'applying', differenceResult.new_messages.length, 'channel new messages')
|
||||
differenceResult.new_messages.forEach((apiMessage: any) => {
|
||||
this.saveUpdate({
|
||||
_: 'updateNewChannelMessage',
|
||||
@ -305,13 +308,13 @@ export class ApiUpdatesManager {
|
||||
});
|
||||
});
|
||||
|
||||
console.log(dT(), 'apply channel diff', channelState.pts);
|
||||
this.log(dT(), 'apply channel diff', channelState.pts);
|
||||
|
||||
if(differenceResult._ == 'updates.channelDifference' &&
|
||||
!differenceResult.pFlags['final']) {
|
||||
this.getChannelDifference(channelID);
|
||||
} else {
|
||||
console.log(dT(), 'finished channel get diff');
|
||||
this.log(dT(), 'finished channel get diff');
|
||||
$rootScope.$broadcast('stateSynchronized');
|
||||
channelState.syncLoading = false;
|
||||
}
|
||||
|
@ -741,6 +741,11 @@ export class AppDialogsManager {
|
||||
public setUnreadMessages(dialog: Dialog) {
|
||||
let dom = this.getDialogDom(dialog.peerID);
|
||||
|
||||
if(!dom) {
|
||||
this.log.error('setUnreadMessages no dom!', dialog);
|
||||
return;
|
||||
}
|
||||
|
||||
let lastMessage = appMessagesManager.getMessage(dialog.top_message);
|
||||
if(lastMessage._ != 'messageEmpty' && !lastMessage.deleted &&
|
||||
lastMessage.from_id == $rootScope.myID && lastMessage.peerID != $rootScope.myID &&
|
||||
|
@ -1,6 +1,6 @@
|
||||
//import apiManager from '../mtproto/apiManager';
|
||||
import apiManager from '../mtproto/mtprotoworker';
|
||||
import { $rootScope, numberWithCommas, findUpClassName, formatNumber, placeCaretAtEnd, findUpTag, langPack, whichChild } from "../utils";
|
||||
import { $rootScope, numberWithCommas, findUpClassName, formatNumber, placeCaretAtEnd, findUpTag, langPack, whichChild, cancelEvent } from "../utils";
|
||||
import appUsersManager from "./appUsersManager";
|
||||
import appMessagesManager, { Dialog } from "./appMessagesManager";
|
||||
import appPeersManager from "./appPeersManager";
|
||||
@ -36,7 +36,7 @@ console.log('appImManager included33!');
|
||||
|
||||
appSidebarLeft; // just to include
|
||||
|
||||
const testScroll = true;
|
||||
const testScroll = false;
|
||||
|
||||
const IGNOREACTIONS = ['messageActionChannelMigrateFrom'];
|
||||
|
||||
@ -237,8 +237,7 @@ export class AppImManager {
|
||||
public updateStatusInterval = 0;
|
||||
|
||||
public pinnedMsgID = 0;
|
||||
private pinnedMessageContainer = this.columnEl.querySelector('.pinned-message') as HTMLDivElement;
|
||||
private pinnedMessageContent = this.pinnedMessageContainer.querySelector('.pinned-message-subtitle') as HTMLDivElement;
|
||||
private pinnedMessageContainer: HTMLDivElement = null;
|
||||
|
||||
public lazyLoadQueue = new LazyLoadQueue();
|
||||
|
||||
@ -496,8 +495,17 @@ export class AppImManager {
|
||||
}, {once: true});
|
||||
});
|
||||
|
||||
(this.columnEl.querySelector('.person') as HTMLDivElement).addEventListener('click', () => {
|
||||
appSidebarRight.toggleSidebar(true);
|
||||
this.topbar.addEventListener('click', (e) => {
|
||||
const pinned = findUpClassName(e.target, 'pinned-message');
|
||||
if(pinned) {
|
||||
e.preventDefault();
|
||||
e.cancelBubble = true;
|
||||
|
||||
let mid = +pinned.dataset.mid;
|
||||
this.setPeer(this.peerID, mid);
|
||||
} else {
|
||||
appSidebarRight.toggleSidebar(true);
|
||||
}
|
||||
});
|
||||
|
||||
this.bubblesContainer.addEventListener('click', (e) => {
|
||||
@ -630,14 +638,6 @@ export class AppImManager {
|
||||
}
|
||||
});
|
||||
|
||||
this.pinnedMessageContainer.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.cancelBubble = true;
|
||||
|
||||
let mid = +this.pinnedMessageContainer.getAttribute('data-mid');
|
||||
this.setPeer(this.peerID, mid);
|
||||
});
|
||||
|
||||
[this.btnMute, this.menuButtons.mute].forEach(el => {
|
||||
el.addEventListener('click', () => this.mutePeer(this.peerID));
|
||||
});
|
||||
@ -757,10 +757,21 @@ export class AppImManager {
|
||||
|
||||
public setPinnedMessage(message: any) {
|
||||
/////this.log('setting pinned message', message);
|
||||
return;
|
||||
this.pinnedMessageContainer.dataset.mid = '' + message.mid;
|
||||
//return;
|
||||
const scrollTop = this.scrollable.container.scrollTop;
|
||||
const newPinned = wrapReply('Pinned Message', message.message, message, true);
|
||||
newPinned.dataset.mid = '' + message.mid;
|
||||
|
||||
this.topbar.insertBefore(newPinned, this.btnMute);
|
||||
this.topbar.classList.add('is-pinned-shown');
|
||||
this.pinnedMessageContent.innerHTML = message.rReply;
|
||||
|
||||
if(this.pinnedMessageContainer) {
|
||||
this.pinnedMessageContainer.remove();
|
||||
}
|
||||
|
||||
this.pinnedMessageContainer = newPinned;
|
||||
//this.pinnedMessageContent.innerHTML = message.rReply;
|
||||
this.scrollable.scrollTop = scrollTop + 60;
|
||||
}
|
||||
|
||||
public updateStatus() {
|
||||
@ -784,7 +795,7 @@ export class AppImManager {
|
||||
}
|
||||
|
||||
public loadMoreHistory(top: boolean) {
|
||||
this.log('loadMoreHistory', top);
|
||||
//this.log('loadMoreHistory', top);
|
||||
if(!this.peerID || testScroll || this.setPeerPromise || (top && this.getHistoryTopPromise) || (!top && this.getHistoryBottomPromise)) return;
|
||||
|
||||
// warning, если иды только отрицательные то вниз не попадёт (хотя мб и так не попадёт)
|
||||
@ -811,13 +822,13 @@ export class AppImManager {
|
||||
}
|
||||
}
|
||||
|
||||
public onScroll() {
|
||||
public onScroll(e: Event) {
|
||||
if(this.onScrollRAF) window.cancelAnimationFrame(this.onScrollRAF);
|
||||
|
||||
//if(this.scrollable.scrollLocked) return;
|
||||
|
||||
this.onScrollRAF = window.requestAnimationFrame(() => {
|
||||
lottieLoader.checkAnimations(false, 'chat');
|
||||
//lottieLoader.checkAnimations(false, 'chat');
|
||||
|
||||
if(!touchSupport) {
|
||||
if(this.isScrollingTimeout) {
|
||||
@ -1076,7 +1087,11 @@ export class AppImManager {
|
||||
if(!cached) {
|
||||
this.scrollable.container.innerHTML = '';
|
||||
//oldChatInner.remove();
|
||||
!samePeer && this.finishPeerChange();
|
||||
|
||||
if(!samePeer) {
|
||||
this.finishPeerChange();
|
||||
}
|
||||
|
||||
this.preloader.attach(this.bubblesContainer);
|
||||
|
||||
if(mediaSizes.isMobile) {
|
||||
@ -1093,11 +1108,9 @@ export class AppImManager {
|
||||
if(cached) {
|
||||
this.scrollable.container.innerHTML = '';
|
||||
//oldChatInner.remove();
|
||||
!samePeer && this.finishPeerChange();
|
||||
|
||||
const pinned = appMessagesManager.getPinnedMessage(peerID);
|
||||
if(pinned && !pinned.deleted) {
|
||||
this.setPinnedMessage(pinned);
|
||||
|
||||
if(!samePeer) {
|
||||
this.finishPeerChange();
|
||||
}
|
||||
|
||||
if(mediaSizes.isMobile) {
|
||||
@ -1206,6 +1219,14 @@ export class AppImManager {
|
||||
this.btnMute.style.display = appPeersManager.isBroadcast(peerID) ? '' : 'none';
|
||||
this.menuButtons.mute.style.display = this.myID == this.peerID ? 'none' : '';
|
||||
|
||||
const pinned = appMessagesManager.getPinnedMessage(peerID);
|
||||
if(pinned && !pinned.deleted) {
|
||||
this.setPinnedMessage(pinned);
|
||||
} else if(this.pinnedMessageContainer) {
|
||||
this.pinnedMessageContainer.remove();
|
||||
this.pinnedMessageContainer = null;
|
||||
}
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
let title = '';
|
||||
if(this.peerID == this.myID) title = 'Saved Messages';
|
||||
@ -1258,7 +1279,7 @@ export class AppImManager {
|
||||
//bubble.remove();
|
||||
});
|
||||
|
||||
lottieLoader.checkAnimations();
|
||||
lottieLoader.checkAnimations(false, 'chat');
|
||||
this.deleteEmptyDateGroups();
|
||||
}
|
||||
|
||||
@ -1366,7 +1387,7 @@ export class AppImManager {
|
||||
if(el instanceof HTMLVideoElement) {
|
||||
let source = el.firstElementChild as HTMLSourceElement;
|
||||
if(!source || !source.src) {
|
||||
this.log.warn('no source', el, source, 'src', source.src);
|
||||
//this.log.warn('no source', el, source, 'src', source.src);
|
||||
return;
|
||||
} else if(el.readyState >= 4) return;
|
||||
} else if(el.complete || !el.src) return;
|
||||
@ -1381,8 +1402,8 @@ export class AppImManager {
|
||||
};
|
||||
|
||||
if(el instanceof HTMLVideoElement) {
|
||||
el.addEventListener('loadeddata', onLoad);
|
||||
r = () => el.readyState >= 4;
|
||||
el.addEventListener('canplay', onLoad);
|
||||
r = () => el.readyState >= 1;
|
||||
} else {
|
||||
el.addEventListener('load', onLoad);
|
||||
r = () => el.complete;
|
||||
@ -1393,8 +1414,9 @@ export class AppImManager {
|
||||
window.requestAnimationFrame(c);
|
||||
|
||||
let timeout = setTimeout(() => {
|
||||
console.log('did not called', el, el.parentElement, el.complete, src);
|
||||
reject();
|
||||
// @ts-ignore
|
||||
this.log.error('did not called', el, el.parentElement, el.complete, el.readyState, src);
|
||||
resolve();
|
||||
}, 1500);
|
||||
});
|
||||
|
||||
@ -2242,6 +2264,8 @@ export class AppImManager {
|
||||
let scrollTop = this.scrollable.scrollTop;
|
||||
|
||||
previousScrollHeightMinusTop = this.scrollable.scrollHeight - scrollTop;
|
||||
//this.chatInner.style.height = '100%';
|
||||
//previousScrollHeightMinusTop = 0;
|
||||
/* if(reverse) {
|
||||
previousScrollHeightMinusTop = this.scrollable.scrollHeight - scrollTop;
|
||||
} else {
|
||||
@ -2262,7 +2286,11 @@ export class AppImManager {
|
||||
if(previousScrollHeightMinusTop !== undefined) {
|
||||
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
|
||||
touchSupport && (this.scrollable.container.style.overflow = 'hidden');
|
||||
this.scrollable.scrollTop = newScrollTop;
|
||||
touchSupport && (this.scrollable.container.style.overflow = '');
|
||||
}
|
||||
|
||||
resolve(true);
|
||||
|
@ -777,7 +777,9 @@ export class AppMediaViewer {
|
||||
let video = mover.querySelector('video') || document.createElement('video');
|
||||
let source = video.firstElementChild as HTMLSourceElement || document.createElement('source');
|
||||
|
||||
video.setAttribute('playsinline', '');
|
||||
if(media.type == 'gif') {
|
||||
video.muted = true;
|
||||
video.autoplay = true;
|
||||
video.loop = true;
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ import appPollsManager from "./appPollsManager";
|
||||
import searchIndexManager from '../searchIndexManager';
|
||||
import { MTDocument, MTPhotoSize } from "../../types";
|
||||
|
||||
console.trace('include');
|
||||
//console.trace('include');
|
||||
|
||||
const APITIMEOUT = 0;
|
||||
|
||||
@ -238,10 +238,10 @@ export class AppMessagesManager {
|
||||
apiUpdatesManager.attach(updates ?? null);
|
||||
|
||||
resolve();
|
||||
}).catch(resolve);
|
||||
}).catch(resolve).finally(() => {
|
||||
setInterval(() => this.saveState(), 10000);
|
||||
});
|
||||
});
|
||||
|
||||
setInterval(() => this.saveState(), 10000);
|
||||
}
|
||||
|
||||
public saveState() {
|
||||
@ -1986,7 +1986,7 @@ export class AppMessagesManager {
|
||||
str = langPack[_] + suffix;
|
||||
}
|
||||
|
||||
console.log('message action:', action);
|
||||
//console.log('message action:', action);
|
||||
|
||||
messageText = '<i>' + str + '</i>';
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ class AppWebpManager {
|
||||
|
||||
if(!res) {
|
||||
(window as any).webpLoaded = () => {
|
||||
console.log('webpHero loaded');
|
||||
//console.log('webpHero loaded');
|
||||
this.webpMachine = new (window as any).WebpMachine();
|
||||
resolve();
|
||||
};
|
||||
@ -56,7 +56,7 @@ class AppWebpManager {
|
||||
this.busyPromise = this.convert(bytes);
|
||||
let res = await this.busyPromise;
|
||||
|
||||
console.log('converted webp', res);
|
||||
//console.log('converted webp', res);
|
||||
|
||||
callback(res as Uint8Array);
|
||||
|
||||
@ -85,7 +85,7 @@ class AppWebpManager {
|
||||
}
|
||||
|
||||
public convertToPng(bytes: Uint8Array) {
|
||||
console.warn('convertToPng!');
|
||||
//console.warn('convertToPng!');
|
||||
return new Promise<Uint8Array>((resolve, reject) => {
|
||||
// @ts-ignore
|
||||
this.queue.push({bytes, callback: resolve});
|
||||
|
@ -1,12 +1,12 @@
|
||||
import {blobConstruct, bytesToBase64, blobSafeMimeType, dataUrlToBlob} from './bin_utils';
|
||||
import {blobConstruct} from './bin_utils';
|
||||
import FileManager from './filemanager';
|
||||
import { logger } from './polyfill';
|
||||
//import { logger } from './polyfill';
|
||||
|
||||
class CacheStorageController {
|
||||
public dbName = 'cachedFiles';
|
||||
public openDbPromise: Promise<Cache>;
|
||||
|
||||
private log: ReturnType<typeof logger> = logger('CS');
|
||||
//private log: ReturnType<typeof logger> = logger('CS');
|
||||
|
||||
constructor() {
|
||||
this.openDatabase();
|
||||
|
@ -92,13 +92,16 @@ export const mediaSizes = new MediaSizes();
|
||||
// @ts-ignore
|
||||
export const touchSupport = ('ontouchstart' in window) || (window.DocumentTouch && document instanceof DocumentTouch);
|
||||
|
||||
export const isApple = navigator.userAgent.search(/OS X|iPhone|iPad|iOS/i) != -1;
|
||||
|
||||
const Config = {
|
||||
Emoji,
|
||||
LatinizeMap,
|
||||
TLD,
|
||||
Countries,
|
||||
MediaSizes: mediaSizes,
|
||||
touchSupport
|
||||
touchSupport,
|
||||
isApple
|
||||
};
|
||||
(window as any).Config = Config;
|
||||
export default Config;
|
@ -1,10 +1,19 @@
|
||||
import { isInDOM } from "./utils";
|
||||
import { isApple } from "./config";
|
||||
|
||||
let convert = (value: number) => {
|
||||
return Math.round(Math.min(Math.max(value, 0), 1) * 255);
|
||||
};
|
||||
|
||||
type RLottiePlayerListeners = 'enterFrame' | 'ready';
|
||||
type RLottieOptions = {
|
||||
container: HTMLElement,
|
||||
autoplay?: boolean,
|
||||
animationData: any,
|
||||
loop?: boolean,
|
||||
width?: number,
|
||||
height?: number
|
||||
};
|
||||
|
||||
export class RLottiePlayer {
|
||||
public static reqId = 0;
|
||||
@ -16,8 +25,8 @@ export class RLottiePlayer {
|
||||
|
||||
public worker: QueryableWorker;
|
||||
|
||||
public width: number;
|
||||
public height: number;
|
||||
private width = 0;
|
||||
private height = 0;
|
||||
|
||||
public listeners: Partial<{
|
||||
[k in RLottiePlayerListeners]: (res: any) => void
|
||||
@ -40,21 +49,38 @@ export class RLottiePlayer {
|
||||
private frThen: number;
|
||||
private rafId: number;
|
||||
|
||||
private playedTimes = 0;
|
||||
//private playedTimes = 0;
|
||||
|
||||
constructor({el, width, height, worker}: {
|
||||
constructor({el, worker, options}: {
|
||||
el: HTMLElement,
|
||||
width: number,
|
||||
height: number,
|
||||
worker: QueryableWorker
|
||||
worker: QueryableWorker,
|
||||
options: RLottieOptions
|
||||
}) {
|
||||
this.reqId = ++RLottiePlayer['reqId'];
|
||||
this.el = el;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.worker = worker;
|
||||
|
||||
for(let i in options) {
|
||||
if(this.hasOwnProperty(i)) {
|
||||
// @ts-ignore
|
||||
this[i] = options[i];
|
||||
}
|
||||
}
|
||||
|
||||
//console.log("RLottiePlayer width:", this.width, this.height, options);
|
||||
|
||||
if(window.devicePixelRatio > 1) {
|
||||
if(isApple) {
|
||||
this.width *= window.devicePixelRatio;
|
||||
this.height *= window.devicePixelRatio;
|
||||
} else {
|
||||
this.width *= (window.devicePixelRatio - 1.5);
|
||||
this.height *= (window.devicePixelRatio - 1.5);
|
||||
}
|
||||
}
|
||||
|
||||
this.canvas = document.createElement('canvas');
|
||||
this.canvas.classList.add('rlottie');
|
||||
this.canvas.width = this.width;
|
||||
this.canvas.height = this.height;
|
||||
this.context = this.canvas.getContext('2d');
|
||||
@ -134,11 +160,11 @@ export class RLottiePlayer {
|
||||
|
||||
public renderFrame(frame: Uint8ClampedArray, frameNo: number) {
|
||||
try {
|
||||
this.context.putImageData(new ImageData(frame, this.width, this.height), 0, 0);
|
||||
this.context.putImageData(new ImageData(frame, this.width, this.height), 0, 0/* , 0, 0, this.canvas.width, this.canvas.height */);
|
||||
} catch(err) {
|
||||
console.error('RLottiePlayer renderFrame error:', err, frame, this.width, this.height);
|
||||
this.autoplay = false;
|
||||
this.stop();
|
||||
this.pause();
|
||||
}
|
||||
|
||||
this.setListenerResult('enterFrame', frameNo);
|
||||
@ -170,7 +196,7 @@ export class RLottiePlayer {
|
||||
private mainLoopForwards() {
|
||||
this.sendQuery('renderFrame', this.curFrame++);
|
||||
if(this.curFrame >= this.frameCount) {
|
||||
this.playedTimes++;
|
||||
//this.playedTimes++;
|
||||
|
||||
if(!this.loop) return false;
|
||||
|
||||
@ -183,7 +209,7 @@ export class RLottiePlayer {
|
||||
private mainLoopBackwards() {
|
||||
this.sendQuery('renderFrame', this.curFrame--);
|
||||
if(this.curFrame < 0) {
|
||||
this.playedTimes++;
|
||||
//this.playedTimes++;
|
||||
|
||||
if(!this.loop) return false;
|
||||
|
||||
@ -385,14 +411,7 @@ class LottieLoader {
|
||||
}
|
||||
}
|
||||
|
||||
public async loadAnimationWorker(params: {
|
||||
container: HTMLElement,
|
||||
autoplay?: boolean,
|
||||
animationData: any,
|
||||
loop?: boolean,
|
||||
width?: number,
|
||||
height?: number
|
||||
}, group = '', toneIndex = -1) {
|
||||
public async loadAnimationWorker(params: RLottieOptions, group = '', toneIndex = -1) {
|
||||
params.autoplay = true;
|
||||
|
||||
if(toneIndex >= 1 && toneIndex <= 5) {
|
||||
@ -403,21 +422,16 @@ class LottieLoader {
|
||||
await this.loadLottieWorkers();
|
||||
}
|
||||
|
||||
const width = params.width || parseInt(params.container.style.width);
|
||||
const height = params.height || parseInt(params.container.style.height);
|
||||
if(!params.width || !params.height) {
|
||||
params.width = parseInt(params.container.style.width);
|
||||
params.height = parseInt(params.container.style.height);
|
||||
}
|
||||
|
||||
if(!width || !height) {
|
||||
if(!params.width || !params.height) {
|
||||
throw new Error('No size for sticker!');
|
||||
}
|
||||
|
||||
const player = this.initPlayer(params.container, params.animationData, width, height);
|
||||
for(let i in params) {
|
||||
// @ts-ignore
|
||||
if(player.hasOwnProperty(i)) {
|
||||
// @ts-ignore
|
||||
player[i] = params[i];
|
||||
}
|
||||
}
|
||||
const player = this.initPlayer(params.container, params);
|
||||
|
||||
(this.byGroups[group] ?? (this.byGroups[group] = [])).push(player);
|
||||
|
||||
@ -425,7 +439,7 @@ class LottieLoader {
|
||||
}
|
||||
|
||||
public checkAnimations(blurred?: boolean, group?: string, destroy = false) {
|
||||
const groups = group && false ? [group] : Object.keys(this.byGroups);
|
||||
const groups = group /* && false */ ? [group] : Object.keys(this.byGroups);
|
||||
|
||||
if(group && !this.byGroups[group]) {
|
||||
console.warn('no animation group:', group);
|
||||
@ -438,20 +452,6 @@ class LottieLoader {
|
||||
|
||||
animations.forEach(player => {
|
||||
this.checkAnimation(player, blurred, destroy);
|
||||
|
||||
//if(!autoplay) continue;
|
||||
|
||||
/* if(blurred || !isElementInViewport(container)) {
|
||||
if(!paused) {
|
||||
this.debug && console.log('pause animation', isElementInViewport(container), container);
|
||||
animation.pause();
|
||||
animations[i].paused = true;
|
||||
}
|
||||
} else if(paused) {
|
||||
this.debug && console.log('play animation', container);
|
||||
animation.play();
|
||||
animations[i].paused = false;
|
||||
} */
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -523,12 +523,11 @@ class LottieLoader {
|
||||
this.workers.length = 0;
|
||||
}
|
||||
|
||||
private initPlayer(el: HTMLElement, json: any, width: number, height: number) {
|
||||
private initPlayer(el: HTMLElement, options: RLottieOptions) {
|
||||
const rlPlayer = new RLottiePlayer({
|
||||
el,
|
||||
width,
|
||||
height,
|
||||
worker: this.workers[this.curWorkerNum++]
|
||||
worker: this.workers[this.curWorkerNum++],
|
||||
options
|
||||
});
|
||||
|
||||
this.players[rlPlayer.reqId] = rlPlayer;
|
||||
@ -536,7 +535,7 @@ class LottieLoader {
|
||||
this.curWorkerNum = 0;
|
||||
}
|
||||
|
||||
rlPlayer.loadFromData(json);
|
||||
rlPlayer.loadFromData(options.animationData);
|
||||
|
||||
return rlPlayer;
|
||||
}
|
||||
|
@ -4,25 +4,30 @@ import {SecureRandom} from 'jsbn';
|
||||
|
||||
export const secureRandom = new SecureRandom();
|
||||
|
||||
export function logger(prefix: string) {
|
||||
export enum LogLevels {
|
||||
log = 1,
|
||||
warn = 2,
|
||||
error = 4
|
||||
};
|
||||
export function logger(prefix: string, level = LogLevels.log | LogLevels.warn | LogLevels.error) {
|
||||
function Log(...args: any[]) {
|
||||
return console.log(dT(), '[' + prefix + ']:', ...args);
|
||||
return level & LogLevels.log && console.log(dT(), '[' + prefix + ']:', ...args);
|
||||
}
|
||||
|
||||
Log.warn = function(...args: any[]) {
|
||||
return console.warn(dT(), '[' + prefix + ']:', ...args);
|
||||
return level & LogLevels.warn && console.warn(dT(), '[' + prefix + ']:', ...args);
|
||||
};
|
||||
|
||||
Log.info = function(...args: any[]) {
|
||||
return console.info(dT(), '[' + prefix + ']:', ...args);
|
||||
return level & LogLevels.log && console.info(dT(), '[' + prefix + ']:', ...args);
|
||||
};
|
||||
|
||||
Log.error = function(...args: any[]) {
|
||||
return console.error(dT(), '[' + prefix + ']:', ...args);
|
||||
return level & LogLevels.error && console.error(dT(), '[' + prefix + ']:', ...args);
|
||||
};
|
||||
|
||||
Log.trace = function(...args: any[]) {
|
||||
return console.trace(dT(), '[' + prefix + ']:', ...args);
|
||||
return level & LogLevels.log && console.trace(dT(), '[' + prefix + ']:', ...args);
|
||||
}
|
||||
|
||||
return Log;
|
||||
|
@ -437,7 +437,7 @@ $time-background: rgba(0, 0, 0, .35);
|
||||
position: relative;
|
||||
/* padding: .25rem; */
|
||||
|
||||
&.is-reply-media {
|
||||
&.is-media {
|
||||
.pinned-message-content, .reply-content {
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
@ -1354,6 +1354,11 @@ img.emoji {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.rlottie {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
/* #chats-container {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
|
Loading…
x
Reference in New Issue
Block a user