Can leave private group chats

pull/565/head
Maxim Shishmarev 6 years ago
parent f5e9a870f7
commit 9f81f67460

@ -928,6 +928,9 @@
"ok": { "ok": {
"message": "OK" "message": "OK"
}, },
"yes": {
"message": "Yes"
},
"cancel": { "cancel": {
"message": "Cancel" "message": "Cancel"
}, },
@ -994,6 +997,9 @@
"description": "description":
"Placeholder text in the message entry field when it is the first message sent to that contact" "Placeholder text in the message entry field when it is the first message sent to that contact"
}, },
"sendMessageLeftGroup": {
"message": "You left this group"
},
"groupMembers": { "groupMembers": {
"message": "Group members" "message": "Group members"
}, },
@ -1917,6 +1923,17 @@
"Button action that the user can click to rename the group or add a new member" "Button action that the user can click to rename the group or add a new member"
}, },
"leaveGroup": {
"message": "Leave Group",
"description": "Button action that the user can click to leave the group"
},
"leaveGroupDialogTitle": {
"message": "Are you sure you want to leave this group?",
"description":
"Title shown to the user to confirm they want to leave the group"
},
"copiedPublicKey": { "copiedPublicKey": {
"message": "Copied public key", "message": "Copied public key",
"description": "A toast message telling the user that the key was copied" "description": "A toast message telling the user that the key was copied"

@ -763,6 +763,12 @@
} }
}); });
Whisper.events.on('leaveGroup', async groupConvo => {
if (appView) {
appView.showLeaveGroupDialog(groupConvo);
}
});
Whisper.events.on('deleteConversation', async conversation => { Whisper.events.on('deleteConversation', async conversation => {
await conversation.destroyMessages(); await conversation.destroyMessages();
await window.Signal.Data.removeConversation(conversation.id, { await window.Signal.Data.removeConversation(conversation.id, {

@ -671,6 +671,11 @@
this.trigger('disable:input', true); this.trigger('disable:input', true);
return; return;
} }
if (!this.isPrivate() && this.get('left')) {
this.trigger('disable:input', true);
this.trigger('change:placeholder', 'left-group');
return;
}
switch (this.get('friendRequestStatus')) { switch (this.get('friendRequestStatus')) {
case FriendRequestStatusEnum.none: case FriendRequestStatusEnum.none:
case FriendRequestStatusEnum.requestExpired: case FriendRequestStatusEnum.requestExpired:
@ -1962,6 +1967,8 @@
textsecure.messaging.leaveGroup(this.id, groupNumbers, options) textsecure.messaging.leaveGroup(this.id, groupNumbers, options)
) )
); );
this.updateTextInputState();
} }
}, },

@ -1816,6 +1816,8 @@
groupUpdate.joined = difference; groupUpdate.joined = difference;
} }
if (conversation.get('left')) { if (conversation.get('left')) {
// TODO: Maybe we shouldn't assume this message adds us:
// we could maybe still get this message by mistake
window.log.warn('re-added to a left group'); window.log.warn('re-added to a left group');
attributes.left = false; attributes.left = false;
} }
@ -1885,6 +1887,9 @@
attributes.active_at = now; attributes.active_at = now;
conversation.set(attributes); conversation.set(attributes);
// Re-enable typing if re-joined the group
conversation.updateTextInputState();
if (message.isExpirationTimerUpdate()) { if (message.isExpirationTimerUpdate()) {
message.set({ message.set({
expirationTimerUpdate: { expirationTimerUpdate: {

@ -50,6 +50,7 @@ const {
const { const {
UpdateGroupDialog, UpdateGroupDialog,
} = require('../../ts/components/conversation/UpdateGroupDialog'); } = require('../../ts/components/conversation/UpdateGroupDialog');
const { ConfirmDialog } = require('../../ts/components/ConfirmDialog');
const { const {
MediaGallery, MediaGallery,
} = require('../../ts/components/conversation/media-gallery/MediaGallery'); } = require('../../ts/components/conversation/media-gallery/MediaGallery');
@ -226,6 +227,7 @@ exports.setup = (options = {}) => {
MainHeader, MainHeader,
MemberList, MemberList,
CreateGroupDialog, CreateGroupDialog,
ConfirmDialog,
UpdateGroupDialog, UpdateGroupDialog,
MediaGallery, MediaGallery,
Message, Message,

@ -215,5 +215,9 @@
const dialog = new Whisper.UpdateGroupDialogView(groupConvo); const dialog = new Whisper.UpdateGroupDialogView(groupConvo);
this.el.append(dialog.el); this.el.append(dialog.el);
}, },
showLeaveGroupDialog(groupConvo) {
const dialog = new Whisper.LeaveGroupDialogView(groupConvo);
this.el.append(dialog.el);
},
}); });
})(); })();

