fix moderator add/remove

This commit is contained in:
Audric Ackermann 2021-06-21 14:04:07 +10:00
parent 9a08ab68bc
commit 9ed030fac6
No known key found for this signature in database
GPG key ID: 999F434D76324AD4
10 changed files with 89 additions and 114 deletions

View file

@ -143,7 +143,7 @@ export const ActionPanelOnionStatusLight = (props: {
let iconColor = red;
//if we are not online or the first path is not valid, we keep red as color
if (isOnline && firstPathLength > 1) {
iconColor = onionPathsCount > 2 ? green : onionPathsCount > 1 ? orange : red;
iconColor = onionPathsCount >= 2 ? green : onionPathsCount >= 1 ? orange : red;
}
return (

View file

@ -1,107 +1,80 @@
import React from 'react';
import React, { useState } from 'react';
import { Avatar, AvatarSize } from './Avatar';
import { SessionButton, SessionButtonColor, SessionButtonType } from './session/SessionButton';
import { SessionIdEditable } from './session/SessionIdEditable';
import { ConversationController } from '../session/conversations';
import { ConversationModel, ConversationTypeEnum } from '../models/conversation';
import { ConversationTypeEnum } from '../models/conversation';
import { SessionWrapperModal } from './session/SessionWrapperModal';
import { SpacerMD } from './basic/Text';
import autoBind from 'auto-bind';
import { updateUserDetailsModal } from '../state/ducks/modalDialog';
import { openConversationExternal } from '../state/ducks/conversations';
// tslint:disable-next-line: no-submodule-imports
import useKey from 'react-use/lib/useKey';
type Props = {
conversationId: string;
authorAvatarPath?: string;
userName: string;
};
interface State {
isEnlargedImageShown: boolean;
}
export const UserDetailsDialog = (props: Props) => {
const [isEnlargedImageShown, setIsEnlargedImageShown] = useState(false);
const convo = ConversationController.getInstance().get(props.conversationId);
export class UserDetailsDialog extends React.Component<Props, State> {
private readonly convo: ConversationModel;
constructor(props: Props) {
super(props);
autoBind(this);
this.convo = ConversationController.getInstance().get(props.conversationId);
window.addEventListener('keyup', this.onKeyUp);
this.state = { isEnlargedImageShown: false };
}
public render() {
return (
<SessionWrapperModal title={this.props.userName} onClose={this.closeDialog}>
<div className="avatar-center">
<div className="avatar-center-inner">{this.renderAvatar()}</div>
</div>
<SpacerMD />
<SessionIdEditable editable={false} text={this.convo.id} />
<div className="session-modal__button-group__center">
<SessionButton
text={window.i18n('startConversation')}
buttonType={SessionButtonType.Default}
buttonColor={SessionButtonColor.Primary}
onClick={this.onClickStartConversation}
/>
</div>
</SessionWrapperModal>
);
}
private renderAvatar() {
const size = this.state.isEnlargedImageShown ? AvatarSize.HUGE : AvatarSize.XL;
const userName = this.props.userName || this.props.conversationId;
return (
<Avatar
avatarPath={this.props.authorAvatarPath}
name={userName}
size={size}
onAvatarClick={this.handleShowEnlargedDialog}
pubkey={this.props.conversationId}
/>
);
}
private readonly handleShowEnlargedDialog = () => {
this.setState({ isEnlargedImageShown: !this.state.isEnlargedImageShown });
};
private onKeyUp(event: any) {
switch (event.key) {
case 'Enter':
void this.onClickStartConversation();
break;
case 'Esc':
case 'Escape':
this.closeDialog();
break;
default:
}
}
private closeDialog() {
window.removeEventListener('keyup', this.onKeyUp);
const size = isEnlargedImageShown ? AvatarSize.HUGE : AvatarSize.XL;
const userName = props.userName || props.conversationId;
function closeDialog() {
window.inboxStore?.dispatch(updateUserDetailsModal(null));
}
private async onClickStartConversation() {
// this.props.onStartConversation();
async function onClickStartConversation() {
const conversation = await ConversationController.getInstance().getOrCreateAndWait(
this.convo.id,
convo.id,
ConversationTypeEnum.PRIVATE
);
window.inboxStore?.dispatch(openConversationExternal(conversation.id));
this.closeDialog();
closeDialog();
}
}
useKey(
'Enter',
() => {
void onClickStartConversation();
},
undefined,
[props.conversationId]
);
return (
<SessionWrapperModal title={props.userName} onClose={closeDialog} showExitIcon={true}>
<div className="avatar-center">
<div className="avatar-center-inner">
<Avatar
avatarPath={props.authorAvatarPath}
name={userName}
size={size}
onAvatarClick={() => {
setIsEnlargedImageShown(!isEnlargedImageShown);
}}
pubkey={props.conversationId}
/>
</div>
</div>
<SpacerMD />
<SessionIdEditable editable={false} text={convo.id} />
<div className="session-modal__button-group__center">
<SessionButton
text={window.i18n('startConversation')}
buttonType={SessionButtonType.Default}
buttonColor={SessionButtonColor.Primary}
onClick={onClickStartConversation}
/>
</div>
</SessionWrapperModal>
);
};

View file

@ -487,7 +487,7 @@ class MessageInner extends React.PureComponent<MessageRegularProps, State> {
onAvatarClick={() => {
window.inboxStore?.dispatch(
updateUserDetailsModal({
conversationId: this.props.convoId,
conversationId: authorPhoneNumber,
userName,
authorAvatarPath,
})

View file

@ -10,6 +10,7 @@ import { SessionWrapperModal } from '../session/SessionWrapperModal';
import { ConversationController } from '../../session/conversations';
import { useDispatch } from 'react-redux';
import { updateAddModeratorsModal } from '../../state/ducks/modalDialog';
import _ from 'lodash';
type Props = {
conversationId: string;

View file

@ -209,9 +209,10 @@ export class RemoveModeratorsDialog extends React.Component<Props, State> {
} else {
window?.log?.info(`${removedMods} removed from moderators...`);
ToastUtils.pushUserRemovedFromModerators();
this.closeDialog();
}
} catch (e) {
window?.log?.error('Got error while adding moderator:', e);
window?.log?.error('Got error while removing moderator:', e);
} finally {
this.refreshModList();
}

View file

@ -57,7 +57,11 @@ class SessionSeedModalInner extends React.Component<{}, State> {
return (
<>
{!loading && (
<SessionWrapperModal title={i18n('showRecoveryPhrase')} onClose={onClose}>
<SessionWrapperModal
title={i18n('showRecoveryPhrase')}
onClose={onClose}
showExitIcon={true}
>
<SpacerSM />
{hasPassword && !passwordValid ? (
@ -111,7 +115,6 @@ class SessionSeedModalInner extends React.Component<{}, State> {
const fgColor = '#1B1B1B';
const hexEncodedSeed = mn_decode(this.state.recoveryPhrase, 'english');
const onClose = () => window.inboxStore?.dispatch(recoveryPhraseModal(null));
return (
<>
@ -133,7 +136,6 @@ class SessionSeedModalInner extends React.Component<{}, State> {
this.copyRecoveryPhrase(this.state.recoveryPhrase);
}}
/>
<SessionButton text={i18n('cancel')} onClick={onClose} />
</div>
</>
);

View file

@ -5,6 +5,9 @@ import { SessionIconButton, SessionIconSize, SessionIconType } from './icon/';
import { SessionButton, SessionButtonColor, SessionButtonType } from './SessionButton';
import { DefaultTheme, useTheme } from 'styled-components';
// tslint:disable-next-line: no-submodule-imports
import useKey from 'react-use/lib/useKey';
type Props = {
title: string;
onClose: any;
@ -58,21 +61,23 @@ export const SessionWrapperModal = (props: SessionWrapperModalType) => {
const theme = useTheme();
useEffect(() => {
window.addEventListener('keyup', keyUpHandler);
useKey(
'Esc',
() => {
props.onClose?.();
},
undefined,
[props.onClose]
);
return () => {
window.removeEventListener('keyup', keyUpHandler);
};
}, []);
const keyUpHandler = ({ key }: any) => {
if (key === 'Escape') {
if (props.onClose) {
props.onClose();
}
}
};
useKey(
'Escape',
() => {
props.onClose?.();
},
undefined,
[props.onClose]
);
return (
<div className={`loki-dialog modal ${additionalClassName}`}>

View file

@ -149,17 +149,17 @@ export async function removeSenderFromModerator(sender: string, convoId: string)
export async function addSenderAsModerator(sender: string, convoId: string) {
try {
const pubKeyToRemove = PubKey.cast(sender);
const pubKeyToAdd = PubKey.cast(sender);
const convo = ConversationController.getInstance().getOrThrow(convoId);
const roomInfo = convo.toOpenGroupV2();
const res = await ApiV2.addModerator(pubKeyToRemove, roomInfo);
const res = await ApiV2.addModerator(pubKeyToAdd, roomInfo);
if (!res) {
window?.log?.warn('failed to add moderator:', res);
ToastUtils.pushUserNeedsToHaveJoined();
} else {
window?.log?.info(`${pubKeyToRemove.key} removed from moderators...`);
window?.log?.info(`${pubKeyToAdd.key} added to moderators...`);
ToastUtils.pushUserAddedToModerators();
}
} catch (e) {

View file

@ -408,8 +408,8 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
}
public async updateGroupAdmins(groupAdmins: Array<string>) {
const existingAdmins = _.sortBy(this.getGroupAdmins());
const newAdmins = _.sortBy(groupAdmins);
const existingAdmins = _.uniq(_.sortBy(this.getGroupAdmins()));
const newAdmins = _.uniq(_.sortBy(groupAdmins));
if (_.isEqual(existingAdmins, newAdmins)) {
// window?.log?.info(

View file

@ -448,16 +448,9 @@ const handleCompactPollResults = async (
window?.log?.warn('Could not find convo for compactPoll', convoId);
return;
}
const existingModerators = convo.get('moderators') || [];
let changeOnConvo = false;
if (!_.isEqual(existingModerators.sort(), res.moderators.sort())) {
convo.set({ moderators: res.moderators });
changeOnConvo = true;
}
if (changeOnConvo) {
await convo.commit();
}
// this already do the commit
await convo.updateGroupAdmins(res.moderators);
})
);
};