Merge branch 'feature/ses-145/leave-conversation-update' into userconfig_disappearingmessage
commit
24887dd05b
@ -0,0 +1,82 @@
|
||||
import React from 'react';
|
||||
|
||||
import { isEmpty } from 'lodash';
|
||||
import styled from 'styled-components';
|
||||
import { useIsPrivate, useIsPublic } from '../../../../hooks/useParamSelector';
|
||||
import {
|
||||
ConversationInteractionStatus,
|
||||
ConversationInteractionType,
|
||||
} from '../../../../interactions/conversationInteractions';
|
||||
import { PropsForInteractionNotification } from '../../../../state/ducks/conversations';
|
||||
import { assertUnreachable } from '../../../../types/sqlSharedTypes';
|
||||
import { Flex } from '../../../basic/Flex';
|
||||
import { ReadableMessage } from './ReadableMessage';
|
||||
|
||||
const StyledFailText = styled.div`
|
||||
color: var(--danger-color);
|
||||
`;
|
||||
|
||||
export const InteractionNotification = (props: PropsForInteractionNotification) => {
|
||||
const { notificationType, convoId, messageId, receivedAt, isUnread } = props;
|
||||
|
||||
const { interactionStatus, interactionType } = notificationType;
|
||||
|
||||
const isGroup = !useIsPrivate(convoId);
|
||||
const isCommunity = useIsPublic(convoId);
|
||||
|
||||
// NOTE at this time we don't show visible control messages in communities, that might change in future...
|
||||
if (isCommunity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (interactionStatus !== ConversationInteractionStatus.Error) {
|
||||
// NOTE For now we only show interaction errors in the message history
|
||||
return null;
|
||||
}
|
||||
|
||||
let text = '';
|
||||
|
||||
switch (interactionType) {
|
||||
case ConversationInteractionType.Hide:
|
||||
text = window.i18n('hideConversationFailedPleaseTryAgain');
|
||||
break;
|
||||
case ConversationInteractionType.Leave:
|
||||
text = isCommunity
|
||||
? window.i18n('leaveCommunityFailedPleaseTryAgain')
|
||||
: isGroup
|
||||
? window.i18n('leaveGroupFailedPleaseTryAgain')
|
||||
: window.i18n('deleteConversationFailedPleaseTryAgain');
|
||||
break;
|
||||
default:
|
||||
assertUnreachable(
|
||||
interactionType,
|
||||
`InteractionErrorMessage: Missing case error "${interactionType}"`
|
||||
);
|
||||
}
|
||||
|
||||
if (isEmpty(text)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ReadableMessage
|
||||
messageId={messageId}
|
||||
receivedAt={receivedAt}
|
||||
isUnread={isUnread}
|
||||
key={`readable-message-${messageId}`}
|
||||
dataTestId="interaction-notification"
|
||||
>
|
||||
<Flex
|
||||
id={`convo-interaction-${convoId}`}
|
||||
container={true}
|
||||
flexDirection="row"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
margin={'var(--margins-md) var(--margins-sm)'}
|
||||
data-testid="control-message"
|
||||
>
|
||||
<StyledFailText>{text}</StyledFailText>
|
||||
</Flex>
|
||||
</ReadableMessage>
|
||||
);
|
||||
};
|
@ -1,61 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import styled from 'styled-components';
|
||||
import { getConversationController } from '../../session/conversations';
|
||||
import { adminLeaveClosedGroup } from '../../state/ducks/modalDialog';
|
||||
import { SessionWrapperModal } from '../SessionWrapperModal';
|
||||
import { SessionButton, SessionButtonColor, SessionButtonType } from '../basic/SessionButton';
|
||||
import { SpacerLG } from '../basic/Text';
|
||||
import { SessionSpinner } from '../basic/SessionSpinner';
|
||||
|
||||
const StyledWarning = styled.p`
|
||||
max-width: 500px;
|
||||
line-height: 1.3333;
|
||||
`;
|
||||
|
||||
export const AdminLeaveClosedGroupDialog = (props: { conversationId: string }) => {
|
||||
const dispatch = useDispatch();
|
||||
const convo = getConversationController().get(props.conversationId);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const titleText = `${window.i18n('leaveGroup')} ${convo?.getRealSessionUsername() || ''}`;
|
||||
|
||||
const closeDialog = () => {
|
||||
dispatch(adminLeaveClosedGroup(null));
|
||||
};
|
||||
|
||||
const onClickOK = async () => {
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
setLoading(true);
|
||||
// we know want to delete a closed group right after we've left it, so we can call the deleteContact which takes care of it all
|
||||
await getConversationController().deleteClosedGroup(props.conversationId, {
|
||||
fromSyncMessage: false,
|
||||
sendLeaveMessage: true,
|
||||
});
|
||||
setLoading(false);
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
return (
|
||||
<SessionWrapperModal title={titleText} onClose={closeDialog}>
|
||||
<SpacerLG />
|
||||
<StyledWarning>{window.i18n('leaveGroupConfirmationAdmin')}</StyledWarning>
|
||||
<SessionSpinner loading={loading} />
|
||||
|
||||
<div className="session-modal__button-group">
|
||||
<SessionButton
|
||||
text={window.i18n('leaveAndRemoveForEveryone')}
|
||||
buttonColor={SessionButtonColor.Danger}
|
||||
buttonType={SessionButtonType.Simple}
|
||||
onClick={onClickOK}
|
||||
/>
|
||||
<SessionButton
|
||||
text={window.i18n('cancel')}
|
||||
buttonType={SessionButtonType.Simple}
|
||||
onClick={closeDialog}
|
||||
/>
|
||||
</div>
|
||||
</SessionWrapperModal>
|
||||
);
|
||||
};
|
@ -0,0 +1,105 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { isEmpty } from 'lodash';
|
||||
|
||||
import { useIsPrivate, useIsPublic } from '../../../hooks/useParamSelector';
|
||||
import { MessageBody } from '../../conversation/message/message-content/MessageBody';
|
||||
import { assertUnreachable } from '../../../types/sqlSharedTypes';
|
||||
import {
|
||||
ConversationInteractionStatus,
|
||||
ConversationInteractionType,
|
||||
} from '../../../interactions/conversationInteractions';
|
||||
import styled from 'styled-components';
|
||||
import { getConversationController } from '../../../session/conversations';
|
||||
import { LastMessageType } from '../../../state/ducks/conversations';
|
||||
|
||||
const StyledInteractionItemText = styled.div<{ isError: boolean }>`
|
||||
${props => props.isError && 'color: var(--danger-color) !important;'}
|
||||
`;
|
||||
|
||||
type InteractionItemProps = {
|
||||
conversationId: string;
|
||||
lastMessage: LastMessageType | null;
|
||||
};
|
||||
|
||||
export const InteractionItem = (props: InteractionItemProps) => {
|
||||
const { conversationId, lastMessage } = props;
|
||||
const isGroup = !useIsPrivate(conversationId);
|
||||
const isCommunity = useIsPublic(conversationId);
|
||||
|
||||
if (!lastMessage) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { interactionType, interactionStatus } = lastMessage;
|
||||
|
||||
if (!interactionType || !interactionStatus) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const [storedLastMessageText, setStoredLastMessageText] = useState(lastMessage?.text);
|
||||
const [storedLastMessageInteractionStatus, setStoredLastMessageInteractionStatus] = useState(
|
||||
lastMessage?.interactionStatus
|
||||
);
|
||||
|
||||
// NOTE we want to reset the interaction state when the last message changes
|
||||
useEffect(() => {
|
||||
if (conversationId) {
|
||||
const convo = getConversationController().get(conversationId);
|
||||
|
||||
if (storedLastMessageInteractionStatus !== convo.get('lastMessageInteractionStatus')) {
|
||||
setStoredLastMessageInteractionStatus(convo.get('lastMessageInteractionStatus'));
|
||||
setStoredLastMessageText(convo.get('lastMessage'));
|
||||
}
|
||||
}
|
||||
}, [conversationId]);
|
||||
|
||||
let text = storedLastMessageText || '';
|
||||
let errorText = '';
|
||||
|
||||
switch (interactionType) {
|
||||
case ConversationInteractionType.Hide:
|
||||
errorText = window.i18n('hideConversationFailed');
|
||||
text =
|
||||
interactionStatus === ConversationInteractionStatus.Error
|
||||
? errorText
|
||||
: interactionStatus === ConversationInteractionStatus.Start ||
|
||||
interactionStatus === ConversationInteractionStatus.Loading
|
||||
? window.i18n('hiding')
|
||||
: text;
|
||||
break;
|
||||
case ConversationInteractionType.Leave:
|
||||
errorText = isCommunity
|
||||
? window.i18n('leaveCommunityFailed')
|
||||
: isGroup
|
||||
? window.i18n('leaveGroupFailed')
|
||||
: window.i18n('deleteConversationFailed');
|
||||
text =
|
||||
interactionStatus === ConversationInteractionStatus.Error
|
||||
? errorText
|
||||
: interactionStatus === ConversationInteractionStatus.Start ||
|
||||
interactionStatus === ConversationInteractionStatus.Loading
|
||||
? window.i18n('leaving')
|
||||
: text;
|
||||
break;
|
||||
default:
|
||||
assertUnreachable(
|
||||
interactionType,
|
||||
`InteractionItem: Missing case error "${interactionType}"`
|
||||
);
|
||||
}
|
||||
|
||||
if (isEmpty(text)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="module-conversation-list-item__message">
|
||||
<StyledInteractionItemText
|
||||
className="module-conversation-list-item__message__text"
|
||||
isError={Boolean(interactionStatus === ConversationInteractionStatus.Error)}
|
||||
>
|
||||
<MessageBody text={text} disableJumbomoji={true} disableLinks={true} isGroup={isGroup} />
|
||||
</StyledInteractionItemText>
|
||||
</div>
|
||||
);
|
||||
};
|
Loading…
Reference in New Issue