|
|
@ -27,21 +27,35 @@ console.log('appImManager included!'); |
|
|
|
let testScroll = false; |
|
|
|
let testScroll = false; |
|
|
|
|
|
|
|
|
|
|
|
class ScrollPosition { |
|
|
|
class ScrollPosition { |
|
|
|
public previousScrollHeightMinusTop = 0; |
|
|
|
previousScrollHeightMinusTop = 0; |
|
|
|
public readyFor = 'up'; |
|
|
|
readyFor = 'up'; |
|
|
|
public container: HTMLElement; |
|
|
|
container: HTMLElement; |
|
|
|
|
|
|
|
rAF: number; |
|
|
|
|
|
|
|
debug = true; |
|
|
|
|
|
|
|
|
|
|
|
constructor(public node: HTMLElement) { |
|
|
|
constructor(node: HTMLElement) { |
|
|
|
this.container = node.parentElement; |
|
|
|
this.container = node.parentElement; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public restore() { |
|
|
|
restore() { |
|
|
|
//console.log('scrollPosition restore 2', this.node.scrollHeight, (this.node.scrollHeight
|
|
|
|
let setScrollTop = this.container.scrollHeight - this.previousScrollHeightMinusTop; |
|
|
|
//- this.previousScrollHeightMinusTop) + 'px', this.container);
|
|
|
|
if(this.debug) appImManager.log('scrollPosition restore', this.readyFor, this.container.scrollHeight, |
|
|
|
|
|
|
|
setScrollTop, this.container, this.container.parentElement.classList.contains('scrolled-down')); |
|
|
|
|
|
|
|
|
|
|
|
if(this.readyFor === 'up' || appImManager.scroll.parentElement.classList.contains('scrolled-down')) { |
|
|
|
if(this.readyFor === 'up'/* || this.container.parentElement.classList.contains('scrolled-down') */) { |
|
|
|
this.container.scrollTop = this.node.scrollHeight |
|
|
|
if(this.debug) appImManager.log('scrollPosition restore 2', this.readyFor, this.container.scrollHeight, |
|
|
|
- this.previousScrollHeightMinusTop; |
|
|
|
setScrollTop, this.container); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(this.rAF) window.cancelAnimationFrame(this.rAF); |
|
|
|
|
|
|
|
this.rAF = window.requestAnimationFrame(() => { |
|
|
|
|
|
|
|
this.container.scrollTop = this.container.scrollHeight - this.previousScrollHeightMinusTop; |
|
|
|
|
|
|
|
this.rAF = 0; |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} else if(this.container.parentElement.classList.contains('scrolled-down')) { |
|
|
|
|
|
|
|
if(this.debug) appImManager.log('scrollPosition restore 2', this.readyFor, this.container.scrollHeight, |
|
|
|
|
|
|
|
setScrollTop, this.container); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.container.scrollTop = setScrollTop; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 'down' doesn't need to be special cased unless the
|
|
|
|
// 'down' doesn't need to be special cased unless the
|
|
|
@ -50,12 +64,130 @@ class ScrollPosition { |
|
|
|
// a Facebook messages effect
|
|
|
|
// a Facebook messages effect
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public prepareFor(direction: string) { |
|
|
|
prepareFor(direction = 'up') { |
|
|
|
this.readyFor = direction || 'up'; |
|
|
|
if(this.rAF) { |
|
|
|
this.previousScrollHeightMinusTop = this.node.scrollHeight |
|
|
|
window.cancelAnimationFrame(this.rAF); |
|
|
|
- this.container.scrollTop; |
|
|
|
this.rAF = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.readyFor = direction; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(direction == 'down') { |
|
|
|
|
|
|
|
let scrollTop = this.container.scrollTop; |
|
|
|
|
|
|
|
this.previousScrollHeightMinusTop = scrollTop > 0 ? this.container.scrollHeight - scrollTop : 0; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
this.previousScrollHeightMinusTop = this.container.scrollHeight - this.container.scrollTop; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
//let scrollTop = this.container.scrollTop;
|
|
|
|
|
|
|
|
//this.previousScrollHeightMinusTop = scrollTop > 0 || this.readyFor == 'up' ? this.container.scrollHeight - this.container.scrollTop : 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(this.debug) appImManager.log.trace('scrollPosition prepareFor', direction, this.container.scrollHeight, |
|
|
|
|
|
|
|
this.container.scrollTop, this.previousScrollHeightMinusTop); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class BubbleGroups { |
|
|
|
|
|
|
|
bubblesByGroups: Array<{timestamp: number, fromID: number, mid: number, group: HTMLDivElement[]}> = []; // map to group
|
|
|
|
|
|
|
|
groups: Array<HTMLDivElement[]> = []; |
|
|
|
|
|
|
|
updateRAFs: Map<HTMLDivElement[], number> = new Map(); |
|
|
|
|
|
|
|
newGroupDiff = 120; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
removeBubble(bubble: HTMLDivElement, mid: number) { |
|
|
|
|
|
|
|
let details = this.bubblesByGroups.findAndSplice(g => g.mid == mid); |
|
|
|
|
|
|
|
if(details && details.group.length) { |
|
|
|
|
|
|
|
details.group.findAndSplice(d => d == bubble); |
|
|
|
|
|
|
|
if(!details.group.length) { |
|
|
|
|
|
|
|
this.groups.findAndSplice(g => g == details.group); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
addBubble(bubble: HTMLDivElement, message: any, reverse: boolean) { |
|
|
|
|
|
|
|
let timestamp = message.date; |
|
|
|
|
|
|
|
let fromID = message.fromID; |
|
|
|
|
|
|
|
let group: HTMLDivElement[]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// try to find added
|
|
|
|
|
|
|
|
//this.removeBubble(message.mid);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(this.bubblesByGroups.length) { |
|
|
|
|
|
|
|
if(reverse) { |
|
|
|
|
|
|
|
let g = this.bubblesByGroups[0]; |
|
|
|
|
|
|
|
if(g.fromID == fromID && (g.timestamp - timestamp) < this.newGroupDiff) { |
|
|
|
|
|
|
|
group = g.group; |
|
|
|
|
|
|
|
group.unshift(bubble); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
this.groups.unshift(group = [bubble]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
let g = this.bubblesByGroups[this.bubblesByGroups.length - 1]; |
|
|
|
|
|
|
|
if(g.fromID == fromID && (timestamp - g.timestamp) < this.newGroupDiff) { |
|
|
|
|
|
|
|
group = g.group; |
|
|
|
|
|
|
|
group.push(bubble); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
this.groups.push(group = [bubble]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
this.groups.push(group = [bubble]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.log('addBubble', bubble, message.mid, fromID, reverse, group); |
|
|
|
|
|
|
|
|
|
|
|
//console.log('scrollPosition prepareFor', direction, this.node.scrollHeight, this.previousScrollHeightMinusTop + 'px')
|
|
|
|
this.bubblesByGroups[reverse ? 'unshift' : 'push']({timestamp, fromID, mid: message.mid, group}); |
|
|
|
|
|
|
|
this.updateGroup(group); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
updateGroup(group: HTMLDivElement[]) { |
|
|
|
|
|
|
|
if(this.updateRAFs.has(group)) { |
|
|
|
|
|
|
|
window.cancelAnimationFrame(this.updateRAFs.get(group)); |
|
|
|
|
|
|
|
this.updateRAFs.delete(group); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.updateRAFs.set(group, window.requestAnimationFrame(() => { |
|
|
|
|
|
|
|
this.updateRAFs.delete(group); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!group.length) { |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let first = group[0]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.log('updateGroup', group, first); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(group.length == 1) { |
|
|
|
|
|
|
|
first.classList.add('is-group-first', 'is-group-last'); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
first.classList.remove('is-group-last'); |
|
|
|
|
|
|
|
first.classList.add('is-group-first'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let length = group.length - 1; |
|
|
|
|
|
|
|
for(let i = 1; i < length; ++i) { |
|
|
|
|
|
|
|
let bubble = group[i]; |
|
|
|
|
|
|
|
bubble.classList.remove('is-group-last', 'is-group-first'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let last = group[group.length - 1]; |
|
|
|
|
|
|
|
last.classList.remove('is-group-first'); |
|
|
|
|
|
|
|
last.classList.add('is-group-last'); |
|
|
|
|
|
|
|
})); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
updateGroupByMessageID(mid: number) { |
|
|
|
|
|
|
|
let details = this.bubblesByGroups.find(g => g.mid == mid); |
|
|
|
|
|
|
|
if(details) { |
|
|
|
|
|
|
|
this.updateGroup(details.group); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cleanup() { |
|
|
|
|
|
|
|
this.bubblesByGroups = []; |
|
|
|
|
|
|
|
for(let value of this.updateRAFs.values()) { |
|
|
|
|
|
|
|
window.cancelAnimationFrame(value); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
this.updateRAFs.clear(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -128,6 +260,8 @@ export class AppImManager { |
|
|
|
|
|
|
|
|
|
|
|
private setPeerPromise: Promise<boolean> = null; |
|
|
|
private setPeerPromise: Promise<boolean> = null; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public bubbleGroups = new BubbleGroups(); |
|
|
|
|
|
|
|
|
|
|
|
constructor() { |
|
|
|
constructor() { |
|
|
|
this.log = logger('IM'); |
|
|
|
this.log = logger('IM'); |
|
|
|
|
|
|
|
|
|
|
@ -152,12 +286,14 @@ export class AppImManager { |
|
|
|
this.myID = userAuth ? userAuth.id : 0; |
|
|
|
this.myID = userAuth ? userAuth.id : 0; |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// will call when message is sent (only 1)
|
|
|
|
$rootScope.$on('history_append', (e: CustomEvent) => { |
|
|
|
$rootScope.$on('history_append', (e: CustomEvent) => { |
|
|
|
let details = e.detail; |
|
|
|
let details = e.detail; |
|
|
|
|
|
|
|
|
|
|
|
this.renderMessagesByIDs([details.messageID]); |
|
|
|
this.renderMessagesByIDs([details.messageID]); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// will call when sent for update pos
|
|
|
|
$rootScope.$on('history_update', (e: CustomEvent) => { |
|
|
|
$rootScope.$on('history_update', (e: CustomEvent) => { |
|
|
|
let details = e.detail; |
|
|
|
let details = e.detail; |
|
|
|
|
|
|
|
|
|
|
@ -169,6 +305,7 @@ export class AppImManager { |
|
|
|
|
|
|
|
|
|
|
|
let message = appMessagesManager.getMessage(mid); |
|
|
|
let message = appMessagesManager.getMessage(mid); |
|
|
|
//this.log('history_update', this.bubbles[mid], mid, message);
|
|
|
|
//this.log('history_update', this.bubbles[mid], mid, message);
|
|
|
|
|
|
|
|
|
|
|
|
this.renderMessage(message, false, false, bubble); |
|
|
|
this.renderMessage(message, false, false, bubble); |
|
|
|
|
|
|
|
|
|
|
|
this.deleteEmptySideDivs(); |
|
|
|
this.deleteEmptySideDivs(); |
|
|
@ -219,6 +356,8 @@ export class AppImManager { |
|
|
|
bubble.classList.remove('is-sending'); |
|
|
|
bubble.classList.remove('is-sending'); |
|
|
|
bubble.classList.add('is-sent'); |
|
|
|
bubble.classList.add('is-sent'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.bubbleGroups.removeBubble(bubble, tempID); |
|
|
|
|
|
|
|
|
|
|
|
delete this.bubbles[tempID]; |
|
|
|
delete this.bubbles[tempID]; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
this.log.warn('message_sent there is no bubble', e.detail); |
|
|
|
this.log.warn('message_sent there is no bubble', e.detail); |
|
|
@ -363,9 +502,7 @@ export class AppImManager { |
|
|
|
let ids = Object.keys(this.bubbles).map(k => +k).filter(id => { |
|
|
|
let ids = Object.keys(this.bubbles).map(k => +k).filter(id => { |
|
|
|
let message = appMessagesManager.getMessage(id); |
|
|
|
let message = appMessagesManager.getMessage(id); |
|
|
|
|
|
|
|
|
|
|
|
return message.media && (message.media.photo |
|
|
|
return message.media && (message.media.photo || (message.media.document && (message.media.document.type == 'video' || message.media.document.type == 'gif')) || (message.media.webpage && (message.media.webpage.document || message.media.webpage.photo))); |
|
|
|
|| (message.media.document && (message.media.document.type == 'video' || message.media.document.type == 'gif')) |
|
|
|
|
|
|
|
|| (message.media.webpage && (message.media.webpage.document || message.media.webpage.photo))); |
|
|
|
|
|
|
|
}).sort(); |
|
|
|
}).sort(); |
|
|
|
let idx = ids.findIndex(i => i == messageID); |
|
|
|
let idx = ids.findIndex(i => i == messageID); |
|
|
|
|
|
|
|
|
|
|
@ -458,8 +595,7 @@ export class AppImManager { |
|
|
|
|
|
|
|
|
|
|
|
if(!msgID) return; |
|
|
|
if(!msgID) return; |
|
|
|
|
|
|
|
|
|
|
|
if(this.myID == this.peerID || |
|
|
|
if(this.myID == this.peerID || (this.peerID < 0 && !appPeersManager.isChannel(this.peerID) && !appPeersManager.isMegagroup(this.peerID))) { |
|
|
|
(this.peerID < 0 && !appPeersManager.isChannel(this.peerID) && !appPeersManager.isMegagroup(this.peerID))) { |
|
|
|
|
|
|
|
this.contextMenuPin.style.display = ''; |
|
|
|
this.contextMenuPin.style.display = ''; |
|
|
|
} else this.contextMenuPin.style.display = 'none'; |
|
|
|
} else this.contextMenuPin.style.display = 'none'; |
|
|
|
|
|
|
|
|
|
|
@ -646,40 +782,8 @@ export class AppImManager { |
|
|
|
this.loadMediaQueueProcess(); |
|
|
|
this.loadMediaQueueProcess(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public async loadMediaQueueProcessOld(): Promise<void[]> { |
|
|
|
|
|
|
|
if(this.loadMediaQueuePromise /* || 1 == 1 */) return this.loadMediaQueuePromise; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let woo = this.loadMediaQueue.splice(-5, 5).reverse().map(f => f()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(woo.length) { |
|
|
|
|
|
|
|
///this.log('Will load more media:', woo.length);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
woo.forEach(async(promise) => { |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
await promise; |
|
|
|
|
|
|
|
} catch(err) { |
|
|
|
|
|
|
|
this.log.error('loadMediaQueue error:', err); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.loadingMedia--; |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
this.loadMediaQueuePromise = Promise.all(woo); |
|
|
|
|
|
|
|
await this.loadMediaQueuePromise; |
|
|
|
|
|
|
|
} catch(err) { |
|
|
|
|
|
|
|
this.log.error('loadMediaQueue error:', err); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.loadMediaQueuePromise = null; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(this.loadMediaQueue.length) return this.loadMediaQueueProcess(); |
|
|
|
|
|
|
|
return this.loadMediaQueuePromise; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public async loadMediaQueueProcess(): Promise<void[]> { |
|
|
|
public async loadMediaQueueProcess(): Promise<void[]> { |
|
|
|
if(this.loadingMedia >= 5) return; |
|
|
|
if(this.loadingMedia >= 5/* || 1 == 1 */) return; |
|
|
|
|
|
|
|
|
|
|
|
let item = this.loadMediaQueue.pop(); |
|
|
|
let item = this.loadMediaQueue.pop(); |
|
|
|
if(item) { |
|
|
|
if(item) { |
|
|
@ -709,44 +813,10 @@ export class AppImManager { |
|
|
|
return apiManager.invokeApi('account.updateStatus', {offline: this.offline}); |
|
|
|
return apiManager.invokeApi('account.updateStatus', {offline: this.offline}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public onScroll() { |
|
|
|
public loadMoreHistory(top: boolean) { |
|
|
|
let readed: number[] = []; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.unreaded.forEachReverse((msgID, idx) => { |
|
|
|
|
|
|
|
let bubble = this.bubbles[msgID]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(isElementInViewport(bubble)) { |
|
|
|
|
|
|
|
readed.push(msgID); |
|
|
|
|
|
|
|
this.unreaded.splice(idx, 1); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lottieLoader.checkAnimations(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(readed.length) { |
|
|
|
|
|
|
|
let max = Math.max(...readed); |
|
|
|
|
|
|
|
let min = Math.min(...readed); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(this.peerID < 0) { |
|
|
|
|
|
|
|
max = appMessagesIDsManager.getMessageIDInfo(max)[0]; |
|
|
|
|
|
|
|
min = appMessagesIDsManager.getMessageIDInfo(min)[0]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//appMessagesManager.readMessages(readed);
|
|
|
|
|
|
|
|
appMessagesManager.readHistory(this.peerID, max, min).catch((err: any) => { |
|
|
|
|
|
|
|
this.log.error('readHistory err:', err); |
|
|
|
|
|
|
|
appMessagesManager.readHistory(this.peerID, max, min); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(this.scroll.scrollHeight - (this.scroll.scrollTop + this.scroll.offsetHeight) == 0/* <= 5 */) { |
|
|
|
|
|
|
|
this.scroll.parentElement.classList.add('scrolled-down'); |
|
|
|
|
|
|
|
} else if(this.scroll.parentElement.classList.contains('scrolled-down')) { |
|
|
|
|
|
|
|
this.scroll.parentElement.classList.remove('scrolled-down'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// load more history
|
|
|
|
// load more history
|
|
|
|
if(!this.getHistoryPromise && !this.getHistoryTimeout && !testScroll) { |
|
|
|
// возможно нужно добавить разные таймауты для верха и низа
|
|
|
|
|
|
|
|
if(!this.getHistoryPromise && !this.getHistoryTimeout && this.peerID && !testScroll) { |
|
|
|
this.getHistoryTimeout = setTimeout(() => { // must be
|
|
|
|
this.getHistoryTimeout = setTimeout(() => { // must be
|
|
|
|
let history = Object.keys(this.bubbles).map(id => +id).sort(); |
|
|
|
let history = Object.keys(this.bubbles).map(id => +id).sort(); |
|
|
|
|
|
|
|
|
|
|
@ -765,32 +835,13 @@ export class AppImManager { |
|
|
|
|
|
|
|
|
|
|
|
this.getHistoryTimeout = 0; |
|
|
|
this.getHistoryTimeout = 0; |
|
|
|
|
|
|
|
|
|
|
|
let willLoad = false; |
|
|
|
if(!this.scrolledAll && top) { |
|
|
|
if(!this.scrolledAll) { |
|
|
|
this.log('Will load more (up) history by id:', history[0], 'maxID:', history[history.length - 1], history); |
|
|
|
let length = history.length < 10 ? history.length : 10; |
|
|
|
|
|
|
|
for(let i = 0; i < length; ++i) { |
|
|
|
|
|
|
|
let msgID = history[i]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let bubble = this.bubbles[msgID]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!bubble) { |
|
|
|
|
|
|
|
this.log.error('no bubble by msgID:', msgID); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(isElementInViewport(bubble)) { |
|
|
|
|
|
|
|
willLoad = true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////this.log('Will load more (up) history by id:', history[0], 'maxID:', history[history.length - 1], history, bubble);
|
|
|
|
|
|
|
|
/* false && */!testScroll && this.getHistory(history[0], true).then(() => { // uncomment
|
|
|
|
/* false && */!testScroll && this.getHistory(history[0], true).then(() => { // uncomment
|
|
|
|
this.onScroll(); |
|
|
|
this.onScroll(); |
|
|
|
}).catch(err => { |
|
|
|
}).catch(err => { |
|
|
|
this.log.warn('Could not load more history, err:', err); |
|
|
|
this.log.warn('Could not load more history, err:', err); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(this.scrolledAllDown) return; |
|
|
|
if(this.scrolledAllDown) return; |
|
|
@ -802,34 +853,62 @@ export class AppImManager { |
|
|
|
} */ |
|
|
|
} */ |
|
|
|
|
|
|
|
|
|
|
|
// if scroll down after search
|
|
|
|
// if scroll down after search
|
|
|
|
if(!willLoad && (!dialog || history.indexOf(dialog.top_message) === -1)) { |
|
|
|
if(!top && (!dialog || history.indexOf(dialog.top_message) === -1)) { |
|
|
|
let lastMsgIDs = history.slice(-10); |
|
|
|
this.log('Will load more (down) history by maxID:', history[history.length - 1], history); |
|
|
|
for(let msgID of lastMsgIDs) { |
|
|
|
/* false && */!testScroll && this.getHistory(history[history.length - 1], false, true).then(() => { // uncomment
|
|
|
|
let bubble = this.bubbles[msgID]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(isElementInViewport(bubble)) { |
|
|
|
|
|
|
|
willLoad = true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////this.log('Will load more (down) history by maxID:', lastMsgIDs[lastMsgIDs.length - 1], lastMsgIDs, bubble);
|
|
|
|
|
|
|
|
/* false && */!testScroll && this.getHistory(lastMsgIDs[lastMsgIDs.length - 1], false, true).then(() => { // uncomment
|
|
|
|
|
|
|
|
this.onScroll(); |
|
|
|
this.onScroll(); |
|
|
|
}).catch(err => { |
|
|
|
}).catch(err => { |
|
|
|
this.log.warn('Could not load more history, err:', err); |
|
|
|
this.log.warn('Could not load more history, err:', err); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}, 0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
break; |
|
|
|
public onScroll() { |
|
|
|
|
|
|
|
let readed: number[] = []; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.unreaded.forEachReverse((msgID, idx) => { |
|
|
|
|
|
|
|
let bubble = this.bubbles[msgID]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(isElementInViewport(bubble)) { |
|
|
|
|
|
|
|
readed.push(msgID); |
|
|
|
|
|
|
|
this.unreaded.splice(idx, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lottieLoader.checkAnimations(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(readed.length) { |
|
|
|
|
|
|
|
let max = Math.max(...readed); |
|
|
|
|
|
|
|
let min = Math.min(...readed); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(this.peerID < 0) { |
|
|
|
|
|
|
|
max = appMessagesIDsManager.getMessageIDInfo(max)[0]; |
|
|
|
|
|
|
|
min = appMessagesIDsManager.getMessageIDInfo(min)[0]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//appMessagesManager.readMessages(readed);
|
|
|
|
|
|
|
|
appMessagesManager.readHistory(this.peerID, max, min).catch((err: any) => { |
|
|
|
|
|
|
|
this.log.error('readHistory err:', err); |
|
|
|
|
|
|
|
appMessagesManager.readHistory(this.peerID, max, min); |
|
|
|
|
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
}, 0); |
|
|
|
|
|
|
|
|
|
|
|
if(this.scroll.scrollHeight - (this.scroll.scrollTop + this.scroll.offsetHeight) == 0/* <= 5 */) { |
|
|
|
|
|
|
|
this.scroll.parentElement.classList.add('scrolled-down'); |
|
|
|
|
|
|
|
} else if(this.scroll.parentElement.classList.contains('scrolled-down')) { |
|
|
|
|
|
|
|
this.scroll.parentElement.classList.remove('scrolled-down'); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public setScroll() { |
|
|
|
public setScroll() { |
|
|
|
this.scrollable = new Scrollable(this.bubblesContainer, false, true, 750, 'IM'/* 1500 */); |
|
|
|
this.scrollable = new Scrollable(this.bubblesContainer, false, true, 750, 'IM', this.chatInner/* 1500 */, 300); |
|
|
|
this.scroll = this.scrollable.container; |
|
|
|
this.scroll = this.scrollable.container; |
|
|
|
|
|
|
|
|
|
|
|
this.scrollable.setVirtualContainer(this.chatInner); |
|
|
|
this.scrollable.setVirtualContainer(this.chatInner); |
|
|
|
|
|
|
|
this.scrollable.onScrolledTop = () => this.loadMoreHistory(true); |
|
|
|
|
|
|
|
this.scrollable.onScrolledBottom = () => this.loadMoreHistory(false); |
|
|
|
|
|
|
|
|
|
|
|
this.scrollPosition = new ScrollPosition(this.chatInner); |
|
|
|
this.scrollPosition = new ScrollPosition(this.chatInner); |
|
|
|
this.scroll.addEventListener('scroll', this.onScroll.bind(this)); |
|
|
|
this.scroll.addEventListener('scroll', this.onScroll.bind(this)); |
|
|
@ -937,6 +1016,7 @@ export class AppImManager { |
|
|
|
} |
|
|
|
} |
|
|
|
this.bubbles = {}; |
|
|
|
this.bubbles = {}; |
|
|
|
this.dateMessages = {}; |
|
|
|
this.dateMessages = {}; |
|
|
|
|
|
|
|
this.bubbleGroups.cleanup(); |
|
|
|
this.unreaded = []; |
|
|
|
this.unreaded = []; |
|
|
|
this.unreadOut = []; |
|
|
|
this.unreadOut = []; |
|
|
|
this.loadMediaQueue = []; |
|
|
|
this.loadMediaQueue = []; |
|
|
@ -984,7 +1064,8 @@ export class AppImManager { |
|
|
|
if(dialog && lastMsgID == dialog.top_message) { |
|
|
|
if(dialog && lastMsgID == dialog.top_message) { |
|
|
|
this.scroll.scrollTop = this.scroll.scrollHeight; |
|
|
|
this.scroll.scrollTop = this.scroll.scrollHeight; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
this.bubbles[lastMsgID].scrollIntoView(); |
|
|
|
//this.bubbles[lastMsgID].scrollIntoView();
|
|
|
|
|
|
|
|
this.scrollable.scrollIntoView(this.bubbles[lastMsgID]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return Promise.resolve(true); |
|
|
|
return Promise.resolve(true); |
|
|
@ -1038,7 +1119,7 @@ export class AppImManager { |
|
|
|
this.titleEl.innerHTML = appSidebarRight.profileElements.name.innerHTML = title; |
|
|
|
this.titleEl.innerHTML = appSidebarRight.profileElements.name.innerHTML = title; |
|
|
|
|
|
|
|
|
|
|
|
this.topbar.style.display = this.goDownBtn.style.display = ''; |
|
|
|
this.topbar.style.display = this.goDownBtn.style.display = ''; |
|
|
|
//appSidebarRight.toggleSidebar(true);
|
|
|
|
appSidebarRight.toggleSidebar(true); |
|
|
|
|
|
|
|
|
|
|
|
this.chatInput.style.display = appPeersManager.isChannel(peerID) && !appPeersManager.isMegagroup(peerID) ? 'none' : ''; |
|
|
|
this.chatInput.style.display = appPeersManager.isChannel(peerID) && !appPeersManager.isMegagroup(peerID) ? 'none' : ''; |
|
|
|
|
|
|
|
|
|
|
@ -1048,6 +1129,8 @@ export class AppImManager { |
|
|
|
this.chatInner.classList.remove('is-chat'); |
|
|
|
this.chatInner.classList.remove('is-chat'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//this.scroll.scrollTop = this.scroll.scrollHeight;
|
|
|
|
|
|
|
|
|
|
|
|
return this.setPeerPromise = Promise.all([ |
|
|
|
return this.setPeerPromise = Promise.all([ |
|
|
|
this.getHistory(forwarding ? lastMsgID + 1 : lastMsgID).then(() => { |
|
|
|
this.getHistory(forwarding ? lastMsgID + 1 : lastMsgID).then(() => { |
|
|
|
////this.log('setPeer removing preloader');
|
|
|
|
////this.log('setPeer removing preloader');
|
|
|
@ -1068,18 +1151,18 @@ export class AppImManager { |
|
|
|
this.scroll.scrollTop = this.scroll.scrollHeight; |
|
|
|
this.scroll.scrollTop = this.scroll.scrollHeight; |
|
|
|
} |
|
|
|
} |
|
|
|
} else if(dialog && dialog.top_message) { // add last message, bc in getHistory will load < max_id
|
|
|
|
} else if(dialog && dialog.top_message) { // add last message, bc in getHistory will load < max_id
|
|
|
|
this.renderMessage(appMessagesManager.getMessage(dialog.top_message)); |
|
|
|
this.renderMessage(appMessagesManager.getMessage(dialog.top_message), false, true); |
|
|
|
|
|
|
|
//this.scroll.scrollTop = this.scroll.scrollHeight;
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(this.scroll) { |
|
|
|
|
|
|
|
this.onScroll(); |
|
|
|
this.onScroll(); |
|
|
|
} |
|
|
|
this.scrollable.onScroll(); |
|
|
|
|
|
|
|
|
|
|
|
this.preloader.detach(); |
|
|
|
this.preloader.detach(); |
|
|
|
|
|
|
|
|
|
|
|
//setTimeout(() => {
|
|
|
|
//setTimeout(() => {
|
|
|
|
//appSidebarRight.fillProfileElements();
|
|
|
|
//appSidebarRight.fillProfileElements();
|
|
|
|
appSidebarRight.loadSidebarMedia(); |
|
|
|
appSidebarRight.loadSidebarMedia(true); |
|
|
|
//}, 500);
|
|
|
|
//}, 500);
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
@ -1123,7 +1206,6 @@ export class AppImManager { |
|
|
|
|
|
|
|
|
|
|
|
///////this.log('updateUnreadByDialog', maxID, dialog, this.unreadOut);
|
|
|
|
///////this.log('updateUnreadByDialog', maxID, dialog, this.unreadOut);
|
|
|
|
|
|
|
|
|
|
|
|
let length = this.unreadOut.length; |
|
|
|
|
|
|
|
this.unreadOut.forEachReverse((msgID, idx) => { |
|
|
|
this.unreadOut.forEachReverse((msgID, idx) => { |
|
|
|
if(msgID > 0 && msgID <= maxID) { |
|
|
|
if(msgID > 0 && msgID <= maxID) { |
|
|
|
let bubble = this.bubbles[msgID]; |
|
|
|
let bubble = this.bubbles[msgID]; |
|
|
@ -1148,13 +1230,9 @@ export class AppImManager { |
|
|
|
if(!(id in this.bubbles)) return; |
|
|
|
if(!(id in this.bubbles)) return; |
|
|
|
|
|
|
|
|
|
|
|
let bubble = this.bubbles[id]; |
|
|
|
let bubble = this.bubbles[id]; |
|
|
|
let parent = bubble.parentNode as HTMLDivElement; |
|
|
|
|
|
|
|
delete this.bubbles[id]; |
|
|
|
delete this.bubbles[id]; |
|
|
|
bubble.remove(); |
|
|
|
this.scrollable.removeElement(bubble); |
|
|
|
|
|
|
|
//bubble.remove();
|
|
|
|
if(!parent.childNodes.length) { |
|
|
|
|
|
|
|
parent.remove(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
lottieLoader.checkAnimations(); |
|
|
|
lottieLoader.checkAnimations(); |
|
|
@ -1210,11 +1288,36 @@ export class AppImManager { |
|
|
|
//bubble.innerHTML = '';
|
|
|
|
//bubble.innerHTML = '';
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(message._ == 'messageService') { |
|
|
|
|
|
|
|
bubble.className = 'bubble service'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let action = message.action; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let title = appPeersManager.getPeerTitle(message.fromID); |
|
|
|
|
|
|
|
let name = document.createElement('div'); |
|
|
|
|
|
|
|
name.classList.add('name'); |
|
|
|
|
|
|
|
name.dataset.peerID = message.fromID; |
|
|
|
|
|
|
|
name.innerHTML = title; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let _ = action._; |
|
|
|
|
|
|
|
if(_ == "messageActionPhoneCall") { |
|
|
|
|
|
|
|
_ += '.' + action.type; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
|
|
let str = (name.innerText ? name.outerHTML + ' ' : '') + langPack[_]; |
|
|
|
|
|
|
|
bubbleContainer.innerHTML = `<div class="service-msg">${str}</div>`; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!multipleRender) { |
|
|
|
|
|
|
|
this.scrollPosition.restore(); // лагает из-за этого
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// time section
|
|
|
|
// time section
|
|
|
|
|
|
|
|
|
|
|
|
let date = new Date(message.date * 1000); |
|
|
|
let date = new Date(message.date * 1000); |
|
|
|
let time = ('0' + date.getHours()).slice(-2) + |
|
|
|
let time = ('0' + date.getHours()).slice(-2) + ':' + ('0' + date.getMinutes()).slice(-2); |
|
|
|
':' + ('0' + date.getMinutes()).slice(-2); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(message.views) { |
|
|
|
if(message.views) { |
|
|
|
bubble.classList.add('channel-post'); |
|
|
|
bubble.classList.add('channel-post'); |
|
|
@ -1461,7 +1564,7 @@ export class AppImManager { |
|
|
|
|
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
} else if(doc.mime_type == 'video/mp4' && doc.size <= 20e6) { |
|
|
|
} else if(doc.mime_type == 'video/mp4' && doc.size <= 20e6) { |
|
|
|
////////this.log('never get free 2', doc);
|
|
|
|
this.log('never get free 2', doc); |
|
|
|
|
|
|
|
|
|
|
|
if(doc.type == 'round') { |
|
|
|
if(doc.type == 'round') { |
|
|
|
bubble.classList.add('round'); |
|
|
|
bubble.classList.add('round'); |
|
|
@ -1470,6 +1573,16 @@ export class AppImManager { |
|
|
|
bubble.classList.add('video'); |
|
|
|
bubble.classList.add('video'); |
|
|
|
wrapVideo.call(this, doc, attachmentDiv, message, true, null, false, doc.type == 'round'); |
|
|
|
wrapVideo.call(this, doc, attachmentDiv, message, true, null, false, doc.type == 'round'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} else if(doc.mime_type == 'audio/ogg') { |
|
|
|
|
|
|
|
let docDiv = wrapDocument(doc); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
messageDiv.classList.remove('message-empty'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bubble.classList.add('bubble-audio'); |
|
|
|
|
|
|
|
messageDiv.append(docDiv); |
|
|
|
|
|
|
|
processingWebPage = true; |
|
|
|
|
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
let docDiv = wrapDocument(doc); |
|
|
|
let docDiv = wrapDocument(doc); |
|
|
@ -1513,13 +1626,8 @@ export class AppImManager { |
|
|
|
if(message.savedFrom) { |
|
|
|
if(message.savedFrom) { |
|
|
|
let fwd = document.createElement('div'); |
|
|
|
let fwd = document.createElement('div'); |
|
|
|
fwd.classList.add('forward'/* , 'tgico-forward' */); |
|
|
|
fwd.classList.add('forward'/* , 'tgico-forward' */); |
|
|
|
fwd.innerHTML = ` |
|
|
|
fwd.innerHTML = `<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24">
|
|
|
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"> |
|
|
|
<defs><path d="M13.55 3.24L13.64 3.25L13.73 3.27L13.81 3.29L13.9 3.32L13.98 3.35L14.06 3.39L14.14 3.43L14.22 3.48L14.29 3.53L14.36 3.59L14.43 3.64L22.23 10.85L22.36 10.99L22.48 11.15L22.57 11.31L22.64 11.48L22.69 11.66L22.72 11.85L22.73 12.04L22.71 12.22L22.67 12.41L22.61 12.59L22.53 12.76L22.42 12.93L22.29 13.09L22.23 13.15L14.43 20.36L14.28 20.48L14.12 20.58L13.95 20.66L13.77 20.72L13.58 20.76L13.4 20.77L13.22 20.76L13.03 20.73L12.85 20.68L12.68 20.61L12.52 20.52L12.36 20.4L12.22 20.27L12.16 20.2L12.1 20.13L12.05 20.05L12.01 19.98L11.96 19.9L11.93 19.82L11.89 19.73L11.87 19.65L11.84 19.56L11.83 19.47L11.81 19.39L11.81 19.3L11.8 19.2L11.8 16.42L11 16.49L10.23 16.58L9.51 16.71L8.82 16.88L8.18 17.09L7.57 17.33L7.01 17.6L6.48 17.91L5.99 18.26L5.55 18.64L5.14 19.05L4.77 19.51L4.43 19.99L4.29 20.23L4.21 20.35L4.11 20.47L4 20.57L3.88 20.65L3.75 20.72L3.62 20.78L3.48 20.82L3.33 20.84L3.19 20.84L3.04 20.83L2.9 20.79L2.75 20.74L2.62 20.68L2.53 20.62L2.45 20.56L2.38 20.5L2.31 20.43L2.25 20.36L2.2 20.28L2.15 20.19L2.11 20.11L2.07 20.02L2.04 19.92L2.02 19.83L2.01 19.73L2 19.63L2.04 17.99L2.19 16.46L2.46 15.05L2.85 13.75L3.35 12.58L3.97 11.53L4.7 10.6L5.55 9.8L6.51 9.12L7.59 8.56L8.77 8.13L10.07 7.83L11.48 7.65L11.8 7.63L11.8 4.8L11.91 4.56L12.02 4.35L12.14 4.16L12.25 3.98L12.37 3.82L12.48 3.68L12.61 3.56L12.73 3.46L12.85 3.38L12.98 3.31L13.11 3.27L13.24 3.24L13.37 3.23L13.46 3.23L13.55 3.24Z" id="b13RmHDQtl"></path></defs><use xlink:href="#b13RmHDQtl" opacity="1" fill="#fff" fill-opacity="1"></use></svg>`;
|
|
|
|
<defs> |
|
|
|
|
|
|
|
<path d="M13.55 3.24L13.64 3.25L13.73 3.27L13.81 3.29L13.9 3.32L13.98 3.35L14.06 3.39L14.14 3.43L14.22 3.48L14.29 3.53L14.36 3.59L14.43 3.64L22.23 10.85L22.36 10.99L22.48 11.15L22.57 11.31L22.64 11.48L22.69 11.66L22.72 11.85L22.73 12.04L22.71 12.22L22.67 12.41L22.61 12.59L22.53 12.76L22.42 12.93L22.29 13.09L22.23 13.15L14.43 20.36L14.28 20.48L14.12 20.58L13.95 20.66L13.77 20.72L13.58 20.76L13.4 20.77L13.22 20.76L13.03 20.73L12.85 20.68L12.68 20.61L12.52 20.52L12.36 20.4L12.22 20.27L12.16 20.2L12.1 20.13L12.05 20.05L12.01 19.98L11.96 19.9L11.93 19.82L11.89 19.73L11.87 19.65L11.84 19.56L11.83 19.47L11.81 19.39L11.81 19.3L11.8 19.2L11.8 16.42L11 16.49L10.23 16.58L9.51 16.71L8.82 16.88L8.18 17.09L7.57 17.33L7.01 17.6L6.48 17.91L5.99 18.26L5.55 18.64L5.14 19.05L4.77 19.51L4.43 19.99L4.29 20.23L4.21 20.35L4.11 20.47L4 20.57L3.88 20.65L3.75 20.72L3.62 20.78L3.48 20.82L3.33 20.84L3.19 20.84L3.04 20.83L2.9 20.79L2.75 20.74L2.62 20.68L2.53 20.62L2.45 20.56L2.38 20.5L2.31 20.43L2.25 20.36L2.2 20.28L2.15 20.19L2.11 20.11L2.07 20.02L2.04 19.92L2.02 19.83L2.01 19.73L2 19.63L2.04 17.99L2.19 16.46L2.46 15.05L2.85 13.75L3.35 12.58L3.97 11.53L4.7 10.6L5.55 9.8L6.51 9.12L7.59 8.56L8.77 8.13L10.07 7.83L11.48 7.65L11.8 7.63L11.8 4.8L11.91 4.56L12.02 4.35L12.14 4.16L12.25 3.98L12.37 3.82L12.48 3.68L12.61 3.56L12.73 3.46L12.85 3.38L12.98 3.31L13.11 3.27L13.24 3.24L13.37 3.23L13.46 3.23L13.55 3.24Z" id="b13RmHDQtl"></path> |
|
|
|
|
|
|
|
</defs> |
|
|
|
|
|
|
|
<use xlink:href="#b13RmHDQtl" opacity="1" fill="#fff" fill-opacity="1"></use> |
|
|
|
|
|
|
|
</svg>`;
|
|
|
|
|
|
|
|
bubbleContainer.append(fwd); |
|
|
|
bubbleContainer.append(fwd); |
|
|
|
bubble.dataset.savedFrom = message.savedFrom; |
|
|
|
bubble.dataset.savedFrom = message.savedFrom; |
|
|
|
} |
|
|
|
} |
|
|
@ -1568,17 +1676,9 @@ export class AppImManager { |
|
|
|
} else /* if(!message.reply_to_mid) */ { |
|
|
|
} else /* if(!message.reply_to_mid) */ { |
|
|
|
bubble.classList.add('hide-name'); |
|
|
|
bubble.classList.add('hide-name'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//bubble.prepend(avatarDiv);
|
|
|
|
|
|
|
|
/* if(messageDiv.nextElementSibling) { |
|
|
|
|
|
|
|
bubble.insertBefore(avatarDiv, messageDiv.nextElementSibling); |
|
|
|
|
|
|
|
} else { */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(!our && this.peerID < 0 && |
|
|
|
if(!our && this.peerID < 0 && (!appPeersManager.isChannel(this.peerID) || appPeersManager.isMegagroup(this.peerID))) { |
|
|
|
(!appPeersManager.isChannel(this.peerID) || appPeersManager.isMegagroup(this.peerID))) { |
|
|
|
|
|
|
|
let avatarDiv = document.createElement('div'); |
|
|
|
let avatarDiv = document.createElement('div'); |
|
|
|
avatarDiv.classList.add('user-avatar'); |
|
|
|
avatarDiv.classList.add('user-avatar'); |
|
|
|
|
|
|
|
|
|
|
@ -1599,26 +1699,6 @@ export class AppImManager { |
|
|
|
bubble.classList.add('hide-name'); |
|
|
|
bubble.classList.add('hide-name'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(message._ == 'messageService') { |
|
|
|
|
|
|
|
bubble.className = 'bubble service'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let action = message.action; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let title = appPeersManager.getPeerTitle(message.fromID); |
|
|
|
|
|
|
|
let name = document.createElement('div'); |
|
|
|
|
|
|
|
name.classList.add('name'); |
|
|
|
|
|
|
|
name.dataset.peerID = message.fromID; |
|
|
|
|
|
|
|
name.innerHTML = title; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let _ = action._; |
|
|
|
|
|
|
|
if(_ == "messageActionPhoneCall") { |
|
|
|
|
|
|
|
_ += '.' + action.type; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
|
|
let str = (name.innerText ? name.outerHTML + ' ' : '') + langPack[_]; |
|
|
|
|
|
|
|
bubbleContainer.innerHTML = `<div class="service-msg">${str}</div>`; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bubble.classList.add(our ? 'is-out' : 'is-in'); |
|
|
|
bubble.classList.add(our ? 'is-out' : 'is-in'); |
|
|
|
if(updatePosition) { |
|
|
|
if(updatePosition) { |
|
|
|
if(reverse) { |
|
|
|
if(reverse) { |
|
|
@ -1627,6 +1707,8 @@ export class AppImManager { |
|
|
|
this.scrollable.append(bubble); |
|
|
|
this.scrollable.append(bubble); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.bubbleGroups.addBubble(bubble, message, reverse); |
|
|
|
|
|
|
|
|
|
|
|
let justDate = new Date(date.getFullYear(), date.getMonth(), date.getDate()); |
|
|
|
let justDate = new Date(date.getFullYear(), date.getMonth(), date.getDate()); |
|
|
|
let dateTimestamp = justDate.getTime(); |
|
|
|
let dateTimestamp = justDate.getTime(); |
|
|
|
if(!(dateTimestamp in this.dateMessages)) { |
|
|
|
if(!(dateTimestamp in this.dateMessages)) { |
|
|
@ -1640,8 +1722,7 @@ export class AppImManager { |
|
|
|
if(today < date) { |
|
|
|
if(today < date) { |
|
|
|
str = 'Today'; |
|
|
|
str = 'Today'; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
const months = ['January', 'February', 'March', 'April', 'May', 'June', |
|
|
|
const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; |
|
|
|
'July', 'August', 'September', 'October', 'November', 'December']; |
|
|
|
|
|
|
|
str = justDate.getFullYear() == new Date().getFullYear() ? |
|
|
|
str = justDate.getFullYear() == new Date().getFullYear() ? |
|
|
|
months[justDate.getMonth()] + ' ' + justDate.getDate() : |
|
|
|
months[justDate.getMonth()] + ' ' + justDate.getDate() : |
|
|
|
justDate.toISOString().split('T')[0].split('-').reverse().join('.'); |
|
|
|
justDate.toISOString().split('T')[0].split('-').reverse().join('.'); |
|
|
@ -1664,6 +1745,8 @@ export class AppImManager { |
|
|
|
this.scrollable.insertBefore(dateMessage.div, bubble); |
|
|
|
this.scrollable.insertBefore(dateMessage.div, bubble); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
this.bubbleGroups.updateGroupByMessageID(message.mid); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* if(bubble.classList.contains('webpage')) { |
|
|
|
/* if(bubble.classList.contains('webpage')) { |
|
|
@ -1675,8 +1758,6 @@ export class AppImManager { |
|
|
|
if(!multipleRender) { |
|
|
|
if(!multipleRender) { |
|
|
|
this.scrollPosition.restore(); // лагает из-за этого
|
|
|
|
this.scrollPosition.restore(); // лагает из-за этого
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//this.log('history msg', message);
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// reverse means scroll up
|
|
|
|
// reverse means scroll up
|
|
|
@ -1688,9 +1769,7 @@ export class AppImManager { |
|
|
|
maxID = dialog.top_message/* + 1 */; |
|
|
|
maxID = dialog.top_message/* + 1 */; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let loadCount = Object.keys(this.bubbles).length > 0 ? |
|
|
|
let loadCount = Object.keys(this.bubbles).length > 0 ? 20 : this.scrollable.container.parentElement.scrollHeight / 30 * 1.25 | 0; |
|
|
|
20 : |
|
|
|
|
|
|
|
this.scrollable.container.parentElement.scrollHeight / 30 * 1.25 | 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* if(testScroll) { |
|
|
|
/* if(testScroll) { |
|
|
|
loadCount = 1; |
|
|
|
loadCount = 1; |
|
|
@ -1800,7 +1879,7 @@ export class AppImManager { |
|
|
|
peer: inputPeer |
|
|
|
peer: inputPeer |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
let settings: any = { |
|
|
|
let settings = { |
|
|
|
_: 'inputPeerNotifySettings', |
|
|
|
_: 'inputPeerNotifySettings', |
|
|
|
flags: 0, |
|
|
|
flags: 0, |
|
|
|
mute_until: 0 |
|
|
|
mute_until: 0 |
|
|
@ -1850,9 +1929,7 @@ export class AppImManager { |
|
|
|
this.typingUsers[update.user_id] = peerID; |
|
|
|
this.typingUsers[update.user_id] = peerID; |
|
|
|
|
|
|
|
|
|
|
|
if(!appUsersManager.hasUser(update.user_id)) { |
|
|
|
if(!appUsersManager.hasUser(update.user_id)) { |
|
|
|
if(update.chat_id && |
|
|
|
if(update.chat_id && appChatsManager.hasChat(update.chat_id) && !appChatsManager.isChannel(update.chat_id)) { |
|
|
|
appChatsManager.hasChat(update.chat_id) && |
|
|
|
|
|
|
|
!appChatsManager.isChannel(update.chat_id)) { |
|
|
|
|
|
|
|
appProfileManager.getChatFull(update.chat_id); |
|
|
|
appProfileManager.getChatFull(update.chat_id); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|