Browse Source

Fix deleting channels

Fix dropping chats when they are deleted
Confirm popups by Enter
master
morethanwords 3 years ago
parent
commit
3fc26e0262
  1. 1
      src/components/appSelectPeers.ts
  2. 8
      src/components/chat/bubbles.ts
  3. 2
      src/components/chat/contextMenu.ts
  4. 18
      src/components/chat/input.ts
  5. 5
      src/components/chat/topbar.ts
  6. 2
      src/components/dialogsContextMenu.ts
  7. 8
      src/components/emoticonsDropdown/index.ts
  8. 19
      src/components/popups/avatar.ts
  9. 22
      src/components/popups/createPoll.ts
  10. 13
      src/components/popups/datePicker.ts
  11. 36
      src/components/popups/deleteDialog.ts
  12. 55
      src/components/popups/index.ts
  13. 17
      src/components/popups/newMedia.ts
  14. 5
      src/components/popups/reportMessages.ts
  15. 3
      src/components/popups/schedule.ts
  16. 29
      src/components/popups/stickers.ts
  17. 4
      src/components/sidebarLeft/tabs/newChannel.ts
  18. 35
      src/components/sidebarRight/tabs/editChat.ts
  19. 28
      src/components/sidebarRight/tabs/sharedMedia.ts
  20. 6
      src/lang.ts
  21. 17
      src/lib/appManagers/appChatsManager.ts
  22. 2
      src/lib/appManagers/appImManager.ts
  23. 13
      src/lib/appManagers/appMessagesManager.ts
  24. 6
      src/lib/appManagers/appPeersManager.ts
  25. 12
      src/lib/storages/dialogs.ts
  26. 15
      src/scss/style.scss

1
src/components/appSelectPeers.ts

@ -7,7 +7,6 @@ @@ -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";

8
src/components/chat/bubbles.ts

