Browse Source

Fix folders reordering with pinned chats

master
Eduard Kuzmenko 3 years ago
parent
commit
a055959137
  1. 2
      src/components/appSelectPeers.ts
  2. 4
      src/components/dialogsContextMenu.ts
  3. 4
      src/components/sidebarLeft/tabs/archivedTab.ts
  4. 2
      src/components/sidebarLeft/tabs/chatFolders.ts
  5. 4
      src/index.ts
  6. 16
      src/layer.d.ts
  7. 115
      src/lib/appManagers/appDialogsManager.ts
  8. 4
      src/lib/appManagers/appMessagesManager.ts
  9. 92
      src/lib/storages/dialogs.ts
  10. 34
      src/lib/storages/filters.ts
  11. 18
      src/scripts/in/schema_additional_params.json
  12. 2
      src/scss/partials/_chat.scss
  13. 23
      src/scss/partials/_chatlist.scss

2
src/components/appSelectPeers.ts

@ -261,7 +261,7 @@ export default class AppSelectPeers {
const pageCount = windowSize.windowH / 72 * 1.25 | 0; const pageCount = windowSize.windowH / 72 * 1.25 | 0;
const tempId = this.getTempId('dialogs'); const tempId = this.getTempId('dialogs');
const promise = appMessagesManager.getConversations(this.query, this.offsetIndex, pageCount, this.folderId); const promise = appMessagesManager.getConversations(this.query, this.offsetIndex, pageCount, this.folderId, true);
this.promise = promise; this.promise = promise;
const value = await promise; const value = await promise;
if(this.tempIds.dialogs !== tempId) { if(this.tempIds.dialogs !== tempId) {

4
src/components/dialogsContextMenu.ts

@ -49,7 +49,7 @@ export default class DialogsContextMenu {
text: 'ChatList.Context.Pin', text: 'ChatList.Context.Pin',
onClick: this.onPinClick, onClick: this.onPinClick,
verify: () => { verify: () => {
const isPinned = this.filterId > 1 ? appMessagesManager.filtersStorage.filters[this.filterId].pinned_peers.includes(this.dialog.peerId) : !!this.dialog.pFlags?.pinned; const isPinned = this.filterId > 1 ? appMessagesManager.filtersStorage.getFilter(this.filterId).pinned_peers.includes(this.dialog.peerId) : !!this.dialog.pFlags?.pinned;
return !isPinned; return !isPinned;
} }
}, { }, {
@ -57,7 +57,7 @@ export default class DialogsContextMenu {
text: 'ChatList.Context.Unpin', text: 'ChatList.Context.Unpin',
onClick: this.onPinClick, onClick: this.onPinClick,
verify: () => { verify: () => {
const isPinned = this.filterId > 1 ? appMessagesManager.filtersStorage.filters[this.filterId].pinned_peers.includes(this.dialog.peerId) : !!this.dialog.pFlags?.pinned; const isPinned = this.filterId > 1 ? appMessagesManager.filtersStorage.getFilter(this.filterId).pinned_peers.includes(this.dialog.peerId) : !!this.dialog.pFlags?.pinned;
return isPinned; return isPinned;
} }
}, { }, {

4
src/components/sidebarLeft/tabs/archivedTab.ts

@ -34,7 +34,7 @@ export default class AppArchivedTab extends SliderSuperTab {
} }
this.wasFilterId = appDialogsManager.filterId; this.wasFilterId = appDialogsManager.filterId;
appDialogsManager.filterId = AppArchivedTab.filterId; appDialogsManager.setFilterId(AppArchivedTab.filterId);
appDialogsManager.onTabChange(); appDialogsManager.onTabChange();
} }
@ -44,7 +44,7 @@ export default class AppArchivedTab extends SliderSuperTab {
} }
onClose() { onClose() {
appDialogsManager.filterId = this.wasFilterId; appDialogsManager.setFilterId(this.wasFilterId);
appDialogsManager.onTabChange(); appDialogsManager.onTabChange();
} }

2
src/components/sidebarLeft/tabs/chatFolders.ts

@ -97,7 +97,7 @@ export default class AppChatFoldersTab extends SliderSuperTab {
const filterId = filter.id; const filterId = filter.id;
if(!this.filtersRendered.hasOwnProperty(filter.id)) { if(!this.filtersRendered.hasOwnProperty(filter.id)) {
attachClickEvent(row.container, () => { attachClickEvent(row.container, () => {
new AppEditFolderTab(this.slider).open(appMessagesManager.filtersStorage.filters[filterId]); new AppEditFolderTab(this.slider).open(appMessagesManager.filtersStorage.getFilter(filterId));
}, {listenerSetter: this.listenerSetter}); }, {listenerSetter: this.listenerSetter});
} }

4
src/index.ts

@ -169,10 +169,12 @@ console.timeEnd('get storage1'); */
document.documentElement.classList.add('is-safari'); document.documentElement.classList.add('is-safari');
} }
document.documentElement.classList.add('is-mac', 'emoji-supported'); document.documentElement.classList.add('emoji-supported');
if(userAgent.isAppleMobile) { if(userAgent.isAppleMobile) {
document.documentElement.classList.add('is-ios'); document.documentElement.classList.add('is-ios');
} else {
document.documentElement.classList.add('is-mac');
} }
} else if(userAgent.isAndroid) { } else if(userAgent.isAndroid) {
document.documentElement.classList.add('is-android'); document.documentElement.classList.add('is-android');

16
src/layer.d.ts vendored

@ -1239,6 +1239,17 @@ export namespace Dialog {
draft?: DraftMessage, draft?: DraftMessage,
folder_id?: number, folder_id?: number,
index?: number, index?: number,
index_0?: number,
index_1?: number,
index_2?: number,
index_3?: number,
index_4?: number,
index_5?: number,
index_6?: number,
index_7?: number,
index_8?: number,
index_9?: number,
index_10?: number,
peerId?: number, peerId?: number,
topMessage?: any, topMessage?: any,
migratedTo?: number migratedTo?: number
@ -8092,7 +8103,10 @@ export namespace DialogFilter {
emoticon?: string, emoticon?: string,
pinned_peers: Array<InputPeer>, pinned_peers: Array<InputPeer>,
include_peers: Array<InputPeer>, include_peers: Array<InputPeer>,
exclude_peers: Array<InputPeer> exclude_peers: Array<InputPeer>,
orderIndex?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10,
peerId?: number,
folder_id?: number
}; };
} }

