Fix bugged chatlist on reload

Fix displaying deleted chat in forward popup
Fix adding dialog in wrong folder position
Fix broken document thumb on forward
Fix broken slider animation from new group
This commit is contained in:
Eduard Kuzmenko 2022-11-19 16:56:25 +04:00
parent aec29e029c
commit 757207a0be
20 changed files with 156 additions and 105 deletions

View File

@ -19,7 +19,7 @@ export function horizontalMenu(
content: HTMLElement,
onClick?: (id: number, tabContent: HTMLDivElement, animate: boolean) => void | boolean | Promise<void | boolean>,
onTransitionEnd?: () => void,
transitionTime = 250,
transitionTime = 200,
scrollableX?: ScrollableX,
listenerSetter?: ListenerSetter
) {

View File

@ -38,12 +38,12 @@ export default class PopupDeleteDialog {
let promise = managers.appChatsManager.leave(peerId.toChatId());
if(flush) {
promise = promise.finally(() => {
promise = promise.then(() => {
return managers.appMessagesManager.flushHistory(peerId);
}) as any;
}
onSelect && onSelect(promise);
onSelect?.(promise);
};
const callbackDelete = (checked: PopupPeerButtonCallbackCheckboxes) => {
@ -59,7 +59,7 @@ export default class PopupDeleteDialog {
}
}
onSelect && onSelect(promise);
onSelect?.(promise);
};
let title: LangPackKey, description: LangPackKey, descriptionArgs: any[], buttons: PopupPeerOptions['buttons'], checkboxes: PopupPeerOptions['checkboxes'];

View File

@ -49,7 +49,7 @@ export default class PopupReportMessages extends PopupPeer {
});
}, {listenerSetter: this.listenerSetter});
this.body.style.margin = '0 -1rem';
// this.body.style.margin = '0 -1rem';
this.buttonsEl.style.marginTop = '.5rem';
this.show();

View File

