Browse Source

Restrict sending messages to left megagroup

master
Eduard Kuzmenko 4 years ago
parent
commit
094ec4c858
  1. 2
      src/components/appMediaViewer.ts
  2. 19
      src/components/chat/bubbles.ts
  3. 8
      src/components/chat/contextMenu.ts
  4. 54
      src/components/chat/input.ts
  5. 6
      src/components/chat/topbar.ts
  6. 10
      src/components/popups/deleteDialog.ts
  7. 2
      src/config/app.ts
  8. 1
      src/lang.ts
  9. 26
      src/lib/appManagers/appChatsManager.ts
  10. 34
      src/lib/appManagers/appMessagesManager.ts
  11. 2
      src/lib/appManagers/appStateManager.ts
  12. 1
      src/lib/langPack.ts
  13. 2
      src/lib/rootScope.ts
  14. 12
      src/scss/partials/_sidebar.scss
  15. 16
      src/scss/partials/popups/_popup.scss

2
src/components/appMediaViewer.ts

@ -133,7 +133,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType @@ -133,7 +133,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
buttonsDiv.classList.add(MEDIA_VIEWER_CLASSNAME + '-buttons');
topButtons.concat(['download', 'close']).forEach(name => {
const button = ButtonIcon(name);
const button = ButtonIcon(name, {noRipple: name === 'close' || undefined});
this.buttons[name] = button;
buttonsDiv.append(button);
});

19
src/components/chat/bubbles.ts

