diff --git a/src/components/appForward.ts b/src/components/appForward.ts index d3e49c2f..a90b8476 100644 --- a/src/components/appForward.ts +++ b/src/components/appForward.ts @@ -73,7 +73,7 @@ class AppForward { } else { this.sendBtn.classList.remove('is-visible'); } - }, 'dialogs', () => { + }, 'both', () => { //console.log('forward rendered:', this.container.querySelector('.selector ul').childElementCount); this.sidebarWasActive = appSidebarRight.sidebarEl.classList.contains('active'); appSidebarRight.toggleSidebar(true); diff --git a/src/components/appSelectPeers.ts b/src/components/appSelectPeers.ts index 813b7ca4..4049d32e 100644 --- a/src/components/appSelectPeers.ts +++ b/src/components/appSelectPeers.ts @@ -24,13 +24,16 @@ export class AppSelectPeers { private myID = $rootScope.myID; + private folderID = 0; private offsetIndex = 0; private promise: Promise; private query = ''; private cachedContacts: number[]; + + private loadedWhat: Partial<{[k in 'dialogs' | 'archived' | 'contacts']: true}> = {}; - constructor(private appendTo: HTMLElement, private onChange?: (length: number) => void, private peerType: 'contacts' | 'dialogs' = 'dialogs', onFirstRender?: () => void, private renderResultsFunc?: (peerIDs: number[]) => void) { + constructor(private appendTo: HTMLElement, private onChange?: (length: number) => void, private peerType: 'contacts' | 'dialogs' | 'both' = 'dialogs', onFirstRender?: () => void, private renderResultsFunc?: (peerIDs: number[]) => void) { this.container.classList.add('selector'); if(!this.renderResultsFunc) { @@ -93,15 +96,25 @@ export class AppSelectPeers { this.input.addEventListener('input', () => { let value = this.input.value; if(this.query != value) { - if(this.peerType == 'contacts') { + if(this.peerType == 'contacts' || this.peerType == 'both') { + delete this.loadedWhat.contacts; this.cachedContacts = null; - } else { + } + + if(this.peerType == 'dialogs' || this.peerType == 'both') { + delete this.loadedWhat.dialogs; + delete this.loadedWhat.archived; + this.folderID = 0; this.offsetIndex = 0; } this.promise = null; this.list.innerHTML = ''; this.query = value; + + if(this.query && 'saved messages'.includes(this.query.toLowerCase())) { + this.renderResultsFunc([$rootScope.myID]); + } //console.log('selectPeers input:', this.query); this.getMoreResults(); @@ -126,33 +139,51 @@ export class AppSelectPeers { }, 0); } - private async getMoreDialogs() { + private async getMoreDialogs(): Promise { if(this.promise) return this.promise; + + if(this.loadedWhat.dialogs && this.loadedWhat.archived) { + return; + } // в десктопе - сначала без группы, потом архивные, потом контакты без сообщений const pageCount = appPhotosManager.windowH / 72 * 1.25 | 0; - this.promise = appMessagesManager.getConversations(this.query, this.offsetIndex, pageCount, 0); + this.promise = appMessagesManager.getConversations(this.query, this.offsetIndex, pageCount, this.folderID); const value = await this.promise; let dialogs = value.dialogs as Dialog[]; - if(!dialogs.length) { - return; - } - - const newOffsetIndex = dialogs[dialogs.length - 1].index || 0; - - dialogs = dialogs.filter(d => d.peerID != this.myID); - if(!this.offsetIndex && !this.query) { - dialogs.unshift({ - peerID: this.myID, - pFlags: {} - } as any); - } + if(dialogs.length) { + const newOffsetIndex = dialogs[dialogs.length - 1].index || 0; + + dialogs = dialogs.filter(d => d.peerID != this.myID); + if(!this.offsetIndex && this.folderID == 0 && !this.query) { + dialogs.unshift({ + peerID: this.myID, + pFlags: {} + } as any); + } - this.offsetIndex = newOffsetIndex; + this.offsetIndex = newOffsetIndex; - this.renderResultsFunc(dialogs.map(dialog => dialog.peerID)); + this.renderResultsFunc(dialogs.map(dialog => dialog.peerID)); + } else { + if(!this.loadedWhat.dialogs) { + this.loadedWhat.dialogs = true; + this.offsetIndex = 0; + this.folderID = 1; + + this.promise = null; + return this.getMoreDialogs(); + } else { + this.loadedWhat.archived = true; + + if(!this.loadedWhat.contacts && this.peerType == 'both') { + this.promise = null; + return this.getMoreContacts(); + } + } + } this.promise = null; } @@ -160,6 +191,10 @@ export class AppSelectPeers { private async getMoreContacts() { if(this.promise) return this.promise; + if(this.loadedWhat.contacts) { + return; + } + if(!this.cachedContacts) { this.promise = appUsersManager.getContacts(this.query); this.cachedContacts = (await this.promise).slice(); @@ -171,15 +206,26 @@ export class AppSelectPeers { const pageCount = appPhotosManager.windowH / 72 * 1.25 | 0; const arr = this.cachedContacts.splice(0, pageCount); this.renderResultsFunc(arr); + } else { + this.loadedWhat.contacts = true; } } private getMoreResults() { - if(this.peerType == 'dialogs') { - return this.getMoreDialogs(); - } else { - return this.getMoreContacts(); + const promises: Promise[] = []; + if(this.peerType == 'dialogs' || this.peerType == 'both') { + promises.push(this.getMoreDialogs()); + + if(!this.loadedWhat.archived) { + return Promise.all(promises); + } } + + if(this.peerType == 'contacts' || this.peerType == 'both') { + promises.push(this.getMoreContacts()); + } + + return Promise.all(promises); } private renderResults(peerIDs: number[]) { diff --git a/src/components/sidebarLeft/chatFolders.ts b/src/components/sidebarLeft/chatFolders.ts index 8142a5af..7949e948 100644 --- a/src/components/sidebarLeft/chatFolders.ts +++ b/src/components/sidebarLeft/chatFolders.ts @@ -7,6 +7,7 @@ import appPeersManager from "../../lib/appManagers/appPeersManager"; import { $rootScope, cancelEvent } from "../../lib/utils"; import appSidebarLeft from "../../lib/appManagers/appSidebarLeft"; import { ripple } from "../ripple"; +import { toast } from "../toast"; type DialogFilterSuggested = { _: 'dialogFilterSuggested', @@ -98,7 +99,11 @@ export default class AppChatFoldersTab implements SliderTab { this.createFolderBtn = this.container.querySelector('.btn-create-folder'); this.createFolderBtn.addEventListener('click', () => { - appSidebarLeft.editFolderTab.open(); + if(Object.keys(this.filtersRendered).length >= 10) { + toast('Sorry, you can\'t create more folders.'); + } else { + appSidebarLeft.editFolderTab.open(); + } }); lottieLoader.loadAnimationFromURL({ @@ -162,6 +167,12 @@ export default class AppChatFoldersTab implements SliderTab { button.addEventListener('click', (e) => { cancelEvent(e); + + if(Object.keys(this.filtersRendered).length >= 10) { + toast('Sorry, you can\'t create more folders.'); + return; + } + button.setAttribute('disabled', 'true'); appMessagesManager.filtersStorage.createDialogFilter(filter.filter).then(bool => { diff --git a/src/components/sidebarLeft/editFolder.ts b/src/components/sidebarLeft/editFolder.ts index c3f8652b..fcb4abbc 100644 --- a/src/components/sidebarLeft/editFolder.ts +++ b/src/components/sidebarLeft/editFolder.ts @@ -108,6 +108,12 @@ export default class AppEditFolderTab implements SliderTab { if(bool) { this.closeBtn.click(); } + }).catch(err => { + if(err.type == 'DIALOG_FILTERS_TOO_MUCH') { + toast('Sorry, you can\'t create more folders.'); + } else { + console.error('updateDialogFilter error:', err); + } }).finally(() => { this.confirmBtn.removeAttribute('disabled'); }); diff --git a/src/components/sidebarLeft/editProfile.ts b/src/components/sidebarLeft/editProfile.ts index 18290565..8d19a510 100644 --- a/src/components/sidebarLeft/editProfile.ts +++ b/src/components/sidebarLeft/editProfile.ts @@ -7,6 +7,8 @@ import Scrollable from "../scrollable_new"; import appUsersManager from "../../lib/appManagers/appUsersManager"; import { $rootScope } from "../../lib/utils"; +// TODO: аватарка не поменяется в этой вкладке после изменения почему-то (если поставить в другом клиенте, и потом тут проверить, для этого ещё вышел в чатлист) + export default class AppEditProfileTab implements SliderTab { private container = document.querySelector('.edit-profile-container') as HTMLDivElement; private scrollWrapper = this.container.querySelector('.scroll-wrapper') as HTMLDivElement; diff --git a/src/components/wrappers.ts b/src/components/wrappers.ts index fbc71fe5..8c0cc731 100644 --- a/src/components/wrappers.ts +++ b/src/components/wrappers.ts @@ -414,7 +414,7 @@ function wrapMediaWithTail(photo: MTPhoto | MTDocument, message: {mid: number, m return img; } -export function wrapPhoto(photo: MTPhoto | MTDocument, 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(photo: MTPhoto | MTDocument, message: any, container: HTMLDivElement, boxWidth = mediaSizes.active.regular.width, boxHeight = mediaSizes.active.regular.height, withTail: boolean, isOut: boolean, lazyLoadQueue: LazyLoadQueue, middleware: () => boolean, size: MTPhotoSize = null) { let image: HTMLImageElement; if(withTail) { image = wrapMediaWithTail(photo, message, container, boxWidth, boxHeight, isOut); diff --git a/src/helpers/blob.ts b/src/helpers/blob.ts index e36cc1c5..a85fa514 100644 --- a/src/helpers/blob.ts +++ b/src/helpers/blob.ts @@ -1,7 +1,7 @@ export const readBlobAsText = (blob: Blob) => { return new Promise(resolve => { const reader = new FileReader(); - reader.addEventListener('loadend', async(e) => { + reader.addEventListener('loadend', (e) => { // @ts-ignore resolve(e.srcElement.result); }); diff --git a/src/lib/appManagers/appSidebarRight.ts b/src/lib/appManagers/appSidebarRight.ts index 12a6e4b2..5deca80f 100644 --- a/src/lib/appManagers/appSidebarRight.ts +++ b/src/lib/appManagers/appSidebarRight.ts @@ -1,7 +1,7 @@ import { putPreloader, renderImageFromUrl } from "../../components/misc"; //import Scrollable from '../../components/scrollable'; import Scrollable from '../../components/scrollable_new'; -import { $rootScope, findUpClassName } from "../utils"; +import { $rootScope } from "../utils"; import appMessagesManager from "./appMessagesManager"; import appPhotosManager from "./appPhotosManager"; import appPeersManager from "./appPeersManager"; @@ -12,12 +12,12 @@ import { logger, LogLevels } from "../logger"; import appImManager from "./appImManager"; import appMediaViewer from "./appMediaViewer"; import LazyLoadQueue from "../../components/lazyLoadQueue"; -import { wrapDocument, wrapAudio, wrapSticker } from "../../components/wrappers"; +import { wrapDocument, wrapAudio } from "../../components/wrappers"; import AppSearch, { SearchGroup } from "../../components/appSearch"; import AvatarElement from "../../components/avatar"; import appForward from "../../components/appForward"; import { mediaSizes } from "../config"; -import SidebarSlider, { SliderTab } from "../../components/slider"; +import SidebarSlider from "../../components/slider"; import SearchInput from "../../components/searchInput"; import { horizontalMenu } from "../../components/horizontalMenu"; import AppStickersTab from "../../components/sidebarRight/stickers"; @@ -55,6 +55,9 @@ const contentToSharedMap: {[contentType in ContentType]: SharedMediaType} = { contentAudio: 'inputMessagesFilterMusic' }; +// TODO: отправленное сообщение с картинкой, или же новое полученное апдейтом сообщение не отобразится в медии +// TODO: по-хорошему, нужно просто сделать апдейты для всего сайдбара + export class AppSidebarRight extends SidebarSlider { public static SLIDERITEMSIDS = { search: 1, @@ -633,7 +636,7 @@ export class AppSidebarRight extends SidebarSlider { //this.contentContainer.classList.add('loaded'); - if(!messages.length) { + if(!messages.length && !sharedMediaDiv.childElementCount) { const div = document.createElement('div'); div.innerText = 'Nothing interesting here yet...'; div.classList.add('position-center', 'text-center', 'content-empty', 'no-select'); diff --git a/src/lib/utils.ts b/src/lib/utils.ts index ca6f572f..1d39ce42 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -151,17 +151,6 @@ export function getRichElementValue(node: any, lines: string[], line: string[], } } */ -type BroadcastKeys = 'download_progress' | 'user_update' | 'user_auth' | 'peer_changed' | - 'filter_delete' | 'filter_update' | 'message_edit' | 'dialog_draft' | 'messages_pending' | - 'history_append' | 'history_update' | 'dialogs_multiupdate' | 'dialog_unread' | 'dialog_flush' | - 'dialog_drop' | 'dialog_migrate' | 'dialog_top' | 'history_reply_markup' | 'history_multiappend' | - 'messages_read' | 'history_delete' | 'history_forbidden' | 'history_reload' | 'message_views' | - 'message_sent' | 'history_request' | 'messages_downloaded' | 'contacts_update' | 'avatar_update' | - 'stickers_installed' | 'stickers_deleted' | 'chat_full_update' | 'peer_pinned_message' | - 'poll_update' | 'dialogs_archived_unread' | 'audio_play' | 'audio_pause' | 'chat_update' | - 'apiUpdate' | 'stateSynchronized' | 'channel_settings' | 'webpage_updated' | 'draft_updated' | - 'dialog_notify_settings'; - type BroadcastEvents = { 'download_progress': any, 'user_update': any, @@ -222,7 +211,7 @@ export const $rootScope = { // @ts-ignore document.addEventListener(name, callback); }, - $off: (name: BroadcastKeys, callback: (e: CustomEvent) => any) => { + $off: (name: T, callback: (e: Omit & {detail: BroadcastEvents[T]}) => any) => { // @ts-ignore document.removeEventListener(name, callback); }, diff --git a/src/pages/pageSignIn.ts b/src/pages/pageSignIn.ts index 37318368..7d9d9f92 100644 --- a/src/pages/pageSignIn.ts +++ b/src/pages/pageSignIn.ts @@ -247,7 +247,7 @@ let onFirstMount = () => { } //lang_code: navigator.language || 'en' }).then((code: any) => { - console.log('got code', code); + //console.log('got code', code); pageAuthCode.mount(Object.assign(code, {phone_number: phone_number})); }).catch(err => { diff --git a/src/scss/partials/_chatlist.scss b/src/scss/partials/_chatlist.scss index a76e7257..0ffd5575 100644 --- a/src/scss/partials/_chatlist.scss +++ b/src/scss/partials/_chatlist.scss @@ -105,7 +105,7 @@ .user-title { &:after { content: $tgico-nosound; - color: #707579; + color: #a3a3a3; font-size: 1.125rem; line-height: 27px; vertical-align: middle; diff --git a/src/scss/partials/_rightSidebar.scss b/src/scss/partials/_rightSidebar.scss index 0e0fa11d..f3dedec5 100644 --- a/src/scss/partials/_rightSidebar.scss +++ b/src/scss/partials/_rightSidebar.scss @@ -238,6 +238,10 @@ > div { //height: 100%; position: relative; + + /* > div:not(:empty) + .content-empty { + display: none; + } */ } /* > div > div:not(.scroll-padding) { diff --git a/webpack.common.js b/webpack.common.js index 35548477..86ebc3dd 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -6,7 +6,7 @@ const postcssPresetEnv = require('postcss-preset-env'); const ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin'); const fs = require('fs'); -const allowedIPs = ['195.66.140.39', '192.168.31.144', '127.0.0.1', '192.168.31.1', '192.168.31.192', '176.100.18.181', '46.219.250.22', '193.42.119.184', '46.133.168.67']; +const allowedIPs = ['195.66.140.39', '192.168.31.144', '127.0.0.1', '192.168.31.1', '192.168.31.192', '176.100.18.181', '46.219.250.22', '193.42.119.184', '46.133.168.67', '78.26.144.197', '46.133.225.88']; const devMode = process.env.NODE_ENV !== 'production'; const useLocal = false;