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/background.js b/js/background.js index 6714c5025..ca167d886 100644 --- a/js/background.js +++ b/js/background.js @@ -1160,6 +1160,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; } diff --git a/js/models/messages.js b/js/models/messages.js index e6dc4f074..5aa089040 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,8 @@ multiSelectMode: conversation && conversation.selectedMessages.size > 0, isPublic: !!this.get('isPublic'), isRss: !!this.get('isRss'), + isKickedFromGroup: + conversation && conversation.get('isKickedFromGroup'), senderIsModerator: !!this.get('isPublic') && conversation && 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/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 ddf8d5745..c4bec8b9f 100644 --- a/js/views/invite_friends_dialog_view.js +++ b/js/views/invite_friends_dialog_view.js @@ -14,11 +14,14 @@ const convos = window.getConversations().models; - const friends = convos.filter( + 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.friends = friends; this.chatName = convo.get('name'); this.chatServer = convo.get('server'); this.channelId = convo.get('channelId'); 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 { 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 @@ - 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/conversation/Message.tsx b/ts/components/conversation/Message.tsx index 16b7700c8..0e5d7fd21 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,9 @@ export class Message extends React.PureComponent { }} > {this.renderError(isIncoming)} - {isRss ? null : this.renderMenu(!isIncoming, triggerId)} + {isRss || isKickedFromGroup + ? null + : this.renderMenu(!isIncoming, triggerId)}
void; onInviteFriends: () => void; @@ -212,14 +213,17 @@ 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 +234,10 @@ 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 +298,7 @@ export class SessionGroupSettings extends React.Component { buttonColor={SessionButtonColor.Danger} buttonType={SessionButtonType.SquareOutline} onClick={onLeaveGroup} + disabled={isKickedFromGroup} />
); @@ -305,9 +312,10 @@ export class SessionGroupSettings extends React.Component { avatarPath, isAdmin, isPublic, + isKickedFromGroup, } = this.props; - const showInviteFriends = isPublic || isAdmin; + const showInviteFriends = (isPublic || isAdmin) && !isKickedFromGroup; return (