diff --git a/src/components/appSearchSuper..ts b/src/components/appSearchSuper..ts index 7d3421d7..35dd1f06 100644 --- a/src/components/appSearchSuper..ts +++ b/src/components/appSearchSuper..ts @@ -35,6 +35,10 @@ import { getMiddleware } from "../helpers/middleware"; import appProfileManager from "../lib/appManagers/appProfileManager"; import { ChannelParticipant, ChatFull, ChatParticipant, ChatParticipants } from "../layer"; import SortedUserList from "./sortedUserList"; +import findUpTag from "../helpers/dom/findUpTag"; +import appSidebarRight from "./sidebarRight"; +import mediaSizes from "../helpers/mediaSizes"; +import appImManager from "../lib/appManagers/appImManager"; //const testScroll = false; @@ -88,6 +92,7 @@ export default class AppSearchSuper { private loadPromises: Partial<{[type in SearchSuperType]: Promise}> = {}; private loaded: Partial<{[type in SearchSuperType]: boolean}> = {}; private loadedChats = false; + private firstLoad = true; private log = logger('SEARCH-SUPER'); public selectTab: ReturnType; @@ -855,6 +860,22 @@ export default class AppSearchSuper { if(!this.membersList) { this.membersList = new SortedUserList(); + this.membersList.list.addEventListener('click', (e) => { + const li = findUpTag(e.target, 'LI'); + if(!li) { + return; + } + + const peerId = +li.dataset.peerId; + let promise: Promise = Promise.resolve(); + if(mediaSizes.isMobile) { + promise = appSidebarRight.toggleSidebar(false); + } + + promise.then(() => { + appImManager.setInnerPeer(peerId); + }); + }); mediaTab.contentTab.append(this.membersList.list); this.afterPerforming(1, mediaTab.contentTab); } @@ -1039,7 +1060,7 @@ export default class AppSearchSuper { }); } - public load(single = false, justLoad = false) { + public async load(single = false, justLoad = false) { // if(testScroll/* || 1 === 1 */) { // return; // } @@ -1048,6 +1069,57 @@ export default class AppSearchSuper { const peerId = this.searchContext.peerId; this.log('load', single, peerId, this.loadPromises); + const middleware = this.middleware.get(); + + if(this.firstLoad) { + if(this.hideEmptyTabs) { + const mediaTabs = this.mediaTabs.filter(mediaTab => mediaTab.inputFilter !== 'inputMessagesFilterEmpty') + const filters = mediaTabs.map(mediaTab => ({_: mediaTab.inputFilter})); + + const counters = await appMessagesManager.getSearchCounters(peerId, filters); + if(!middleware()) { + return; + } + + if(this.loadMutex) { + await this.loadMutex; + + if(!middleware()) { + return; + } + } + + let firstMediaTab: SearchSuperMediaTab; + mediaTabs.forEach(mediaTab => { + const counter = counters.find(c => c.filter._ === mediaTab.inputFilter); + + mediaTab.menuTab.classList.toggle('hide', !counter.count); + mediaTab.menuTab.classList.remove('active'); + //mediaTab.contentTab.classList.toggle('hide', !counter.count); + + if(counter.count && firstMediaTab === undefined) { + firstMediaTab = mediaTab; + } + }); + + const membersTab = this.mediaTabsMap.get('members'); + const canViewMembers = this.canViewMembers(); + membersTab.menuTab.classList.toggle('hide', !canViewMembers); + + if(canViewMembers) { + firstMediaTab = membersTab; + } + + this.container.classList.toggle('hide', !firstMediaTab); + this.container.parentElement.classList.toggle('search-empty', !firstMediaTab); + this.selectTab(this.mediaTabs.indexOf(firstMediaTab), false); + if(firstMediaTab) { + firstMediaTab.menuTab.classList.add('active'); + } + } + + this.firstLoad = false; + } let toLoad = single ? [this.mediaTab] : this.mediaTabs.filter(t => t !== this.mediaTab); toLoad = toLoad.filter(mediaTab => { @@ -1060,12 +1132,11 @@ export default class AppSearchSuper { } const loadCount = justLoad ? 50 : Math.round((appPhotosManager.windowH / 130 | 0) * 3 * 1.25); // that's good for all types - const middleware = this.middleware.get(); const promises: Promise[] = toLoad.map(mediaTab => { return this.loadType(mediaTab, justLoad, loadCount, middleware) }); - + return Promise.all(promises).catch(err => { this.log.error('Load error all promises:', err); }); @@ -1118,6 +1189,7 @@ export default class AppSearchSuper { this.loaded = {}; this.loadedChats = false; this.nextRates = {}; + this.firstLoad = true; this.lazyLoadQueue.clear(); @@ -1126,11 +1198,11 @@ export default class AppSearchSuper { }); // * must go to first tab (это костыль) - const membersTab = this.mediaTabsMap.get('members'); + /* const membersTab = this.mediaTabsMap.get('members'); if(membersTab) { const tab = this.canViewMembers() ? membersTab : this.mediaTabs[this.mediaTabs.indexOf(membersTab) + 1]; this.mediaTab = tab; - } + } */ this.middleware.clean(); this.cleanScrollPositions(); @@ -1154,9 +1226,11 @@ export default class AppSearchSuper { this.mediaTabs.forEach((tab) => { tab.contentTab.innerHTML = ''; - /* if(this.hideEmptyTabs) { - tab.menuTab.classList.add('hide'); - } */ + if(this.hideEmptyTabs) { + //tab.menuTab.classList.add('hide'); + this.container.classList.add('hide'); + this.container.parentElement.classList.add('search-empty'); + } if(tab.type === 'chats') { return; @@ -1177,7 +1251,7 @@ export default class AppSearchSuper { } }); - if(goFirst) { + /* if(goFirst) { const membersTab = this.mediaTabsMap.get('members'); if(membersTab) { let idx = this.canViewMembers() ? 0 : 1; @@ -1187,7 +1261,7 @@ export default class AppSearchSuper { } else { this.selectTab(0, false); } - } + } */ this.monthContainers = {}; this.searchGroupMedia.clear(); diff --git a/src/components/chat/bubbles.ts b/src/components/chat/bubbles.ts index 84ce628c..85d60190 100644 --- a/src/components/chat/bubbles.ts +++ b/src/components/chat/bubbles.ts @@ -181,6 +181,8 @@ export default class ChatBubbles { } }); + //this.listenerSetter.add(rootScope, '') + this.listenerSetter.add(rootScope, 'dialog_flush', (e) => { let peerId: number = e.peerId; if(this.peerId === peerId) { @@ -434,7 +436,7 @@ export default class ChatBubbles { const msgIdsByPeer = e; if(!(this.peerId in msgIdsByPeer)) return; - const msgIds = (msgIdsByPeer[this.peerId] as number[]).slice().sort((a, b) => b - a); + const msgIds = Array.from(msgIdsByPeer[this.peerId] as number[]).slice().sort((a, b) => b - a); this.renderNewMessagesByIds(msgIds); }); diff --git a/src/components/chat/topbar.ts b/src/components/chat/topbar.ts index 0da54c95..6d4fdb37 100644 --- a/src/components/chat/topbar.ts +++ b/src/components/chat/topbar.ts @@ -451,7 +451,7 @@ export default class ChatTopbar { else titleEl = i18n('PinnedMessagesCount', [count]); if(count === undefined) { - this.appMessagesManager.getSearchCounters(this.peerId, [{_: 'inputMessagesFilterPinned'}]).then(result => { + this.appMessagesManager.getSearchCounters(this.peerId, [{_: 'inputMessagesFilterPinned'}], false).then(result => { const count = result[0].count; this.setTitle(count); @@ -490,7 +490,14 @@ export default class ChatTopbar { this.appMessagesManager.getHistory(this.peerId, 0, 1, 0, this.chat.threadId), Promise.resolve() ]).then(() => { - this.setTitle(this.appMessagesManager.getHistoryStorage(this.peerId, this.chat.threadId).count); + const count = this.appMessagesManager.getHistoryStorage(this.peerId, this.chat.threadId).count; + if(count === null) { + setTimeout(() => { + this.setTitle(); + }, 30); + } else { + this.setTitle(count); + } }); } } else if(this.chat.type === 'chat') { diff --git a/src/components/sidebarLeft/tabs/background.ts b/src/components/sidebarLeft/tabs/background.ts index 4667efcc..925d1b4c 100644 --- a/src/components/sidebarLeft/tabs/background.ts +++ b/src/components/sidebarLeft/tabs/background.ts @@ -32,8 +32,8 @@ export default class AppBackgroundTab extends SliderSuperTab { { const container = generateSection(this.scrollable); - const uploadButton = Button('btn-primary btn-transparent', {icon: 'cameraadd', text: 'ChatBackground.UploadWallpaper', disabled: true}); - const colorButton = Button('btn-primary btn-transparent', {icon: 'colorize', text: 'ChatBackground.SetColor', disabled: true}); + //const uploadButton = Button('btn-primary btn-transparent', {icon: 'cameraadd', text: 'ChatBackground.UploadWallpaper', disabled: true}); + //const colorButton = Button('btn-primary btn-transparent', {icon: 'colorize', text: 'ChatBackground.SetColor', disabled: true}); const blurCheckboxField = new CheckboxField({ text: 'ChatBackground.Blur', @@ -51,7 +51,7 @@ export default class AppBackgroundTab extends SliderSuperTab { }, 100); }); - container.append(uploadButton, colorButton, blurCheckboxField.label); + container.append(/* uploadButton, colorButton, */blurCheckboxField.label); } const grid = document.createElement('div'); diff --git a/src/components/sidebarLeft/tabs/privacy/profilePhoto.ts b/src/components/sidebarLeft/tabs/privacy/profilePhoto.ts index f8e61160..3cabac47 100644 --- a/src/components/sidebarLeft/tabs/privacy/profilePhoto.ts +++ b/src/components/sidebarLeft/tabs/privacy/profilePhoto.ts @@ -18,7 +18,7 @@ export default class AppPrivacyProfilePhotoTab extends SliderSuperTabEventable { new PrivacySection({ tab: this, title: 'PrivacyProfilePhotoTitle', - inputKey: 'inputPrivacyKeyChatInvite', + inputKey: 'inputPrivacyKeyProfilePhoto', captions: [caption, caption, caption], exceptionTexts: ['PrivacySettingsController.NeverShare', 'PrivacySettingsController.AlwaysShare'], appendTo: this.scrollable, diff --git a/src/components/sidebarRight/tabs/editChannel.ts b/src/components/sidebarRight/tabs/editChannel.ts index 421c2e68..e82962f6 100644 --- a/src/components/sidebarRight/tabs/editChannel.ts +++ b/src/components/sidebarRight/tabs/editChannel.ts @@ -95,7 +95,7 @@ export default class AppEditChannelTab extends SliderSuperTab { }, {listenerSetter: this.listenerSetter}); } - if(appChatsManager.hasRights(-this.peerId, 'change_type')) { + /* if(appChatsManager.hasRights(-this.peerId, 'change_type')) { const channelTypeRow = new Row({ titleLangKey: 'ChannelType', subtitleLangKey: 'TypePrivate', @@ -133,12 +133,12 @@ export default class AppEditChannelTab extends SliderSuperTab { }); section.content.append(signMessagesCheckboxField.label); - } + } */ this.scrollable.append(section.container); } - { + /* { const section = new SettingSection({ }); @@ -154,7 +154,7 @@ export default class AppEditChannelTab extends SliderSuperTab { section.content.append(subscribersRow.container); this.scrollable.append(section.container); - } + } */ if(appChatsManager.hasRights(-this.peerId, 'delete_chat')) { const section = new SettingSection({ diff --git a/src/components/sidebarRight/tabs/editGroup.ts b/src/components/sidebarRight/tabs/editGroup.ts index caf5683a..f92c4304 100644 --- a/src/components/sidebarRight/tabs/editGroup.ts +++ b/src/components/sidebarRight/tabs/editGroup.ts @@ -132,14 +132,14 @@ export default class AppEditGroupTab extends SliderSuperTab { }); } - const administratorsRow = new Row({ + /* const administratorsRow = new Row({ titleLangKey: 'PeerInfo.Administrators', subtitle: '' + ((chatFull as ChatFull.channelFull).admins_count || 1), icon: 'admin', clickable: true }); - section.content.append(administratorsRow.container); + section.content.append(administratorsRow.container); */ this.scrollable.append(section.container); diff --git a/src/components/sidebarRight/tabs/groupPermissions.ts b/src/components/sidebarRight/tabs/groupPermissions.ts index 0c22e21e..51a3b176 100644 --- a/src/components/sidebarRight/tabs/groupPermissions.ts +++ b/src/components/sidebarRight/tabs/groupPermissions.ts @@ -185,14 +185,16 @@ export default class AppGroupPermissionsTab extends SliderSuperTabEventable { tab.open(); }; - const removedUsersRow = new Row({ + section.content.append(addExceptionRow.container); + + /* const removedUsersRow = new Row({ titleLangKey: 'ChannelBlockedUsers', subtitleLangKey: 'NoBlockedUsers', icon: 'deleteuser', clickable: true }); - section.content.append(addExceptionRow.container, removedUsersRow.container); + section.content.append(removedUsersRow.container); */ const c = section.generateContentElement(); c.classList.add('chatlist-container'); diff --git a/src/components/sortedUserList.ts b/src/components/sortedUserList.ts index 01a9dcd0..6161b486 100644 --- a/src/components/sortedUserList.ts +++ b/src/components/sortedUserList.ts @@ -23,7 +23,6 @@ export default class SortedUserList { constructor() { this.list = appDialogsManager.createChatList(); - appDialogsManager.setListClickListener(this.list, undefined, undefined, true, true); this.users = new Map(); this.sorted = []; diff --git a/src/helpers/listenerSetter.ts b/src/helpers/listenerSetter.ts index e2b282a4..ad3aa85c 100644 --- a/src/helpers/listenerSetter.ts +++ b/src/helpers/listenerSetter.ts @@ -4,32 +4,56 @@ * https://github.com/morethanwords/tweb/blob/master/LICENSE */ -export type Listener = {element: ListenerElement, event: ListenerEvent, callback: ListenerCallback, options?: ListenerOptions}; -export type ListenerElement = any; -export type ListenerEvent = string; -export type ListenerOptions = any; +import type { RootScope } from "../lib/rootScope"; +import { ArgumentTypes } from "../types"; + +/* export type Listener = { + element: ListenerElement, + event: ListenerEvent, + callback: ListenerCallback, + options?: ListenerOptions +}; + +export type ListenerElement = HTMLElement | RootScope; +export type ListenerEvent = ArgumentTypes[0]; +export type ListenerCallback = ArgumentTypes[1]; +export type ListenerOptions = any; */ +export type Listener = { + element: ListenerElement, + event: ListenerEvent, + callback: ListenerCallback, + options?: ListenerOptions +}; + +export type ListenerElement = Window | Document | HTMLElement | Element | RootScope | any; +//export type ListenerEvent = ArgumentTypes[0]; +export type ListenerEvent = string; export type ListenerCallback = (...args: any[]) => any; +export type ListenerOptions = any; + export default class ListenerSetter { - private listeners: Set = new Set(); + private listeners: Set> = new Set(); - public add(element: ListenerElement, event: ListenerEvent, callback: ListenerCallback, options?: ListenerOptions) { - const listener = {element, event, callback, options}; + public add(element: T, event: ListenerEvent, callback: ListenerCallback, options?: ListenerOptions) { + const listener: Listener = {element, event, callback, options}; this.addManual(listener); return listener; } - public addManual(listener: Listener) { + public addManual(listener: Listener) { + // @ts-ignore listener.element.addEventListener(listener.event, listener.callback, listener.options); this.listeners.add(listener); } - public remove(listener: Listener) { + public remove(listener: Listener) { + // @ts-ignore listener.element.removeEventListener(listener.event, listener.callback, listener.options); this.listeners.delete(listener); } - public removeManual(element: ListenerElement, event: ListenerEvent, callback: ListenerCallback, options?: ListenerOptions) { - let listener: Listener; + public removeManual(element: T, event: ListenerEvent, callback: ListenerCallback, options?: ListenerOptions) { + let listener: Listener; for(const _listener of this.listeners) { if(_listener.element === element && _listener.event === event && _listener.callback === callback && _listener.options === options) { listener = _listener; diff --git a/src/layer.d.ts b/src/layer.d.ts index ecdd017a..a7f7ac77 100644 --- a/src/layer.d.ts +++ b/src/layer.d.ts @@ -1882,7 +1882,7 @@ export namespace MessagesFilter { /** * @link https://core.telegram.org/type/Update */ -export type Update = Update.updateNewMessage | Update.updateMessageID | Update.updateDeleteMessages | Update.updateUserTyping | Update.updateChatUserTyping | Update.updateChatParticipants | Update.updateUserStatus | Update.updateUserName | Update.updateUserPhoto | Update.updateNewEncryptedMessage | Update.updateEncryptedChatTyping | Update.updateEncryption | Update.updateEncryptedMessagesRead | Update.updateChatParticipantAdd | Update.updateChatParticipantDelete | Update.updateDcOptions | Update.updateNotifySettings | Update.updateServiceNotification | Update.updatePrivacy | Update.updateUserPhone | Update.updateReadHistoryInbox | Update.updateReadHistoryOutbox | Update.updateWebPage | Update.updateReadMessagesContents | Update.updateChannelTooLong | Update.updateChannel | Update.updateNewChannelMessage | Update.updateReadChannelInbox | Update.updateDeleteChannelMessages | Update.updateChannelMessageViews | Update.updateChatParticipantAdmin | Update.updateNewStickerSet | Update.updateStickerSetsOrder | Update.updateStickerSets | Update.updateSavedGifs | Update.updateBotInlineQuery | Update.updateBotInlineSend | Update.updateEditChannelMessage | Update.updateBotCallbackQuery | Update.updateEditMessage | Update.updateInlineBotCallbackQuery | Update.updateReadChannelOutbox | Update.updateDraftMessage | Update.updateReadFeaturedStickers | Update.updateRecentStickers | Update.updateConfig | Update.updatePtsChanged | Update.updateChannelWebPage | Update.updateDialogPinned | Update.updatePinnedDialogs | Update.updateBotWebhookJSON | Update.updateBotWebhookJSONQuery | Update.updateBotShippingQuery | Update.updateBotPrecheckoutQuery | Update.updatePhoneCall | Update.updateLangPackTooLong | Update.updateLangPack | Update.updateFavedStickers | Update.updateChannelReadMessagesContents | Update.updateContactsReset | Update.updateChannelAvailableMessages | Update.updateDialogUnreadMark | Update.updateMessagePoll | Update.updateChatDefaultBannedRights | Update.updateFolderPeers | Update.updatePeerSettings | Update.updatePeerLocated | Update.updateNewScheduledMessage | Update.updateDeleteScheduledMessages | Update.updateTheme | Update.updateGeoLiveViewed | Update.updateLoginToken | Update.updateMessagePollVote | Update.updateDialogFilter | Update.updateDialogFilterOrder | Update.updateDialogFilters | Update.updatePhoneCallSignalingData | Update.updateChannelMessageForwards | Update.updateReadChannelDiscussionInbox | Update.updateReadChannelDiscussionOutbox | Update.updatePeerBlocked | Update.updateChannelUserTyping | Update.updatePinnedMessages | Update.updatePinnedChannelMessages | Update.updateChat | Update.updateGroupCallParticipants | Update.updateGroupCall | Update.updatePeerHistoryTTL | Update.updateChatParticipant | Update.updateChannelParticipant | Update.updateBotStopped; +export type Update = Update.updateNewMessage | Update.updateMessageID | Update.updateDeleteMessages | Update.updateUserTyping | Update.updateChatUserTyping | Update.updateChatParticipants | Update.updateUserStatus | Update.updateUserName | Update.updateUserPhoto | Update.updateNewEncryptedMessage | Update.updateEncryptedChatTyping | Update.updateEncryption | Update.updateEncryptedMessagesRead | Update.updateChatParticipantAdd | Update.updateChatParticipantDelete | Update.updateDcOptions | Update.updateNotifySettings | Update.updateServiceNotification | Update.updatePrivacy | Update.updateUserPhone | Update.updateReadHistoryInbox | Update.updateReadHistoryOutbox | Update.updateWebPage | Update.updateReadMessagesContents | Update.updateChannelTooLong | Update.updateChannel | Update.updateNewChannelMessage | Update.updateReadChannelInbox | Update.updateDeleteChannelMessages | Update.updateChannelMessageViews | Update.updateChatParticipantAdmin | Update.updateNewStickerSet | Update.updateStickerSetsOrder | Update.updateStickerSets | Update.updateSavedGifs | Update.updateBotInlineQuery | Update.updateBotInlineSend | Update.updateEditChannelMessage | Update.updateBotCallbackQuery | Update.updateEditMessage | Update.updateInlineBotCallbackQuery | Update.updateReadChannelOutbox | Update.updateDraftMessage | Update.updateReadFeaturedStickers | Update.updateRecentStickers | Update.updateConfig | Update.updatePtsChanged | Update.updateChannelWebPage | Update.updateDialogPinned | Update.updatePinnedDialogs | Update.updateBotWebhookJSON | Update.updateBotWebhookJSONQuery | Update.updateBotShippingQuery | Update.updateBotPrecheckoutQuery | Update.updatePhoneCall | Update.updateLangPackTooLong | Update.updateLangPack | Update.updateFavedStickers | Update.updateChannelReadMessagesContents | Update.updateContactsReset | Update.updateChannelAvailableMessages | Update.updateDialogUnreadMark | Update.updateMessagePoll | Update.updateChatDefaultBannedRights | Update.updateFolderPeers | Update.updatePeerSettings | Update.updatePeerLocated | Update.updateNewScheduledMessage | Update.updateDeleteScheduledMessages | Update.updateTheme | Update.updateGeoLiveViewed | Update.updateLoginToken | Update.updateMessagePollVote | Update.updateDialogFilter | Update.updateDialogFilterOrder | Update.updateDialogFilters | Update.updatePhoneCallSignalingData | Update.updateChannelMessageForwards | Update.updateReadChannelDiscussionInbox | Update.updateReadChannelDiscussionOutbox | Update.updatePeerBlocked | Update.updateChannelUserTyping | Update.updatePinnedMessages | Update.updatePinnedChannelMessages | Update.updateChat | Update.updateGroupCallParticipants | Update.updateGroupCall | Update.updatePeerHistoryTTL | Update.updateChatParticipant | Update.updateChannelParticipant | Update.updateBotStopped | Update.updateNewDiscussionMessage | Update.updateDeleteDiscussionMessages; export namespace Update { export type updateNewMessage = { @@ -2524,6 +2524,17 @@ export namespace Update { stopped: boolean, qts: number }; + + export type updateNewDiscussionMessage = { + _: 'updateNewDiscussionMessage', + message?: Message + }; + + export type updateDeleteDiscussionMessages = { + _: 'updateDeleteDiscussionMessages', + messages?: number[], + channel_id?: number + }; } /** @@ -9619,6 +9630,8 @@ export interface ConstructorDeclMap { 'messageActionChatReturn': MessageAction.messageActionChatReturn, 'messageActionChatJoinedYou': MessageAction.messageActionChatJoinedYou, 'messageActionChatReturnYou': MessageAction.messageActionChatReturnYou, + 'updateNewDiscussionMessage': Update.updateNewDiscussionMessage, + 'updateDeleteDiscussionMessages': Update.updateDeleteDiscussionMessages, } export type InvokeAfterMsg = { diff --git a/src/lib/appManagers/appImManager.ts b/src/lib/appManagers/appImManager.ts index 11c4b866..c0697c54 100644 --- a/src/lib/appManagers/appImManager.ts +++ b/src/lib/appManagers/appImManager.ts @@ -408,7 +408,7 @@ export class AppImManager { const msgIdsByPeer = e; for(const peerId in msgIdsByPeer) { - appSidebarRight.sharedMediaTab.renderNewMessages(+peerId, msgIdsByPeer[peerId]); + appSidebarRight.sharedMediaTab.renderNewMessages(+peerId, Array.from(msgIdsByPeer[peerId])); } }); diff --git a/src/lib/appManagers/appMessagesManager.ts b/src/lib/appManagers/appMessagesManager.ts index db6c8476..9773704f 100644 --- a/src/lib/appManagers/appMessagesManager.ts +++ b/src/lib/appManagers/appMessagesManager.ts @@ -141,6 +141,7 @@ export class AppMessagesManager { [randomId: string]: { peerId: number, tempId: number, + threadId: number, storage: MessagesStorage } } = {}; @@ -169,7 +170,7 @@ export class AppMessagesManager { public migratedToFrom: {[peerId: number]: number} = {}; public newMessagesHandlePromise = 0; - public newMessagesToHandle: {[peerId: string]: number[]} = {}; + public newMessagesToHandle: {[peerId: string]: Set} = {}; public newDialogsHandlePromise = 0; public newDialogsToHandle: {[peerId: string]: {reload: true} | Dialog} = {}; public newUpdatesAfterReloadToHandle: {[peerId: string]: Set} = {}; @@ -1095,8 +1096,10 @@ export class AppMessagesManager { return this.sendFile(peerId, file, o).message; }); - if(options.clearDraft) { + if(options.threadId) { appDraftsManager.syncDraft(peerId, options.threadId); + } else { + appDraftsManager.saveDraft(peerId, options.threadId, null, {notify: true}); } // * test pending @@ -1382,16 +1385,16 @@ export class AppMessagesManager { rootScope.broadcast('scheduled_new', {peerId, mid: messageId}); }, 0); } else { - if(options.threadId && this.threadsStorage[peerId]) { + /* if(options.threadId && this.threadsStorage[peerId]) { delete this.threadsStorage[peerId][options.threadId]; - } - //if(options.threadId) { - const historyStorage = this.getHistoryStorage(peerId/* , options.threadId */); + } */ + if(options.threadId) { + const historyStorage = this.getHistoryStorage(peerId, options.threadId); historyStorage.history.unshift(messageId); - //} + } - /* const historyStorage = this.getHistoryStorage(peerId); - historyStorage.history.unshift(messageId); */ + const historyStorage = this.getHistoryStorage(peerId); + historyStorage.history.unshift(messageId); //if(!options.isGroupedItem) { this.saveMessages([message], {storage, isOutgoing: true}); @@ -1401,11 +1404,20 @@ export class AppMessagesManager { }, 0); } - if(!options.isGroupedItem && options.clearDraft && !options.threadId) { - appDraftsManager.syncDraft(peerId, options.threadId); + if(!options.isGroupedItem && options.clearDraft) { + if(options.threadId) { + appDraftsManager.syncDraft(peerId, options.threadId); + } else { + appDraftsManager.saveDraft(peerId, options.threadId, null, {notify: true}); + } } - this.pendingByRandomId[message.random_id] = {peerId, tempId: messageId, storage}; + this.pendingByRandomId[message.random_id] = { + peerId, + tempId: messageId, + threadId: options.threadId, + storage + }; if(!options.isGroupedItem && message.send) { setTimeout(message.send, 0); @@ -3259,8 +3271,9 @@ export class AppMessagesManager { return this.searchesStorage[peerId][inputFilter]; } - public getSearchCounters(peerId: number, filters: MessagesFilter[]) { - return apiManager.invokeApi('messages.getSearchCounters', { + public getSearchCounters(peerId: number, filters: MessagesFilter[], canCache = true) { + const func = (canCache ? apiManager.invokeApiCacheable : apiManager.invokeApi).bind(apiManager); + return func('messages.getSearchCounters', { peer: appPeersManager.getInputPeerById(peerId), filters }); @@ -3907,13 +3920,16 @@ export class AppMessagesManager { const pendingData = this.pendingByRandomId[randomId]; //this.log('AMM updateMessageID:', update, pendingData); if(pendingData) { - const {peerId, tempId, storage} = pendingData; + const {peerId, tempId, threadId, storage} = pendingData; //const mid = update.id; const mid = this.generateMessageId(update.id); const message = this.getMessageFromStorage(storage, mid); if(!message.deleted) { - const historyStorage = this.getHistoryStorage(peerId); - historyStorage.history.delete(tempId); + [this.getHistoryStorage(peerId), threadId ? this.getHistoryStorage(peerId, threadId) : undefined] + .filter(Boolean) + .forEach(storage => { + storage.history.delete(tempId); + }); this.finalizePendingMessageCallbacks(storage, tempId, mid); } else { @@ -3924,6 +3940,7 @@ export class AppMessagesManager { break; } + case 'updateNewDiscussionMessage': case 'updateNewMessage': case 'updateNewChannelMessage': { const message = update.message as MyMessage; @@ -3931,7 +3948,24 @@ export class AppMessagesManager { const storage = this.getMessagesStorage(peerId); const foundDialog = this.getDialogByPeerId(peerId); - if(!foundDialog.length) { + // * local update + const isLocalThreadUpdate = update._ === 'updateNewDiscussionMessage'; + + // * temporary save the message for info (peerId, reply mids...) + this.saveMessages([message], {storage: {}}); + + const threadKey = this.getThreadKey(message); + const threadId = threadKey ? +threadKey.split('_')[1] : undefined; + if(threadId && !isLocalThreadUpdate && this.threadsStorage[peerId] && this.threadsStorage[peerId][threadId]) { + const update = { + _: 'updateNewDiscussionMessage', + message + } as Update.updateNewDiscussionMessage; + + this.handleUpdate(update); + } + + if(!foundDialog.length && !isLocalThreadUpdate) { let good = true; if(peerId < 0) { const chat = appChatsManager.getChat(-peerId); @@ -3974,8 +4008,11 @@ export class AppMessagesManager { } */ const pendingMessage = this.checkPendingMessage(message); - const historyStorage = this.getHistoryStorage(peerId); - this.updateMessageRepliesIfNeeded(message); + const historyStorage = this.getHistoryStorage(peerId, isLocalThreadUpdate ? threadId : undefined); + + if(!isLocalThreadUpdate) { + this.updateMessageRepliesIfNeeded(message); + } if(historyStorage.history.findSlice(message.mid)) { return false; @@ -3994,7 +4031,7 @@ export class AppMessagesManager { if(historyStorage.count !== null) { historyStorage.count++; } - + if(this.mergeReplyKeyboard(historyStorage, message)) { rootScope.broadcast('history_reply_markup', {peerId}); } @@ -4005,14 +4042,18 @@ export class AppMessagesManager { if(!pendingMessage) { if(this.newMessagesToHandle[peerId] === undefined) { - this.newMessagesToHandle[peerId] = []; + this.newMessagesToHandle[peerId] = new Set(); } - this.newMessagesToHandle[peerId].push(message.mid); + this.newMessagesToHandle[peerId].add(message.mid); if(!this.newMessagesHandlePromise) { this.newMessagesHandlePromise = window.setTimeout(this.handleNewMessages, 0); } } + + if(isLocalThreadUpdate) { + break; + } const dialog = foundDialog[0]; const inboxUnread = !message.pFlags.out && message.pFlags.unread; @@ -4402,16 +4443,33 @@ export class AppMessagesManager { const channelId: number = (update as Update.updateDeleteChannelMessages).channel_id; //const messages = (update as any as Update.updateDeleteChannelMessages).messages; const messages = (update as any as Update.updateDeleteChannelMessages).messages.map(id => this.generateMessageId(id)); - const peerId = channelId ? -channelId : this.getMessageById(messages[0]).peerId; + const peerId: number = channelId ? -channelId : this.getMessageById(messages[0]).peerId; if(!peerId) { break; } + + apiManager.clearCache('messages.getSearchCounters', (params) => { + return appPeersManager.getPeerId(params.peer) === peerId; + }); + + const threadKeys: Set = new Set(); + for(const mid of messages) { + const message = this.getMessageByPeer(peerId, mid); + const threadKey = this.getThreadKey(message); + if(threadKey && this.threadsStorage[peerId] && this.threadsStorage[peerId][+threadKey.split('_')[1]]) { + threadKeys.add(threadKey); + } + } const historyUpdated = this.handleDeletedMessages(peerId, this.getMessagesStorage(peerId), messages); - const historyStorage = this.getHistoryStorage(peerId); - //if(historyStorage !== undefined) { + const threadsStorages = Array.from(threadKeys).map(threadKey => { + const splitted = threadKey.split('_'); + return this.getHistoryStorage(+splitted[0], +splitted[1]); + }); + + [this.getHistoryStorage(peerId)].concat(threadsStorages).forEach(historyStorage => { for(const mid in historyUpdated.msgs) { historyStorage.history.delete(+mid); } @@ -4423,9 +4481,9 @@ export class AppMessagesManager { historyStorage.count = 0; } } + }); - rootScope.broadcast('history_delete', {peerId, msgs: historyUpdated.msgs}); - //} + rootScope.broadcast('history_delete', {peerId, msgs: historyUpdated.msgs}); const foundDialog = this.getDialogByPeerId(peerId)[0]; if(foundDialog) { @@ -4658,9 +4716,8 @@ export class AppMessagesManager { private updateMessageRepliesIfNeeded(threadMessage: MyMessage) { try { // * на всякий случай, скорее всего это не понадобится - if(threadMessage.peerId < 0 && threadMessage.reply_to) { - const threadId = threadMessage.reply_to.reply_to_top_id || threadMessage.reply_to.reply_to_msg_id; - const threadKey = threadMessage.peerId + '_' + threadId; + const threadKey = this.getThreadKey(threadMessage); + if(threadKey) { const repliesKey = this.threadsToReplies[threadKey]; if(repliesKey) { const [peerId, mid] = repliesKey.split('_').map(n => +n); @@ -4673,6 +4730,16 @@ export class AppMessagesManager { } } + private getThreadKey(threadMessage: MyMessage) { + let threadKey = ''; + if(threadMessage.peerId < 0 && threadMessage.reply_to) { + const threadId = threadMessage.reply_to.reply_to_top_id || threadMessage.reply_to.reply_to_msg_id; + threadKey = threadMessage.peerId + '_' + threadId; + } + + return threadKey; + } + public updateMessage(peerId: number, mid: number, broadcastEventName?: 'replies_updated'): Promise { const promise: Promise = this.wrapSingleMessage(peerId, mid, true).then(() => { const message = this.getMessageByPeer(peerId, mid); @@ -4738,11 +4805,15 @@ export class AppMessagesManager { // this.log('pdata', randomID, pendingData) if(pendingData) { - const {peerId, tempId, storage} = pendingData; - const historyStorage = this.getHistoryStorage(peerId); + const {peerId, tempId, threadId, storage} = pendingData; + + [this.getHistoryStorage(peerId), threadId ? this.getHistoryStorage(peerId, threadId) : undefined] + .filter(Boolean) + .forEach(storage => { + storage.history.delete(tempId); + }); // this.log('pending', randomID, historyStorage.pending) - historyStorage.history.delete(tempId); const message = this.getMessageFromStorage(storage, tempId); if(!message.deleted) { @@ -5322,11 +5393,8 @@ export class AppMessagesManager { delete storage[mid]; const peerMessagesToHandle = this.newMessagesToHandle[peerId]; - if(peerMessagesToHandle && peerMessagesToHandle.length) { - const peerMessagesHandlePos = peerMessagesToHandle.indexOf(mid); - if(peerMessagesHandlePos !== -1) { - peerMessagesToHandle.splice(peerMessagesHandlePos); - } + if(peerMessagesToHandle && peerMessagesToHandle.has(mid)) { + peerMessagesToHandle.delete(mid); } } diff --git a/src/lib/rootScope.ts b/src/lib/rootScope.ts index d302e9c4..fbadc32b 100644 --- a/src/lib/rootScope.ts +++ b/src/lib/rootScope.ts @@ -112,7 +112,7 @@ export type BroadcastEvents = { 'language_change': void, }; -class RootScope extends EventListenerBase { +export class RootScope extends EventListenerBase { private _overlayIsActive: boolean = false; public myId = 0; public idle = { @@ -169,3 +169,11 @@ class RootScope extends EventListenerBase { const rootScope = new RootScope(); MOUNT_CLASS_TO.rootScope = rootScope; export default rootScope; + +rootScope.addEventListener('album_edit', (e) => { + +}); + +rootScope.addEventListener<'album_edit'>('album_edit', (e) => { + +}); diff --git a/src/scripts/in/schema_additional_params.json b/src/scripts/in/schema_additional_params.json index eac89a44..35e18f03 100644 --- a/src/scripts/in/schema_additional_params.json +++ b/src/scripts/in/schema_additional_params.json @@ -214,4 +214,17 @@ {"name": "local", "type": "boolean"}, {"name": "appVersion", "type": "string"} ] +}, { + "predicate": "updateNewDiscussionMessage", + "params": [ + {"name": "message", "type": "Message"} + ], + "type": "Update" +}, { + "predicate": "updateDeleteDiscussionMessages", + "params": [ + {"name": "messages", "type": "number[]"}, + {"name": "channel_id", "type": "number"} + ], + "type": "Update" }] \ No newline at end of file diff --git a/src/scss/partials/_checkbox.scss b/src/scss/partials/_checkbox.scss index 03e92f79..7aeccd16 100644 --- a/src/scss/partials/_checkbox.scss +++ b/src/scss/partials/_checkbox.scss @@ -98,7 +98,8 @@ padding-left: 3.3125rem; cursor: pointer; display: inline-block; - height: 24px; + min-height: 24px; + margin-top: 1px; line-height: 26px; user-select: none; transition: .2s opacity; diff --git a/src/scss/partials/_leftSidebar.scss b/src/scss/partials/_leftSidebar.scss index b5971d5e..87e82fb9 100644 --- a/src/scss/partials/_leftSidebar.scss +++ b/src/scss/partials/_leftSidebar.scss @@ -893,6 +893,14 @@ .general-settings-container { user-select: none; + + .sidebar-left-section { + padding-bottom: 0; + } + + .sidebar-left-section:last-child { + padding-bottom: .5rem; + } } .two-step-verification { diff --git a/src/scss/partials/_profile.scss b/src/scss/partials/_profile.scss index 16381be6..3b298602 100644 --- a/src/scss/partials/_profile.scss +++ b/src/scss/partials/_profile.scss @@ -174,6 +174,12 @@ top: -12px; } } */ + + &.search-empty { + .gradient-delimiter { + display: none; + } + } } &-container { diff --git a/src/scss/partials/_rightSidebar.scss b/src/scss/partials/_rightSidebar.scss index b500da36..342bb79c 100644 --- a/src/scss/partials/_rightSidebar.scss +++ b/src/scss/partials/_rightSidebar.scss @@ -301,7 +301,8 @@ .preloader { padding: 0; position: absolute !important; - height: 100%; + top: 100px; + transform: translate(-50%); > svg { height: 50px;