@ -456,7 +456,7 @@ export default class ChatBubbles { @@ -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 { @@ -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 { @@ -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 { @@ -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);

2
src/components/chat/contextMenu.ts

@ -188,7 +188,7 @@ export default class ChatContextMenu { @@ -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'/* ,

18
src/components/chat/input.ts

@ -107,7 +107,7 @@ export default class ChatInput { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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;
}

5
src/components/chat/topbar.ts

@ -314,7 +314,7 @@ export default class ChatTopbar { @@ -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 { @@ -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 */;

2
src/components/dialogsContextMenu.ts

@ -149,7 +149,7 @@ export default class DialogsContextMenu { @@ -149,7 +149,7 @@ export default class DialogsContextMenu {
};
private onDeleteClick = () => {
new PopupDeleteDialog(this.selectedId);
new PopupDeleteDialog(this.selectedId/* , 'delete' */);
};
onContextMenu = (e: MouseEvent | Touch) => {

8
src/components/emoticonsDropdown/index.ts

@ -5,7 +5,6 @@ @@ -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"; @@ -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 { @@ -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');

19
src/components/popups/avatar.ts

@ -7,14 +7,13 @@ @@ -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 { @@ -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 { @@ -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 { @@ -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();

22
src/components/popups/createPoll.ts

@ -18,6 +18,7 @@ import { cancelEvent } from "../../helpers/dom/cancelEvent"; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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);

13
src/components/popups/datePicker.ts

@ -5,6 +5,7 @@ @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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);

36
src/components/popups/deleteDialog.ts

@ -12,7 +12,12 @@ import PeerTitle from "../peerTitle"; @@ -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,6 +56,20 @@ export default class PopupDeleteDialog { @@ -51,6 +56,20 @@ export default class PopupDeleteDialog {
let title: LangPackKey, description: LangPackKey, descriptionArgs: any[], buttons: PopupPeerOptions['buttons'], checkboxes: PopupPeerOptions['checkboxes'];
switch(peerType) {
case 'channel': {
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];
@ -59,6 +78,7 @@ export default class PopupDeleteDialog { @@ -59,6 +78,7 @@ export default class PopupDeleteDialog {
isDanger: true,
callback: callbackLeave
}];
}
break;
}
@ -80,6 +100,12 @@ export default class PopupDeleteDialog { @@ -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 { @@ -87,12 +113,6 @@ export default class PopupDeleteDialog {
]
}];
buttons = [{
langKey: 'DeleteChatUser',
isDanger: true,
callback: callbackDelete
}];
break;
}
@ -110,7 +130,7 @@ export default class PopupDeleteDialog { @@ -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 = [{

55
src/components/popups/index.ts

@ -12,6 +12,9 @@ import { i18n, LangPackKey } from "../../lib/langPack"; @@ -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 = { @@ -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 { @@ -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 { @@ -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 { @@ -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');
@ -116,24 +124,27 @@ export default class PopupElement { @@ -116,24 +124,27 @@ export default class PopupElement {
button.append(i18n(b.langKey, b.langArgs));
}
if(b.callback) {
button.addEventListener('click', () => {
b.callback();
attachClickEvent(button, () => {
b.callback && b.callback();
this.destroy();
}, {once: true});
} else if(b.isCancel) {
button.addEventListener('click', () => {
this.destroy();
}, {once: true});
}
}, {listenerSetter: this.listenerSetter, once: true});
return button;
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 { @@ -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 { @@ -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
src/components/popups/newMedia.ts

@ -17,11 +17,11 @@ import { MyDocument } from "../../lib/appManagers/appDocsManager"; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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();
}

5
src/components/popups/reportMessages.ts

@ -4,6 +4,7 @@ @@ -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 { @@ -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 { @@ -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';

3
src/components/popups/schedule.ts

@ -37,7 +37,8 @@ export default class PopupSchedule extends PopupDatePicker { @@ -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');

29
src/components/popups/stickers.ts

@ -19,6 +19,7 @@ import { i18n } from "../../lib/langPack"; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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();

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

@ -35,12 +35,12 @@ export default class AppNewChannelTab extends SliderSuperTab { @@ -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
});

35
src/components/sidebarRight/tabs/editChat.ts

@ -18,7 +18,6 @@ import rootScope from "../../../lib/rootScope"; @@ -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 { @@ -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,37 +280,10 @@ export default class AppEditChatTab extends SliderSuperTab { @@ -281,37 +280,10 @@ 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) => {
new PopupDeleteDialog(-this.chatId/* , 'delete' */, undefined, (promise) => {
const toggle = toggleDisability([btnDelete], true);
promise.then(() => {
this.close();
@ -319,7 +291,6 @@ export default class AppEditChatTab extends SliderSuperTab { @@ -319,7 +291,6 @@ export default class AppEditChatTab extends SliderSuperTab {
toggle();
});
});
}
}, {listenerSetter: this.listenerSetter});
section.content.append(btnDelete);

28
src/components/sidebarRight/tabs/sharedMedia.ts

@ -810,7 +810,7 @@ export default class AppSharedMediaTab extends SliderSuperTab { @@ -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 { @@ -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 { @@ -1175,16 +1181,18 @@ export default class AppSharedMediaTab extends SliderSuperTab {
this.profile.fillProfileElements();
if(this.peerId > 0) {
if(this.peerId !== rootScope.myId && appUsersManager.isContact(this.peerId)) {
this.editBtn.classList.remove('hide');
this.toggleEditBtn();
}
private toggleEditBtn() {
let show: boolean;
if(this.peerId > 0) {
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) {

6
src/lang.ts

@ -175,7 +175,8 @@ const lang = { @@ -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 = { @@ -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 = { @@ -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",

17
src/lib/appManagers/appChatsManager.ts

@ -206,25 +206,26 @@ export class AppChatsManager { @@ -206,25 +206,26 @@ 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._ === 'chatForbidden' ||
chat._ === 'channelForbidden' ||
(chat as Chat.chat).pFlags.kicked ||
(chat.pFlags.left && !(chat as Chat.channel).pFlags.megagroup)) {
return false;
}
if((chat as Chat.chat).pFlags.deactivated && action !== 'view_messages') {
return false;
}
if(chat.pFlags.creator && rights === undefined) {
if((chat as Chat.chat).pFlags.creator && rights === undefined) {
return true;
}
if(chat._ === 'chatForbidden' ||
chat._ === 'channelForbidden' ||
(chat as Chat.chat).pFlags.kicked ||
(chat.pFlags.left && !(chat as Chat.channel).pFlags.megagroup)) {
return false;
}
if(!rights) {
rights = chat.admin_rights || (chat as Chat.channel).banned_rights || chat.default_banned_rights;

2
src/lib/appManagers/appImManager.ts

@ -998,7 +998,7 @@ export class AppImManager { @@ -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') => {

13
src/lib/appManagers/appMessagesManager.ts

@ -32,7 +32,7 @@ import DialogsStorage from "../storages/dialogs"; @@ -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 { @@ -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 { @@ -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 { @@ -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._
) {

6
src/lib/appManagers/appPeersManager.ts

@ -288,13 +288,11 @@ export class AppPeersManager { @@ -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';

12
src/lib/storages/dialogs.ts

@ -93,6 +93,18 @@ export default class DialogsStorage { @@ -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,

15
src/scss/style.scss

@ -706,7 +706,20 @@ hr { @@ -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…
Cancel
Save