Fix deleting channels
Fix dropping chats when they are deleted Confirm popups by Enter
This commit is contained in:
parent
c5f6af469b
commit
3fc26e0262
@ -7,7 +7,6 @@
|
||||
import appChatsManager, { ChatRights } from "../lib/appManagers/appChatsManager";
|
||||
import appDialogsManager from "../lib/appManagers/appDialogsManager";
|
||||
import appMessagesManager, { Dialog } from "../lib/appManagers/appMessagesManager";
|
||||
import appPhotosManager from "../lib/appManagers/appPhotosManager";
|
||||
import appUsersManager from "../lib/appManagers/appUsersManager";
|
||||
import rootScope from "../lib/rootScope";
|
||||
import Scrollable from "./scrollable";
|
||||
|
@ -456,7 +456,7 @@ export default class ChatBubbles {
|
||||
if(!isMobile) {
|
||||
this.listenerSetter.add(this.bubblesContainer)('dblclick', (e) => {
|
||||
if(this.chat.selection.isSelecting ||
|
||||
!this.appMessagesManager.canWriteToPeer(this.peerId, this.chat.threadId)) {
|
||||
!this.appMessagesManager.canSendToPeer(this.peerId, this.chat.threadId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -559,7 +559,7 @@ export default class ChatBubbles {
|
||||
const chatId: number = e;
|
||||
if(this.peerId === -chatId) {
|
||||
const hadRights = this.chatInner.classList.contains('has-rights');
|
||||
const hasRights = this.appMessagesManager.canWriteToPeer(this.peerId, this.chat.threadId);
|
||||
const hasRights = this.appMessagesManager.canSendToPeer(this.peerId, this.chat.threadId);
|
||||
|
||||
if(hadRights !== hasRights) {
|
||||
this.finishPeerChange();
|
||||
@ -2007,7 +2007,7 @@ export default class ChatBubbles {
|
||||
public finishPeerChange() {
|
||||
const peerId = this.peerId;
|
||||
const isChannel = this.appPeersManager.isChannel(peerId);
|
||||
const canWrite = this.appMessagesManager.canWriteToPeer(peerId, this.chat.threadId);
|
||||
const canWrite = this.appMessagesManager.canSendToPeer(peerId, this.chat.threadId);
|
||||
|
||||
this.chatInner.classList.toggle('has-rights', canWrite);
|
||||
this.bubblesContainer.classList.toggle('is-chat-input-hidden', !canWrite);
|
||||
@ -3495,7 +3495,7 @@ export default class ChatBubbles {
|
||||
this.renderEmptyPlaceholder('group', bubble, message, elements);
|
||||
} else if(rootScope.myId === this.peerId) {
|
||||
this.renderEmptyPlaceholder('saved', bubble, message, elements);
|
||||
} else if(this.peerId > 0 && !isBot && this.appMessagesManager.canWriteToPeer(this.peerId) && this.chat.type === 'chat') {
|
||||
} else if(this.peerId > 0 && !isBot && this.appMessagesManager.canSendToPeer(this.peerId) && this.chat.type === 'chat') {
|
||||
this.renderEmptyPlaceholder('greeting', bubble, message, elements);
|
||||
} else if(this.chat.type === 'scheduled') {
|
||||
this.renderEmptyPlaceholder('noScheduledMessages', bubble, message, elements);
|
||||
|
@ -188,7 +188,7 @@ export default class ChatContextMenu {
|
||||
icon: 'reply',
|
||||
text: 'Reply',
|
||||
onClick: this.onReplyClick,
|
||||
verify: () => this.appMessagesManager.canWriteToPeer(this.peerId, this.chat.threadId) &&
|
||||
verify: () => this.appMessagesManager.canSendToPeer(this.peerId, this.chat.threadId) &&
|
||||
!this.message.pFlags.is_outgoing &&
|
||||
!!this.chat.input.messageInput &&
|
||||
this.chat.type !== 'scheduled'/* ,
|
||||
|
@ -107,7 +107,7 @@ export default class ChatInput {
|
||||
private replyKeyboard: ReplyKeyboard;
|
||||
|
||||
private attachMenu: HTMLButtonElement;
|
||||
private attachMenuButtons: (ButtonMenuItemOptions & {verify: (peerId: number) => boolean})[];
|
||||
private attachMenuButtons: (ButtonMenuItemOptions & {verify: (peerId: number, threadId: number) => boolean})[];
|
||||
|
||||
private sendMenu: SendMenu;
|
||||
|
||||
@ -371,7 +371,7 @@ export default class ChatInput {
|
||||
this.willAttachType = 'media';
|
||||
this.fileInput.click();
|
||||
},
|
||||
verify: (peerId: number) => peerId > 0 || this.appChatsManager.hasRights(peerId, 'send_media')
|
||||
verify: (peerId, threadId) => this.appMessagesManager.canSendToPeer(peerId, threadId, 'send_media')
|
||||
}, {
|
||||
icon: 'document',
|
||||
text: 'Chat.Input.Attach.Document',
|
||||
@ -381,14 +381,14 @@ export default class ChatInput {
|
||||
this.willAttachType = 'document';
|
||||
this.fileInput.click();
|
||||
},
|
||||
verify: (peerId: number) => peerId > 0 || this.appChatsManager.hasRights(peerId, 'send_media')
|
||||
verify: (peerId, threadId) => this.appMessagesManager.canSendToPeer(peerId, threadId, 'send_media')
|
||||
}, {
|
||||
icon: 'poll',
|
||||
text: 'Poll',
|
||||
onClick: () => {
|
||||
new PopupCreatePoll(this.chat).show();
|
||||
},
|
||||
verify: (peerId: number) => peerId < 0 && this.appChatsManager.hasRights(peerId, 'send_polls')
|
||||
verify: (peerId, threadId) => this.appMessagesManager.canSendToPeer(peerId, threadId, 'send_polls')
|
||||
}];
|
||||
|
||||
this.attachMenu = ButtonMenuToggle({noRipple: true, listenerSetter: this.listenerSetter}, 'top-left', this.attachMenuButtons);
|
||||
@ -814,14 +814,14 @@ export default class ChatInput {
|
||||
}
|
||||
|
||||
public updateMessageInput() {
|
||||
const canWrite = this.appMessagesManager.canWriteToPeer(this.chat.peerId, this.chat.threadId);
|
||||
const canWrite = this.appMessagesManager.canSendToPeer(this.chat.peerId, this.chat.threadId);
|
||||
this.chatInput.classList.add('no-transition');
|
||||
this.chatInput.classList.toggle('is-hidden', !canWrite);
|
||||
void this.chatInput.offsetLeft; // reflow
|
||||
this.chatInput.classList.remove('no-transition');
|
||||
|
||||
const visible = this.attachMenuButtons.filter(button => {
|
||||
const good = button.verify(this.chat.peerId);
|
||||
const good = button.verify(this.chat.peerId, this.chat.threadId);
|
||||
button.element.classList.toggle('hide', !good);
|
||||
return good;
|
||||
});
|
||||
@ -1328,7 +1328,7 @@ export default class ChatInput {
|
||||
|
||||
if(this.stickersHelper &&
|
||||
rootScope.settings.stickers.suggest &&
|
||||
(this.chat.peerId > 0 || this.appChatsManager.hasRights(this.chat.peerId, 'send_stickers')) &&
|
||||
this.appMessagesManager.canSendToPeer(this.chat.peerId, this.chat.threadId, 'send_stickers') &&
|
||||
entity?._ === 'messageEntityEmoji' && entity.length === value.length && !entity.offset) {
|
||||
foundHelper = this.stickersHelper;
|
||||
this.stickersHelper.checkEmoticon(value);
|
||||
@ -1414,7 +1414,7 @@ export default class ChatInput {
|
||||
this.sendMessage();
|
||||
}
|
||||
} else {
|
||||
if(this.chat.peerId < 0 && !this.appChatsManager.hasRights(this.chat.peerId, 'send_media')) {
|
||||
if(this.chat.peerId < 0 && !this.appMessagesManager.canSendToPeer(this.chat.peerId, this.chat.threadId, 'send_media')) {
|
||||
toast(POSTING_MEDIA_NOT_ALLOWED);
|
||||
return;
|
||||
}
|
||||
@ -1694,7 +1694,7 @@ export default class ChatInput {
|
||||
document = this.appDocsManager.getDoc(document);
|
||||
|
||||
const flag = document.type === 'sticker' ? 'send_stickers' : (document.type === 'gif' ? 'send_gifs' : 'send_media');
|
||||
if(this.chat.peerId < 0 && !this.appChatsManager.hasRights(this.chat.peerId, flag)) {
|
||||
if(this.chat.peerId < 0 && !this.appMessagesManager.canSendToPeer(this.chat.peerId, this.chat.threadId, flag)) {
|
||||
toast(POSTING_MEDIA_NOT_ALLOWED);
|
||||
return false;
|
||||
}
|
||||
|
@ -314,7 +314,7 @@ export default class ChatTopbar {
|
||||
icon: 'delete danger',
|
||||
text: 'Delete',
|
||||
onClick: () => {
|
||||
new PopupDeleteDialog(this.peerId);
|
||||
new PopupDeleteDialog(this.peerId/* , 'leave' */);
|
||||
},
|
||||
verify: () => this.chat.type === 'chat' && !!this.appMessagesManager.getDialogOnly(this.peerId)
|
||||
}];
|
||||
@ -377,8 +377,7 @@ export default class ChatTopbar {
|
||||
});
|
||||
}, {listenerSetter: this.listenerSetter});
|
||||
|
||||
this.listenerSetter.add(rootScope)('chat_update', (e) => {
|
||||
const chatId: number = e;
|
||||
this.listenerSetter.add(rootScope)('chat_update', (chatId) => {
|
||||
if(this.peerId === -chatId) {
|
||||
const chat = this.appChatsManager.getChat(chatId) as Channel/* | Chat */;
|
||||
|
||||
|
@ -149,7 +149,7 @@ export default class DialogsContextMenu {
|
||||
};
|
||||
|
||||
private onDeleteClick = () => {
|
||||
new PopupDeleteDialog(this.selectedId);
|
||||
new PopupDeleteDialog(this.selectedId/* , 'delete' */);
|
||||
};
|
||||
|
||||
onContextMenu = (e: MouseEvent | Touch) => {
|
||||
|
@ -5,7 +5,6 @@
|
||||
*/
|
||||
|
||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||
import appChatsManager from "../../lib/appManagers/appChatsManager";
|
||||
import appImManager from "../../lib/appManagers/appImManager";
|
||||
import rootScope from "../../lib/rootScope";
|
||||
import animationIntersector from "../animationIntersector";
|
||||
@ -27,6 +26,7 @@ import whichChild from "../../helpers/dom/whichChild";
|
||||
import { cancelEvent } from "../../helpers/dom/cancelEvent";
|
||||
import DropdownHover from "../../helpers/dropdownHover";
|
||||
import { pause } from "../../helpers/schedulers/pause";
|
||||
import appMessagesManager from "../../lib/appManagers/appMessagesManager";
|
||||
|
||||
export const EMOTICONSSTICKERGROUP = 'emoticons-dropdown';
|
||||
|
||||
@ -188,14 +188,14 @@ export class EmoticonsDropdown extends DropdownHover {
|
||||
};
|
||||
|
||||
private checkRights = () => {
|
||||
const peerId = appImManager.chat.peerId;
|
||||
const {peerId, threadId} = appImManager.chat;
|
||||
const children = this.tabsEl.children;
|
||||
const tabsElements = Array.from(children) as HTMLElement[];
|
||||
|
||||
const canSendStickers = peerId > 0 || appChatsManager.hasRights(peerId, 'send_stickers');
|
||||
const canSendStickers = appMessagesManager.canSendToPeer(peerId, threadId, 'send_stickers');
|
||||
tabsElements[2].toggleAttribute('disabled', !canSendStickers);
|
||||
|
||||
const canSendGifs = peerId > 0 || appChatsManager.hasRights(peerId, 'send_gifs');
|
||||
const canSendGifs = appMessagesManager.canSendToPeer(peerId, threadId, 'send_gifs');
|
||||
tabsElements[3].toggleAttribute('disabled', !canSendGifs);
|
||||
|
||||
const active = this.tabsEl.querySelector('.active');
|
||||
|
@ -7,14 +7,13 @@
|
||||
import appDownloadManager from "../../lib/appManagers/appDownloadManager";
|
||||
import resizeableImage from "../../lib/cropper";
|
||||
import PopupElement from ".";
|
||||
import { ripple } from "../ripple";
|
||||
import { _i18n } from "../../lib/langPack";
|
||||
import { readBlobAsDataURL } from "../../helpers/blob";
|
||||
import { attachClickEvent } from "../../helpers/dom/clickEvent";
|
||||
|
||||
export default class PopupAvatar extends PopupElement {
|
||||
private cropContainer: HTMLElement;
|
||||
private input: HTMLInputElement;
|
||||
private btnSubmit: HTMLElement;
|
||||
private h6: HTMLElement;
|
||||
|
||||
private image = new Image();
|
||||
@ -29,7 +28,7 @@ export default class PopupAvatar extends PopupElement {
|
||||
private onCrop: (upload: () => ReturnType<typeof appDownloadManager.upload>) => void;
|
||||
|
||||
constructor() {
|
||||
super('popup-avatar', null, {closable: true});
|
||||
super('popup-avatar', null, {closable: true, withConfirm: true});
|
||||
|
||||
this.h6 = document.createElement('h6');
|
||||
_i18n(this.h6, 'Popup.Avatar.Title');
|
||||
@ -45,7 +44,7 @@ export default class PopupAvatar extends PopupElement {
|
||||
this.input = document.createElement('input');
|
||||
this.input.type = 'file';
|
||||
this.input.style.display = 'none';
|
||||
this.input.addEventListener('change', (e: any) => {
|
||||
this.listenerSetter.add(this.input)('change', (e: any) => {
|
||||
const file = e.target.files[0];
|
||||
if(!file) {
|
||||
return;
|
||||
@ -68,21 +67,19 @@ export default class PopupAvatar extends PopupElement {
|
||||
});
|
||||
}, false);
|
||||
|
||||
this.btnSubmit = document.createElement('button');
|
||||
this.btnSubmit.className = 'btn-primary btn-color-primary btn-circle btn-crop btn-icon tgico-check z-depth-1';
|
||||
ripple(this.btnSubmit);
|
||||
this.btnSubmit.addEventListener('click', () => {
|
||||
this.btnConfirm.className = 'btn-primary btn-color-primary btn-circle btn-crop btn-icon tgico-check z-depth-1';
|
||||
attachClickEvent(this.btnConfirm, () => {
|
||||
this.cropper.crop();
|
||||
this.btnClose.click();
|
||||
this.hide();
|
||||
|
||||
this.canvas.toBlob(blob => {
|
||||
this.blob = blob; // save blob to send after reg
|
||||
this.darkenCanvas();
|
||||
this.resolve();
|
||||
}, 'image/jpeg', 1);
|
||||
});
|
||||
}, {listenerSetter: this.listenerSetter});
|
||||
|
||||
this.container.append(this.cropContainer, this.btnSubmit, this.input);
|
||||
this.container.append(this.cropContainer, this.btnConfirm, this.input);
|
||||
|
||||
this.onCloseAfterTimeout = () => {
|
||||
this.cropper.removeHandlers();
|
||||
|
@ -18,6 +18,7 @@ import { cancelEvent } from "../../helpers/dom/cancelEvent";
|
||||
import getRichValue from "../../helpers/dom/getRichValue";
|
||||
import isInputEmpty from "../../helpers/dom/isInputEmpty";
|
||||
import whichChild from "../../helpers/dom/whichChild";
|
||||
import { attachClickEvent } from "../../helpers/dom/clickEvent";
|
||||
|
||||
const MAX_LENGTH_QUESTION = 255;
|
||||
const MAX_LENGTH_OPTION = 100;
|
||||
@ -49,7 +50,7 @@ export default class PopupCreatePoll extends PopupElement {
|
||||
maxLength: MAX_LENGTH_QUESTION
|
||||
});
|
||||
|
||||
this.questionInputField.input.addEventListener('input', () => {
|
||||
this.listenerSetter.add(this.questionInputField.input)('input', () => {
|
||||
this.handleChange();
|
||||
});
|
||||
|
||||
@ -110,12 +111,12 @@ export default class PopupCreatePoll extends PopupElement {
|
||||
name: 'quiz'
|
||||
});
|
||||
|
||||
this.multipleCheckboxField.input.addEventListener('change', () => {
|
||||
this.listenerSetter.add(this.multipleCheckboxField.input)('change', () => {
|
||||
const checked = this.multipleCheckboxField.input.checked;
|
||||
this.quizCheckboxField.input.toggleAttribute('disabled', checked);
|
||||
});
|
||||
|
||||
this.quizCheckboxField.input.addEventListener('change', () => {
|
||||
this.listenerSetter.add(this.quizCheckboxField.input)('change', () => {
|
||||
const checked = this.quizCheckboxField.input.checked;
|
||||
|
||||
(Array.from(this.questions.children) as HTMLElement[]).map(el => {
|
||||
@ -153,7 +154,7 @@ export default class PopupCreatePoll extends PopupElement {
|
||||
maxLength: MAX_LENGTH_SOLUTION
|
||||
});
|
||||
|
||||
this.questionInputField.input.addEventListener('input', () => {
|
||||
this.listenerSetter.add(this.questionInputField.input)('input', () => {
|
||||
this.handleChange();
|
||||
});
|
||||
|
||||
@ -169,7 +170,7 @@ export default class PopupCreatePoll extends PopupElement {
|
||||
this.body.parentElement.insertBefore(hr, this.body);
|
||||
this.body.append(d, this.questions, document.createElement('hr'), settingsCaption, dd, ...quizElements);
|
||||
|
||||
this.btnConfirm.addEventListener('click', this.onSubmitClick);
|
||||
attachClickEvent(this.btnConfirm, this.onSubmitClick, {listenerSetter: this.listenerSetter});
|
||||
|
||||
this.scrollable = new Scrollable(this.body);
|
||||
this.appendMoreField();
|
||||
@ -246,8 +247,7 @@ export default class PopupCreatePoll extends PopupElement {
|
||||
return;
|
||||
}
|
||||
|
||||
this.btnClose.click();
|
||||
this.btnConfirm.removeEventListener('click', this.onSubmitClick);
|
||||
this.hide();
|
||||
|
||||
//const randomID = [nextRandomInt(0xFFFFFFFF), nextRandomInt(0xFFFFFFFF)];
|
||||
//const randomIDS = bigint(randomID[0]).shiftLeft(32).add(bigint(randomID[1])).toString();
|
||||
@ -350,20 +350,20 @@ export default class PopupCreatePoll extends PopupElement {
|
||||
name: 'question-' + tempId,
|
||||
maxLength: MAX_LENGTH_OPTION
|
||||
});
|
||||
questionField.input.addEventListener('input', this.onInput);
|
||||
this.listenerSetter.add(questionField.input)('input', this.onInput);
|
||||
|
||||
const radioField = new RadioField({
|
||||
text: '',
|
||||
name: 'question'
|
||||
});
|
||||
radioField.main.append(questionField.container);
|
||||
questionField.input.addEventListener('click', cancelEvent);
|
||||
attachClickEvent(questionField.input, cancelEvent, {listenerSetter: this.listenerSetter});
|
||||
radioField.label.classList.add('hidden-widget');
|
||||
radioField.input.disabled = true;
|
||||
if(!this.quizCheckboxField.input.checked) {
|
||||
radioField.label.classList.remove('radio-field');
|
||||
}
|
||||
radioField.input.addEventListener('change', () => {
|
||||
this.listenerSetter.add(radioField.input)('change', () => {
|
||||
const checked = radioField.input.checked;
|
||||
if(checked) {
|
||||
const idx = whichChild(radioField.label);
|
||||
@ -376,7 +376,7 @@ export default class PopupCreatePoll extends PopupElement {
|
||||
deleteBtn.classList.add('btn-icon', 'tgico-close');
|
||||
questionField.container.append(deleteBtn);
|
||||
|
||||
deleteBtn.addEventListener('click', this.onDeleteClick, {once: true});
|
||||
attachClickEvent(deleteBtn, this.onDeleteClick, {listenerSetter: this.listenerSetter, once: true});
|
||||
|
||||
this.questions.append(radioField.label);
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
import PopupElement, { PopupOptions } from ".";
|
||||
import { attachClickEvent } from "../../helpers/dom/clickEvent";
|
||||
import mediaSizes from "../../helpers/mediaSizes";
|
||||
import I18n, { i18n, LangPackKey } from "../../lib/langPack";
|
||||
import InputField from "../inputField";
|
||||
@ -62,11 +63,11 @@ export default class PopupDatePicker extends PopupElement {
|
||||
|
||||
this.prevBtn = document.createElement('button');
|
||||
this.prevBtn.classList.add('btn-icon', 'tgico-down', 'date-picker-prev');
|
||||
this.prevBtn.addEventListener('click', this.onPrevClick);
|
||||
attachClickEvent(this.prevBtn, this.onPrevClick, {listenerSetter: this.listenerSetter});
|
||||
|
||||
this.nextBtn = document.createElement('button');
|
||||
this.nextBtn.classList.add('btn-icon', 'tgico-down', 'date-picker-next');
|
||||
this.nextBtn.addEventListener('click', this.onNextClick);
|
||||
attachClickEvent(this.nextBtn, this.onNextClick, {listenerSetter: this.listenerSetter});
|
||||
|
||||
this.monthTitle = document.createElement('div');
|
||||
this.monthTitle.classList.add('date-picker-month-title');
|
||||
@ -76,7 +77,7 @@ export default class PopupDatePicker extends PopupElement {
|
||||
// Month
|
||||
this.monthsContainer = document.createElement('div');
|
||||
this.monthsContainer.classList.add('date-picker-months');
|
||||
this.monthsContainer.addEventListener('click', this.onDateClick);
|
||||
attachClickEvent(this.monthsContainer, this.onDateClick, {listenerSetter: this.listenerSetter});
|
||||
|
||||
this.body.append(this.controlsDiv, this.monthsContainer);
|
||||
|
||||
@ -91,7 +92,7 @@ export default class PopupDatePicker extends PopupElement {
|
||||
|
||||
const handleTimeInput = (max: number, inputField: InputField, onInput: (length: number) => void, onOverflow?: (number: number) => void) => {
|
||||
const maxString = '' + max;
|
||||
inputField.input.addEventListener('input', (e) => {
|
||||
this.listenerSetter.add(inputField.input)('input', (e) => {
|
||||
let value = inputField.value.replace(/\D/g, '');
|
||||
if(value.length > 2) {
|
||||
value = value.slice(0, 2);
|
||||
@ -141,14 +142,14 @@ export default class PopupDatePicker extends PopupElement {
|
||||
|
||||
this.timeDiv.append(this.hoursInputField.container, delimiter, this.minutesInputField.container);
|
||||
|
||||
this.btnConfirm.addEventListener('click', () => {
|
||||
attachClickEvent(this.btnClose, () => {
|
||||
if(this.onPick) {
|
||||
this.selectedDate.setHours(+this.hoursInputField.value || 0, +this.minutesInputField.value || 0, 0, 0);
|
||||
this.onPick(this.selectedDate.getTime() / 1000 | 0);
|
||||
}
|
||||
|
||||
this.hide();
|
||||
}, {once: true});
|
||||
}, {listenerSetter: this.listenerSetter});
|
||||
|
||||
this.body.append(this.timeDiv);
|
||||
|
||||
|
@ -12,7 +12,12 @@ import PeerTitle from "../peerTitle";
|
||||
import PopupPeer, { PopupPeerButtonCallbackCheckboxes, PopupPeerOptions } from "./peer";
|
||||
|
||||
export default class PopupDeleteDialog {
|
||||
constructor(peerId: number, peerType: PeerType = appPeersManager.getDialogType(peerId), onSelect?: (promise: Promise<any>) => void) {
|
||||
constructor(
|
||||
peerId: number,
|
||||
// actionType: 'leave' | 'delete',
|
||||
peerType: PeerType = appPeersManager.getDialogType(peerId),
|
||||
onSelect?: (promise: Promise<any>) => void
|
||||
) {
|
||||
const peerTitleElement = new PeerTitle({peerId}).element;
|
||||
|
||||
/* const callbackFlush = (checked: PopupPeerButtonCallbackCheckboxes) => {
|
||||
@ -51,14 +56,29 @@ export default class PopupDeleteDialog {
|
||||
let title: LangPackKey, description: LangPackKey, descriptionArgs: any[], buttons: PopupPeerOptions['buttons'], checkboxes: PopupPeerOptions['checkboxes'];
|
||||
switch(peerType) {
|
||||
case 'channel': {
|
||||
title = 'LeaveChannelMenu';
|
||||
description = 'ChannelLeaveAlertWithName';
|
||||
descriptionArgs = [peerTitleElement];
|
||||
buttons = [{
|
||||
langKey: 'LeaveChannel',
|
||||
isDanger: true,
|
||||
callback: callbackLeave
|
||||
}];
|
||||
if(/* actionType === 'delete' && */appChatsManager.hasRights(-peerId, 'delete_chat')) {
|
||||
appChatsManager.deleteChannel
|
||||
title = 'ChannelDeleteMenu';
|
||||
description = 'AreYouSureDeleteAndExitChannel';
|
||||
buttons = [{
|
||||
langKey: 'ChannelDeleteMenu',
|
||||
isDanger: true,
|
||||
callback: callbackDelete
|
||||
}];
|
||||
|
||||
checkboxes = [{
|
||||
text: 'DeleteChannelForAll'
|
||||
}];
|
||||
} else {
|
||||
title = 'LeaveChannelMenu';
|
||||
description = 'ChannelLeaveAlertWithName';
|
||||
descriptionArgs = [peerTitleElement];
|
||||
buttons = [{
|
||||
langKey: 'LeaveChannel',
|
||||
isDanger: true,
|
||||
callback: callbackLeave
|
||||
}];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
@ -80,6 +100,12 @@ export default class PopupDeleteDialog {
|
||||
description = 'AreYouSureDeleteThisChatWithUser';
|
||||
descriptionArgs = [peerTitleElement];
|
||||
|
||||
buttons = [{
|
||||
langKey: 'DeleteChatUser',
|
||||
isDanger: true,
|
||||
callback: callbackDelete
|
||||
}];
|
||||
|
||||
checkboxes = [{
|
||||
text: 'DeleteMessagesOptionAlso',
|
||||
textArgs: [
|
||||
@ -87,12 +113,6 @@ export default class PopupDeleteDialog {
|
||||
]
|
||||
}];
|
||||
|
||||
buttons = [{
|
||||
langKey: 'DeleteChatUser',
|
||||
isDanger: true,
|
||||
callback: callbackDelete
|
||||
}];
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -110,7 +130,7 @@ export default class PopupDeleteDialog {
|
||||
|
||||
case 'megagroup':
|
||||
case 'group': {
|
||||
if(appChatsManager.hasRights(-peerId, 'delete_chat')) {
|
||||
if(/* actionType === 'delete' && */appChatsManager.hasRights(-peerId, 'delete_chat')) {
|
||||
title = 'DeleteMegaMenu';
|
||||
description = 'AreYouSureDeleteAndExit';
|
||||
buttons = [{
|
||||
|
@ -12,6 +12,9 @@ import { i18n, LangPackKey } from "../../lib/langPack";
|
||||
import findUpClassName from "../../helpers/dom/findUpClassName";
|
||||
import blurActiveElement from "../../helpers/dom/blurActiveElement";
|
||||
import ListenerSetter from "../../helpers/listenerSetter";
|
||||
import { attachClickEvent, simulateClickEvent } from "../../helpers/dom/clickEvent";
|
||||
import isSendShortcutPressed from "../../helpers/dom/isSendShortcutPressed";
|
||||
import { cancelEvent } from "../../helpers/dom/cancelEvent";
|
||||
|
||||
export type PopupButton = {
|
||||
text?: string,
|
||||
@ -19,14 +22,16 @@ export type PopupButton = {
|
||||
langKey?: LangPackKey,
|
||||
langArgs?: any[],
|
||||
isDanger?: true,
|
||||
isCancel?: true
|
||||
isCancel?: true,
|
||||
element?: HTMLButtonElement
|
||||
};
|
||||
|
||||
export type PopupOptions = Partial<{
|
||||
closable: true,
|
||||
overlayClosable: true,
|
||||
withConfirm: LangPackKey | true,
|
||||
body: true
|
||||
body: true,
|
||||
confirmShortcutIsSendShortcut: boolean
|
||||
}>;
|
||||
|
||||
export default class PopupElement {
|
||||
@ -47,6 +52,9 @@ export default class PopupElement {
|
||||
|
||||
protected listenerSetter: ListenerSetter;
|
||||
|
||||
protected confirmShortcutIsSendShortcut: boolean;
|
||||
protected btnConfirmOnEnter: HTMLButtonElement;
|
||||
|
||||
constructor(className: string, buttons?: Array<PopupButton>, options: PopupOptions = {}) {
|
||||
this.element.classList.add('popup');
|
||||
this.element.className = 'popup' + (className ? ' ' + className : '');
|
||||
@ -59,24 +67,23 @@ export default class PopupElement {
|
||||
|
||||
this.listenerSetter = new ListenerSetter();
|
||||
|
||||
this.confirmShortcutIsSendShortcut = options.confirmShortcutIsSendShortcut;
|
||||
|
||||
if(options.closable) {
|
||||
this.btnClose = document.createElement('span');
|
||||
this.btnClose.classList.add('btn-icon', 'popup-close', 'tgico-close');
|
||||
//ripple(this.closeBtn);
|
||||
this.header.prepend(this.btnClose);
|
||||
|
||||
this.btnClose.addEventListener('click', this.hide, {once: true});
|
||||
attachClickEvent(this.btnClose, this.hide, {listenerSetter: this.listenerSetter, once: true});
|
||||
}
|
||||
|
||||
if(options.overlayClosable) {
|
||||
const onOverlayClick = (e: MouseEvent) => {
|
||||
attachClickEvent(this.element, (e: MouseEvent) => {
|
||||
if(!findUpClassName(e.target, 'popup-container')) {
|
||||
this.hide();
|
||||
this.element.removeEventListener('click', onOverlayClick);
|
||||
}
|
||||
};
|
||||
|
||||
this.element.addEventListener('click', onOverlayClick);
|
||||
}, {listenerSetter: this.listenerSetter});
|
||||
}
|
||||
|
||||
if(options.withConfirm) {
|
||||
@ -96,6 +103,7 @@ export default class PopupElement {
|
||||
this.container.append(this.body);
|
||||
}
|
||||
|
||||
let btnConfirmOnEnter = this.btnConfirm;
|
||||
if(buttons && buttons.length) {
|
||||
const buttonsDiv = this.buttons = document.createElement('div');
|
||||
buttonsDiv.classList.add('popup-buttons');
|
||||
@ -103,11 +111,11 @@ export default class PopupElement {
|
||||
if(buttons.length === 2) {
|
||||
buttonsDiv.classList.add('popup-buttons-row');
|
||||
}
|
||||
|
||||
|
||||
const buttonsElements = buttons.map(b => {
|
||||
const button = document.createElement('button');
|
||||
button.className = 'btn' + (b.isDanger ? ' danger' : ' primary');
|
||||
|
||||
|
||||
ripple(button);
|
||||
|
||||
if(b.text) {
|
||||
@ -115,25 +123,28 @@ export default class PopupElement {
|
||||
} else {
|
||||
button.append(i18n(b.langKey, b.langArgs));
|
||||
}
|
||||
|
||||
if(b.callback) {
|
||||
button.addEventListener('click', () => {
|
||||
b.callback();
|
||||
this.destroy();
|
||||
}, {once: true});
|
||||
} else if(b.isCancel) {
|
||||
button.addEventListener('click', () => {
|
||||
this.destroy();
|
||||
}, {once: true});
|
||||
}
|
||||
|
||||
return button;
|
||||
|
||||
attachClickEvent(button, () => {
|
||||
b.callback && b.callback();
|
||||
this.destroy();
|
||||
}, {listenerSetter: this.listenerSetter, once: true});
|
||||
|
||||
return b.element = button;
|
||||
});
|
||||
|
||||
|
||||
if(!btnConfirmOnEnter && buttons.length === 2) {
|
||||
const button = buttons.find(button => !button.isCancel);
|
||||
if(button) {
|
||||
btnConfirmOnEnter = button.element;
|
||||
}
|
||||
}
|
||||
|
||||
buttonsDiv.append(...buttonsElements);
|
||||
this.container.append(buttonsDiv);
|
||||
}
|
||||
|
||||
this.btnConfirmOnEnter = btnConfirmOnEnter;
|
||||
|
||||
this.element.append(this.container);
|
||||
}
|
||||
|
||||
@ -152,6 +163,13 @@ export default class PopupElement {
|
||||
this.element.classList.add('active');
|
||||
rootScope.isOverlayActive = true;
|
||||
animationIntersector.checkAnimations(true);
|
||||
|
||||
this.listenerSetter.add(document.body)('keydown', (e) => {
|
||||
if(this.confirmShortcutIsSendShortcut ? isSendShortcutPressed(e) : e.key === 'Enter') {
|
||||
simulateClickEvent(this.btnConfirmOnEnter);
|
||||
cancelEvent(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public hide = () => {
|
||||
@ -164,7 +182,6 @@ export default class PopupElement {
|
||||
this.element.classList.remove('active');
|
||||
this.listenerSetter.removeAll();
|
||||
|
||||
if(this.btnClose) this.btnClose.removeEventListener('click', this.hide);
|
||||
rootScope.isOverlayActive = false;
|
||||
|
||||
appNavigationController.removeItem(this.navigationItem);
|
||||
|
@ -17,11 +17,11 @@ import { MyDocument } from "../../lib/appManagers/appDocsManager";
|
||||
import I18n, { i18n, LangPackKey } from "../../lib/langPack";
|
||||
import appDownloadManager from "../../lib/appManagers/appDownloadManager";
|
||||
import calcImageInBox from "../../helpers/calcImageInBox";
|
||||
import isSendShortcutPressed from "../../helpers/dom/isSendShortcutPressed";
|
||||
import placeCaretAtEnd from "../../helpers/dom/placeCaretAtEnd";
|
||||
import rootScope from "../../lib/rootScope";
|
||||
import RichTextProcessor from "../../lib/richtextprocessor";
|
||||
import { MediaSize } from "../../helpers/mediaSizes";
|
||||
import { attachClickEvent } from "../../helpers/dom/clickEvent";
|
||||
|
||||
type SendFileParams = Partial<{
|
||||
file: File,
|
||||
@ -57,11 +57,11 @@ export default class PopupNewMedia extends PopupElement {
|
||||
private inputField: InputField;
|
||||
|
||||
constructor(private chat: Chat, files: File[], willAttachType: PopupNewMedia['willAttach']['type']) {
|
||||
super('popup-send-photo popup-new-media', null, {closable: true, withConfirm: 'Modal.Send'});
|
||||
super('popup-send-photo popup-new-media', null, {closable: true, withConfirm: 'Modal.Send', confirmShortcutIsSendShortcut: true});
|
||||
|
||||
this.willAttach.type = willAttachType;
|
||||
|
||||
this.btnConfirm.addEventListener('click', () => this.send());
|
||||
attachClickEvent(this.btnConfirm, () => this.send(), {listenerSetter: this.listenerSetter});
|
||||
|
||||
if(this.chat.type !== 'scheduled') {
|
||||
const sendMenu = new SendContextMenu({
|
||||
@ -76,6 +76,7 @@ export default class PopupNewMedia extends PopupElement {
|
||||
},
|
||||
openSide: 'bottom-left',
|
||||
onContextElement: this.btnConfirm,
|
||||
listenerSetter: this.listenerSetter
|
||||
});
|
||||
|
||||
sendMenu.setPeerId(this.chat.peerId);
|
||||
@ -112,7 +113,7 @@ export default class PopupNewMedia extends PopupElement {
|
||||
this.groupCheckboxField.input.checked = true;
|
||||
this.willAttach.group = true;
|
||||
|
||||
this.groupCheckboxField.input.addEventListener('change', () => {
|
||||
this.listenerSetter.add(this.groupCheckboxField.input)('change', () => {
|
||||
const checked = this.groupCheckboxField.input.checked;
|
||||
|
||||
this.willAttach.group = checked;
|
||||
@ -139,10 +140,6 @@ export default class PopupNewMedia extends PopupElement {
|
||||
this.input.focus();
|
||||
placeCaretAtEnd(this.input);
|
||||
}
|
||||
|
||||
if(isSendShortcutPressed(e)) {
|
||||
this.btnConfirm.click();
|
||||
}
|
||||
};
|
||||
|
||||
public send(force = false) {
|
||||
@ -455,13 +452,11 @@ export default class PopupNewMedia extends PopupElement {
|
||||
|
||||
// show now
|
||||
if(!this.element.classList.contains('active')) {
|
||||
document.body.addEventListener('keydown', this.onKeyDown);
|
||||
this.listenerSetter.add(document.body)('keydown', this.onKeyDown);
|
||||
this.onClose = () => {
|
||||
if(this.wasInputValue) {
|
||||
this.chat.input.messageInputField.value = this.wasInputValue;
|
||||
}
|
||||
|
||||
document.body.removeEventListener('keydown', this.onKeyDown);
|
||||
};
|
||||
this.show();
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import { attachClickEvent } from "../../helpers/dom/clickEvent";
|
||||
import findUpClassName from "../../helpers/dom/findUpClassName";
|
||||
import whichChild from "../../helpers/dom/whichChild";
|
||||
import { ReportReason } from "../../layer";
|
||||
@ -35,7 +36,7 @@ export default class PopupReportMessages extends PopupPeer {
|
||||
|
||||
const preloadStickerPromise = appStickersManager.preloadAnimatedEmojiSticker(PopupReportMessagesConfirm.STICKER_EMOJI);
|
||||
|
||||
this.body.addEventListener('click', (e) => {
|
||||
attachClickEvent(this.body, (e) => {
|
||||
const target = findUpClassName(e.target, 'btn-primary');
|
||||
const reason = buttons[whichChild(target)][1];
|
||||
|
||||
@ -44,7 +45,7 @@ export default class PopupReportMessages extends PopupPeer {
|
||||
|
||||
new PopupReportMessagesConfirm(peerId, mids, reason, onConfirm);
|
||||
});
|
||||
});
|
||||
}, {listenerSetter: this.listenerSetter});
|
||||
|
||||
this.body.style.margin = '0 -1rem';
|
||||
this.buttons.style.marginTop = '.5rem';
|
||||
|
@ -37,7 +37,8 @@ export default class PopupSchedule extends PopupDatePicker {
|
||||
minDate: getMinDate(),
|
||||
maxDate: getMaxDate(),
|
||||
withTime: true,
|
||||
showOverflowMonths: true
|
||||
showOverflowMonths: true,
|
||||
confirmShortcutIsSendShortcut: true
|
||||
});
|
||||
|
||||
this.element.classList.add('popup-schedule');
|
||||
|
@ -19,6 +19,7 @@ import { i18n } from "../../lib/langPack";
|
||||
import Button from "../button";
|
||||
import findUpClassName from "../../helpers/dom/findUpClassName";
|
||||
import toggleDisability from "../../helpers/dom/toggleDisability";
|
||||
import { attachClickEvent } from "../../helpers/dom/clickEvent";
|
||||
|
||||
const ANIMATION_GROUP = 'STICKERS-POPUP';
|
||||
|
||||
@ -39,8 +40,6 @@ export default class PopupStickers extends PopupElement {
|
||||
|
||||
this.onClose = () => {
|
||||
animationIntersector.setOnlyOnePlayableGroup('');
|
||||
this.stickersFooter.removeEventListener('click', this.onFooterClick);
|
||||
this.stickersDiv.removeEventListener('click', this.onStickersClick);
|
||||
};
|
||||
|
||||
const div = document.createElement('div');
|
||||
@ -49,6 +48,8 @@ export default class PopupStickers extends PopupElement {
|
||||
this.stickersDiv = document.createElement('div');
|
||||
this.stickersDiv.classList.add('sticker-set-stickers', 'is-loading');
|
||||
|
||||
attachClickEvent(this.stickersDiv, this.onStickersClick, {listenerSetter: this.listenerSetter});
|
||||
|
||||
putPreloader(this.stickersDiv, true);
|
||||
|
||||
this.stickersFooter = document.createElement('div');
|
||||
@ -71,17 +72,7 @@ export default class PopupStickers extends PopupElement {
|
||||
this.loadStickerSet();
|
||||
}
|
||||
|
||||
onFooterClick = () => {
|
||||
const toggle = toggleDisability([this.stickersFooter], true);
|
||||
|
||||
appStickersManager.toggleStickerSet(this.set).then(() => {
|
||||
this.hide();
|
||||
}).catch(() => {
|
||||
toggle();
|
||||
});
|
||||
};
|
||||
|
||||
onStickersClick = (e: MouseEvent) => {
|
||||
private onStickersClick = (e: MouseEvent) => {
|
||||
const target = findUpClassName(e.target, 'sticker-set-sticker');
|
||||
if(!target) return;
|
||||
|
||||
@ -116,11 +107,15 @@ export default class PopupStickers extends PopupElement {
|
||||
this.stickersFooter.textContent = '';
|
||||
this.stickersFooter.append(button);
|
||||
|
||||
button.addEventListener('click', this.onFooterClick);
|
||||
attachClickEvent(button, () => {
|
||||
const toggle = toggleDisability([button], true);
|
||||
|
||||
if(set.documents.length) {
|
||||
this.stickersDiv.addEventListener('click', this.onStickersClick);
|
||||
}
|
||||
appStickersManager.toggleStickerSet(this.set).then(() => {
|
||||
this.hide();
|
||||
}).catch(() => {
|
||||
toggle();
|
||||
});
|
||||
});
|
||||
|
||||
const lazyLoadQueue = new LazyLoadQueue();
|
||||
|
||||
|
@ -35,12 +35,12 @@ export default class AppNewChannelTab extends SliderSuperTab {
|
||||
inputWrapper.classList.add('input-wrapper');
|
||||
|
||||
this.channelNameInputField = new InputField({
|
||||
label: 'Channel.ChannelNameHolder',
|
||||
label: 'EnterChannelName',
|
||||
maxLength: 128
|
||||
});
|
||||
|
||||
this.channelDescriptionInputField = new InputField({
|
||||
label: 'Channel.DescriptionPlaceholder',
|
||||
label: 'DescriptionOptionalPlaceholder',
|
||||
maxLength: 255
|
||||
});
|
||||
|
||||
|
@ -18,7 +18,6 @@ import rootScope from "../../../lib/rootScope";
|
||||
import AppGroupPermissionsTab from "./groupPermissions";
|
||||
import { i18n, LangPackKey } from "../../../lib/langPack";
|
||||
import PopupDeleteDialog from "../../popups/deleteDialog";
|
||||
import { addCancelButton } from "../../popups";
|
||||
import PopupPeer from "../../popups/peer";
|
||||
import { attachClickEvent } from "../../../helpers/dom/clickEvent";
|
||||
import toggleDisability from "../../../helpers/dom/toggleDisability";
|
||||
@ -63,7 +62,7 @@ export default class AppEditChatTab extends SliderSuperTab {
|
||||
inputWrapper.classList.add('input-wrapper');
|
||||
|
||||
this.chatNameInputField = new InputField({
|
||||
label: isBroadcast ? 'Channel.ChannelNameHolder' : 'CreateGroup.NameHolder',
|
||||
label: isBroadcast ? 'EnterChannelName' : 'CreateGroup.NameHolder',
|
||||
name: 'chat-name',
|
||||
maxLength: 255,
|
||||
required: true
|
||||
@ -281,45 +280,17 @@ export default class AppEditChatTab extends SliderSuperTab {
|
||||
if(appChatsManager.hasRights(this.chatId, 'delete_chat')) {
|
||||
const section = new SettingSection({});
|
||||
|
||||
const btnDelete = Button('btn-primary btn-transparent danger', {icon: 'delete', text: isBroadcast ? 'PeerInfo.DeleteChannel' : 'DeleteMega'});
|
||||
const btnDelete = Button('btn-primary btn-transparent danger', {icon: 'delete', text: isBroadcast ? 'PeerInfo.DeleteChannel' : 'DeleteAndExitButton'});
|
||||
|
||||
attachClickEvent(btnDelete, () => {
|
||||
if(isBroadcast) {
|
||||
new PopupPeer('popup-delete-channel', {
|
||||
peerId: -this.chatId,
|
||||
titleLangKey: 'ChannelDeleteMenu',
|
||||
descriptionLangKey: 'AreYouSureDeleteAndExitChannel',
|
||||
buttons: addCancelButton([{
|
||||
langKey: 'ChannelDeleteMenu',
|
||||
callback: () => {
|
||||
const toggle = toggleDisability([btnDelete], true);
|
||||
|
||||
},
|
||||
isDanger: true
|
||||
}, {
|
||||
langKey: 'DeleteChannelForAll',
|
||||
callback: () => {
|
||||
const toggle = toggleDisability([btnDelete], true);
|
||||
|
||||
appChatsManager.deleteChannel(this.chatId).then(() => {
|
||||
this.close();
|
||||
}, () => {
|
||||
toggle();
|
||||
});
|
||||
},
|
||||
isDanger: true
|
||||
}])
|
||||
}).show();
|
||||
} else {
|
||||
new PopupDeleteDialog(-this.chatId, undefined, (promise) => {
|
||||
const toggle = toggleDisability([btnDelete], true);
|
||||
promise.then(() => {
|
||||
this.close();
|
||||
}, () => {
|
||||
toggle();
|
||||
});
|
||||
new PopupDeleteDialog(-this.chatId/* , 'delete' */, undefined, (promise) => {
|
||||
const toggle = toggleDisability([btnDelete], true);
|
||||
promise.then(() => {
|
||||
this.close();
|
||||
}, () => {
|
||||
toggle();
|
||||
});
|
||||
}
|
||||
});
|
||||
}, {listenerSetter: this.listenerSetter});
|
||||
|
||||
section.content.append(btnDelete);
|
||||
|
@ -810,7 +810,7 @@ export default class AppSharedMediaTab extends SliderSuperTab {
|
||||
private searchSuper: AppSearchSuper;
|
||||
|
||||
private profile: PeerProfile;
|
||||
peerChanged: boolean;
|
||||
private peerChanged: boolean;
|
||||
|
||||
constructor(slider: SidebarSlider) {
|
||||
super(slider, false);
|
||||
@ -911,8 +911,14 @@ export default class AppSharedMediaTab extends SliderSuperTab {
|
||||
});
|
||||
|
||||
rootScope.addEventListener('contacts_update', (userId) => {
|
||||
if(this.peerId === userId && rootScope.myId !== userId) {
|
||||
this.editBtn.classList.toggle('hide', !appUsersManager.isContact(userId));
|
||||
if(this.peerId === userId) {
|
||||
this.toggleEditBtn();
|
||||
}
|
||||
});
|
||||
|
||||
rootScope.addEventListener('chat_update', (chatId) => {
|
||||
if(this.peerId === -chatId) {
|
||||
this.toggleEditBtn();
|
||||
}
|
||||
});
|
||||
|
||||
@ -1175,16 +1181,18 @@ export default class AppSharedMediaTab extends SliderSuperTab {
|
||||
|
||||
this.profile.fillProfileElements();
|
||||
|
||||
this.toggleEditBtn();
|
||||
}
|
||||
|
||||
private toggleEditBtn() {
|
||||
let show: boolean;
|
||||
if(this.peerId > 0) {
|
||||
if(this.peerId !== rootScope.myId && appUsersManager.isContact(this.peerId)) {
|
||||
this.editBtn.classList.remove('hide');
|
||||
}
|
||||
show = this.peerId !== rootScope.myId && appUsersManager.isContact(this.peerId);
|
||||
} else {
|
||||
const chat: Chat = appChatsManager.getChat(-this.peerId);
|
||||
if((chat._ === 'chat' || (chat as Chat.channel).admin_rights) && !(chat as Chat.chat).pFlags.deactivated) {
|
||||
this.editBtn.classList.remove('hide');
|
||||
}
|
||||
show = appChatsManager.hasRights(-this.peerId, 'change_info');
|
||||
}
|
||||
|
||||
this.editBtn.classList.toggle('hide', !show);
|
||||
}
|
||||
|
||||
public loadSidebarMedia(single: boolean, justLoad = false) {
|
||||
|
@ -175,7 +175,8 @@ const lang = {
|
||||
"Bot": "bot",
|
||||
//"ChannelJoined": "You joined this channel",
|
||||
"ChannelMegaJoined": "You joined this group",
|
||||
"Channel.DescriptionPlaceholder": "Description (optional)",
|
||||
"EnterChannelName": "Channel name",
|
||||
"DescriptionOptionalPlaceholder": "Description (optional)",
|
||||
"DescriptionPlaceholder": "Description",
|
||||
"DiscussionStarted": "Discussion started",
|
||||
"Draft": "Draft",
|
||||
@ -356,6 +357,8 @@ const lang = {
|
||||
"GroupMembers": "Members",
|
||||
"DeleteMega": "Delete Group",
|
||||
"DeleteMegaMenu": "Delete group",
|
||||
"DeleteAndExitButton": "Delete and Leave Group",
|
||||
"ChannelDelete": "Delete Channel",
|
||||
"ChannelDeleteMenu": "Delete channel",
|
||||
"ChannelPermissions": "Permissions",
|
||||
"ChannelPermissionsHeader": "What can members of this group do?",
|
||||
@ -666,7 +669,6 @@ const lang = {
|
||||
"ChatList.Filter.Archive": "Archived",
|
||||
"ChatList.Filter.Include.LimitReached": "Sorry, you can only add up to 100 individual chats. Try using chat types.",
|
||||
"ChatList.Filter.Exclude.LimitReached": "Sorry, you can only add up to 100 individual chats. Try using chat types.",
|
||||
"Channel.ChannelNameHolder": "Channel Name",
|
||||
"Channel.DescriptionHolderDescrpiton": "You can provide an optional description for your channel.",
|
||||
"CreateGroup.NameHolder": "Group Name",
|
||||
"Date.Today": "Today",
|
||||
|
@ -206,10 +206,19 @@ export class AppChatsManager {
|
||||
return rights;
|
||||
}
|
||||
|
||||
// * creator can still send messages to left channel. so this function shows server rights. see canSendToPeer for local rights in messages manager.
|
||||
public hasRights(id: number, action: ChatRights, rights?: ChatAdminRights | ChatBannedRights, isThread?: boolean) {
|
||||
const chat: Chat = this.getChat(id);
|
||||
if(chat._ === 'chatEmpty') return false;
|
||||
|
||||
if((chat as Chat.chat).pFlags.deactivated && action !== 'view_messages') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if((chat as Chat.chat).pFlags.creator && rights === undefined) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(chat._ === 'chatForbidden' ||
|
||||
chat._ === 'channelForbidden' ||
|
||||
(chat as Chat.chat).pFlags.kicked ||
|
||||
@ -217,14 +226,6 @@ export class AppChatsManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
if((chat as Chat.chat).pFlags.deactivated && action !== 'view_messages') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(chat.pFlags.creator && rights === undefined) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!rights) {
|
||||
rights = chat.admin_rights || (chat as Chat.channel).banned_rights || chat.default_banned_rights;
|
||||
|
||||
|
@ -998,7 +998,7 @@ export class AppImManager {
|
||||
|
||||
private canDrag() {
|
||||
const peerId = this.chat?.peerId;
|
||||
return !(!peerId || rootScope.isOverlayActive || (peerId < 0 && !appChatsManager.hasRights(peerId, 'send_media')));
|
||||
return !(!peerId || rootScope.isOverlayActive || !appMessagesManager.canSendToPeer(peerId, this.chat.threadId, 'send_media'));
|
||||
}
|
||||
|
||||
private onDocumentPaste = (e: ClipboardEvent | DragEvent, attachType?: 'media' | 'document') => {
|
||||
|
@ -32,7 +32,7 @@ import DialogsStorage from "../storages/dialogs";
|
||||
import FiltersStorage from "../storages/filters";
|
||||
//import { telegramMeWebService } from "../mtproto/mtproto";
|
||||
import apiUpdatesManager from "./apiUpdatesManager";
|
||||
import appChatsManager from "./appChatsManager";
|
||||
import appChatsManager, { ChatRights } from "./appChatsManager";
|
||||
import appDocsManager, { MyDocument } from "./appDocsManager";
|
||||
import appDownloadManager from "./appDownloadManager";
|
||||
import appPeersManager from "./appPeersManager";
|
||||
@ -4673,11 +4673,12 @@ export class AppMessagesManager {
|
||||
}, settings);
|
||||
}
|
||||
|
||||
public canWriteToPeer(peerId: number, threadId?: number) {
|
||||
public canSendToPeer(peerId: number, threadId?: number, action: ChatRights = 'send_messages') {
|
||||
if(peerId < 0) {
|
||||
//const isChannel = appPeersManager.isChannel(peerId);
|
||||
const hasRights = /* isChannel && */appChatsManager.hasRights(-peerId, 'send_messages', undefined, !!threadId);
|
||||
return /* !isChannel || */hasRights;
|
||||
const chat: Chat.chat = appChatsManager.getChat(-peerId);
|
||||
const hasRights = /* isChannel && */appChatsManager.hasRights(-peerId, action, undefined, !!threadId);
|
||||
return /* !isChannel || */hasRights && (!chat.pFlags.left || !!threadId);
|
||||
} else {
|
||||
return appUsersManager.canSendToUser(peerId);
|
||||
}
|
||||
@ -4875,7 +4876,7 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
public getScheduledMessages(peerId: number): Promise<number[]> {
|
||||
if(!this.canWriteToPeer(peerId)) return Promise.resolve([]);
|
||||
if(!this.canSendToPeer(peerId)) return Promise.resolve([]);
|
||||
|
||||
const storage = this.getScheduledMessagesStorage(peerId);
|
||||
if(Object.keys(storage).length) {
|
||||
@ -5299,7 +5300,7 @@ export class AppMessagesManager {
|
||||
let typing = this.typings[peerId];
|
||||
if(!rootScope.myId ||
|
||||
!peerId ||
|
||||
!this.canWriteToPeer(peerId) ||
|
||||
!this.canSendToPeer(peerId) ||
|
||||
peerId === rootScope.myId ||
|
||||
typing?.type === action._
|
||||
) {
|
||||
|
@ -288,13 +288,11 @@ export class AppPeersManager {
|
||||
public getDeleteButtonText(peerId: number): LangPackKey {
|
||||
switch(this.getDialogType(peerId)) {
|
||||
case 'channel':
|
||||
return 'ChatList.Context.LeaveChannel';
|
||||
return appChatsManager.hasRights(-peerId, 'delete_chat') ? 'ChannelDelete' : 'ChatList.Context.LeaveChannel';
|
||||
|
||||
case 'megagroup':
|
||||
return 'ChatList.Context.LeaveGroup';
|
||||
|
||||
case 'group':
|
||||
return 'ChatList.Context.DeleteAndExit';
|
||||
return appChatsManager.hasRights(-peerId, 'delete_chat') ? 'DeleteMega' : 'ChatList.Context.LeaveGroup';
|
||||
|
||||
default:
|
||||
return 'ChatList.Context.DeleteChat';
|
||||
|
@ -93,6 +93,18 @@ export default class DialogsStorage {
|
||||
}
|
||||
});
|
||||
|
||||
rootScope.addEventListener('chat_update', (chatId) => {
|
||||
const chat: Chat.chat = this.appChatsManager.getChat(chatId);
|
||||
|
||||
const peerId = -chatId;
|
||||
if(chat.pFlags.left && this.getDialogOnly(peerId)) {
|
||||
const dropped = this.dropDialog(peerId);
|
||||
if(dropped.length) {
|
||||
rootScope.dispatchEvent('dialog_drop', {peerId, dialog: dropped[0]});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
rootScope.addMultipleEventsListeners({
|
||||
updateFolderPeers: this.onUpdateFolderPeers,
|
||||
|
||||
|
@ -706,7 +706,20 @@ hr {
|
||||
max-height: 100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: var(--primary-color);
|
||||
background: linear-gradient(var(--avatar-color-top), var(--avatar-color-bottom));
|
||||
}
|
||||
|
||||
html.no-touch body.animation-level-2 & {
|
||||
.tgico-cameraadd {
|
||||
transform: translateY(-50%) translateX(-50%) scale(1);
|
||||
transition: transform .2s ease-in-out;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.tgico-cameraadd {
|
||||
transform: translateY(-50%) translateX(-50%) scale(1.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tgico-cameraadd {
|
||||
|
Loading…
Reference in New Issue
Block a user