|
|
|
@ -15,6 +15,10 @@ import { cancelEvent } from "../../helpers/dom/cancelEvent";
@@ -15,6 +15,10 @@ import { cancelEvent } from "../../helpers/dom/cancelEvent";
|
|
|
|
|
import whichChild from "../../helpers/dom/whichChild"; |
|
|
|
|
import replaceContent from "../../helpers/dom/replaceContent"; |
|
|
|
|
import { i18n } from "../../lib/langPack"; |
|
|
|
|
import ListenerSetter from "../../helpers/listenerSetter"; |
|
|
|
|
import { attachClickEvent } from "../../helpers/dom/clickEvent"; |
|
|
|
|
import appNavigationController, { NavigationItem } from "../appNavigationController"; |
|
|
|
|
import { IS_MOBILE_SAFARI } from "../../environment/userAgent"; |
|
|
|
|
|
|
|
|
|
export default class ChatSearch { |
|
|
|
|
private element: HTMLElement; |
|
|
|
@ -36,28 +40,26 @@ export default class ChatSearch {
@@ -36,28 +40,26 @@ export default class ChatSearch {
|
|
|
|
|
private foundCount = 0; |
|
|
|
|
private selectedIndex = 0; |
|
|
|
|
private setPeerPromise: Promise<any>; |
|
|
|
|
private listenerSetter: ListenerSetter; |
|
|
|
|
private navigationItem: NavigationItem; |
|
|
|
|
|
|
|
|
|
constructor(private topbar: ChatTopbar, private chat: Chat, private query?: string) { |
|
|
|
|
constructor(private topbar: ChatTopbar, private chat: Chat, query?: string) { |
|
|
|
|
this.element = document.createElement('div'); |
|
|
|
|
this.element.classList.add('sidebar-header', 'chat-search', 'chatlist-container'); |
|
|
|
|
|
|
|
|
|
this.backBtn = document.createElement('button'); |
|
|
|
|
this.backBtn.classList.add('btn-icon', 'tgico-left', 'sidebar-close-button'); |
|
|
|
|
ripple(this.backBtn); |
|
|
|
|
|
|
|
|
|
const listenerSetter = this.listenerSetter = new ListenerSetter(); |
|
|
|
|
|
|
|
|
|
const attachClick = (element: HTMLElement, callback: (e: MouseEvent) => void) => { |
|
|
|
|
attachClickEvent(element, callback, {listenerSetter}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
this.backBtn.addEventListener('click', () => { |
|
|
|
|
this.topbar.container.classList.remove('hide-pinned'); |
|
|
|
|
this.element.remove(); |
|
|
|
|
this.inputSearch.remove(); |
|
|
|
|
this.results.remove(); |
|
|
|
|
this.footer.remove(); |
|
|
|
|
this.footer.removeEventListener('click', this.onFooterClick); |
|
|
|
|
this.dateBtn.removeEventListener('click', this.onDateClick); |
|
|
|
|
this.upBtn.removeEventListener('click', this.onUpClick); |
|
|
|
|
this.downBtn.removeEventListener('click', this.onDownClick); |
|
|
|
|
this.searchGroup.list.removeEventListener('click', this.onResultsClick); |
|
|
|
|
this.chat.bubbles.bubblesContainer.classList.remove('search-results-active'); |
|
|
|
|
}, {once: true}); |
|
|
|
|
attachClick(this.backBtn, () => { |
|
|
|
|
this.destroy(); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
this.inputSearch = new InputSearch('Search'); |
|
|
|
|
|
|
|
|
@ -66,7 +68,7 @@ export default class ChatSearch {
@@ -66,7 +68,7 @@ export default class ChatSearch {
|
|
|
|
|
this.results.classList.add('chat-search-results', 'chatlist-container'); |
|
|
|
|
|
|
|
|
|
this.searchGroup = new SearchGroup(false, 'messages', undefined, '', false); |
|
|
|
|
this.searchGroup.list.addEventListener('click', this.onResultsClick); |
|
|
|
|
attachClick(this.searchGroup.list, this.onResultsClick); |
|
|
|
|
|
|
|
|
|
this.appSearch = new AppSearch(this.results, this.inputSearch, { |
|
|
|
|
messages: this.searchGroup |
|
|
|
@ -74,7 +76,7 @@ export default class ChatSearch {
@@ -74,7 +76,7 @@ export default class ChatSearch {
|
|
|
|
|
this.foundCount = count; |
|
|
|
|
|
|
|
|
|
if(!this.foundCount) { |
|
|
|
|
this.foundCountEl.replaceWith(this.inputSearch.value ? i18n('NoResult') : ''); |
|
|
|
|
replaceContent(this.foundCountEl, this.inputSearch.value ? i18n('NoResult') : ''); |
|
|
|
|
this.results.classList.remove('active'); |
|
|
|
|
this.chat.bubbles.bubblesContainer.classList.remove('search-results-active'); |
|
|
|
|
this.upBtn.setAttribute('disabled', 'true'); |
|
|
|
@ -92,7 +94,7 @@ export default class ChatSearch {
@@ -92,7 +94,7 @@ export default class ChatSearch {
|
|
|
|
|
this.footer = document.createElement('div'); |
|
|
|
|
this.footer.classList.add('chat-search-footer'); |
|
|
|
|
|
|
|
|
|
this.footer.addEventListener('click', this.onFooterClick); |
|
|
|
|
attachClick(this.footer, this.onFooterClick); |
|
|
|
|
ripple(this.footer); |
|
|
|
|
|
|
|
|
|
this.foundCountEl = document.createElement('span'); |
|
|
|
@ -112,9 +114,9 @@ export default class ChatSearch {
@@ -112,9 +114,9 @@ export default class ChatSearch {
|
|
|
|
|
this.upBtn.setAttribute('disabled', 'true'); |
|
|
|
|
this.downBtn.setAttribute('disabled', 'true'); |
|
|
|
|
|
|
|
|
|
this.dateBtn.addEventListener('click', this.onDateClick); |
|
|
|
|
this.upBtn.addEventListener('click', this.onUpClick); |
|
|
|
|
this.downBtn.addEventListener('click', this.onDownClick); |
|
|
|
|
attachClick(this.dateBtn, this.onDateClick); |
|
|
|
|
attachClick(this.upBtn, this.onUpClick); |
|
|
|
|
attachClick(this.downBtn, this.onDownClick); |
|
|
|
|
this.controls.append(this.upBtn, this.downBtn); |
|
|
|
|
|
|
|
|
|
this.footer.append(this.foundCountEl, this.dateBtn, this.controls); |
|
|
|
@ -129,15 +131,44 @@ export default class ChatSearch {
@@ -129,15 +131,44 @@ export default class ChatSearch {
|
|
|
|
|
|
|
|
|
|
this.inputSearch.input.focus(); |
|
|
|
|
|
|
|
|
|
query && (this.inputSearch.inputField.value = query); |
|
|
|
|
if(query) { |
|
|
|
|
this.setQuery(query); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(!IS_MOBILE_SAFARI) { |
|
|
|
|
this.navigationItem = { |
|
|
|
|
type: 'mobile-search', |
|
|
|
|
onPop: () => { |
|
|
|
|
this.destroy(); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
appNavigationController.pushItem(this.navigationItem); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
onDateClick = (e: MouseEvent) => { |
|
|
|
|
public destroy() { |
|
|
|
|
this.topbar.container.classList.remove('hide-pinned'); |
|
|
|
|
this.element.remove(); |
|
|
|
|
this.inputSearch.remove(); |
|
|
|
|
this.results.remove(); |
|
|
|
|
this.footer.remove(); |
|
|
|
|
this.listenerSetter.removeAll(); |
|
|
|
|
this.chat.bubbles.bubblesContainer.classList.remove('search-results-active'); |
|
|
|
|
this.chat.search = undefined; |
|
|
|
|
appNavigationController.removeItem(this.navigationItem); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public setQuery(query: string) { |
|
|
|
|
this.inputSearch.inputField.value = query; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private onDateClick = (e: MouseEvent) => { |
|
|
|
|
cancelEvent(e); |
|
|
|
|
new PopupDatePicker(new Date(), this.chat.bubbles.onDatePick).show(); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
selectResult = (elem: HTMLElement) => { |
|
|
|
|
private selectResult(elem: HTMLElement) { |
|
|
|
|
if(this.setPeerPromise) return this.setPeerPromise; |
|
|
|
|
|
|
|
|
|
const peerId = elem.dataset.peerId.toPeerId(); |
|
|
|
@ -172,29 +203,29 @@ export default class ChatSearch {
@@ -172,29 +203,29 @@ export default class ChatSearch {
|
|
|
|
|
}).finally(() => { |
|
|
|
|
this.setPeerPromise = null; |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
onResultsClick = (e: MouseEvent) => { |
|
|
|
|
private onResultsClick = (e: MouseEvent) => { |
|
|
|
|
const target = findUpTag(e.target, 'LI'); |
|
|
|
|
if(target) { |
|
|
|
|
this.selectResult(target); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onFooterClick = (e: MouseEvent) => { |
|
|
|
|
private onFooterClick = (e: MouseEvent) => { |
|
|
|
|
if(this.foundCount) { |
|
|
|
|
this.chat.bubbles.bubblesContainer.classList.toggle('search-results-active'); |
|
|
|
|
this.results.classList.toggle('active'); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onUpClick = (e: MouseEvent) => { |
|
|
|
|
private onUpClick = (e: MouseEvent) => { |
|
|
|
|
cancelEvent(e); |
|
|
|
|
this.selectResult(this.searchGroup.list.children[this.selectedIndex + 1] as HTMLElement); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onDownClick = (e: MouseEvent) => { |
|
|
|
|
private onDownClick = (e: MouseEvent) => { |
|
|
|
|
cancelEvent(e); |
|
|
|
|
this.selectResult(this.searchGroup.list.children[this.selectedIndex - 1] as HTMLElement); |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|