@ -42,7 +42,7 @@ import { AppChatsManager } from "../../lib/appManagers/appChatsManager"; @@ -42,7 +42,7 @@ import { AppChatsManager } from "../../lib/appManagers/appChatsManager";
import ListenerSetter from "../../helpers/listenerSetter";
import PollElement from "../poll";
import AudioElement from "../audio";
import { Message, MessageEntity, MessageReplyHeader } from "../../layer";
import { Message, MessageEntity, MessageReplyHeader, Update } from "../../layer";
import { REPLIES_PEER_ID } from "../../lib/mtproto/mtproto_config";
import { FocusDirection } from "../../helpers/fastSmoothScroll";
import useHeavyAnimationCheck, { getHeavyAnimationPromise, dispatchHeavyAnimationEvent, interruptHeavyAnimation } from "../../hooks/useHeavyAnimationCheck";
@ -408,7 +408,7 @@ export default class ChatBubbles { @@ -408,7 +408,7 @@ export default class ChatBubbles {
}
this.listenerSetter.add(this.bubblesContainer, 'dblclick', (e) => {
if(this.chat.selection.isSelecting || !this.appMessagesManager.canWriteToPeer(this.peerId)) {
if(this.chat.selection.isSelecting || !this.appMessagesManager.canWriteToPeer(this.peerId, this.chat.threadId)) {
return;
}
@ -502,6 +502,19 @@ export default class ChatBubbles { @@ -502,6 +502,19 @@ export default class ChatBubbles {
}
});
this.listenerSetter.add(rootScope, 'chat_update', (e) => {
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);
if(hadRights !== hasRights) {
this.finishPeerChange();
this.chat.input.updateMessageInput();
}
}
});
this.unreadedObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if(entry.isIntersecting) {
@ -1748,7 +1761,7 @@ export default class ChatBubbles { @@ -1748,7 +1761,7 @@ export default class ChatBubbles {
public finishPeerChange() {
const peerId = this.peerId;
const isChannel = this.appPeersManager.isChannel(peerId);
const canWrite = this.appMessagesManager.canWriteToPeer(peerId);
const canWrite = this.appMessagesManager.canWriteToPeer(peerId, this.chat.threadId);
this.chatInner.classList.toggle('has-rights', canWrite);
this.bubblesContainer.classList.toggle('is-chat-input-hidden', !canWrite);

8
src/components/chat/contextMenu.ts

@ -35,9 +35,9 @@ export default class ChatContextMenu { @@ -35,9 +35,9 @@ export default class ChatContextMenu {
private isTargetAGroupedItem: boolean;
private isTextSelected: boolean;
private isAnchorTarget: boolean;
public peerId: number;
public mid: number;
public message: any;
private peerId: number;
private mid: number;
private message: any;
constructor(private attachTo: HTMLElement, private chat: Chat, private appMessagesManager: AppMessagesManager, private appChatsManager: AppChatsManager, private appPeersManager: AppPeersManager, private appPollsManager: AppPollsManager) {
const onContextMenu = (e: MouseEvent | Touch | TouchEvent) => {
@ -190,7 +190,7 @@ export default class ChatContextMenu { @@ -190,7 +190,7 @@ export default class ChatContextMenu {
icon: 'reply',
text: 'Reply',
onClick: this.onReplyClick,
verify: () => this.appMessagesManager.canWriteToPeer(this.peerId) &&
verify: () => this.appMessagesManager.canWriteToPeer(this.peerId, this.chat.threadId) &&
!this.message.pFlags.is_outgoing &&
!!this.chat.input.messageInput &&
this.chat.type !== 'scheduled'/* ,

54
src/components/chat/input.ts

@ -692,31 +692,7 @@ export default class ChatInput { @@ -692,31 +692,7 @@ export default class ChatInput {
}
if(this.messageInput) {
const canWrite = this.appMessagesManager.canWriteToPeer(peerId);
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(peerId);
button.element.classList.toggle('hide', !good);
return good;
});
if(!canWrite) {
this.messageInput.removeAttribute('contenteditable');
} else {
this.messageInput.setAttribute('contenteditable', 'true');
this.setDraft(undefined, false);
if(!this.messageInput.innerHTML) {
this.messageInputField.onFakeInput();
}
}
this.attachMenu.toggleAttribute('disabled', !visible.length);
this.updateSendBtn();
this.updateMessageInput();
} else if(this.pinnedControlBtn) {
if(this.appPeersManager.canPinMessage(this.chat.peerId)) {
this.pinnedControlBtn.append(i18n('Chat.Input.UnpinAll'));
@ -728,6 +704,34 @@ export default class ChatInput { @@ -728,6 +704,34 @@ export default class ChatInput {
}
}
public updateMessageInput() {
const canWrite = this.appMessagesManager.canWriteToPeer(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);
button.element.classList.toggle('hide', !good);
return good;
});
if(!canWrite) {
this.messageInput.removeAttribute('contenteditable');
} else {
this.messageInput.setAttribute('contenteditable', 'true');
this.setDraft(undefined, false);
if(!this.messageInput.innerHTML) {
this.messageInputField.onFakeInput();
}
}
this.attachMenu.toggleAttribute('disabled', !visible.length);
this.updateSendBtn();
}
private attachMessageInputField() {
const oldInputField = this.messageInputField;
this.messageInputField = new InputField({

6
src/components/chat/topbar.ts

@ -289,9 +289,9 @@ export default class ChatTopbar { @@ -289,9 +289,9 @@ export default class ChatTopbar {
}, {listenerSetter: this.listenerSetter});
this.listenerSetter.add(rootScope, 'chat_update', (e) => {
const peerId: number = e;
if(this.peerId === -peerId) {
const chat = this.appChatsManager.getChat(peerId) as Channel/* | Chat */;
const chatId: number = e;
if(this.peerId === -chatId) {
const chat = this.appChatsManager.getChat(chatId) as Channel/* | Chat */;
this.btnJoin.classList.toggle('hide', !(chat as Channel)?.pFlags?.left);
this.setUtilsWidth();

10
src/components/popups/deleteDialog.ts

@ -24,9 +24,13 @@ export default class PopupDeleteDialog { @@ -24,9 +24,13 @@ export default class PopupDeleteDialog {
}; */
const callbackLeave = (checked: PopupPeerButtonCallbackCheckboxes) => {
const promise = appChatsManager.leave(-peerId).then(() => {
return appMessagesManager.flushHistory(-peerId);
});
let promise = appChatsManager.leave(-peerId);
if(checkboxes && checked[checkboxes[0].text]) {
promise = promise.then(() => {
return appMessagesManager.flushHistory(peerId);
}) as any;
}
onSelect && onSelect(promise);
};

2
src/config/app.ts

@ -13,7 +13,7 @@ const App = { @@ -13,7 +13,7 @@ const App = {
id: 1025907,
hash: '452b0359b988148995f22ff0f4229750',
version: '0.5.3',
langPackVersion: '0.1.6',
langPackVersion: '0.1.7',
langPack: 'macos',
langPackCode: 'en',
domains: [] as string[],

1
src/lang.ts

@ -417,6 +417,7 @@ const lang = { @@ -417,6 +417,7 @@ const lang = {
"Online": "online",
"MessageScheduleSend": "Send Now",
"MessageScheduleEditTime": "Reschedule",
"YouLeft": "You left this group",
// * macos
"AccountSettings.Filters": "Chat Folders",

26
src/lib/appManagers/appChatsManager.ts

@ -44,11 +44,11 @@ export class AppChatsManager { @@ -44,11 +44,11 @@ export class AppChatsManager {
constructor() {
rootScope.addMultipleEventsListeners({
updateChannel: (update) => {
/* updateChannel: (update) => {
const channelId = update.channel_id;
//console.log('updateChannel:', update);
rootScope.broadcast('channel_settings', {channelId});
},
}, */
updateChannelParticipant: (update) => {
apiManagerProxy.clearCache('channels.getParticipants', (params) => {
@ -268,7 +268,7 @@ export class AppChatsManager { @@ -268,7 +268,7 @@ export class AppChatsManager {
return rights;
}
public hasRights(id: number, action: ChatRights, rights?: ChatAdminRights | ChatBannedRights) {
public hasRights(id: number, action: ChatRights, rights?: ChatAdminRights | ChatBannedRights, isThread?: boolean) {
const chat: Chat = this.getChat(id);
if(chat._ === 'chatEmpty') return false;
@ -285,14 +285,16 @@ export class AppChatsManager { @@ -285,14 +285,16 @@ export class AppChatsManager {
if(!rights) {
rights = chat.admin_rights || (chat as Chat.channel).banned_rights || chat.default_banned_rights;
}
if(!rights) {
return false;
if(!rights) {
return false;
}
}
let myFlags: Partial<{[flag in keyof ChatBannedRights['pFlags'] | keyof ChatAdminRights['pFlags']]: true}> = {};
if(rights) myFlags = rights.pFlags as any;
if(rights) {
myFlags = rights.pFlags as any;
}
switch(action) {
case 'embed_links':
@ -303,12 +305,16 @@ export class AppChatsManager { @@ -303,12 +305,16 @@ export class AppChatsManager {
case 'send_messages':
case 'send_polls':
case 'send_stickers': {
if(!isThread && chat.pFlags.left) {
return false;
}
if(rights._ === 'chatBannedRights' && myFlags[action]) {
return false;
}
if(chat._ === 'channel') {
if((!chat.pFlags.megagroup && !myFlags.post_messages)) {
if(!chat.pFlags.megagroup && !myFlags.post_messages) {
return false;
}
}
@ -375,7 +381,6 @@ export class AppChatsManager { @@ -375,7 +381,6 @@ export class AppChatsManager {
} */
public isChannel(id: number) {
if(id < 0) id = -id;
const chat = this.chats[id];
return chat && (chat._ === 'channel' || chat._ === 'channelForbidden')/* || this.channelAccess[id] */;
}
@ -409,7 +414,6 @@ export class AppChatsManager { @@ -409,7 +414,6 @@ export class AppChatsManager {
}
public getChannelInput(id: number): InputChannel {
if(id < 0) id = -id;
const chat: Chat = this.getChat(id);
if(chat._ === 'chatEmpty' || !(chat as Chat.channel).access_hash) {
return {

34
src/lib/appManagers/appMessagesManager.ts

@ -183,7 +183,7 @@ export class AppMessagesManager { @@ -183,7 +183,7 @@ export class AppMessagesManager {
}} = {};
private reloadConversationsPromise: Promise<void>;
private reloadConversationsPeers: number[] = [];
private reloadConversationsPeers: Set<number> = new Set();
public log = logger('MESSAGES', LogTypes.Error | LogTypes.Debug | LogTypes.Log | LogTypes.Warn);
@ -1883,8 +1883,8 @@ export class AppMessagesManager { @@ -1883,8 +1883,8 @@ export class AppMessagesManager {
public reloadConversation(peerId: number | number[]) {
[].concat(peerId).forEach(peerId => {
if(!this.reloadConversationsPeers.includes(peerId)) {
this.reloadConversationsPeers.push(peerId);
if(!this.reloadConversationsPeers.has(peerId)) {
this.reloadConversationsPeers.add(peerId);
//this.log('will reloadConversation', peerId);
}
});
@ -1892,8 +1892,8 @@ export class AppMessagesManager { @@ -1892,8 +1892,8 @@ export class AppMessagesManager {
if(this.reloadConversationsPromise) return this.reloadConversationsPromise;
return this.reloadConversationsPromise = new Promise((resolve, reject) => {
setTimeout(() => {
const peers = this.reloadConversationsPeers.map(peerId => appPeersManager.getInputDialogPeerById(peerId));
this.reloadConversationsPeers.length = 0;
const peers = Array.from(this.reloadConversationsPeers).map(peerId => appPeersManager.getInputDialogPeerById(peerId));
this.reloadConversationsPeers.clear();
apiManager.invokeApi('messages.getPeerDialogs', {peers}).then((result) => {
this.dialogsStorage.applyDialogs(result);
@ -1947,7 +1947,7 @@ export class AppMessagesManager { @@ -1947,7 +1947,7 @@ export class AppMessagesManager {
_: 'updateChannelAvailableMessages',
channel_id: channelId,
available_min_id: maxId
}
} as Update.updateChannelAvailableMessages
});
return true;
@ -2297,6 +2297,7 @@ export class AppMessagesManager { @@ -2297,6 +2297,7 @@ export class AppMessagesManager {
if(message.action) {
let migrateFrom: number;
let migrateTo: number;
const suffix = message.fromId === appUsersManager.getSelf().id ? 'You' : '';
switch(message.action._) {
//case 'messageActionChannelEditPhoto':
case 'messageActionChatEditPhoto':
@ -2332,7 +2333,6 @@ export class AppMessagesManager { @@ -2332,7 +2333,6 @@ export class AppMessagesManager {
if(message.action.users.length === 1) {
message.action.user_id = message.action.users[0];
if(message.fromId === message.action.user_id) {
let suffix = message.fromId === appUsersManager.getSelf().id ? 'You' : '';
if(isChannel) {
message.action._ = 'messageActionChatJoined' + suffix;
} else {
@ -2346,7 +2346,7 @@ export class AppMessagesManager { @@ -2346,7 +2346,7 @@ export class AppMessagesManager {
case 'messageActionChatDeleteUser':
if(message.fromId === message.action.user_id) {
message.action._ = 'messageActionChatLeave';
message.action._ = 'messageActionChatLeave' + suffix;
}
break;
@ -4029,19 +4029,19 @@ export class AppMessagesManager { @@ -4029,19 +4029,19 @@ export class AppMessagesManager {
private onUpdateChannel = (update: Update.updateChannel) => {
const channelId: number = update.channel_id;
const peerId = -channelId;
const channel = appChatsManager.getChat(channelId);
const needDialog = channel._ === 'channel' && appChatsManager.isInChat(channelId);
const dialog = this.getDialogOnly(peerId);
const channel: Chat.channel = appChatsManager.getChat(channelId);
const canViewHistory = channel._ === 'channel' && (channel.username || !channel.pFlags.left && !channel.pFlags.kicked);
const needDialog = appChatsManager.isInChat(channelId);
const canViewHistory = !!channel.username || !channel.pFlags.left;
const hasHistory = this.historiesStorage[peerId] !== undefined;
if(canViewHistory !== hasHistory) {
delete this.historiesStorage[peerId];
rootScope.broadcast('history_forbidden', peerId);
}
const dialog = this.getDialogOnly(peerId);
if(!!dialog !== needDialog) {
if(needDialog) {
this.reloadConversation(-channelId);
@ -4299,10 +4299,10 @@ export class AppMessagesManager { @@ -4299,10 +4299,10 @@ export class AppMessagesManager {
}, settings);
}
public canWriteToPeer(peerId: number) {
public canWriteToPeer(peerId: number, threadId?: number) {
if(peerId < 0) {
const isChannel = appPeersManager.isChannel(peerId);
const hasRights = isChannel && appChatsManager.hasRights(-peerId, 'send_messages');
const hasRights = isChannel && appChatsManager.hasRights(-peerId, 'send_messages', undefined, !!threadId);
return !isChannel || hasRights;
} else {
return appUsersManager.canSendToUser(peerId);

2
src/lib/appManagers/appStateManager.ts

@ -369,7 +369,7 @@ export class AppStateManager extends EventListenerBase<{ @@ -369,7 +369,7 @@ export class AppStateManager extends EventListenerBase<{
public keepPeerSingle(peerId: number, type: string) {
const existsPeerId = this.singlePeerMap.get(type);
if(existsPeerId && existsPeerId !== peerId) {
if(existsPeerId && existsPeerId !== peerId && this.neededPeers.has(existsPeerId)) {
const set = this.neededPeers.get(existsPeerId);
set.delete(type);

1
src/lib/langPack.ts

@ -28,6 +28,7 @@ export const langPack: {[actionType: string]: LangPackKey} = { @@ -28,6 +28,7 @@ export const langPack: {[actionType: string]: LangPackKey} = {
"messageActionChatAddUser": "ActionAddUser",
"messageActionChatAddUsers": "ActionAddUser",
"messageActionChatLeave": "ActionLeftUser",
"messageActionChatLeaveYou": "YouLeft",
"messageActionChatDeleteUser": "ActionKickUser",
"messageActionChatJoinedByLink": "ActionInviteUser",
"messageActionPinMessage": "ActionPinnedNoText",

2
src/lib/rootScope.ts

@ -83,7 +83,7 @@ export type BroadcastEvents = { @@ -83,7 +83,7 @@ export type BroadcastEvents = {
'chat_full_update': number,
'poll_update': {poll: Poll, results: PollResults},
'chat_update': number,
'channel_settings': {channelId: number},
//'channel_settings': {channelId: number},
'webpage_updated': {id: string, msgs: number[]},
'download_progress': any,

12
src/scss/partials/_sidebar.scss

@ -11,13 +11,13 @@ @@ -11,13 +11,13 @@
align-items: center;
justify-content: space-between;
padding: 0 1rem;
min-height: 56px;
min-height: 3.5rem;
flex: 0 0 auto;
user-select: none;
cursor: default;
@include respond-to(handhelds) {
padding: 7.5px 8px;
padding: 0 .5rem;
}
/* //position: sticky !important;
@ -28,8 +28,8 @@ @@ -28,8 +28,8 @@
&__title {
flex: 1;
font-weight: 500;
padding-left: 24px;
font-size: 20px;
padding-left: 1.5rem;
font-size: 1.25rem;
color: var(--primary-text-color);
}
@ -40,8 +40,8 @@ @@ -40,8 +40,8 @@
&-close-button {
overflow: inherit !important;
width: 40px;
height: 40px;
width: 2.5rem;
height: 2.5rem;
}
&-content {

16
src/scss/partials/popups/_popup.scss

@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
z-index: 3;
background-color: rgba(0, 0, 0, .3);
margin: 0;
padding: 2.5rem;
padding: 1.875rem;
box-shadow: none;
opacity: 0;
visibility: hidden;
@ -70,21 +70,9 @@ @@ -70,21 +70,9 @@
}
&-close {
cursor: pointer;
color: var(--secondary-text-color);
z-index: 3;
text-align: center;
justify-self: center;
line-height: 1;
//transition: color .2s;
body.animation-level-0 & {
transition: none;
}
/* @include hover() {
color: #000;
} */
flex: 0 0 auto;
}
&-header {

Loading…
Cancel
Save