From 28597e3539aedd38a01ae46466674871d51ae4bb Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 6 Apr 2020 11:14:14 +1000 Subject: [PATCH 1/9] filter out already members in invite dialog for closed groups --- js/views/invite_friends_dialog_view.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/js/views/invite_friends_dialog_view.js b/js/views/invite_friends_dialog_view.js index ddf8d5745..3d2bde0af 100644 --- a/js/views/invite_friends_dialog_view.js +++ b/js/views/invite_friends_dialog_view.js @@ -14,11 +14,16 @@ const convos = window.getConversations().models; - const friends = convos.filter( - d => !!d && d.isFriend() && d.isPrivate() && !d.isMe() - ); + if(convo.isPublic){ + this.friends = convos.filter( + d => !!d && d.isFriend() && d.isPrivate() && !d.isMe() + ); + } else { + this.friends = convos.filter( + d => !!d && d.isFriend() && d.isPrivate() && !d.isMe() && !convo.get('members').includes(d.id) + ); + } - this.friends = friends; this.chatName = convo.get('name'); this.chatServer = convo.get('server'); this.channelId = convo.get('channelId'); From 67b6ef7ac9f1abccda213ee622791216c2694a1a Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 6 Apr 2020 13:54:29 +1000 Subject: [PATCH 2/9] make invite dialog width relative to window width --- stylesheets/_session.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stylesheets/_session.scss b/stylesheets/_session.scss index c8833aeb2..1398a5e51 100644 --- a/stylesheets/_session.scss +++ b/stylesheets/_session.scss @@ -1565,7 +1565,7 @@ input { } .friend-selection-list { - width: 40vh; + width: 20vw; } .session-beta-disclaimer { From f48136678ef3c7f053ba0a617b6ddac9e4b2cedb Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 7 Apr 2020 17:32:40 +1000 Subject: [PATCH 3/9] use isKickedFromGroup to disable ui components --- js/views/conversation_view.js | 2 + js/views/invite_friends_dialog_view.js | 9 +++- .../conversation/ConversationHeader.tsx | 49 ++++++++++--------- .../session/SessionGroupSettings.tsx | 14 ++++-- 4 files changed, 45 insertions(+), 29 deletions(-) diff --git a/js/views/conversation_view.js b/js/views/conversation_view.js index 564db2dd6..858cfccee 100644 --- a/js/views/conversation_view.js +++ b/js/views/conversation_view.js @@ -196,6 +196,7 @@ value: item.get('seconds'), })), hasNickname: !!this.model.getNickname(), + isKickedFromGroup: this.model.get('isKickedFromGroup'), onSetDisappearingMessages: seconds => this.setDisappearingMessages(seconds), @@ -294,6 +295,7 @@ amMod: this.model.isModerator( window.storage.get('primaryDevicePubKey') ), + isKickedFromGroup: this.model.get('isKickedFromGroup'), timerOptions: Whisper.ExpirationTimerOptions.map(item => ({ name: item.getName(), diff --git a/js/views/invite_friends_dialog_view.js b/js/views/invite_friends_dialog_view.js index 3d2bde0af..a0be59718 100644 --- a/js/views/invite_friends_dialog_view.js +++ b/js/views/invite_friends_dialog_view.js @@ -14,13 +14,18 @@ const convos = window.getConversations().models; - if(convo.isPublic){ + if (convo.isPublic) { this.friends = convos.filter( d => !!d && d.isFriend() && d.isPrivate() && !d.isMe() ); } else { this.friends = convos.filter( - d => !!d && d.isFriend() && d.isPrivate() && !d.isMe() && !convo.get('members').includes(d.id) + d => + !!d && + d.isFriend() && + d.isPrivate() && + !d.isMe() && + !convo.get('members').includes(d.id) ); } diff --git a/ts/components/conversation/ConversationHeader.tsx b/ts/components/conversation/ConversationHeader.tsx index 227f66246..ad4cd46be 100644 --- a/ts/components/conversation/ConversationHeader.tsx +++ b/ts/components/conversation/ConversationHeader.tsx @@ -62,6 +62,7 @@ interface Props { isOnline?: boolean; selectedMessages: any; + isKickedFromGroup: boolean; onSetDisappearingMessages: (seconds: number) => void; onDeleteMessages: () => void; @@ -145,6 +146,7 @@ export class ConversationHeader extends React.Component { subscriberCount, isFriendRequestPending, isMe, + isKickedFromGroup, name, } = this.props; @@ -179,7 +181,7 @@ export class ConversationHeader extends React.Component { } const textEl = - text === '' ? null : ( + text === '' || isKickedFromGroup ? null : ( {text} ); @@ -298,6 +300,7 @@ export class ConversationHeader extends React.Component { isPublic, isRss, isGroup, + isKickedFromGroup, amMod, onDeleteMessages, onDeleteContact, @@ -320,20 +323,20 @@ export class ConversationHeader extends React.Component { {copyIdLabel} ) : null} {i18n('deleteMessages')} - {amMod ? ( + {amMod && !isKickedFromGroup ? ( {i18n('addModerators')} ) : null} - {amMod ? ( + {amMod && !isKickedFromGroup ? ( {i18n('removeModerators')} ) : null} - {amMod ? ( + {amMod && !isKickedFromGroup ? ( {i18n('editGroupNameOrPicture')} ) : null} - {isPrivateGroup ? ( + {isPrivateGroup && !isKickedFromGroup ? ( {i18n('leaveGroup')} ) : null} {/* TODO: add delete group */} @@ -391,7 +394,7 @@ export class ConversationHeader extends React.Component { } public render() { - const { id } = this.props; + const { id, isKickedFromGroup } = this.props; const triggerId = `conversation-${id}-${Date.now()}`; return ( @@ -407,7 +410,7 @@ export class ConversationHeader extends React.Component { {/*isPrivateGroup ? this.renderMemberCount() : null*/} - {this.renderExpirationLength()} + {!isKickedFromGroup && this.renderExpirationLength()} {!this.props.isRss && this.renderAvatar()} @@ -436,6 +439,8 @@ export class ConversationHeader extends React.Component { isBlocked, isMe, isGroup, + isFriend, + isKickedFromGroup, isArchived, isPublic, isRss, @@ -452,7 +457,6 @@ export class ConversationHeader extends React.Component { // hasNickname, // onClearNickname, // onChangeNickname, - isFriend, } = this.props; if (isPublic || isRss) { @@ -464,20 +468,21 @@ export class ConversationHeader extends React.Component { const blockTitle = isBlocked ? i18n('unblockUser') : i18n('blockUser'); const blockHandler = isBlocked ? onUnblockUser : onBlockUser; - const disappearingMessagesMenuItem = isFriend && ( - - {(timerOptions || []).map(item => ( - { - onSetDisappearingMessages(item.value); - }} - > - {item.name} - - ))} - - ); + const disappearingMessagesMenuItem = isFriend && + !isKickedFromGroup && ( + + {(timerOptions || []).map(item => ( + { + onSetDisappearingMessages(item.value); + }} + > + {item.name} + + ))} + + ); const showMembersMenuItem = isGroup && ( {i18n('showMembers')} ); diff --git a/ts/components/session/SessionGroupSettings.tsx b/ts/components/session/SessionGroupSettings.tsx index 919cf0876..3342f4fa9 100644 --- a/ts/components/session/SessionGroupSettings.tsx +++ b/ts/components/session/SessionGroupSettings.tsx @@ -21,6 +21,7 @@ interface Props { isPublic: boolean; isAdmin: boolean; amMod: boolean; + isKickedFromGroup: boolean; onGoBack: () => void; onInviteFriends: () => void; @@ -212,14 +213,15 @@ export class SessionGroupSettings extends React.Component { onLeaveGroup, isPublic, isAdmin, + isKickedFromGroup, amMod, } = this.props; const { documents, media, onItemClick } = this.state; const showMemberCount = !!(memberCount && memberCount > 0); - const hasDisappearingMessages = !isPublic; + const hasDisappearingMessages = !isPublic && !isKickedFromGroup; const leaveGroupString = isPublic ? window.i18n('leaveOpenGroup') - : window.i18n('leaveClosedGroup'); + : isKickedFromGroup ? window.i18n('youAreKickedFromThisGroup') : window.i18n('leaveClosedGroup'); const disappearingMessagesOptions = timerOptions.map(option => { return { @@ -230,8 +232,8 @@ export class SessionGroupSettings extends React.Component { }; }); - const showUpdateGroupNameButton = isPublic ? amMod : isAdmin; - const showUpdateGroupMembersButton = !isPublic && isAdmin; + const showUpdateGroupNameButton = isPublic && !isKickedFromGroup ? amMod : isAdmin; + const showUpdateGroupMembersButton = !isPublic && !isKickedFromGroup && isAdmin; return (
@@ -292,6 +294,7 @@ export class SessionGroupSettings extends React.Component { buttonColor={SessionButtonColor.Danger} buttonType={SessionButtonType.SquareOutline} onClick={onLeaveGroup} + disabled={isKickedFromGroup} />
); @@ -305,9 +308,10 @@ export class SessionGroupSettings extends React.Component { avatarPath, isAdmin, isPublic, + isKickedFromGroup, } = this.props; - const showInviteFriends = isPublic || isAdmin; + const showInviteFriends = (isPublic || isAdmin) && !isKickedFromGroup; return (
From ab77b0f9a5db62f77798c6189a4819e29cc14347 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 8 Apr 2020 09:53:24 +1000 Subject: [PATCH 4/9] disable message contextmenu on group chats when kicked --- js/models/messages.js | 8 +++++++- ts/components/conversation/Message.tsx | 10 +++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/js/models/messages.js b/js/models/messages.js index e6dc4f074..ed0a66e15 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -113,6 +113,8 @@ this.propsForMessage = this.getPropsForMessage(); } }; + const triggerChange = () => this.trigger('change'); + this.on('change', generateProps); const applicableConversationChanges = @@ -120,8 +122,11 @@ const conversation = this.getConversation(); const fromContact = this.getIncomingContact(); - this.listenTo(conversation, applicableConversationChanges, generateProps); + + // trigger a change event on this component. + // this will call generateProps and refresh the Message.tsx component with new props + this.listenTo(conversation, 'disable:input', triggerChange ); if (fromContact) { this.listenTo( fromContact, @@ -703,6 +708,7 @@ multiSelectMode: conversation && conversation.selectedMessages.size > 0, isPublic: !!this.get('isPublic'), isRss: !!this.get('isRss'), + isKickedFromGroup: conversation.get('isKickedFromGroup'), senderIsModerator: !!this.get('isPublic') && conversation && diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index 16b7700c8..ad21af24f 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -100,6 +100,7 @@ export interface Props { isPublic?: boolean; isRss?: boolean; selected: boolean; + isKickedFromGroup: boolean; // whether or not to show check boxes multiSelectMode: boolean; @@ -782,11 +783,12 @@ export class Message extends React.PureComponent { attachments, direction, disableMenu, + isKickedFromGroup, onDownload, onReply, } = this.props; - if (!isCorrectSide || disableMenu) { + if (!isCorrectSide || disableMenu || isKickedFromGroup) { return null; } @@ -1051,12 +1053,14 @@ export class Message extends React.PureComponent { return false; } + // tslint:disable-next-line: cyclomatic-complexity public render() { const { authorPhoneNumber, authorColor, direction, id, + isKickedFromGroup, isRss, timestamp, selected, @@ -1106,7 +1110,7 @@ export class Message extends React.PureComponent { divClasses.push('public-chat-message-wrapper'); } - const enableContextMenu = !isRss && !multiSelectMode; + const enableContextMenu = !isRss && !multiSelectMode && !isKickedFromGroup; return (
@@ -1136,7 +1140,7 @@ export class Message extends React.PureComponent { }} > {this.renderError(isIncoming)} - {isRss ? null : this.renderMenu(!isIncoming, triggerId)} + {isRss || isKickedFromGroup ? null : this.renderMenu(!isIncoming, triggerId)}
Date: Thu, 9 Apr 2020 12:01:52 +1000 Subject: [PATCH 5/9] invite friends to closed group: hide already members --- js/models/messages.js | 2 +- js/views/invite_friends_dialog_view.js | 2 +- ts/components/conversation/Message.tsx | 4 +++- ts/components/session/SessionGroupSettings.tsx | 10 +++++++--- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/js/models/messages.js b/js/models/messages.js index ed0a66e15..59a15f964 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -126,7 +126,7 @@ // trigger a change event on this component. // this will call generateProps and refresh the Message.tsx component with new props - this.listenTo(conversation, 'disable:input', triggerChange ); + this.listenTo(conversation, 'disable:input', triggerChange); if (fromContact) { this.listenTo( fromContact, diff --git a/js/views/invite_friends_dialog_view.js b/js/views/invite_friends_dialog_view.js index a0be59718..a5e52aec4 100644 --- a/js/views/invite_friends_dialog_view.js +++ b/js/views/invite_friends_dialog_view.js @@ -14,7 +14,7 @@ const convos = window.getConversations().models; - if (convo.isPublic) { + if (convo.isPublic()) { this.friends = convos.filter( d => !!d && d.isFriend() && d.isPrivate() && !d.isMe() ); diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index ad21af24f..0e5d7fd21 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -1140,7 +1140,9 @@ export class Message extends React.PureComponent { }} > {this.renderError(isIncoming)} - {isRss || isKickedFromGroup ? null : this.renderMenu(!isIncoming, triggerId)} + {isRss || isKickedFromGroup + ? null + : this.renderMenu(!isIncoming, triggerId)}
{ const hasDisappearingMessages = !isPublic && !isKickedFromGroup; const leaveGroupString = isPublic ? window.i18n('leaveOpenGroup') - : isKickedFromGroup ? window.i18n('youAreKickedFromThisGroup') : window.i18n('leaveClosedGroup'); + : isKickedFromGroup + ? window.i18n('youAreKickedFromThisGroup') + : window.i18n('leaveClosedGroup'); const disappearingMessagesOptions = timerOptions.map(option => { return { @@ -232,8 +234,10 @@ export class SessionGroupSettings extends React.Component { }; }); - const showUpdateGroupNameButton = isPublic && !isKickedFromGroup ? amMod : isAdmin; - const showUpdateGroupMembersButton = !isPublic && !isKickedFromGroup && isAdmin; + const showUpdateGroupNameButton = + isPublic && !isKickedFromGroup ? amMod : isAdmin; + const showUpdateGroupMembersButton = + !isPublic && !isKickedFromGroup && isAdmin; return (
From 0d0a0a1eb5c50eaf7c55801f34e29e66b28c5141 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 9 Apr 2020 13:18:26 +1000 Subject: [PATCH 6/9] remove unused file connecting_to_server_dialog_view.js --- background.html | 1 - background_test.html | 1 - js/views/connecting_to_server_dialog_view.js | 61 -------------------- test/index.html | 1 - 4 files changed, 64 deletions(-) delete mode 100644 js/views/connecting_to_server_dialog_view.js diff --git a/background.html b/background.html index c3994d233..e4efe99a9 100644 --- a/background.html +++ b/background.html @@ -495,7 +495,6 @@ - diff --git a/background_test.html b/background_test.html index 8433a9af4..c47e98b62 100644 --- a/background_test.html +++ b/background_test.html @@ -495,7 +495,6 @@ - diff --git a/js/views/connecting_to_server_dialog_view.js b/js/views/connecting_to_server_dialog_view.js deleted file mode 100644 index b2d800f1b..000000000 --- a/js/views/connecting_to_server_dialog_view.js +++ /dev/null @@ -1,61 +0,0 @@ -/* global Whisper, i18n, log */ - -// eslint-disable-next-line func-names -(function() { - 'use strict'; - - window.Whisper = window.Whisper || {}; - - Whisper.ConnectingToServerDialogView = Whisper.View.extend({ - templateName: 'connecting-to-server-template', - className: 'loki-dialog connecting-to-server modal', - initialize(options = {}) { - this.title = i18n('connectingLoad'); - this.cancelText = options.cancelText || i18n('cancel'); - this.serverUrl = options.serverUrl; - this.channelId = options.channelId; - this.once('attemptConnection', () => - this.attemptConnection(options.serverUrl, options.channelId) - ); - this.render(); - }, - events: { - keyup: 'onKeyup', - 'click .cancel': 'close', - }, - async attemptConnection(serverUrl, channelId) { - let conversation = null; - try { - conversation = await window.attemptConnection(serverUrl, channelId); - } catch (e) { - log.error('can not connect', e.message, e.code); - return this.resolveWith({ errorCode: e.message }); - } - return this.resolveWith({ conversation }); - }, - resolveWith(result) { - this.trigger('connectionResult', result); - this.remove(); - }, - render_attributes() { - return { - title: this.title, - cancel: this.cancelText, - }; - }, - close() { - this.trigger('connectionResult', { cancelled: true }); - this.remove(); - }, - onKeyup(event) { - switch (event.key) { - case 'Escape': - case 'Esc': - this.close(); - break; - default: - break; - } - }, - }); -})(); diff --git a/test/index.html b/test/index.html index a779fba6d..b503f8b23 100644 --- a/test/index.html +++ b/test/index.html @@ -542,7 +542,6 @@ - From a3575c02954c7ccb3b1c729c3d9acda2ccee080d Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 14 Apr 2020 09:55:21 +1000 Subject: [PATCH 7/9] showtoast on invite accept from already member open-group --- js/background.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/js/background.js b/js/background.js index 6a800039b..806f0a09f 100644 --- a/js/background.js +++ b/js/background.js @@ -1156,6 +1156,11 @@ const conversationExists = ConversationController.get(conversationId); if (conversationExists) { window.log.warn('We are already a member of this public chat'); + window.pushToast({ + description: window.i18n('publicChatExists'), + type: 'info', + id: 'alreadyMemberPublicChat', + }); return; } From 6d6f4a00e4eed2cc29ddcc43497a4db3afdc2a17 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 14 Apr 2020 10:59:31 +1000 Subject: [PATCH 8/9] address review: remove code duplication --- js/views/invite_friends_dialog_view.js | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/js/views/invite_friends_dialog_view.js b/js/views/invite_friends_dialog_view.js index a5e52aec4..c4bec8b9f 100644 --- a/js/views/invite_friends_dialog_view.js +++ b/js/views/invite_friends_dialog_view.js @@ -14,19 +14,12 @@ const convos = window.getConversations().models; - if (convo.isPublic()) { - this.friends = convos.filter( - d => !!d && d.isFriend() && d.isPrivate() && !d.isMe() - ); - } else { - this.friends = convos.filter( - d => - !!d && - d.isFriend() && - d.isPrivate() && - !d.isMe() && - !convo.get('members').includes(d.id) - ); + this.friends = convos.filter( + d => !!d && d.isFriend() && d.isPrivate() && !d.isMe() + ); + if (!convo.isPublic()) { + const members = convo.get('members') || []; + this.friends = this.friends.filter(d => !members.includes(d.id)); } this.chatName = convo.get('name'); From 6848eb975a32b1bbcf1c6387a6e9475be582f8ea Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 14 Apr 2020 11:09:39 +1000 Subject: [PATCH 9/9] fix tests --- js/models/messages.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/models/messages.js b/js/models/messages.js index 59a15f964..5aa089040 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -708,7 +708,8 @@ multiSelectMode: conversation && conversation.selectedMessages.size > 0, isPublic: !!this.get('isPublic'), isRss: !!this.get('isRss'), - isKickedFromGroup: conversation.get('isKickedFromGroup'), + isKickedFromGroup: + conversation && conversation.get('isKickedFromGroup'), senderIsModerator: !!this.get('isPublic') && conversation &&