115
src/lib/appManagers/appDialogsManager.ts

@ -20,7 +20,7 @@ import apiUpdatesManager from "./apiUpdatesManager";
import appPeersManager from './appPeersManager'; import appPeersManager from './appPeersManager';
import appImManager from "./appImManager"; import appImManager from "./appImManager";
import appMessagesManager, { Dialog } from "./appMessagesManager"; import appMessagesManager, { Dialog } from "./appMessagesManager";
import {MyDialogFilter as DialogFilter} from "../storages/filters"; import {MyDialogFilter as DialogFilter, MyDialogFilter} from "../storages/filters";
import appStateManager, { State } from "./appStateManager"; import appStateManager, { State } from "./appStateManager";
import appUsersManager from "./appUsersManager"; import appUsersManager from "./appUsersManager";
import Button from "../../components/button"; import Button from "../../components/button";
@ -33,7 +33,7 @@ import I18n, { FormatterArguments, i18n, LangPackKey, _i18n } from "../langPack"
import findUpTag from "../../helpers/dom/findUpTag"; import findUpTag from "../../helpers/dom/findUpTag";
import { LazyLoadQueueIntersector } from "../../components/lazyLoadQueue"; import { LazyLoadQueueIntersector } from "../../components/lazyLoadQueue";
import lottieLoader from "../lottieLoader"; import lottieLoader from "../lottieLoader";
import { wrapLocalSticker } from "../../components/wrappers"; import { wrapLocalSticker, wrapPhoto } from "../../components/wrappers";
import AppEditFolderTab from "../../components/sidebarLeft/tabs/editFolder"; import AppEditFolderTab from "../../components/sidebarLeft/tabs/editFolder";
import appSidebarLeft, { SettingSection } from "../../components/sidebarLeft"; import appSidebarLeft, { SettingSection } from "../../components/sidebarLeft";
import { attachClickEvent } from "../../helpers/dom/clickEvent"; import { attachClickEvent } from "../../helpers/dom/clickEvent";
@ -48,6 +48,8 @@ import { isTouchSupported } from "../../helpers/touchSupport";
import handleTabSwipe from "../../helpers/dom/handleTabSwipe"; import handleTabSwipe from "../../helpers/dom/handleTabSwipe";
import windowSize from "../../helpers/windowSize"; import windowSize from "../../helpers/windowSize";
import isInDOM from "../../helpers/dom/isInDOM"; import isInDOM from "../../helpers/dom/isInDOM";
import appPhotosManager from "./appPhotosManager";
import DialogsStorage from "../storages/dialogs";
export type DialogDom = { export type DialogDom = {
avatarEl: AvatarElement, avatarEl: AvatarElement,
@ -61,7 +63,7 @@ export type DialogDom = {
lastMessageSpan: HTMLSpanElement, lastMessageSpan: HTMLSpanElement,
containerEl: HTMLElement, containerEl: HTMLElement,
listEl: HTMLLIElement, listEl: HTMLLIElement,
messageEl: HTMLElement subtitleEl: HTMLElement
}; };
//const testScroll = false; //const testScroll = false;
@ -116,6 +118,8 @@ export class AppDialogsManager {
private loadContacts: () => void; private loadContacts: () => void;
private processContact: (peerId: number) => void; private processContact: (peerId: number) => void;
private indexKey: ReturnType<DialogsStorage['getDialogIndexKey']>;
constructor() { constructor() {
this.chatsPreloader = putPreloader(null, true); this.chatsPreloader = putPreloader(null, true);
@ -156,7 +160,7 @@ export class AppDialogsManager {
}); });
} }
this.filterId = 0; this.setFilterId(0);
this.addFilter({ this.addFilter({
id: this.filterId, id: this.filterId,
title: '', title: '',
@ -207,7 +211,7 @@ export class AppDialogsManager {
const dialog = appMessagesManager.getDialogOnly(peerId); const dialog = appMessagesManager.getDialogOnly(peerId);
if(dialog) { if(dialog) {
this.setLastMessage(dialog); this.setLastMessage(dialog);
this.validateForFilter(); this.validateDialogForFilter(dialog);
this.setFiltersUnreadCount(); this.setFiltersUnreadCount();
} }
}); });
@ -220,9 +224,10 @@ export class AppDialogsManager {
if(this.processContact) { if(this.processContact) {
this.processContact(+id); this.processContact(+id);
} }
this.validateDialogForFilter(dialog);
} }
this.validateForFilter();
this.setFiltersUnreadCount(); this.setFiltersUnreadCount();
}); });
@ -239,7 +244,7 @@ export class AppDialogsManager {
const dialog = appMessagesManager.getDialogOnly(peerId); const dialog = appMessagesManager.getDialogOnly(peerId);
if(dialog) { if(dialog) {
this.setUnreadMessages(dialog); this.setUnreadMessages(dialog);
this.validateForFilter(); this.validateDialogForFilter(dialog);
this.setFiltersUnreadCount(); this.setFiltersUnreadCount();
} }
}); });
@ -283,7 +288,7 @@ export class AppDialogsManager {
} else if(filter.id === this.filterId) { // это нет тут смысла вызывать, так как будет dialogs_multiupdate } else if(filter.id === this.filterId) { // это нет тут смысла вызывать, так как будет dialogs_multiupdate
//this.validateForFilter(); //this.validateForFilter();
const folder = appMessagesManager.dialogsStorage.getFolder(filter.id); const folder = appMessagesManager.dialogsStorage.getFolder(filter.id);
this.validateForFilter(); this.validateListForFilter();
for(let i = 0, length = folder.length; i < length; ++i) { for(let i = 0, length = folder.length; i < length; ++i) {
const dialog = folder[i]; const dialog = folder[i];
this.updateDialog(dialog); this.updateDialog(dialog);
@ -318,13 +323,15 @@ export class AppDialogsManager {
rootScope.addEventListener('filter_order', (order) => { rootScope.addEventListener('filter_order', (order) => {
const containerToAppend = this.folders.menu as HTMLElement; const containerToAppend = this.folders.menu as HTMLElement;
order.forEach((filterId) => { order.forEach((filterId) => {
const filter = appMessagesManager.filtersStorage.filters[filterId]; const filter = appMessagesManager.filtersStorage.getFilter(filterId);
const renderedFilter = this.filtersRendered[filterId]; const renderedFilter = this.filtersRendered[filterId];
positionElementByIndex(renderedFilter.menu, containerToAppend, filter.orderIndex); positionElementByIndex(renderedFilter.menu, containerToAppend, filter.orderIndex);
positionElementByIndex(renderedFilter.container, this.folders.container, filter.orderIndex); positionElementByIndex(renderedFilter.container, this.folders.container, filter.orderIndex);
}); });
this.indexKey = appMessagesManager.dialogsStorage.getDialogIndexKey(this.filterId);
/* if(this.filterId) { /* if(this.filterId) {
const tabIndex = order.indexOf(this.filterId) + 1; const tabIndex = order.indexOf(this.filterId) + 1;
selectTab.prevId = tabIndex; selectTab.prevId = tabIndex;
@ -367,7 +374,7 @@ export class AppDialogsManager {
clearPromises.push(storage.clear()); clearPromises.push(storage.clear());
} */ } */
this.validateForFilter(); this.validateListForFilter();
this.onStateLoaded(state); this.onStateLoaded(state);
})//, 5000); })//, 5000);
@ -385,7 +392,7 @@ export class AppDialogsManager {
if(this.filterId === id) return; if(this.filterId === id) return;
this.chatLists[id].innerHTML = ''; this.chatLists[id].innerHTML = '';
this.filterId = id; this.setFilterId(id);
this.onTabChange(); this.onTabChange();
}, () => { }, () => {
for(const folderId in this.chatLists) { for(const folderId in this.chatLists) {
@ -429,6 +436,11 @@ export class AppDialogsManager {
}, 200); }, 200);
} }
public setFilterId(filterId: number) {
this.filterId = filterId;
this.indexKey = appMessagesManager.dialogsStorage ? appMessagesManager.dialogsStorage.getDialogIndexKey(this.filterId) : 'index';
}
private async onStateLoaded(state: State) { private async onStateLoaded(state: State) {
appNotificationsManager.getNotifyPeerTypeSettings(); appNotificationsManager.getNotifyPeerTypeSettings();
@ -478,7 +490,7 @@ export class AppDialogsManager {
return true; return true;
} }
const index = dialog.index; const index = dialog[this.indexKey];
return (!topOffset.index || index <= topOffset.index) && (!bottomOffset.index || index >= bottomOffset.index); return (!topOffset.index || index <= topOffset.index) && (!bottomOffset.index || index >= bottomOffset.index);
} }
@ -587,7 +599,7 @@ export class AppDialogsManager {
/** /**
* Удалит неподходящие чаты из списка, но не добавит их(!) * Удалит неподходящие чаты из списка, но не добавит их(!)
*/ */
private validateForFilter() { private validateListForFilter() {
// !WARNING, возможно это было зачем-то, но комментарий исправил архивирование // !WARNING, возможно это было зачем-то, но комментарий исправил архивирование
//if(this.filterId === 0) return; //if(this.filterId === 0) return;
@ -602,6 +614,23 @@ export class AppDialogsManager {
} }
} }
/**
* Удалит неподходящие чат из списка, но не добавит его(!)
*/
private validateDialogForFilter(dialog: Dialog, filter?: MyDialogFilter) {
if(this.filterId <= 1 || !this.doms[dialog.peerId]) {
return;
}
if(!filter) {
filter = appMessagesManager.filtersStorage.getFilter(this.filterId);
}
if(!appMessagesManager.filtersStorage.testDialogForFilter(dialog, filter)) {
this.deleteDialog(dialog.peerId);
}
}
public generateScrollable(list: HTMLUListElement, filterId: number) { public generateScrollable(list: HTMLUListElement, filterId: number) {
const scrollable = new Scrollable(null, 'CL', 500); const scrollable = new Scrollable(null, 'CL', 500);
scrollable.container.addEventListener('scroll', this.onChatsRegularScroll); scrollable.container.addEventListener('scroll', this.onChatsRegularScroll);
@ -705,11 +734,11 @@ export class AppDialogsManager {
const {index: currentOffsetIndex} = this.getOffsetIndex(side); const {index: currentOffsetIndex} = this.getOffsetIndex(side);
if(currentOffsetIndex) { if(currentOffsetIndex) {
if(side === 'top') { if(side === 'top') {
const storage = appMessagesManager.dialogsStorage.getFolder(filterId); const storage = appMessagesManager.dialogsStorage.getFolder(filterId, true);
const index = storage.findIndex(dialog => dialog.index <= currentOffsetIndex); const index = storage.findIndex(dialog => dialog[this.indexKey] <= currentOffsetIndex);
const needIndex = Math.max(0, index - loadCount); const needIndex = Math.max(0, index - loadCount);
loadCount = index - needIndex; loadCount = index - needIndex;
offsetIndex = storage[needIndex].index + 1; offsetIndex = storage[needIndex][this.indexKey] + 1;
} else { } else {
offsetIndex = currentOffsetIndex; offsetIndex = currentOffsetIndex;
} }
@ -721,7 +750,7 @@ export class AppDialogsManager {
//console.time('getDialogs time'); //console.time('getDialogs time');
const getConversationPromise = (this.filterId > 1 ? appUsersManager.getContacts() as Promise<any> : Promise.resolve()).then(() => { const getConversationPromise = (this.filterId > 1 ? appUsersManager.getContacts() as Promise<any> : Promise.resolve()).then(() => {
return appMessagesManager.getConversations('', offsetIndex, loadCount, filterId); return appMessagesManager.getConversations('', offsetIndex, loadCount, filterId, true);
}); });
const result = await getConversationPromise; const result = await getConversationPromise;
@ -742,7 +771,7 @@ export class AppDialogsManager {
} }
} else { } else {
const storage = appMessagesManager.dialogsStorage.getFolder(filterId); const storage = appMessagesManager.dialogsStorage.getFolder(filterId);
if(!result.dialogs.length || (storage.length && storage[0].index < offsetIndex)) { if(!result.dialogs.length || (storage.length && storage[0][this.indexKey] < offsetIndex)) {
this.scroll.loadedAll[side] = true; this.scroll.loadedAll[side] = true;
} }
} }
@ -760,7 +789,7 @@ export class AppDialogsManager {
const offsetDialog = result.dialogs[side === 'top' ? 0 : result.dialogs.length - 1]; const offsetDialog = result.dialogs[side === 'top' ? 0 : result.dialogs.length - 1];
if(offsetDialog) { if(offsetDialog) {
this.offsets[side] = offsetDialog.index; this.offsets[side] = offsetDialog[this.indexKey];
} }
this.onListLengthChange(); this.onListLengthChange();
@ -887,7 +916,7 @@ export class AppDialogsManager {
}); });
attachClickEvent(button, () => { attachClickEvent(button, () => {
new AppEditFolderTab(appSidebarLeft).open(appMessagesManager.filtersStorage.filters[this.filterId]); new AppEditFolderTab(appSidebarLeft).open(appMessagesManager.filtersStorage.getFilter(this.filterId));
}); });
placeholderContainer.append(button); placeholderContainer.append(button);
@ -1079,8 +1108,8 @@ export class AppDialogsManager {
const firstDialog = this.getDialogFromElement(this.chatList.firstElementChild as HTMLElement); const firstDialog = this.getDialogFromElement(this.chatList.firstElementChild as HTMLElement);
const lastDialog = this.getDialogFromElement(this.chatList.lastElementChild as HTMLElement); const lastDialog = this.getDialogFromElement(this.chatList.lastElementChild as HTMLElement);
this.offsets.top = firstDialog.index; this.offsets.top = firstDialog[this.indexKey];
this.offsets.bottom = lastDialog.index; this.offsets.bottom = lastDialog[this.indexKey];
} }
private getDialogFromElement(element: HTMLElement) { private getDialogFromElement(element: HTMLElement) {
@ -1196,7 +1225,7 @@ export class AppDialogsManager {
const currentOrder = (Array.from(this.chatList.children) as HTMLElement[]).map(el => +el.dataset.peerId); const currentOrder = (Array.from(this.chatList.children) as HTMLElement[]).map(el => +el.dataset.peerId);
const {index} = this.getOffsetIndex('top'); const {index} = this.getOffsetIndex('top');
const pos = dialogs.findIndex(dialog => dialog.index <= index); const pos = dialogs.findIndex(dialog => dialog[this.indexKey] <= index);
const offset = Math.max(0, pos); const offset = Math.max(0, pos);
dialogs.forEach((dialog, index) => { dialogs.forEach((dialog, index) => {
@ -1267,6 +1296,28 @@ export class AppDialogsManager {
} else if(!lastMessage.deleted) { } else if(!lastMessage.deleted) {
fragment = appMessagesManager.wrapMessageForReply(lastMessage); fragment = appMessagesManager.wrapMessageForReply(lastMessage);
} }
/* if(!lastMessage.deleted && !draftMessage) {
const photo = lastMessage.media?.photo;
if(photo) {
const div = document.createElement('div');
div.classList.add('dialog-subtitle-media');
const size = appPhotosManager.choosePhotoSize(photo, 20, 20);
wrapPhoto({
photo,
message: lastMessage,
container: div,
withoutPreloader: true,
size
});
fragment.prepend(div);
// dom.subtitleEl.prepend(div);
}
} */
replaceContent(dom.lastMessageSpan, fragment); replaceContent(dom.lastMessageSpan, fragment);
/* if(lastMessage.from_id === auth.id) { // You: */ /* if(lastMessage.from_id === auth.id) { // You: */
@ -1344,7 +1395,7 @@ export class AppDialogsManager {
} }
} else dom.statusSpan.classList.remove('tgico-check', 'tgico-checks'); } else dom.statusSpan.classList.remove('tgico-check', 'tgico-checks');
const filter = appMessagesManager.filtersStorage.filters[this.filterId]; const filter = appMessagesManager.filtersStorage.getFilter(this.filterId);
let isPinned: boolean; let isPinned: boolean;
if(filter) { if(filter) {
isPinned = filter.pinned_peers.indexOf(dialog.peerId) !== -1; isPinned = filter.pinned_peers.indexOf(dialog.peerId) !== -1;
@ -1357,7 +1408,7 @@ export class AppDialogsManager {
const isUnreadBadgeMounted = isInDOM(dom.unreadBadge); const isUnreadBadgeMounted = isInDOM(dom.unreadBadge);
if(hasUnreadBadge && !isUnreadBadgeMounted) { if(hasUnreadBadge && !isUnreadBadgeMounted) {
dom.messageEl.append(dom.unreadBadge); dom.subtitleEl.append(dom.unreadBadge);
} }
const hasMentionsBadge = dialog.unread_mentions_count > 1; const hasMentionsBadge = dialog.unread_mentions_count > 1;
@ -1367,7 +1418,7 @@ export class AppDialogsManager {
dom.mentionsBadge = document.createElement('div'); dom.mentionsBadge = document.createElement('div');
dom.mentionsBadge.className = 'dialog-subtitle-badge badge badge-24 mention mention-badge'; dom.mentionsBadge.className = 'dialog-subtitle-badge badge badge-24 mention mention-badge';
dom.mentionsBadge.innerText = '@'; dom.mentionsBadge.innerText = '@';
dom.messageEl.insertBefore(dom.mentionsBadge, dom.lastMessageSpan.nextSibling); dom.subtitleEl.insertBefore(dom.mentionsBadge, dom.lastMessageSpan.nextSibling);
} }
} }
@ -1461,7 +1512,7 @@ export class AppDialogsManager {
if(container === undefined) { if(container === undefined) {
if(this.doms[peerId] || dialog.migratedTo !== undefined) return; if(this.doms[peerId] || dialog.migratedTo !== undefined) return;
const filter = appMessagesManager.filtersStorage.filters[this.filterId]; const filter = appMessagesManager.filtersStorage.getFilter(this.filterId);
if((filter && !appMessagesManager.filtersStorage.testDialogForFilter(dialog, filter)) || (!filter && this.filterId !== dialog.folder_id)) { if((filter && !appMessagesManager.filtersStorage.testDialogForFilter(dialog, filter)) || (!filter && this.filterId !== dialog.folder_id)) {
return; return;
} }
@ -1552,11 +1603,11 @@ export class AppDialogsManager {
rightSpan.append(statusSpan, lastTimeSpan); rightSpan.append(statusSpan, lastTimeSpan);
titleP.append(titleSpanContainer, rightSpan); titleP.append(titleSpanContainer, rightSpan);
const messageEl = document.createElement('p'); const subtitleEl = document.createElement('p');
messageEl.classList.add('dialog-subtitle'); subtitleEl.classList.add('dialog-subtitle');
messageEl.append(span); subtitleEl.append(span);
captionDiv.append(titleP, messageEl); captionDiv.append(titleP, subtitleEl);
const dom: DialogDom = { const dom: DialogDom = {
avatarEl, avatarEl,
@ -1569,7 +1620,7 @@ export class AppDialogsManager {
lastMessageSpan: span, lastMessageSpan: span,
containerEl: li, containerEl: li,
listEl: li, listEl: li,
messageEl subtitleEl
}; };
/* let good = false; /* let good = false;

4
src/lib/appManagers/appMessagesManager.ts

@ -1653,8 +1653,8 @@ export class AppMessagesManager {
return outDialogs; return outDialogs;
} }
public getConversations(query = '', offsetIndex?: number, limit = 20, folderId = 0) { public getConversations(query = '', offsetIndex?: number, limit = 20, folderId = 0, skipMigrated?: boolean) {
return this.dialogsStorage.getDialogs(query, offsetIndex, limit, folderId); return this.dialogsStorage.getDialogs(query, offsetIndex, limit, folderId, skipMigrated);
} }
public getReadMaxIdIfUnread(peerId: number, threadId?: number) { public getReadMaxIdIfUnread(peerId: number, threadId?: number) {

92
src/lib/storages/dialogs.ts

@ -28,12 +28,24 @@ import { safeReplaceObject } from "../../helpers/object";
import { AppStateManager } from "../appManagers/appStateManager"; import { AppStateManager } from "../appManagers/appStateManager";
import { SliceEnd } from "../../helpers/slicedArray"; import { SliceEnd } from "../../helpers/slicedArray";
export type FolderDialog = {
dialog: Dialog,
index: number
};
export type Folder = {
dialogs: FolderDialog[],
count?: number
};
export default class DialogsStorage { export default class DialogsStorage {
private storage: AppStateManager['storages']['dialogs']; private storage: AppStateManager['storages']['dialogs'];
private dialogs: {[peerId: string]: Dialog}; private dialogs: {[peerId: string]: Dialog};
public byFolders: {[folderId: number]: Dialog[]}; public byFolders: {[folderId: number]: Dialog[]};
// public folders: {[folderId: number]: Folder} = {};
private allDialogsLoaded: {[folder_id: number]: boolean}; private allDialogsLoaded: {[folder_id: number]: boolean};
private dialogsOffsetDate: {[folder_id: number]: number}; private dialogsOffsetDate: {[folder_id: number]: number};
private pinnedOrders: {[folder_id: number]: number[]}; private pinnedOrders: {[folder_id: number]: number[]};
@ -167,9 +179,11 @@ export default class DialogsStorage {
return skipMigrated ? arr.filter(dialog => dialog.migratedTo === undefined) : arr; return skipMigrated ? arr.filter(dialog => dialog.migratedTo === undefined) : arr;
} }
const dialogs: {dialog: Dialog, index: number}[] = []; // const dialogs: {dialog: Dialog, index: number}[] = [];
const filter = this.appMessagesManager.filtersStorage.filters[id]; const dialogs: Dialog[] = [];
const filter = this.appMessagesManager.filtersStorage.getFilter(id);
const indexStr = this.getDialogIndexKey(id);
for(const peerId in this.dialogs) { for(const peerId in this.dialogs) {
const dialog = this.dialogs[peerId]; const dialog = this.dialogs[peerId];
if(this.appMessagesManager.filtersStorage.testDialogForFilter(dialog, filter) && (!skipMigrated || dialog.migratedTo === undefined)) { if(this.appMessagesManager.filtersStorage.testDialogForFilter(dialog, filter) && (!skipMigrated || dialog.migratedTo === undefined)) {
@ -177,19 +191,22 @@ export default class DialogsStorage {
const pinnedIndex = filter.pinned_peers.indexOf(dialog.peerId); const pinnedIndex = filter.pinned_peers.indexOf(dialog.peerId);
if(pinnedIndex !== -1) { if(pinnedIndex !== -1) {
index = this.generateDialogIndex(this.generateDialogPinnedDateByIndex(filter.pinned_peers.length - 1 - pinnedIndex)); index = this.generateDialogIndex(this.generateDialogPinnedDateByIndex(filter.pinned_peers.length - 1 - pinnedIndex), true);
} else if(dialog.pFlags?.pinned) { } else if(dialog.pFlags?.pinned) {
index = this.generateIndexForDialog(dialog, true); index = this.generateIndexForDialog(dialog, true);
} else { } else {
index = dialog.index; index = dialog.index;
} }
dialogs.push({dialog, index}); dialog[indexStr] = index;
insertInDescendSortedArray(dialogs, dialog, indexStr, -1);
} }
} }
dialogs.sort((a, b) => b.index - a.index); return dialogs;
return dialogs.map(d => d.dialog);
// dialogs.sort((a, b) => b.index - a.index);
// return dialogs.map(d => d.dialog);
} }
public getDialog(peerId: number, folderId?: number, skipMigrated = true): [Dialog, number] | [] { public getDialog(peerId: number, folderId?: number, skipMigrated = true): [Dialog, number] | [] {
@ -231,28 +248,29 @@ export default class DialogsStorage {
k - m; k - m;
65536 65536
*/ */
public generateDialogIndex(date?: number) { public generateDialogIndex(date?: number, isPinned?: boolean) {
if(date === undefined) { if(date === undefined) {
date = tsNow(true) + this.serverTimeManager.serverTimeOffset; date = tsNow(true) + this.serverTimeManager.serverTimeOffset;
} }
return (date * 0x10000) + ((++this.dialogsNum) & 0xFFFF); return (date * 0x10000) + (isPinned ? 0 : ((++this.dialogsNum) & 0xFFFF));
} }
public generateIndexForDialog(dialog: Dialog, justReturn = false, message?: MyMessage) { public generateIndexForDialog(dialog: Dialog, justReturn = false, message?: MyMessage) {
const channelId = this.appPeersManager.isChannel(dialog.peerId) ? -dialog.peerId : 0; let topDate = 0, isPinned: boolean;
let topDate = 0;
if(dialog.pFlags.pinned && !justReturn) { if(dialog.pFlags.pinned && !justReturn) {
topDate = this.generateDialogPinnedDate(dialog); topDate = this.generateDialogPinnedDate(dialog);
isPinned = true;
} else { } else {
if(!message) { if(!message) {
message = this.appMessagesManager.getMessageByPeer(dialog.peerId, dialog.top_message); message = this.appMessagesManager.getMessageByPeer(dialog.peerId, dialog.top_message);
} }
topDate = (message as Message.message).date || topDate; topDate = (message as Message.message).date || topDate;
const channelId = this.appPeersManager.isChannel(dialog.peerId) ? -dialog.peerId : 0;
if(channelId) { if(channelId) {
const channel = this.appChatsManager.getChat(channelId); const channel: Chat.channel = this.appChatsManager.getChat(channelId);
if(!topDate || (channel.date && channel.date > topDate)) { if(!topDate || (channel.date && channel.date > topDate)) {
topDate = channel.date; topDate = channel.date;
} }
@ -264,10 +282,10 @@ export default class DialogsStorage {
} }
if(!topDate) { if(!topDate) {
topDate = Date.now() / 1000; topDate = tsNow(true);
} }
const index = this.generateDialogIndex(topDate); const index = this.generateDialogIndex(topDate, isPinned);
if(justReturn) return index; if(justReturn) return index;
dialog.index = index; dialog.index = index;
} }
@ -338,6 +356,14 @@ export default class DialogsStorage {
}); });
this.appStateManager.requestPeer(dialog.peerId, 'dialog_' + dialog.peerId, 1); this.appStateManager.requestPeer(dialog.peerId, 'dialog_' + dialog.peerId, 1);
/* for(let id in this.appMessagesManager.filtersStorage.filters) {
const filter = this.appMessagesManager.filtersStorage.filters[id];
if(this.appMessagesManager.filtersStorage.testDialogForFilter(dialog, filter)) {
}
} */
} }
public pushDialog(dialog: Dialog, offsetDate?: number) { public pushDialog(dialog: Dialog, offsetDate?: number) {
@ -397,7 +423,7 @@ export default class DialogsStorage {
this.appChatsManager.saveApiChats(dialogsResult.chats); this.appChatsManager.saveApiChats(dialogsResult.chats);
this.appMessagesManager.saveMessages(dialogsResult.messages); this.appMessagesManager.saveMessages(dialogsResult.messages);
this.appMessagesManager.log('applyConversation', dialogsResult); // this.appMessagesManager.log('applyConversation', dialogsResult);
const updatedDialogs: {[peerId: number]: Dialog} = {}; const updatedDialogs: {[peerId: number]: Dialog} = {};
(dialogsResult.dialogs as Dialog[]).forEach((dialog) => { (dialogsResult.dialogs as Dialog[]).forEach((dialog) => {
@ -565,9 +591,19 @@ export default class DialogsStorage {
this.pushDialog(dialog, saveOffset && message.date); this.pushDialog(dialog, saveOffset && message.date);
} }
public getDialogs(query = '', offsetIndex?: number, limit = 20, folderId = 0) { public getDialogIndexKey(filterId: number) {
const indexStr = filterId > 1 ?
`index_${this.appMessagesManager.filtersStorage.getFilter(filterId).orderIndex}` as const :
'index' as const;
return indexStr;
}
public getDialogs(query = '', offsetIndex?: number, limit = 20, folderId = 0, skipMigrated = false) {
const realFolderId = folderId > 1 ? 0 : folderId; const realFolderId = folderId > 1 ? 0 : folderId;
let curDialogStorage = this.getFolder(folderId, false); let curDialogStorage = this.getFolder(folderId, skipMigrated);
const indexStr = this.getDialogIndexKey(folderId);
if(query) { if(query) {
if(!limit || this.cachedResults.query !== query || this.cachedResults.folderId !== folderId) { if(!limit || this.cachedResults.query !== query || this.cachedResults.folderId !== folderId) {
@ -576,18 +612,17 @@ export default class DialogsStorage {
const results = this.dialogsIndex.search(query); const results = this.dialogsIndex.search(query);
this.cachedResults.dialogs = []; const dialogs: Dialog[] = [];
for(const peerId in this.dialogs) { for(const peerId in this.dialogs) {
const dialog = this.dialogs[peerId]; const dialog = this.dialogs[peerId];
if(results.has(dialog.peerId) && dialog.folder_id === folderId) { if(results.has(dialog.peerId) && dialog.folder_id === folderId) {
this.cachedResults.dialogs.push(dialog); dialogs.push(dialog);
} }
} }
this.cachedResults.dialogs.sort((d1, d2) => d2.index - d1.index); dialogs.sort((d1, d2) => d2[indexStr] - d1[indexStr]);
this.cachedResults.dialogs = dialogs;
this.cachedResults.count = this.cachedResults.dialogs.length; this.cachedResults.count = dialogs.length;
} }
curDialogStorage = this.cachedResults.dialogs; curDialogStorage = this.cachedResults.dialogs;
@ -597,8 +632,8 @@ export default class DialogsStorage {
let offset = 0; let offset = 0;
if(offsetIndex > 0) { if(offsetIndex > 0) {
for(; offset < curDialogStorage.length; offset++) { for(let length = curDialogStorage.length; offset < length; ++offset) {
if(offsetIndex > curDialogStorage[offset].index) { if(offsetIndex > curDialogStorage[offset][indexStr]) {
break; break;
} }
} }
@ -615,11 +650,14 @@ export default class DialogsStorage {
return this.appMessagesManager.getTopMessages(limit, realFolderId).then(result => { return this.appMessagesManager.getTopMessages(limit, realFolderId).then(result => {
//const curDialogStorage = this[folderId]; //const curDialogStorage = this[folderId];
if(skipMigrated) {
curDialogStorage = this.getFolder(folderId, skipMigrated);
}
offset = 0; offset = 0;
if(offsetIndex > 0) { if(offsetIndex > 0) {
for(; offset < curDialogStorage.length; offset++) { for(let length = curDialogStorage.length; offset < length; ++offset) {
if(offsetIndex > curDialogStorage[offset].index) { if(offsetIndex > curDialogStorage[offset][indexStr]) {
break; break;
} }
} }

34
src/lib/storages/filters.ts

@ -21,8 +21,7 @@ import { AppStateManager } from "../appManagers/appStateManager";
export type MyDialogFilter = Modify<DialogFilter, { export type MyDialogFilter = Modify<DialogFilter, {
pinned_peers: number[], pinned_peers: number[],
include_peers: number[], include_peers: number[],
exclude_peers: number[], exclude_peers: number[]
orderIndex?: number
}>; }>;
// ! because 0 index is 'All Chats' // ! because 0 index is 'All Chats'
@ -51,6 +50,10 @@ export default class FiltersStorage {
if(filter.hasOwnProperty('orderIndex') && filter.orderIndex >= this.orderIndex) { if(filter.hasOwnProperty('orderIndex') && filter.orderIndex >= this.orderIndex) {
this.orderIndex = filter.orderIndex + 1; this.orderIndex = filter.orderIndex + 1;
} }
/* this.appMessagesManager.dialogsStorage.folders[+filterId] = {
dialogs: []
}; */
} }
}); });
@ -114,19 +117,17 @@ export default class FiltersStorage {
}; };
public testDialogForFilter(dialog: Dialog, filter: MyDialogFilter) { public testDialogForFilter(dialog: Dialog, filter: MyDialogFilter) {
const peerId = dialog.peerId;
// exclude_peers // exclude_peers
for(const peerId of filter.exclude_peers) { if(filter.exclude_peers.includes(peerId)) {
if(peerId === dialog.peerId) {
return false; return false;
} }
}
// include_peers // include_peers
for(const peerId of filter.include_peers) { if(filter.include_peers.includes(peerId)) {
if(peerId === dialog.peerId) {
return true; return true;
} }
}
const pFlags = filter.pFlags; const pFlags = filter.pFlags;
@ -142,13 +143,12 @@ export default class FiltersStorage {
// exclude_muted // exclude_muted
if(pFlags.exclude_muted) { if(pFlags.exclude_muted) {
const isMuted = this.appNotificationsManager.isPeerLocalMuted(dialog.peerId); const isMuted = this.appNotificationsManager.isPeerLocalMuted(peerId);
if(isMuted) { if(isMuted) {
return false; return false;
} }
} }
const peerId = dialog.peerId;
if(peerId < 0) { if(peerId < 0) {
// broadcasts // broadcasts
if(pFlags.broadcasts && this.appPeersManager.isBroadcast(peerId)) { if(pFlags.broadcasts && this.appPeersManager.isBroadcast(peerId)) {
@ -161,7 +161,7 @@ export default class FiltersStorage {
} }
} else { } else {
// bots // bots
if(this.appPeersManager.isBot(peerId)) { if(this.appUsersManager.isBot(peerId)) {
return !!pFlags.bots; return !!pFlags.bots;
} }
@ -179,6 +179,14 @@ export default class FiltersStorage {
return false; return false;
} }
public testDialogForFilterId(dialog: Dialog, filterId: number) {
return this.testDialogForFilter(dialog, this.filters[filterId]);
}
public getFilter(filterId: number) {
return this.filters[filterId];
}
public toggleDialogPin(peerId: number, filterId: number) { public toggleDialogPin(peerId: number, filterId: number) {
const filter = this.filters[filterId]; const filter = this.filters[filterId];
@ -195,7 +203,7 @@ export default class FiltersStorage {
} }
public createDialogFilter(filter: MyDialogFilter) { public createDialogFilter(filter: MyDialogFilter) {
let maxId = Math.max(1, ...Object.keys(this.filters).map(i => +i)); const maxId = Math.max(1, ...Object.keys(this.filters).map(i => +i));
filter = copy(filter); filter = copy(filter);
filter.id = maxId + 1; filter.id = maxId + 1;
return this.updateDialogFilter(filter); return this.updateDialogFilter(filter);
@ -293,7 +301,7 @@ export default class FiltersStorage {
this.orderIndex = filter.orderIndex + 1; this.orderIndex = filter.orderIndex + 1;
} }
} else { } else {
filter.orderIndex = this.orderIndex++; filter.orderIndex = this.orderIndex++ as DialogFilter['orderIndex'];
} }
this.appStateManager.pushToState('filters', this.filters); this.appStateManager.pushToState('filters', this.filters);

18
src/scripts/in/schema_additional_params.json

@ -29,6 +29,17 @@
"predicate": "dialog", "predicate": "dialog",
"params": [ "params": [
{"name": "index", "type": "number"}, {"name": "index", "type": "number"},
{"name": "index_0", "type": "number"},
{"name": "index_1", "type": "number"},
{"name": "index_2", "type": "number"},
{"name": "index_3", "type": "number"},
{"name": "index_4", "type": "number"},
{"name": "index_5", "type": "number"},
{"name": "index_6", "type": "number"},
{"name": "index_7", "type": "number"},
{"name": "index_8", "type": "number"},
{"name": "index_9", "type": "number"},
{"name": "index_10", "type": "number"},
{"name": "peerId", "type": "number"}, {"name": "peerId", "type": "number"},
{"name": "topMessage", "type": "any"}, {"name": "topMessage", "type": "any"},
{"name": "migratedTo", "type": "number"} {"name": "migratedTo", "type": "number"}
@ -40,6 +51,13 @@
{"name": "peerId", "type": "number"}, {"name": "peerId", "type": "number"},
{"name": "folder_id", "type": "number"} {"name": "folder_id", "type": "number"}
] ]
}, {
"predicate": "dialogFilter",
"params": [
{"name": "orderIndex", "type": "0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10"},
{"name": "peerId", "type": "number"},
{"name": "folder_id", "type": "number"}
]
}, { }, {
"predicate": "message", "predicate": "message",
"params": [ "params": [

2
src/scss/partials/_chat.scss

@ -1148,7 +1148,7 @@ $chat-helper-size: 36px;
@include respond-to(handhelds) { @include respond-to(handhelds) {
padding: 0 $chat-padding-handhelds; padding: 0 $chat-padding-handhelds;
html.is-mac & { html.is-ios & {
-webkit-user-select: none; -webkit-user-select: none;
-webkit-touch-callout: none; -webkit-touch-callout: none;
} }

23
src/scss/partials/_chatlist.scss

@ -295,6 +295,25 @@ ul.chatlist {
transition: none; transition: none;
} */ } */
} }
&-media {
width: 1.25rem;
height: 1.25rem;
position: relative;
flex: 0 0 auto;
border-radius: .1875rem;
margin-top: -0.1875rem;
margin-right: 0.375rem;
display: inline-block;
vertical-align: middle;
.media-photo {
width: inherit;
height: inherit;
object-fit: cover;
border-radius: inherit;
}
}
} }
} }
@ -423,6 +442,10 @@ ul.chatlist {
.mention { .mention {
padding: 0; padding: 0;
background-color: var(--chatlist-status-color) !important; background-color: var(--chatlist-status-color) !important;
html.is-mac & {
line-height: 22px !important;
}
} }
.mention-badge { .mention-badge {

Loading…
Cancel
Save