remove zombies from the UI only

pull/1592/head
Audric Ackermann 4 years ago
parent 2c40d1e623
commit 64eab5160d
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -2056,6 +2056,10 @@
"message": "Anonymous",
"description": "The name of currently unidentified users"
},
"removeResidueMembers": {
"message": "Clicking ok will also remove those members as they left the group.",
"description": "Shown when the admin shows the group member dialog, to warn him that zombies members will be removed"
},
"enterDisplayName": {
"message": "Enter a display name",
"androidKey": "activity_display_name_edit_text_hint"

@ -1,14 +1,21 @@
import React from 'react';
import styled from 'styled-components';
import styled, { DefaultTheme } from 'styled-components';
type TextProps = {
text: string;
subtle?: boolean;
opposite?: boolean;
maxWidth?: string;
padding?: string;
textAlign?: 'center';
theme?: DefaultTheme;
};
const StyledDefaultText = styled.div<TextProps>`
transition: ${props => props.theme.common.animations.defaultDuration};
max-width: ${props => (props.maxWidth ? props.maxWidth : '')};
padding: ${props => (props.padding ? props.padding : '')};
text-align: ${props => (props.textAlign ? props.textAlign : '')};
font-family: ${props => props.theme.common.fonts.sessionFontDefault};
color: ${props =>
props.opposite

@ -143,11 +143,16 @@ class InviteContactsDialogInner extends React.Component<Props, State> {
existingMembers = [];
}
existingMembers = _.compact(existingMembers);
const existingZombies = convo.get('zombies') || [];
const newMembers = pubkeys.filter(d => !existingMembers.includes(d));
if (newMembers.length > 0) {
// Do not trigger an update if there is too many members
if (newMembers.length + existingMembers.length > window.CONSTANTS.CLOSED_GROUP_SIZE_LIMIT) {
// be sure to include current zombies in this count
if (
newMembers.length + existingMembers.length + existingZombies.length >
window.CONSTANTS.CLOSED_GROUP_SIZE_LIMIT
) {
ToastUtils.pushTooManyMembers();
return;
}

@ -2,7 +2,7 @@ import React from 'react';
import classNames from 'classnames';
import { SessionModal } from '../session/SessionModal';
import { SessionButton, SessionButtonColor } from '../session/SessionButton';
import { SessionButton, SessionButtonColor, SessionButtonType } from '../session/SessionButton';
import { ContactType, SessionMemberListItem } from '../session/SessionMemberListItem';
import { DefaultTheme } from 'styled-components';
import { ToastUtils } from '../../session/utils';
@ -11,6 +11,7 @@ import autoBind from 'auto-bind';
import { ConversationController } from '../../session/conversations';
import _ from 'lodash';
import { Text } from '../basic/Text';
interface Props {
titleText: string;
@ -25,8 +26,8 @@ interface Props {
admins: Array<string>; // used for closed group
i18n: LocalizerType;
onSubmit: any;
onClose: any;
onSubmit: (membersLeft: Array<string>) => void;
onClose: () => void;
theme: DefaultTheme;
}
@ -106,7 +107,7 @@ export class UpdateGroupMembersDialog extends React.Component<Props, State> {
}
public render() {
const { okText, cancelText, isAdmin, contactList, titleText } = this.props;
const { okText, cancelText, isAdmin, contactList, titleText, existingZombies } = this.props;
const showNoMembersMessage = contactList.length === 0;
@ -116,6 +117,8 @@ export class UpdateGroupMembersDialog extends React.Component<Props, State> {
this.state.errorDisplayed ? 'error-shown' : 'error-faded'
);
const hasZombies = Boolean(existingZombies.length);
return (
<SessionModal
title={titleText}
@ -169,8 +172,15 @@ export class UpdateGroupMembersDialog extends React.Component<Props, State> {
}
private renderZombiesList() {
return this.state.zombies.map((member: ContactType, index: number) => {
const isSelected = this.props.isAdmin && !member.checkmarked;
const { isAdmin } = this.props;
const { zombies } = this.state;
if (!zombies.length) {
return <></>;
}
const zombieElements = zombies.map((member: ContactType, index: number) => {
const isSelected = isAdmin && !member.checkmarked;
return (
<SessionMemberListItem
member={member}
@ -184,6 +194,22 @@ export class UpdateGroupMembersDialog extends React.Component<Props, State> {
/>
);
});
return (
<>
<div className="spacer-lg" />
{isAdmin && (
<Text
padding="20px"
theme={this.props.theme}
text={window.i18n('removeResidueMembers')}
subtle={true}
maxWidth="400px"
textAlign="center"
/>
)}
{zombieElements}
</>
);
}
private onKeyUp(event: any) {
@ -252,39 +278,11 @@ export class UpdateGroupMembersDialog extends React.Component<Props, State> {
}
private onZombieClicked(selected: ContactType) {
const { isAdmin, admins } = this.props;
const { zombies } = this.state;
const { isAdmin } = this.props;
if (!isAdmin) {
ToastUtils.pushOnlyAdminCanRemove();
return;
}
if (selected.existingMember && !isAdmin) {
window.log.warn('Only group admin can remove members!');
return;
}
if (selected.existingMember && admins.includes(selected.id)) {
window.log.warn(
`User ${selected.id} cannot be removed as they are the creator of the closed group.`
);
ToastUtils.pushCannotRemoveCreatorFromGroup();
return;
}
const updatedZombies = zombies.map(zombie => {
if (zombie.id === selected.id) {
return { ...zombie, checkmarked: !zombie.checkmarked };
} else {
return zombie;
}
});
this.setState(state => {
return {
...state,
zombies: updatedZombies,
};
});
}
}

@ -752,18 +752,11 @@ async function handleClosedGroupMemberLeft(envelope: EnvelopePlus, convo: Conver
await ClosedGroup.addUpdateMessage(convo, groupDiff, 'incoming', _.toNumber(envelope.timestamp));
convo.updateLastMessage();
// if a user just left and we are the admin, we remove him right away for everyone by sending a MEMBERS_REMOVED message so no need to add him as a zombie
if (!isCurrentUserAdmin && oldMembers.includes(sender)) {
if (oldMembers.includes(sender)) {
addMemberToZombies(envelope, PubKey.cast(sender), convo);
}
convo.set('members', newMembers);
// if we are the admin, and there are still some members after the member left, we send a new keypair
// to the remaining members.
// also if we are the admin, we can tell to everyone that this user is effectively removed
if (isCurrentUserAdmin && !!newMembers.length) {
await ClosedGroup.sendRemovedMembers(convo, [sender], newMembers);
}
await convo.commit();
await removeFromCache(envelope);

@ -81,8 +81,6 @@ export async function getGroupSecretKey(groupId: string): Promise<Uint8Array> {
return new Uint8Array(fromHex(secretKey));
}
// tslint:disable: max-func-body-length
// tslint:disable: cyclomatic-complexity
export async function initiateGroupUpdate(
groupId: string,
groupName: string,
@ -109,7 +107,6 @@ export async function initiateGroupUpdate(
throw new Error('Legacy group are not supported anymore.');
}
const oldZombies = convo.get('zombies');
console.warn('initiategroupUpdate old zombies:', oldZombies);
// do not give an admins field here. We don't want to be able to update admins and
// updateOrCreateClosedGroup() will update them if given the choice.
@ -123,7 +120,6 @@ export async function initiateGroupUpdate(
expireTimer: convo.get('expireTimer'),
avatar,
};
console.warn('initiategroupUpdate new zombies:', groupDetails.zombies);
const diff = buildGroupDiff(convo, groupDetails);
@ -207,7 +203,7 @@ export async function addUpdateMessage(
return message;
}
export function buildGroupDiff(convo: ConversationModel, update: UpdatableGroupState): GroupDiff {
function buildGroupDiff(convo: ConversationModel, update: GroupInfo): GroupDiff {
const groupDiff: GroupDiff = {};
if (convo.get('name') !== update.name) {
@ -215,13 +211,17 @@ export function buildGroupDiff(convo: ConversationModel, update: UpdatableGroupS
}
const oldMembers = convo.get('members');
const oldZombies = convo.get('zombies');
const oldMembersWithZombies = _.uniq(oldMembers.concat(oldZombies));
const newMembersWithZombiesLeft = _.uniq(update.members.concat(update.zombies || []));
const addedMembers = _.difference(update.members, oldMembers);
const addedMembers = _.difference(newMembersWithZombiesLeft, oldMembersWithZombies);
if (addedMembers.length > 0) {
groupDiff.joiningMembers = addedMembers;
}
// Check if anyone got kicked:
const removedMembers = _.difference(oldMembers, update.members);
const removedMembers = _.difference(oldMembersWithZombies, newMembersWithZombiesLeft);
if (removedMembers.length > 0) {
groupDiff.leavingMembers = removedMembers;
}

Loading…
Cancel
Save