2021-04-08 15:52:31 +02:00
|
|
|
/*
|
|
|
|
* https://github.com/morethanwords/tweb
|
|
|
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
|
|
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
|
|
|
*/
|
|
|
|
|
2022-08-04 08:49:54 +02:00
|
|
|
import type {Dialog} from '../lib/appManagers/appMessagesManager';
|
2023-01-06 20:27:29 +01:00
|
|
|
import type {ForumTopic} from '../layer';
|
2024-01-05 20:12:30 +01:00
|
|
|
import type {AnyDialog} from '../lib/storages/dialogs';
|
2023-01-06 20:27:29 +01:00
|
|
|
import appDialogsManager, {DIALOG_LIST_ELEMENT_TAG} from '../lib/appManagers/appDialogsManager';
|
2022-08-04 08:49:54 +02:00
|
|
|
import rootScope from '../lib/rootScope';
|
2023-12-05 12:58:30 +01:00
|
|
|
import {ButtonMenuItemOptionsVerifiable} from './buttonMenu';
|
2022-08-04 08:49:54 +02:00
|
|
|
import PopupDeleteDialog from './popups/deleteDialog';
|
2022-09-25 19:49:33 +02:00
|
|
|
import {i18n, LangPackKey, _i18n} from '../lib/langPack';
|
2022-08-04 08:49:54 +02:00
|
|
|
import findUpTag from '../helpers/dom/findUpTag';
|
|
|
|
import {toastNew} from './toast';
|
|
|
|
import PopupMute from './popups/mute';
|
|
|
|
import {AppManagers} from '../lib/appManagers/managers';
|
2024-03-12 09:35:12 +01:00
|
|
|
import {CAN_HIDE_TOPIC, FOLDER_ID_ARCHIVE, GENERAL_TOPIC_ID, REAL_FOLDERS} from '../lib/mtproto/mtproto_config';
|
2023-01-13 22:28:45 +01:00
|
|
|
import showLimitPopup from './popups/limit';
|
2023-01-31 16:04:47 +01:00
|
|
|
import createContextMenu from '../helpers/dom/createContextMenu';
|
2023-03-07 22:25:07 +01:00
|
|
|
import PopupElement from './popups';
|
2023-04-21 18:10:16 +02:00
|
|
|
import cancelEvent from '../helpers/dom/cancelEvent';
|
2023-04-21 23:07:22 +02:00
|
|
|
import IS_SHARED_WORKER_SUPPORTED from '../environment/sharedWorkerSupport';
|
2023-12-05 12:58:30 +01:00
|
|
|
import wrapEmojiText from '../lib/richTextProcessor/wrapEmojiText';
|
2023-12-18 18:55:08 +01:00
|
|
|
import appImManager from '../lib/appManagers/appImManager';
|
2024-01-05 20:12:30 +01:00
|
|
|
import assumeType from '../helpers/assumeType';
|
|
|
|
import {isForumTopic, isSavedDialog} from '../lib/appManagers/utils/dialogs/isDialog';
|
2024-02-10 21:26:20 +01:00
|
|
|
import {appState} from '../stores/appState';
|
2020-10-07 15:57:33 +02:00
|
|
|
|
|
|
|
export default class DialogsContextMenu {
|
2023-01-06 20:27:29 +01:00
|
|
|
private buttons: ButtonMenuItemOptionsVerifiable[];
|
2020-11-23 18:25:14 +01:00
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
private peerId: PeerId;
|
2020-12-11 03:06:16 +01:00
|
|
|
private filterId: number;
|
2023-01-06 20:27:29 +01:00
|
|
|
private threadId: number;
|
2024-01-05 20:12:30 +01:00
|
|
|
private dialog: AnyDialog;
|
2023-01-06 20:27:29 +01:00
|
|
|
private canManageTopics: boolean;
|
2023-01-31 16:04:47 +01:00
|
|
|
private li: HTMLElement;
|
2022-06-17 18:01:43 +02:00
|
|
|
|
|
|
|
constructor(private managers: AppManagers) {
|
|
|
|
|
|
|
|
}
|
2020-11-23 18:25:14 +01:00
|
|
|
|
2023-01-31 16:04:47 +01:00
|
|
|
public attach(element: HTMLElement) {
|
|
|
|
createContextMenu({
|
|
|
|
listenTo: element,
|
|
|
|
buttons: this.getButtons(),
|
|
|
|
appendTo: document.getElementById('page-chats'),
|
2023-09-23 18:27:07 +02:00
|
|
|
onOpen: async(e, li) => {
|
2023-01-31 16:04:47 +01:00
|
|
|
this.li = li;
|
|
|
|
li.classList.add('menu-open');
|
|
|
|
this.peerId = li.dataset.peerId.toPeerId();
|
|
|
|
this.threadId = +li.dataset.threadId || undefined;
|
2024-01-05 20:12:30 +01:00
|
|
|
this.dialog = await this.managers.dialogsStorage.getAnyDialog(this.peerId, this.threadId);
|
2023-01-31 16:04:47 +01:00
|
|
|
this.filterId = this.threadId ? undefined : appDialogsManager.filterId;
|
2024-02-20 13:29:11 +01:00
|
|
|
this.canManageTopics = isForumTopic(this.dialog) ? await this.managers.dialogsStorage.canManageTopic(this.dialog) : undefined;
|
2023-01-31 16:04:47 +01:00
|
|
|
},
|
2023-09-23 18:27:07 +02:00
|
|
|
onOpenBefore: async() => {
|
2023-01-31 16:04:47 +01:00
|
|
|
// delete button
|
2023-02-02 12:19:08 +01:00
|
|
|
const langPackKey: LangPackKey = this.threadId ? 'Delete' : await this.managers.appPeersManager.getDeleteButtonText(this.peerId);
|
|
|
|
const lastButton = this.buttons[this.buttons.length - 1];
|
|
|
|
if(lastButton?.element) {
|
|
|
|
lastButton.element.lastChild.replaceWith(i18n(langPackKey));
|
|
|
|
}
|
2023-01-31 16:04:47 +01:00
|
|
|
},
|
|
|
|
onClose: () => {
|
|
|
|
this.li.classList.remove('menu-open');
|
|
|
|
this.li = this.peerId = this.dialog = this.filterId = this.threadId = this.canManageTopics = undefined;
|
|
|
|
},
|
|
|
|
findElement: (e) => {
|
|
|
|
return findUpTag(e.target, DIALOG_LIST_ELEMENT_TAG);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private getButtons() {
|
2024-03-12 09:35:12 +01:00
|
|
|
this.buttons ??= [{
|
2023-04-21 18:10:16 +02:00
|
|
|
icon: 'newtab',
|
|
|
|
text: 'OpenInNewTab',
|
|
|
|
onClick: (e) => {
|
|
|
|
appDialogsManager.openDialogInNewTab(this.li);
|
|
|
|
cancelEvent(e);
|
2023-04-21 23:07:22 +02:00
|
|
|
},
|
|
|
|
verify: () => IS_SHARED_WORKER_SUPPORTED
|
2023-04-21 18:10:16 +02:00
|
|
|
}, {
|
2023-12-18 18:55:08 +01:00
|
|
|
icon: 'topics',
|
|
|
|
text: 'TopicViewAsTopics',
|
|
|
|
onClick: () => {
|
2024-02-10 21:26:20 +01:00
|
|
|
appImManager.toggleViewAsMessages(this.peerId, false);
|
2023-12-18 18:55:08 +01:00
|
|
|
},
|
|
|
|
verify: () => !!(this.dialog && (this.dialog as Dialog).pFlags.view_forum_as_messages)
|
2024-02-10 21:26:20 +01:00
|
|
|
}, {
|
|
|
|
icon: 'topics',
|
|
|
|
text: 'SavedViewAsChats',
|
|
|
|
onClick: () => {
|
|
|
|
appImManager.toggleViewAsMessages(this.peerId, false);
|
|
|
|
},
|
|
|
|
verify: () => this.peerId === rootScope.myId && !appState.settings.savedAsForum && !this.threadId
|
|
|
|
}, {
|
|
|
|
icon: 'message',
|
|
|
|
text: 'SavedViewAsMessages',
|
|
|
|
onClick: () => {
|
|
|
|
appImManager.toggleViewAsMessages(this.peerId, true);
|
|
|
|
},
|
|
|
|
verify: () => this.peerId === rootScope.myId && appState.settings.savedAsForum && !this.threadId
|
2023-12-18 18:55:08 +01:00
|
|
|
}, {
|
2020-11-23 18:25:14 +01:00
|
|
|
icon: 'unread',
|
2021-03-25 19:07:00 +01:00
|
|
|
text: 'MarkAsUnread',
|
2020-11-23 18:25:14 +01:00
|
|
|
onClick: this.onUnreadClick,
|
2023-01-06 20:27:29 +01:00
|
|
|
verify: async() => !this.threadId && !(await this.managers.appMessagesManager.isDialogUnread(this.dialog))
|
2020-11-23 18:25:14 +01:00
|
|
|
}, {
|
|
|
|
icon: 'readchats',
|
2021-03-25 19:07:00 +01:00
|
|
|
text: 'MarkAsRead',
|
2020-11-23 18:25:14 +01:00
|
|
|
onClick: this.onUnreadClick,
|
2022-04-25 16:54:30 +02:00
|
|
|
verify: () => this.managers.appMessagesManager.isDialogUnread(this.dialog)
|
2020-11-23 18:25:14 +01:00
|
|
|
}, {
|
|
|
|
icon: 'pin',
|
2021-03-25 19:07:00 +01:00
|
|
|
text: 'ChatList.Context.Pin',
|
2020-11-23 18:25:14 +01:00
|
|
|
onClick: this.onPinClick,
|
2022-06-17 18:01:43 +02:00
|
|
|
verify: async() => {
|
2024-01-05 20:12:30 +01:00
|
|
|
if(isSavedDialog(this.dialog)) {
|
|
|
|
return !this.dialog.pFlags.pinned;
|
|
|
|
}
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
if(this.threadId && !this.canManageTopics) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const isPinned = this.filterId !== undefined && this.filterId > 1 ?
|
2022-08-04 08:49:54 +02:00
|
|
|
(await this.managers.appMessagesManager.getFilter(this.filterId)).pinnedPeerIds.includes(this.dialog.peerId) :
|
2022-06-17 18:01:43 +02:00
|
|
|
!!this.dialog.pFlags?.pinned;
|
2020-11-23 18:25:14 +01:00
|
|
|
return !isPinned;
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
icon: 'unpin',
|
2021-03-25 19:07:00 +01:00
|
|
|
text: 'ChatList.Context.Unpin',
|
2020-11-23 18:25:14 +01:00
|
|
|
onClick: this.onPinClick,
|
2022-06-17 18:01:43 +02:00
|
|
|
verify: async() => {
|
2024-01-05 20:12:30 +01:00
|
|
|
if(isSavedDialog(this.dialog)) {
|
|
|
|
return !!this.dialog.pFlags.pinned;
|
|
|
|
}
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
if(this.threadId && !this.canManageTopics) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const isPinned = this.filterId !== undefined && this.filterId > 1 ?
|
2022-08-04 08:49:54 +02:00
|
|
|
(await this.managers.appMessagesManager.getFilter(this.filterId)).pinnedPeerIds.includes(this.dialog.peerId) :
|
2022-06-17 18:01:43 +02:00
|
|
|
!!this.dialog.pFlags?.pinned;
|
2020-11-23 18:25:14 +01:00
|
|
|
return isPinned;
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
icon: 'mute',
|
2021-03-25 19:07:00 +01:00
|
|
|
text: 'ChatList.Context.Mute',
|
2020-11-23 18:25:14 +01:00
|
|
|
onClick: this.onMuteClick,
|
2022-06-17 18:01:43 +02:00
|
|
|
verify: async() => {
|
2023-01-06 20:27:29 +01:00
|
|
|
return this.peerId !== rootScope.myId && !(await this.managers.appNotificationsManager.isPeerLocalMuted({peerId: this.dialog.peerId, threadId: this.threadId}));
|
2020-11-23 18:25:14 +01:00
|
|
|
}
|
|
|
|
}, {
|
|
|
|
icon: 'unmute',
|
2021-03-25 19:07:00 +01:00
|
|
|
text: 'ChatList.Context.Unmute',
|
2021-04-23 18:08:20 +02:00
|
|
|
onClick: this.onUnmuteClick,
|
2023-09-06 22:28:19 +02:00
|
|
|
verify: () => {
|
|
|
|
return this.peerId !== rootScope.myId && this.managers.appNotificationsManager.isPeerLocalMuted({peerId: this.dialog.peerId, threadId: this.threadId});
|
2020-11-23 18:25:14 +01:00
|
|
|
}
|
|
|
|
}, {
|
|
|
|
icon: 'archive',
|
|
|
|
text: 'Archive',
|
|
|
|
onClick: this.onArchiveClick,
|
2023-09-06 22:28:19 +02:00
|
|
|
verify: () => !this.threadId && (this.dialog as Dialog).folder_id !== FOLDER_ID_ARCHIVE && this.peerId !== rootScope.myId
|
2020-11-23 18:25:14 +01:00
|
|
|
}, {
|
|
|
|
icon: 'unarchive',
|
|
|
|
text: 'Unarchive',
|
|
|
|
onClick: this.onArchiveClick,
|
2023-09-06 22:28:19 +02:00
|
|
|
verify: () => this.filterId === FOLDER_ID_ARCHIVE && this.peerId !== rootScope.myId
|
2024-03-12 09:35:12 +01:00
|
|
|
}, CAN_HIDE_TOPIC ? {
|
2023-01-12 15:47:02 +01:00
|
|
|
icon: 'hide',
|
2023-01-06 20:27:29 +01:00
|
|
|
text: 'Hide',
|
2023-01-31 16:04:47 +01:00
|
|
|
onClick: this.onHideTopicClick,
|
|
|
|
verify: () => {
|
2023-01-06 20:27:29 +01:00
|
|
|
return this.canManageTopics && (this.dialog as ForumTopic.forumTopic).id === GENERAL_TOPIC_ID;
|
|
|
|
}
|
2024-03-12 09:35:12 +01:00
|
|
|
} : undefined, {
|
2023-01-06 20:27:29 +01:00
|
|
|
icon: 'lock',
|
|
|
|
text: 'CloseTopic',
|
2023-01-31 16:04:47 +01:00
|
|
|
onClick: this.onToggleTopicClick,
|
2023-01-06 20:27:29 +01:00
|
|
|
verify: () => {
|
|
|
|
return this.canManageTopics && !(this.dialog as ForumTopic.forumTopic).pFlags.closed;
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
icon: 'lockoff',
|
|
|
|
text: 'RestartTopic',
|
2023-01-31 16:04:47 +01:00
|
|
|
onClick: this.onToggleTopicClick,
|
2023-01-06 20:27:29 +01:00
|
|
|
verify: () => {
|
|
|
|
return this.canManageTopics && !!(this.dialog as ForumTopic.forumTopic).pFlags.closed;
|
|
|
|
}
|
2023-12-05 12:58:30 +01:00
|
|
|
}, {
|
|
|
|
icon: 'folder',
|
|
|
|
text: 'FilterAddTo',
|
|
|
|
onClick: () => {},
|
|
|
|
inner: async() => {
|
|
|
|
const filters = await this.managers.filtersStorage.getDialogFilters();
|
|
|
|
return {
|
|
|
|
buttons: filters.map((filter) => {
|
|
|
|
const title = document.createElement('span');
|
|
|
|
title.append(wrapEmojiText(filter.title));
|
|
|
|
return {
|
|
|
|
icon: 'folder',
|
|
|
|
textElement: title,
|
|
|
|
onClick: () => {}
|
|
|
|
};
|
|
|
|
})
|
|
|
|
};
|
|
|
|
},
|
|
|
|
verify: () => false
|
2020-11-23 18:25:14 +01:00
|
|
|
}, {
|
2023-09-06 22:28:19 +02:00
|
|
|
icon: 'delete',
|
|
|
|
className: 'danger',
|
2020-11-23 18:25:14 +01:00
|
|
|
text: 'Delete',
|
|
|
|
onClick: this.onDeleteClick,
|
2023-01-31 16:04:47 +01:00
|
|
|
verify: () => {
|
2023-01-06 20:27:29 +01:00
|
|
|
if(this.threadId) {
|
2024-01-05 20:12:30 +01:00
|
|
|
if(isSavedDialog(this.dialog)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
if(!this.canManageTopics) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (this.dialog as ForumTopic.forumTopic).id !== GENERAL_TOPIC_ID;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2020-11-23 18:25:14 +01:00
|
|
|
}];
|
2024-03-12 09:35:12 +01:00
|
|
|
|
|
|
|
return this.buttons = this.buttons.filter(Boolean);
|
2020-11-23 18:25:14 +01:00
|
|
|
}
|
2020-10-07 15:57:33 +02:00
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
private onArchiveClick = async() => {
|
2023-01-06 20:27:29 +01:00
|
|
|
const dialog = await this.managers.appMessagesManager.getDialogOnly(this.peerId);
|
2020-11-23 18:25:14 +01:00
|
|
|
if(dialog) {
|
2022-04-25 16:54:30 +02:00
|
|
|
this.managers.appMessagesManager.editPeerFolders([dialog.peerId], +!dialog.folder_id);
|
2020-11-23 18:25:14 +01:00
|
|
|
}
|
|
|
|
};
|
2020-10-07 15:57:33 +02:00
|
|
|
|
2023-01-31 16:04:47 +01:00
|
|
|
private onHideTopicClick = () => {
|
2023-01-06 20:27:29 +01:00
|
|
|
this.managers.appChatsManager.editForumTopic({
|
|
|
|
chatId: this.peerId.toChatId(),
|
|
|
|
topicId: this.threadId,
|
|
|
|
hidden: true
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2023-01-31 16:04:47 +01:00
|
|
|
private onToggleTopicClick = () => {
|
2023-01-06 20:27:29 +01:00
|
|
|
this.managers.appChatsManager.editForumTopic({
|
|
|
|
chatId: this.peerId.toChatId(),
|
|
|
|
topicId: this.threadId,
|
|
|
|
closed: !(this.dialog as ForumTopic.forumTopic).pFlags.closed
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2020-11-23 18:25:14 +01:00
|
|
|
private onPinClick = () => {
|
2024-01-05 20:12:30 +01:00
|
|
|
const {peerId, filterId, threadId, dialog} = this;
|
|
|
|
const isSaved = isSavedDialog(dialog);
|
2023-01-06 20:27:29 +01:00
|
|
|
this.managers.appMessagesManager.toggleDialogPin({
|
|
|
|
peerId,
|
|
|
|
filterId,
|
2024-01-05 20:12:30 +01:00
|
|
|
topicOrSavedId: threadId
|
2023-01-06 20:27:29 +01:00
|
|
|
}).catch(async(err: ApiError) => {
|
|
|
|
if(err.type === 'PINNED_DIALOGS_TOO_MUCH' || err.type === 'PINNED_TOO_MUCH') {
|
2024-01-05 20:12:30 +01:00
|
|
|
if(isSaved) {
|
|
|
|
showLimitPopup('savedPin');
|
|
|
|
} else if(threadId) {
|
2023-01-06 20:27:29 +01:00
|
|
|
this.managers.apiManager.getLimit('topicPin').then((limit) => {
|
|
|
|
toastNew({langPackKey: 'LimitReachedPinnedTopics', langPackArguments: [limit]});
|
|
|
|
});
|
2024-01-05 20:12:30 +01:00
|
|
|
} else if(!REAL_FOLDERS.has(filterId)) {
|
2021-07-16 15:41:31 +02:00
|
|
|
toastNew({langPackKey: 'PinFolderLimitReached'});
|
|
|
|
} else {
|
2023-01-13 22:28:45 +01:00
|
|
|
showLimitPopup('pin');
|
2021-07-16 15:41:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2020-11-23 18:25:14 +01:00
|
|
|
};
|
2021-04-23 18:08:20 +02:00
|
|
|
|
|
|
|
private onUnmuteClick = () => {
|
2023-01-06 20:27:29 +01:00
|
|
|
this.managers.appMessagesManager.togglePeerMute({peerId: this.peerId, mute: false, threadId: this.threadId});
|
2021-04-23 18:08:20 +02:00
|
|
|
};
|
2022-08-04 08:49:54 +02:00
|
|
|
|
2020-11-23 18:25:14 +01:00
|
|
|
private onMuteClick = () => {
|
2023-03-07 22:25:07 +01:00
|
|
|
PopupElement.createPopup(PopupMute, this.peerId, this.threadId);
|
2020-11-23 18:25:14 +01:00
|
|
|
};
|
2020-10-07 15:57:33 +02:00
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
private onUnreadClick = async() => {
|
2023-01-06 20:27:29 +01:00
|
|
|
const {peerId, dialog} = this;
|
2024-01-05 20:12:30 +01:00
|
|
|
assumeType<Dialog | ForumTopic>(dialog);
|
2020-11-23 18:25:14 +01:00
|
|
|
if(dialog.unread_count) {
|
2023-01-06 20:27:29 +01:00
|
|
|
if(!this.threadId) {
|
|
|
|
this.managers.appMessagesManager.markDialogUnread(peerId, true);
|
2023-04-05 15:16:51 +02:00
|
|
|
} else {
|
|
|
|
this.managers.appMessagesManager.readHistory(peerId, dialog.top_message, this.threadId);
|
2023-01-06 20:27:29 +01:00
|
|
|
}
|
|
|
|
} else if(!this.threadId) {
|
|
|
|
this.managers.appMessagesManager.markDialogUnread(peerId);
|
2020-11-23 18:25:14 +01:00
|
|
|
}
|
|
|
|
};
|
2020-10-07 15:57:33 +02:00
|
|
|
|
2020-11-23 18:25:14 +01:00
|
|
|
private onDeleteClick = () => {
|
2024-01-05 20:12:30 +01:00
|
|
|
PopupElement.createPopup(
|
|
|
|
PopupDeleteDialog,
|
|
|
|
this.peerId,
|
|
|
|
undefined,
|
|
|
|
undefined,
|
|
|
|
this.threadId
|
|
|
|
);
|
2020-11-23 18:25:14 +01:00
|
|
|
};
|
2021-03-29 20:42:01 +02:00
|
|
|
}
|