|
|
@ -19,7 +19,7 @@ import { horizontalMenu } from "./horizontalMenu"; |
|
|
|
import LazyLoadQueue from "./lazyLoadQueue"; |
|
|
|
import LazyLoadQueue from "./lazyLoadQueue"; |
|
|
|
import { renderImageFromUrl, putPreloader, formatPhoneNumber } from "./misc"; |
|
|
|
import { renderImageFromUrl, putPreloader, formatPhoneNumber } from "./misc"; |
|
|
|
import { ripple } from "./ripple"; |
|
|
|
import { ripple } from "./ripple"; |
|
|
|
import Scrollable from "./scrollable"; |
|
|
|
import Scrollable, { ScrollableX } from "./scrollable"; |
|
|
|
import { wrapDocument } from "./wrappers"; |
|
|
|
import { wrapDocument } from "./wrappers"; |
|
|
|
|
|
|
|
|
|
|
|
const testScroll = false; |
|
|
|
const testScroll = false; |
|
|
@ -33,7 +33,9 @@ export type SearchSuperContext = { |
|
|
|
folderId?: number, |
|
|
|
folderId?: number, |
|
|
|
threadId?: number, |
|
|
|
threadId?: number, |
|
|
|
date?: number, |
|
|
|
date?: number, |
|
|
|
nextRate?: number |
|
|
|
nextRate?: number, |
|
|
|
|
|
|
|
minDate?: number, |
|
|
|
|
|
|
|
maxDate?: number |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
export default class AppSearchSuper { |
|
|
|
export default class AppSearchSuper { |
|
|
@ -43,6 +45,7 @@ export default class AppSearchSuper { |
|
|
|
public tabSelected: HTMLElement; |
|
|
|
public tabSelected: HTMLElement; |
|
|
|
|
|
|
|
|
|
|
|
public container: HTMLElement; |
|
|
|
public container: HTMLElement; |
|
|
|
|
|
|
|
public nav: HTMLElement; |
|
|
|
private tabsContainer: HTMLElement; |
|
|
|
private tabsContainer: HTMLElement; |
|
|
|
private tabsMenu: HTMLUListElement; |
|
|
|
private tabsMenu: HTMLUListElement; |
|
|
|
private prevTabId = -1; |
|
|
|
private prevTabId = -1; |
|
|
@ -74,15 +77,24 @@ export default class AppSearchSuper { |
|
|
|
} |
|
|
|
} |
|
|
|
}> = {}; |
|
|
|
}> = {}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private searchGroupMedia: SearchGroup; |
|
|
|
|
|
|
|
|
|
|
|
constructor(public types: {inputFilter: SearchSuperType, name: string}[], public scrollable: Scrollable, public searchGroups?: {[group in SearchGroupType]: SearchGroup}, public asChatList = false) { |
|
|
|
constructor(public types: {inputFilter: SearchSuperType, name: string}[], public scrollable: Scrollable, public searchGroups?: {[group in SearchGroupType]: SearchGroup}, public asChatList = false) { |
|
|
|
this.container = document.createElement('div'); |
|
|
|
this.container = document.createElement('div'); |
|
|
|
this.container.classList.add('search-super'); |
|
|
|
this.container.classList.add('search-super'); |
|
|
|
|
|
|
|
|
|
|
|
const nav = document.createElement('nav'); |
|
|
|
const navScrollableContainer = document.createElement('div'); |
|
|
|
|
|
|
|
navScrollableContainer.classList.add('search-super-tabs-scrollable', 'menu-horizontal-scrollable'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const navScrollable = new ScrollableX(navScrollableContainer); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nav = this.nav = document.createElement('nav'); |
|
|
|
nav.classList.add('search-super-tabs', 'menu-horizontal'); |
|
|
|
nav.classList.add('search-super-tabs', 'menu-horizontal'); |
|
|
|
this.tabsMenu = document.createElement('ul'); |
|
|
|
this.tabsMenu = document.createElement('ul'); |
|
|
|
nav.append(this.tabsMenu); |
|
|
|
nav.append(this.tabsMenu); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
navScrollable.container.append(nav); |
|
|
|
|
|
|
|
|
|
|
|
for(const type of types) { |
|
|
|
for(const type of types) { |
|
|
|
const li = document.createElement('li'); |
|
|
|
const li = document.createElement('li'); |
|
|
|
const span = document.createElement('span'); |
|
|
|
const span = document.createElement('span'); |
|
|
@ -115,10 +127,12 @@ export default class AppSearchSuper { |
|
|
|
this.tabs[type.inputFilter] = content; |
|
|
|
this.tabs[type.inputFilter] = content; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this.container.append(nav, this.tabsContainer); |
|
|
|
this.container.append(navScrollableContainer, this.tabsContainer); |
|
|
|
|
|
|
|
|
|
|
|
// * construct end
|
|
|
|
// * construct end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.searchGroupMedia = new SearchGroup('', 'messages', true); |
|
|
|
|
|
|
|
|
|
|
|
this.scrollable.onScrolledBottom = () => { |
|
|
|
this.scrollable.onScrolledBottom = () => { |
|
|
|
if(this.tabSelected && this.tabSelected.childElementCount/* && false */) { |
|
|
|
if(this.tabSelected && this.tabSelected.childElementCount/* && false */) { |
|
|
|
//this.log('onScrolledBottom will load media');
|
|
|
|
//this.log('onScrolledBottom will load media');
|
|
|
@ -296,10 +310,19 @@ export default class AppSearchSuper { |
|
|
|
|
|
|
|
|
|
|
|
public async performSearchResult(messages: any[], type: SearchSuperType, append = true) { |
|
|
|
public async performSearchResult(messages: any[], type: SearchSuperType, append = true) { |
|
|
|
const elemsToAppend: {element: HTMLElement, message: any}[] = []; |
|
|
|
const elemsToAppend: {element: HTMLElement, message: any}[] = []; |
|
|
|
|
|
|
|
const sharedMediaDiv: HTMLElement = this.tabs[type]; |
|
|
|
const promises: Promise<any>[] = []; |
|
|
|
const promises: Promise<any>[] = []; |
|
|
|
const sharedMediaDiv: HTMLElement = type === 'inputMessagesFilterEmpty' ? this.searchGroups.messages.list : this.tabs[type]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const middleware = this.getMiddleware(); |
|
|
|
const middleware = this.getMiddleware(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let searchGroup: SearchGroup; |
|
|
|
|
|
|
|
if(type === 'inputMessagesFilterPhotoVideo' && !!this.searchContext.query.trim()) { |
|
|
|
|
|
|
|
type = 'inputMessagesFilterEmpty'; |
|
|
|
|
|
|
|
searchGroup = this.searchGroupMedia; |
|
|
|
|
|
|
|
sharedMediaDiv.append(searchGroup.container); |
|
|
|
|
|
|
|
} else if(type === 'inputMessagesFilterEmpty') { |
|
|
|
|
|
|
|
searchGroup = this.searchGroups.messages; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// https://core.telegram.org/type/MessagesFilter
|
|
|
|
// https://core.telegram.org/type/MessagesFilter
|
|
|
|
switch(type) { |
|
|
|
switch(type) { |
|
|
@ -307,14 +330,14 @@ export default class AppSearchSuper { |
|
|
|
for(const message of messages) { |
|
|
|
for(const message of messages) { |
|
|
|
const {dialog, dom} = appDialogsManager.addDialogNew({ |
|
|
|
const {dialog, dom} = appDialogsManager.addDialogNew({ |
|
|
|
dialog: message.peerId, |
|
|
|
dialog: message.peerId, |
|
|
|
container: sharedMediaDiv as HTMLUListElement/* searchGroup.list */, |
|
|
|
container: searchGroup.list, |
|
|
|
drawStatus: false, |
|
|
|
drawStatus: false, |
|
|
|
avatarSize: 54 |
|
|
|
avatarSize: 54 |
|
|
|
}); |
|
|
|
}); |
|
|
|
appDialogsManager.setLastMessage(dialog, message, dom, this.searchContext.query); |
|
|
|
appDialogsManager.setLastMessage(dialog, message, dom, this.searchContext.query); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this.searchGroups.messages.setActive(); |
|
|
|
searchGroup.setActive(); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -689,7 +712,24 @@ export default class AppSearchSuper { |
|
|
|
.then((contacts) => { |
|
|
|
.then((contacts) => { |
|
|
|
if(contacts) { |
|
|
|
if(contacts) { |
|
|
|
setResults(contacts.my_results, this.searchGroups.contacts, true); |
|
|
|
setResults(contacts.my_results, this.searchGroups.contacts, true); |
|
|
|
setResults(contacts.results, this.searchGroups.globalContacts); |
|
|
|
setResults(contacts.results/* .concat(contacts.results, contacts.results, contacts.results) */, this.searchGroups.globalContacts); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(this.searchGroups.globalContacts.nameEl.lastElementChild) { |
|
|
|
|
|
|
|
this.searchGroups.globalContacts.nameEl.lastElementChild.remove(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.searchGroups.globalContacts.container.classList.add('is-short'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(this.searchGroups.globalContacts.list.childElementCount > 3) { |
|
|
|
|
|
|
|
const showMore = document.createElement('div'); |
|
|
|
|
|
|
|
showMore.classList.add('search-group__show-more'); |
|
|
|
|
|
|
|
showMore.innerText = 'Show more'; |
|
|
|
|
|
|
|
this.searchGroups.globalContacts.nameEl.append(showMore); |
|
|
|
|
|
|
|
showMore.addEventListener('click', () => { |
|
|
|
|
|
|
|
const isShort = this.searchGroups.globalContacts.container.classList.toggle('is-short'); |
|
|
|
|
|
|
|
showMore.innerText = isShort ? 'Show more' : 'Show less'; |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}), |
|
|
|
}), |
|
|
|
|
|
|
|
|
|
|
@ -835,7 +875,7 @@ export default class AppSearchSuper { |
|
|
|
//this.log(logStr + 'search house of glass pre', type, maxId);
|
|
|
|
//this.log(logStr + 'search house of glass pre', type, maxId);
|
|
|
|
|
|
|
|
|
|
|
|
//let loadCount = history.length ? 50 : 15;
|
|
|
|
//let loadCount = history.length ? 50 : 15;
|
|
|
|
return this.loadPromises[type] = appMessagesManager.getSearchNew({ |
|
|
|
return this.loadPromises[type] = appMessagesManager.getSearch({ |
|
|
|
peerId, |
|
|
|
peerId, |
|
|
|
query: this.searchContext.query, |
|
|
|
query: this.searchContext.query, |
|
|
|
inputFilter: {_: type}, |
|
|
|
inputFilter: {_: type}, |
|
|
@ -843,7 +883,9 @@ export default class AppSearchSuper { |
|
|
|
limit: loadCount, |
|
|
|
limit: loadCount, |
|
|
|
nextRate: this.nextRates[type] ?? (this.nextRates[type] = 0), |
|
|
|
nextRate: this.nextRates[type] ?? (this.nextRates[type] = 0), |
|
|
|
threadId: this.searchContext.threadId, |
|
|
|
threadId: this.searchContext.threadId, |
|
|
|
folderId: this.searchContext.folderId |
|
|
|
folderId: this.searchContext.folderId, |
|
|
|
|
|
|
|
minDate: this.searchContext.minDate, |
|
|
|
|
|
|
|
maxDate: this.searchContext.maxDate |
|
|
|
}).then(value => { |
|
|
|
}).then(value => { |
|
|
|
history.push(...value.history.map(m => ({mid: m.mid, peerId: m.peerId}))); |
|
|
|
history.push(...value.history.map(m => ({mid: m.mid, peerId: m.peerId}))); |
|
|
|
|
|
|
|
|
|
|
@ -870,13 +912,15 @@ export default class AppSearchSuper { |
|
|
|
this.usedFromHistory[type] = history.length; |
|
|
|
this.usedFromHistory[type] = history.length; |
|
|
|
|
|
|
|
|
|
|
|
if(!this.loaded[type]) { |
|
|
|
if(!this.loaded[type]) { |
|
|
|
this.loadPromises[type].then(() => { |
|
|
|
(this.loadPromises[type] || Promise.resolve()).then(() => { |
|
|
|
setTimeout(() => { |
|
|
|
setTimeout(() => { |
|
|
|
|
|
|
|
if(!middleware()) return; |
|
|
|
//this.log('will preload more');
|
|
|
|
//this.log('will preload more');
|
|
|
|
if(this.type === type) { |
|
|
|
if(this.type === type) { |
|
|
|
const promise = this.load(true, true); |
|
|
|
const promise = this.load(true, true); |
|
|
|
if(promise) { |
|
|
|
if(promise) { |
|
|
|
promise.then(() => { |
|
|
|
promise.then(() => { |
|
|
|
|
|
|
|
if(!middleware()) return; |
|
|
|
//this.log('preloaded more');
|
|
|
|
//this.log('preloaded more');
|
|
|
|
setTimeout(() => { |
|
|
|
setTimeout(() => { |
|
|
|
this.scrollable.checkForTriggers(); |
|
|
|
this.scrollable.checkForTriggers(); |
|
|
@ -988,6 +1032,7 @@ export default class AppSearchSuper { |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
this.monthContainers = {}; |
|
|
|
this.monthContainers = {}; |
|
|
|
|
|
|
|
this.searchGroupMedia.clear(); |
|
|
|
|
|
|
|
|
|
|
|
if(testScroll) { |
|
|
|
if(testScroll) { |
|
|
|
for(let i = 0; i < 1500; ++i) { |
|
|
|
for(let i = 0; i < 1500; ++i) { |
|
|
@ -1016,19 +1061,23 @@ export default class AppSearchSuper { |
|
|
|
return context; |
|
|
|
return context; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public setQuery({peerId, query, threadId, historyStorage, folderId}: { |
|
|
|
public setQuery({peerId, query, threadId, historyStorage, folderId, minDate, maxDate}: { |
|
|
|
peerId: number, |
|
|
|
peerId: number, |
|
|
|
query?: string, |
|
|
|
query?: string, |
|
|
|
threadId?: number, |
|
|
|
threadId?: number, |
|
|
|
historyStorage?: AppSearchSuper['historyStorage'], |
|
|
|
historyStorage?: AppSearchSuper['historyStorage'], |
|
|
|
folderId?: number |
|
|
|
folderId?: number, |
|
|
|
|
|
|
|
minDate?: number, |
|
|
|
|
|
|
|
maxDate?: number |
|
|
|
}) { |
|
|
|
}) { |
|
|
|
this.searchContext = { |
|
|
|
this.searchContext = { |
|
|
|
peerId: peerId || 0, |
|
|
|
peerId: peerId || 0, |
|
|
|
query: query || '', |
|
|
|
query: query || '', |
|
|
|
inputFilter: this.type, |
|
|
|
inputFilter: this.type, |
|
|
|
threadId, |
|
|
|
threadId, |
|
|
|
folderId |
|
|
|
folderId, |
|
|
|
|
|
|
|
minDate, |
|
|
|
|
|
|
|
maxDate |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
this.historyStorage = historyStorage ?? {}; |
|
|
|
this.historyStorage = historyStorage ?? {}; |
|
|
|