@ -90,9 +90,7 @@ export class AppSidebarLeft extends SidebarSlider {
this.createTab(AppAddMembersTab).open({
type: 'chat',
skippable: false,
takeOut: (peerIds) => {
this.createTab(AppNewGroupTab).open(peerIds);
},
takeOut: (peerIds) => this.createTab(AppNewGroupTab).open(peerIds),
title: 'GroupAddMembers',
placeholder: 'SendMessageTo'
});

View File

@ -32,18 +32,14 @@ export default class AppAddMembersTab extends SliderSuperTab {
this.nextBtn.addEventListener('click', () => {
const peerIds = this.selector.getSelected().map((sel) => sel.toPeerId());
const result = this.takeOut(peerIds);
if(this.skippable) {
this.takeOut(peerIds);
this.close();
} else {
const promise = this.takeOut(peerIds);
if(promise instanceof Promise) {
this.attachToPromise(promise);
} else if(promise === undefined) {
this.close();
}
} else if(result instanceof Promise) {
this.attachToPromise(result);
} else if(result === undefined) {
this.close();
}
});

View File

@ -130,8 +130,7 @@ export default class AppNewGroupTab extends SliderSuperTab {
}
promise.then((chatId) => {
appSidebarLeft.removeTabFromHistory(this);
appSidebarLeft.selectTab(0);
this.close();
appImManager.setInnerPeer({peerId: chatId.toPeerId(true)});
});

View File

@ -61,6 +61,7 @@ export default class SidebarSlider {
public closeTab = (id?: number | SliderSuperTab, animate?: boolean, isNavigation?: boolean) => {
if(id !== undefined && this.historyTabIds[this.historyTabIds.length - 1] !== id) {
this.removeTabFromHistory(id);
return false;
}
@ -144,8 +145,12 @@ export default class SidebarSlider {
const tab: SliderSuperTab = id instanceof SliderSuperTab ? id : this.tabs.get(id);
if(tab) {
// @ts-ignore
tab.onClose?.();
try {
// @ts-ignore
tab.onClose?.();
} catch(err) {
console.error('tab onClose error', tab);
}
// @ts-ignore
if(tab.onCloseAfterTimeout) {

View File

@ -114,7 +114,7 @@ export default async function wrapDocument({message, withTime, fontWeight, voice
const imgs: (HTMLImageElement | HTMLCanvasElement | HTMLVideoElement)[] = [];
// ! WARNING, use thumbs for check when thumb will be generated for media
if(message.pFlags.is_outgoing && ['photo', 'video'].includes(doc.type)) {
if(message.pFlags.is_outgoing && ['photo', 'video'].includes(doc.type) && cacheContext.url) {
icoDiv.innerHTML = `<img src="${cacheContext.url}">`;
imgs.push(icoDiv.firstElementChild as HTMLImageElement);
} else {

View File

@ -1,5 +1,5 @@
export default function indexOfAndSplice<T>(array: Array<T>, item: T) {
const idx = array.indexOf(item);
const spliced = idx !== -1 && array.splice(idx, 1);
return spliced && spliced[0];
const spliced = idx === -1 ? undefined : array.splice(idx, 1);
return spliced?.[0];
}

View File

@ -59,6 +59,9 @@
<div class="whole" id="auth-pages" style="display: none;">
<div class="scrollable scrollable-y">
<div class="tabs-container auth-pages__container" data-animation="tabs">
<div class="tabs-tab page-signImport">
<div class="container center-align"></div>
</div>
<div class="tabs-tab page-sign">
<div class="container">
<div class="auth-image">
@ -73,9 +76,6 @@
<div class="auth-image"></div>
</div>
</div>
<div class="tabs-tab page-signImport">
<div class="container center-align"></div>
</div>
<div class="tabs-tab page-authCode">
<div class="container center-align">
<div class="auth-image"></div>

View File

@ -131,9 +131,7 @@ export class AppChatsManager extends AppManager {
return;
} */
if((chat as Chat.chat).pFlags === undefined) {
(chat as Chat.chat).pFlags = {};
}
(chat as Chat.chat).pFlags ??= {};
if((chat as Chat.channel).pFlags.min && oldChat !== undefined) {
return;

View File

@ -83,6 +83,7 @@ import filterAsync from '../../helpers/array/filterAsync';
import forEachReverse from '../../helpers/array/forEachReverse';
import indexOfAndSplice from '../../helpers/array/indexOfAndSplice';
import whichChild from '../../helpers/dom/whichChild';
import {MiddlewareHelper} from '../../helpers/middleware';
export const DIALOG_LIST_ELEMENT_TAG = 'A';
@ -236,10 +237,13 @@ export class AppDialogsManager {
private doNotRenderChatList: boolean;
private stateMiddlewareHelper: MiddlewareHelper;
public start() {
const managers = this.managers = getProxiedManagers();
this.contextMenu = new DialogsContextMenu(managers);
this.stateMiddlewareHelper = new MiddlewareHelper();
this.folders.menuScrollContainer = this.folders.menu.parentElement;
@ -682,6 +686,8 @@ export class AppDialogsManager {
}
private async onStateLoaded(state: State) {
this.stateMiddlewareHelper.clean();
const middleware = this.stateMiddlewareHelper.get();
const filtersArr = state.filtersArr;
const haveFilters = filtersArr.length > REAL_FOLDERS.size;
// const filter = filtersArr.find((filter) => filter.id !== FOLDER_ID_ARCHIVE);
@ -701,14 +707,19 @@ export class AppDialogsManager {
this.doNotRenderChatList = true;
const loadDialogsPromise = this.onChatsScroll();
await loadDialogsPromise;
const m = middlewarePromise(middleware);
try {
await m(loadDialogsPromise);
} catch(err) {
}
// show the placeholder before the filters, and then will reset to the default tab again
if(!haveFilters) {
this.selectTab(0, false);
}
addFiltersPromise && await addFiltersPromise;
addFiltersPromise && await m(addFiltersPromise);
// this.folders.menu.children[0].classList.add('active');
this.doNotRenderChatList = undefined;
@ -721,11 +732,11 @@ export class AppDialogsManager {
this.initedListeners = true;
}
haveFilters && this.showFiltersPromise && await this.showFiltersPromise;
haveFilters && this.showFiltersPromise && await m(this.showFiltersPromise);
this.managers.appNotificationsManager.getNotifyPeerTypeSettings();
await (await loadDialogsPromise).renderPromise.catch(noop);
await (await m(loadDialogsPromise)).renderPromise.catch(noop);
this.managers.appMessagesManager.fillConversations();
}
@ -1132,15 +1143,22 @@ export class AppDialogsManager {
}).finally(() => {
if(this.loadDialogsRenderPromise === renderPromise) {
this.loadDialogsRenderPromise = undefined;
this.loadDialogsPromise = undefined;
}
});
this.loadDialogsRenderPromise = renderPromise;
return this.loadDialogsPromise = cachedInfoPromise.then((cached) => ({
cached,
renderPromise
}));
const loadDialogsPromise = this.loadDialogsPromise = cachedInfoPromise.then((cached) => {
return {
cached,
renderPromise
};
}).finally(() => {
if(this.loadDialogsPromise === loadDialogsPromise) {
this.loadDialogsPromise = undefined;
}
});
return loadDialogsPromise;
}
private generateEmptyPlaceholder(options: {

View File

@ -3581,14 +3581,20 @@ export class AppMessagesManager extends AppManager {
let newMaxSeenId = 0;
const map = this.newDialogsToHandle;
for(const [peerId, dialog] of map) {
let good = false;
if(!dialog) {
this.reloadConversation(peerId.toPeerId());
map.delete(peerId);
} else {
} else if(this.dialogsStorage.getDialogOnly(peerId)) { // * dialog can be already dropped
this.dialogsStorage.pushDialog(dialog);
if(!this.appPeersManager.isChannel(peerId.toPeerId())) {
if(!this.appPeersManager.isChannel(peerId)) {
newMaxSeenId = Math.max(newMaxSeenId, dialog.top_message || 0);
}
good = true;
}
if(!good) {
map.delete(peerId);
}
}

View File

@ -10,6 +10,7 @@ import assumeType from '../../helpers/assumeType';
import callbackify from '../../helpers/callbackify';
import callbackifyAll from '../../helpers/callbackifyAll';
import copy from '../../helpers/object/copy';
import pause from '../../helpers/schedulers/pause';
import {AvailableReaction, Message, MessagePeerReaction, MessagesAvailableReactions, Reaction, ReactionCount, Update, Updates} from '../../layer';
import {ReferenceContext} from '../mtproto/referenceDatabase';
import {AppManager} from './manager';
@ -54,6 +55,8 @@ export class AppReactionsManager extends AppManager {
availableReaction.appear_animation && this.apiFileManager.downloadMedia({media: availableReaction.appear_animation}),
availableReaction.center_icon && this.apiFileManager.downloadMedia({media: availableReaction.center_icon})
]);
await pause(1000);
}
});
}, 7.5e3);

View File

@ -15,12 +15,13 @@ import MTTransport from './transports/transport';
// #endif
import type {UserAuth} from './mtproto_config';
import type {DcAuthKey, DcId, DcServerSalt, InvokeApiOptions} from '../../types';
import type {MethodDeclMap} from '../../layer';
import type TcpObfuscated from './transports/tcpObfuscated';
import sessionStorage from '../sessionStorage';
import MTPNetworker, {MTMessage} from './networker';
import {ConnectionType, constructTelegramWebSocketUrl, DcConfigurator, TransportType} from './dcConfigurator';
import {logger} from '../logger';
import type {DcAuthKey, DcId, DcServerSalt, InvokeApiOptions} from '../../types';
import type {MethodDeclMap} from '../../layer';
import deferredPromise, {CancellablePromise} from '../../helpers/cancellablePromise';
import App from '../../config/app';
import {MOUNT_CLASS_TO} from '../../config/debug';
@ -36,7 +37,6 @@ import pause from '../../helpers/schedulers/pause';
import ApiManagerMethods from './api_methods';
import {getEnvironment} from '../../environment/utils';
import toggleStorages from '../../helpers/toggleStorages';
import type TcpObfuscated from './transports/tcpObfuscated';
/* class RotatableArray<T> {
public array: Array<T> = [];
@ -617,7 +617,7 @@ export class ApiManager extends ApiManagerMethods {
} else if(!options.rawError && error.code === 420) {
const waitTime = +error.type.match(/^FLOOD_WAIT_(\d+)/)[1] || 1;
if(waitTime > (options.floodMaxTimeout !== undefined ? options.floodMaxTimeout : 60) && !options.prepareTempMessageId) {
if(waitTime > (options.floodMaxTimeout ?? 60) && !options.prepareTempMessageId) {
throw error;
}

View File

@ -543,7 +543,12 @@ export default class DialogsStorage extends AppManager {
}
}
public generateIndexForDialog(dialog: Dialog, justReturn?: boolean, message?: MyMessage, noPinnedOrderUpdate?: boolean) {
public generateIndexForDialog(
dialog: Dialog,
justReturn?: boolean,
message?: MyMessage,
noPinnedOrderUpdate?: boolean
) {
if(!justReturn) {
return;
}
@ -673,21 +678,10 @@ export default class DialogsStorage extends AppManager {
public pushDialog(dialog: Dialog, offsetDate?: number, ignoreOffsetDate?: boolean, saveGlobalOffset?: boolean) {
const {folder_id, peerId} = dialog;
// const dialogs = this.getFolderDialogs(folder_id, false);
// const pos = dialogs.findIndex((d) => d.peerId === peerId);
// if(pos !== -1) {
// dialogs.splice(pos, 1);
// }
// if(!this.dialogs[peerId]) {
this.dialogs[peerId] = dialog;
this.setDialogToState(dialog);
// }
if(offsetDate === undefined) {
offsetDate = this.getDialogOffsetDate(dialog);
}
offsetDate ??= this.getDialogOffsetDate(dialog);
this.processDialogForFilters(dialog);
@ -703,7 +697,7 @@ export default class DialogsStorage extends AppManager {
if(!savedOffsetDate || offsetDate < savedOffsetDate) {
// if(pos !== -1) {
if(!ignoreOffsetDate && !this.isDialogsLoaded(folder_id)) {
this.clearDialogFromState(dialog, true);
this.dropDialog(peerId, true);
return;
}
@ -711,6 +705,8 @@ export default class DialogsStorage extends AppManager {
}
}
this.setDialogToState(dialog);
// if(pos === -1) {
// this.prepareFolderUnreadCountModifyingByDialog(folder_id, dialog, true);
// }
@ -722,12 +718,10 @@ export default class DialogsStorage extends AppManager {
} */
}
public dropDialog(peerId: PeerId): ReturnType<DialogsStorage['getDialog']> {
public dropDialogFromFolders(peerId: PeerId) {
const foundDialog = this.getDialog(peerId, undefined, false);
const [dialog, index] = foundDialog;
if(dialog) {
delete this.dialogs[peerId];
const folder = this.getFolder(dialog.folder_id);
folder.dialogs.splice(index, 1);
const wasPinned = indexOfAndSplice(this.pinnedOrders[dialog.folder_id], peerId) !== undefined;
@ -739,8 +733,20 @@ export default class DialogsStorage extends AppManager {
if(wasPinned) {
this.savePinnedOrders();
}
}
this.clearDialogFromState(dialog, false);
return foundDialog;
}
public dropDialog(peerId: PeerId, keepLocal?: boolean): ReturnType<DialogsStorage['getDialog']> {
const dialog = this.getDialogOnly(peerId);
const foundDialog = this.dropDialogFromFolders(peerId);
if(dialog) {
if(!keepLocal) {
delete this.dialogs[peerId];
}
this.clearDialogFromState(dialog, keepLocal);
}
return foundDialog;
@ -806,8 +812,9 @@ export default class DialogsStorage extends AppManager {
} */
if(topMessage || dialog.draft?._ === 'draftMessage') {
this.saveDialog(dialog);
updatedDialogs.set(peerId, dialog);
if(this.saveDialog(dialog)) {
updatedDialogs.set(peerId, dialog);
}
} else {
this.dropDialogWithEvent(peerId);
}
@ -835,22 +842,7 @@ export default class DialogsStorage extends AppManager {
return message?.date || 0;
}
/**
* Won't save migrated from peer, forbidden peers, left and kicked
*/
public saveDialog(dialog: Dialog, folderId = dialog.folder_id ?? FOLDER_ID_ALL, ignoreOffsetDate?: boolean, saveGlobalOffset?: boolean) {
const peerId = this.appPeersManager.getPeerId(dialog.peer);
if(!peerId) {
console.error('saveConversation no peerId???', dialog, folderId);
return;
}
if(dialog._ !== 'dialog'/* || peerId === 239602833 */) {
console.error('saveConversation not regular dialog', dialog, Object.assign({}, dialog));
}
const channelId = this.appPeersManager.isChannel(peerId) ? peerId.toChatId() : NULL_PEER_ID;
public canSaveDialogByPeerId(peerId: PeerId) {
if(peerId.isAnyChat()) {
const chat: Chat = this.appChatsManager.getChat(peerId.toChatId());
// ! chatForbidden stays for chat where you're kicked
@ -860,10 +852,33 @@ export default class DialogsStorage extends AppManager {
(chat as Chat.chat).pFlags.left
// || (chat as any).pFlags.kicked
) {
return;
return false;
}
}
return true;
}
/**
* Won't save migrated from peer, forbidden peers, left and kicked
*/
public saveDialog(dialog: Dialog, folderId = dialog.folder_id ?? FOLDER_ID_ALL, ignoreOffsetDate?: boolean, saveGlobalOffset?: boolean) {
const peerId = this.appPeersManager.getPeerId(dialog.peer);
if(!peerId) {
console.error('saveConversation no peerId???', dialog, folderId);
return false;
}
if(dialog._ !== 'dialog'/* || peerId === 239602833 */) {
console.error('saveConversation not regular dialog', dialog, Object.assign({}, dialog));
}
if(!this.canSaveDialogByPeerId(peerId)) {
return false;
}
const channelId = this.appPeersManager.isChannel(peerId) ? peerId.toChatId() : NULL_PEER_ID;
const peerText = this.appPeersManager.getPeerSearchText(peerId);
this.dialogsIndex.indexObject(peerId, peerText);
@ -989,6 +1004,8 @@ export default class DialogsStorage extends AppManager {
}
this.pushDialog(dialog, message?.date, ignoreOffsetDate, saveGlobalOffset);
return true;
}
public getDialogs(query = '', offsetIndex?: number, limit = 20, folderId: number = 0, skipMigrated = false): {

View File

@ -206,7 +206,7 @@ export default class FiltersStorage extends AppManager {
public testDialogForFilter(dialog: Dialog, filter: MyDialogFilter) {
if(REAL_FOLDERS.has(filter.id)) {
return dialog.folder_id === filter.id;
return dialog.folder_id === filter.id && this.dialogsStorage.canSaveDialogByPeerId(dialog.peerId);
}
const peerId = dialog.peerId;

View File

@ -77,8 +77,13 @@ avatar-element {
font-size: calc(25px / var(--multiplier));
} */
&.tgico-deletedaccount:before {
font-size: calc(30px / var(--multiplier));
&.tgico-deletedaccount {
--color-top: var(--peer-avatar-archive-top);
--color-bottom: var(--peer-avatar-archive-bottom);
&:before {
font-size: calc(30px / var(--multiplier));
}
}
&:before {

View File

@ -137,8 +137,7 @@ $row-border-radius: $border-radius-medium;
}
&-toggle {
margin: 0;
margin-right: .125rem;
margin: 0 .125rem;
padding: 0;
}
}

View File

@ -64,7 +64,7 @@ $chat-input-inner-padding-handhelds: .25rem;
--pm-transition: .2s ease-in-out;
--layer-transition: .2s cubic-bezier(.4, .0, .2, 1);
--slide-header-transition: .4s ease-in-out;
--tabs-transition: .25s ease-in-out;
--tabs-transition: .2s ease-in-out;
--btn-menu-transition: .2s cubic-bezier(.4, 0, .2, 1);
--esg-transition: var(--btn-menu-transition);
--input-transition: .2s ease-out;
@ -124,20 +124,27 @@ $chat-input-inner-padding-handhelds: .25rem;
--custom-emoji-size: 1.25rem;
// https://github.com/overtake/TelegramSwift/blob/5cc7d2475fe4738a6aa0486c23eaf80a89d33b97/submodules/TGUIKit/TGUIKit/PresentationTheme.swift#L2054
--peer-avatar-red-top: #ff885e;
--peer-avatar-red-bottom: #ff516a;
--peer-avatar-orange-top: #ffcd6a;
--peer-avatar-orange-bottom: #ffa85c;
--peer-avatar-violet-top: #82b1ff;
--peer-avatar-violet-bottom: #665fff;
--peer-avatar-green-top: #a0de7e;
--peer-avatar-green-bottom: #54cb68;
--peer-avatar-red-top: #FF845E;
--peer-avatar-red-bottom: #D45246;
--peer-avatar-orange-top: #FEBB5B;
--peer-avatar-orange-bottom: #F68136;
--peer-avatar-violet-top: #B694F9;
--peer-avatar-violet-bottom: #6C61DF;
--peer-avatar-green-top: #9AD164;
--peer-avatar-green-bottom: #46BA43;
--peer-avatar-cyan-top: #53edd6;
--peer-avatar-cyan-bottom: #28c9b7;
--peer-avatar-blue-top: #72d5fd;
--peer-avatar-blue-bottom: #2a9ef1;
--peer-avatar-pink-top: #e0a2f3;
--peer-avatar-pink-bottom: #d669ed;
--peer-avatar-blue-top: #5BCBE3;
--peer-avatar-blue-bottom: #359AD4;
--peer-avatar-pink-top: #FF8AAC;
--peer-avatar-pink-bottom: #D95574;
--peer-avatar-saved-top: #69BFFA;
--peer-avatar-saved-bottom: #3D9DE0;
--peer-avatar-archive-top: #B8C2CC;
--peer-avatar-archive-bottom: #9EAAB5;
--avatar-color-top: var(--peer-avatar-saved-top);
--avatar-color-bottom: var(--peer-avatar-saved-bottom);
--premium-gradient: linear-gradient(52.62deg, #6B93FF 12.22%, #976FFF 50.25%, #E46ACE 98.83%);
@ -221,8 +228,8 @@ $chat-input-inner-padding-handhelds: .25rem;
@include splitColor(danger-color, #df3f40, true, true);
--avatar-online-color: #0ac630;
--avatar-color-top: var(--peer-avatar-blue-top);
--avatar-color-bottom: var(--peer-avatar-blue-bottom);
// --avatar-color-top: var(--peer-avatar-saved-top);
// --avatar-color-bottom: var(--peer-avatar-saved-bottom);
--chatlist-status-color: var(--avatar-online-color);
--chatlist-pinned-color: #a2abb2;
--badge-text-color: #fff;
@ -298,8 +305,8 @@ $chat-input-inner-padding-handhelds: .25rem;
@include splitColor(danger-color, #ff595a, true, true);
--avatar-online-color: #0ac630;
--avatar-color-top: var(--peer-avatar-violet-top);
--avatar-color-bottom: var(--peer-avatar-violet-bottom);
// --avatar-color-top: var(--peer-avatar-violet-top);
// --avatar-color-bottom: var(--peer-avatar-violet-bottom);
--chatlist-status-color: var(--primary-color);
--chatlist-pinned-color: var(--secondary-color);
--badge-text-color: #fff;