@ -272,6 +272,10 @@
onUpdateGroup: () => { onUpdateGroup: () => {
window.Whisper.events.trigger('updateGroup', this.model); window.Whisper.events.trigger('updateGroup', this.model);
}, },
onLeaveGroup: () => {
window.Whisper.events.trigger('leaveGroup', this.model);
},
}; };
}; };
this.titleView = new Whisper.ReactWrapperView({ this.titleView = new Whisper.ReactWrapperView({
@ -440,6 +444,9 @@
case 'disabled': case 'disabled':
placeholder = i18n('sendMessageDisabled'); placeholder = i18n('sendMessageDisabled');
break; break;
case 'left-group':
placeholder = i18n('sendMessageLeftGroup');
break;
default: default:
placeholder = i18n('sendMessage'); placeholder = i18n('sendMessage');
break; break;

@ -46,8 +46,48 @@
}, },
}); });
Whisper.LeaveGroupDialogView = Whisper.View.extend({
className: 'loki-dialog modal',
initialize(groupConvo) {
this.groupConvo = groupConvo;
this.titleText = groupConvo.get('name');
this.messageText = i18n('leaveGroupDialogTitle');
this.okText = i18n('yes');
this.cancelText = i18n('cancel');
this.close = this.close.bind(this);
this.confirm = this.confirm.bind(this);
this.$el.focus();
this.render();
},
render() {
this.dialogView = new Whisper.ReactWrapperView({
className: 'leave-group-dialog',
Component: window.Signal.Components.ConfirmDialog,
props: {
titleText: this.titleText,
messageText: this.messageText,
okText: this.okText,
cancelText: this.cancelText,
onConfirm: this.confirm,
onClose: this.close,
},
});
this.$el.append(this.dialogView.el);
return this;
},
async confirm() {
await this.groupConvo.leaveGroup();
this.close();
},
close() {
this.remove();
},
});
Whisper.UpdateGroupDialogView = Whisper.View.extend({ Whisper.UpdateGroupDialogView = Whisper.View.extend({
templateName: 'group-creation-template',
className: 'loki-dialog modal', className: 'loki-dialog modal',
initialize(groupConvo) { initialize(groupConvo) {
this.groupName = groupConvo.get('name'); this.groupName = groupConvo.get('name');

@ -1,3 +1,30 @@
.leave-group-dialog {
.content {
max-width: 100% !important;
}
.titleText {
font-size: large;
text-align: center;
margin: 2px;
}
.ok {
background-color: orangered;
min-width: 70px;
border: none;
&:hover {
background-color: red;
}
}
.cancel {
border: none;
min-width: 70px;
}
}
.create-group-dialog { .create-group-dialog {
.content { .content {
max-width: 100% !important; max-width: 100% !important;

@ -0,0 +1,33 @@
import React from 'react';
interface Props {
titleText: string;
messageText: string;
okText: string;
cancelText: string;
onConfirm: any;
onClose: any;
}
export class ConfirmDialog extends React.Component<Props> {
constructor(props: any) {
super(props);
}
public render() {
return (
<div className="content">
<p className="titleText">{this.props.titleText}</p>
<p className="messageText">{this.props.messageText}</p>
<div className="buttons">
<button className="cancel" tabIndex={0} onClick={this.props.onClose}>
{this.props.cancelText}
</button>
<button className="ok" tabIndex={0} onClick={this.props.onConfirm}>
{this.props.okText}
</button>
</div>
</div>
);
}
}

@ -63,6 +63,7 @@ interface Props {
onCopyPublicKey: () => void; onCopyPublicKey: () => void;
onUpdateGroup: () => void; onUpdateGroup: () => void;
onLeaveGroup: () => void;
i18n: LocalizerType; i18n: LocalizerType;
} }
@ -225,6 +226,7 @@ export class ConversationHeader extends React.Component<Props> {
onDeleteContact, onDeleteContact,
onCopyPublicKey, onCopyPublicKey,
onUpdateGroup, onUpdateGroup,
onLeaveGroup,
} = this.props; } = this.props;
return ( return (
@ -233,6 +235,7 @@ export class ConversationHeader extends React.Component<Props> {
<MenuItem onClick={onCopyPublicKey}>{i18n('copyPublicKey')}</MenuItem> <MenuItem onClick={onCopyPublicKey}>{i18n('copyPublicKey')}</MenuItem>
<MenuItem onClick={onDeleteMessages}>{i18n('deleteMessages')}</MenuItem> <MenuItem onClick={onDeleteMessages}>{i18n('deleteMessages')}</MenuItem>
<MenuItem onClick={onUpdateGroup}>{i18n('updateGroup')}</MenuItem> <MenuItem onClick={onUpdateGroup}>{i18n('updateGroup')}</MenuItem>
<MenuItem onClick={onLeaveGroup}>{i18n('leaveGroup')}</MenuItem>
{!isMe && isClosable ? ( {!isMe && isClosable ? (
!isPublic ? ( !isPublic ? (
<MenuItem onClick={onDeleteContact}> <MenuItem onClick={onDeleteContact}>

Loading…
Cancel
Save