tweb/src/components/dialogsContextMenu.ts

321 lines
11 KiB
TypeScript
Raw Permalink Normal View History

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';
import PopupElement from './popups';
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';
import {appState} from '../stores/appState';
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;
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;
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'),
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;
this.canManageTopics = isForumTopic(this.dialog) ? await this.managers.dialogsStorage.canManageTopic(this.dialog) : undefined;
2023-01-31 16:04:47 +01:00
},
onOpenBefore: async() => {
2023-01-31 16:04:47 +01:00
// delete button
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 ??= [{
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-12-18 18:55:08 +01:00
icon: 'topics',
text: 'TopicViewAsTopics',
onClick: () => {
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)
}, {
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,
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) :
!!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,
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) :
!!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,
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',
onClick: this.onUnmuteClick,
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,
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,
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
}, {
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
}
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
}
};
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)) {
toastNew({langPackKey: 'PinFolderLimitReached'});
} else {
2023-01-13 22:28:45 +01:00
showLimitPopup('pin');
}
}
});
2020-11-23 18:25:14 +01:00
};
private onUnmuteClick = () => {
2023-01-06 20:27:29 +01:00
this.managers.appMessagesManager.togglePeerMute({peerId: this.peerId, mute: false, threadId: this.threadId});
};
2022-08-04 08:49:54 +02:00
2020-11-23 18:25:14 +01:00
private onMuteClick = () => {
PopupElement.createPopup(PopupMute, this.peerId, this.threadId);
2020-11-23 18:25:14 +01: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);
} 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-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
};
}