|
|
@ -33,19 +33,9 @@ let setText = (text: string, el: HTMLDivElement) => { |
|
|
|
}); |
|
|
|
}); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
type ContentType = /* 'contentMembers' | */'contentMedia' | 'contentDocuments' | 'contentLinks' | 'contentAudio'; |
|
|
|
|
|
|
|
type SharedMediaType = /* 'inputMessagesFilterContacts' | */'inputMessagesFilterEmpty' | 'inputMessagesFilterPhotoVideo' | 'inputMessagesFilterDocument' | 'inputMessagesFilterUrl' | 'inputMessagesFilterMusic'; |
|
|
|
type SharedMediaType = /* 'inputMessagesFilterContacts' | */'inputMessagesFilterEmpty' | 'inputMessagesFilterPhotoVideo' | 'inputMessagesFilterDocument' | 'inputMessagesFilterUrl' | 'inputMessagesFilterMusic'; |
|
|
|
|
|
|
|
|
|
|
|
const contentToSharedMap: {[contentType in ContentType]: SharedMediaType} = { |
|
|
|
// TODO: отредактированное сообщение не изменится
|
|
|
|
//contentMembers: 'inputMessagesFilterContacts',
|
|
|
|
|
|
|
|
contentMedia: 'inputMessagesFilterPhotoVideo', |
|
|
|
|
|
|
|
contentDocuments: 'inputMessagesFilterDocument', |
|
|
|
|
|
|
|
contentLinks: 'inputMessagesFilterUrl', |
|
|
|
|
|
|
|
contentAudio: 'inputMessagesFilterMusic' |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: отправленное сообщение с картинкой, или же новое полученное апдейтом сообщение не отобразится в медии
|
|
|
|
|
|
|
|
// TODO: по-хорошему, нужно просто сделать апдейты для всего сайдбара
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export default class AppSharedMediaTab implements SliderTab { |
|
|
|
export default class AppSharedMediaTab implements SliderTab { |
|
|
|
public container: HTMLElement; |
|
|
|
public container: HTMLElement; |
|
|
@ -67,7 +57,7 @@ export default class AppSharedMediaTab implements SliderTab { |
|
|
|
notificationsStatus: HTMLParagraphElement |
|
|
|
notificationsStatus: HTMLParagraphElement |
|
|
|
} = {} as any; |
|
|
|
} = {} as any; |
|
|
|
public sharedMedia: { |
|
|
|
public sharedMedia: { |
|
|
|
[t in ContentType]: HTMLDivElement |
|
|
|
[t in SharedMediaType]: HTMLDivElement |
|
|
|
} = {} as any; |
|
|
|
} = {} as any; |
|
|
|
|
|
|
|
|
|
|
|
private loadSidebarMediaPromises: {[type: string]: Promise<void>} = {}; |
|
|
|
private loadSidebarMediaPromises: {[type: string]: Promise<void>} = {}; |
|
|
@ -131,11 +121,12 @@ export default class AppSharedMediaTab implements SliderTab { |
|
|
|
|
|
|
|
|
|
|
|
this.sharedMedia = { |
|
|
|
this.sharedMedia = { |
|
|
|
//contentMembers: this.profileContentEl.querySelector('#content-members'),
|
|
|
|
//contentMembers: this.profileContentEl.querySelector('#content-members'),
|
|
|
|
contentMedia: this.profileContentEl.querySelector('#content-media'), |
|
|
|
//inputMessagesFilterEmpty: null,
|
|
|
|
contentDocuments: this.profileContentEl.querySelector('#content-docs'), |
|
|
|
inputMessagesFilterPhotoVideo: this.profileContentEl.querySelector('#content-media'), |
|
|
|
contentLinks: this.profileContentEl.querySelector('#content-links'), |
|
|
|
inputMessagesFilterDocument: this.profileContentEl.querySelector('#content-docs'), |
|
|
|
contentAudio: this.profileContentEl.querySelector('#content-audio'), |
|
|
|
inputMessagesFilterUrl: this.profileContentEl.querySelector('#content-links'), |
|
|
|
}; |
|
|
|
inputMessagesFilterMusic: this.profileContentEl.querySelector('#content-audio'), |
|
|
|
|
|
|
|
} as any; |
|
|
|
|
|
|
|
|
|
|
|
let container = this.profileContentEl.querySelector('.content-container .tabs-container') as HTMLDivElement; |
|
|
|
let container = this.profileContentEl.querySelector('.content-container .tabs-container') as HTMLDivElement; |
|
|
|
this.profileTabs = this.profileContentEl.querySelector('.profile-tabs'); |
|
|
|
this.profileTabs = this.profileContentEl.querySelector('.profile-tabs'); |
|
|
@ -177,7 +168,7 @@ export default class AppSharedMediaTab implements SliderTab { |
|
|
|
this.onTransitionEnd(); |
|
|
|
this.onTransitionEnd(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
this.sharedMedia.contentMedia.addEventListener('click', (e) => { |
|
|
|
this.sharedMedia.inputMessagesFilterPhotoVideo.addEventListener('click', (e) => { |
|
|
|
const target = e.target as HTMLDivElement; |
|
|
|
const target = e.target as HTMLDivElement; |
|
|
|
|
|
|
|
|
|
|
|
const messageID = +target.dataset.mid; |
|
|
|
const messageID = +target.dataset.mid; |
|
|
@ -210,6 +201,52 @@ export default class AppSharedMediaTab implements SliderTab { |
|
|
|
}); */ |
|
|
|
}); */ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public renderNewMessages(mids: number[]) { |
|
|
|
|
|
|
|
mids = mids.slice().reverse(); // ! because it will be ascend sorted array
|
|
|
|
|
|
|
|
for(const sharedMediaType of this.sharedMediaTypes) { |
|
|
|
|
|
|
|
const filtered = this.filterMessagesByType(mids, sharedMediaType); |
|
|
|
|
|
|
|
if(filtered.length) { |
|
|
|
|
|
|
|
if(this.usedFromHistory[sharedMediaType] !== -1) { |
|
|
|
|
|
|
|
this.historiesStorage[this.peerID][sharedMediaType].unshift(...mids); |
|
|
|
|
|
|
|
this.usedFromHistory[sharedMediaType] += filtered.length; |
|
|
|
|
|
|
|
this.performSearchResult(filtered, sharedMediaType, false); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public deleteDeletedMessages(mids: number[]) { |
|
|
|
|
|
|
|
for(const mid of mids) { |
|
|
|
|
|
|
|
for(const sharedMediaType of this.sharedMediaTypes) { |
|
|
|
|
|
|
|
if(!this.historiesStorage[this.peerID] || !this.historiesStorage[this.peerID][sharedMediaType]) continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const history = this.historiesStorage[this.peerID][sharedMediaType]; |
|
|
|
|
|
|
|
const idx = history.findIndex(m => m == mid); |
|
|
|
|
|
|
|
if(idx !== -1) { |
|
|
|
|
|
|
|
history.splice(idx, 1); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const container = this.sharedMedia[sharedMediaType]; |
|
|
|
|
|
|
|
const div = container.querySelector(`div[data-mid="${mid}"]`); |
|
|
|
|
|
|
|
if(div) { |
|
|
|
|
|
|
|
if(sharedMediaType == 'inputMessagesFilterPhotoVideo') { |
|
|
|
|
|
|
|
delete this.mediaDivsByIDs[mid]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
div.remove(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(this.usedFromHistory[sharedMediaType] >= (idx + 1)) { |
|
|
|
|
|
|
|
this.usedFromHistory[sharedMediaType]--; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private onTransitionStart = () => { |
|
|
|
private onTransitionStart = () => { |
|
|
|
// Jolly Cobra's // Workaround for scrollable content flickering during animation.
|
|
|
|
// Jolly Cobra's // Workaround for scrollable content flickering during animation.
|
|
|
|
const container = this.scroll.container; |
|
|
|
const container = this.scroll.container; |
|
|
@ -302,28 +339,27 @@ export default class AppSharedMediaTab implements SliderTab { |
|
|
|
return filtered; |
|
|
|
return filtered; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public async performSearchResult(messages: any[], type: SharedMediaType) { |
|
|
|
public async performSearchResult(messages: any[], type: SharedMediaType, append = true) { |
|
|
|
const peerID = this.peerID; |
|
|
|
const peerID = this.peerID; |
|
|
|
const elemsToAppend: HTMLElement[] = []; |
|
|
|
const elemsToAppend: HTMLElement[] = []; |
|
|
|
const promises: Promise<any>[] = []; |
|
|
|
const promises: Promise<any>[] = []; |
|
|
|
let sharedMediaDiv: HTMLDivElement; |
|
|
|
const sharedMediaDiv = this.sharedMedia[type]; |
|
|
|
|
|
|
|
|
|
|
|
/* for(let contentType in contentToSharedMap) { |
|
|
|
/* for(let contentType in contentToSharedMap) { |
|
|
|
if(contentToSharedMap[contentType as ContentType] == type) { |
|
|
|
if(contentToSharedMap[contentType as ContentType] == type) { |
|
|
|
sharedMediaDiv = this.sharedMedia[contentType as ContentType]; |
|
|
|
sharedMediaDiv = this.sharedMedia[contentType as ContentType]; |
|
|
|
} |
|
|
|
} |
|
|
|
} */ |
|
|
|
} */ |
|
|
|
|
|
|
|
|
|
|
|
// https://core.telegram.org/type/MessagesFilter
|
|
|
|
// https://core.telegram.org/type/MessagesFilter
|
|
|
|
switch(type) { |
|
|
|
switch(type) { |
|
|
|
case 'inputMessagesFilterPhotoVideo': { |
|
|
|
case 'inputMessagesFilterPhotoVideo': { |
|
|
|
sharedMediaDiv = this.sharedMedia.contentMedia; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(const message of messages) { |
|
|
|
for(const message of messages) { |
|
|
|
const media = message.media.photo || message.media.document || (message.media.webpage && message.media.webpage.document); |
|
|
|
const media = message.media.photo || message.media.document || (message.media.webpage && message.media.webpage.document); |
|
|
|
|
|
|
|
|
|
|
|
const div = document.createElement('div'); |
|
|
|
const div = document.createElement('div'); |
|
|
|
div.classList.add('grid-item'); |
|
|
|
div.classList.add('grid-item'); |
|
|
|
|
|
|
|
div.dataset.mid = '' + message.mid; |
|
|
|
//console.log(message, photo);
|
|
|
|
//console.log(message, photo);
|
|
|
|
|
|
|
|
|
|
|
|
const isPhoto = media._ == 'photo'; |
|
|
|
const isPhoto = media._ == 'photo'; |
|
|
@ -428,18 +464,15 @@ export default class AppSharedMediaTab implements SliderTab { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
case 'inputMessagesFilterDocument': { |
|
|
|
case 'inputMessagesFilterDocument': { |
|
|
|
sharedMediaDiv = this.sharedMedia.contentDocuments; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(let message of messages) { |
|
|
|
for(let message of messages) { |
|
|
|
let div = wrapDocument(message.media.document, true, false, message.mid); |
|
|
|
let div = wrapDocument(message.media.document, true, false, message.mid); |
|
|
|
|
|
|
|
div.dataset.mid = '' + message.mid; |
|
|
|
elemsToAppend.push(div); |
|
|
|
elemsToAppend.push(div); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
case 'inputMessagesFilterUrl': { |
|
|
|
case 'inputMessagesFilterUrl': { |
|
|
|
sharedMediaDiv = this.sharedMedia.contentLinks; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(let message of messages) { |
|
|
|
for(let message of messages) { |
|
|
|
let webpage: any; |
|
|
|
let webpage: any; |
|
|
|
|
|
|
|
|
|
|
@ -546,17 +579,16 @@ export default class AppSharedMediaTab implements SliderTab { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
case 'inputMessagesFilterMusic': { |
|
|
|
case 'inputMessagesFilterMusic': { |
|
|
|
sharedMediaDiv = this.sharedMedia.contentAudio; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(let message of messages) { |
|
|
|
for(let message of messages) { |
|
|
|
let div = wrapAudio(message.media.document, true, message.mid); |
|
|
|
let div = wrapAudio(message.media.document, true, message.mid); |
|
|
|
|
|
|
|
div.dataset.mid = '' + message.mid; |
|
|
|
elemsToAppend.push(div); |
|
|
|
elemsToAppend.push(div); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
default: |
|
|
|
console.warn('death is my friend', messages); |
|
|
|
//console.warn('death is my friend', messages);
|
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -573,7 +605,7 @@ export default class AppSharedMediaTab implements SliderTab { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(elemsToAppend.length) { |
|
|
|
if(elemsToAppend.length) { |
|
|
|
sharedMediaDiv.append(...elemsToAppend); |
|
|
|
sharedMediaDiv[append ? 'append' : 'prepend'](...elemsToAppend); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(sharedMediaDiv) { |
|
|
|
if(sharedMediaDiv) { |
|
|
@ -621,7 +653,7 @@ export default class AppSharedMediaTab implements SliderTab { |
|
|
|
// render from cache
|
|
|
|
// render from cache
|
|
|
|
if(history.length && this.usedFromHistory[type] < history.length) { |
|
|
|
if(history.length && this.usedFromHistory[type] < history.length) { |
|
|
|
let messages: any[] = []; |
|
|
|
let messages: any[] = []; |
|
|
|
let used = this.usedFromHistory[type]; |
|
|
|
let used = Math.max(0, this.usedFromHistory[type]); |
|
|
|
|
|
|
|
|
|
|
|
do { |
|
|
|
do { |
|
|
|
let ids = history.slice(used, used + loadCount); |
|
|
|
let ids = history.slice(used, used + loadCount); |
|
|
@ -694,7 +726,7 @@ export default class AppSharedMediaTab implements SliderTab { |
|
|
|
this.lazyLoadQueue.clear(); |
|
|
|
this.lazyLoadQueue.clear(); |
|
|
|
|
|
|
|
|
|
|
|
this.sharedMediaTypes.forEach(type => { |
|
|
|
this.sharedMediaTypes.forEach(type => { |
|
|
|
this.usedFromHistory[type] = 0; |
|
|
|
this.usedFromHistory[type] = -1; |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
this.sharedMediaType = 'inputMessagesFilterPhotoVideo'; |
|
|
|
this.sharedMediaType = 'inputMessagesFilterPhotoVideo'; |
|
|
@ -718,12 +750,11 @@ export default class AppSharedMediaTab implements SliderTab { |
|
|
|
this.urlsToRevoke.length = 0; |
|
|
|
this.urlsToRevoke.length = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
(Object.keys(this.sharedMedia) as ContentType[]).forEach(key => { |
|
|
|
(Object.keys(this.sharedMedia) as SharedMediaType[]).forEach(sharedMediaType => { |
|
|
|
this.sharedMedia[key].innerHTML = ''; |
|
|
|
this.sharedMedia[sharedMediaType].innerHTML = ''; |
|
|
|
|
|
|
|
|
|
|
|
const inputFilter = contentToSharedMap[key]; |
|
|
|
if(!this.historiesStorage[this.peerID] || !this.historiesStorage[this.peerID][sharedMediaType]) { |
|
|
|
if(!this.historiesStorage[this.peerID] || !this.historiesStorage[this.peerID][inputFilter]) { |
|
|
|
const parent = this.sharedMedia[sharedMediaType].parentElement; |
|
|
|
const parent = this.sharedMedia[key].parentElement; |
|
|
|
|
|
|
|
if(!testScroll) { |
|
|
|
if(!testScroll) { |
|
|
|
if(!parent.querySelector('.preloader')) { |
|
|
|
if(!parent.querySelector('.preloader')) { |
|
|
|
putPreloader(parent, true); |
|
|
|
putPreloader(parent, true); |
|
|
@ -744,7 +775,7 @@ export default class AppSharedMediaTab implements SliderTab { |
|
|
|
div.classList.add('grid-item'); |
|
|
|
div.classList.add('grid-item'); |
|
|
|
div.dataset.id = '' + (i / 3 | 0); |
|
|
|
div.dataset.id = '' + (i / 3 | 0); |
|
|
|
//div.innerText = '' + (i / 3 | 0);
|
|
|
|
//div.innerText = '' + (i / 3 | 0);
|
|
|
|
this.sharedMedia.contentMedia.append(div); |
|
|
|
this.sharedMedia.inputMessagesFilterPhotoVideo.append(div); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|