fix: improved reaction alignment based on avatar visibility
This commit is contained in:
parent
828f1923a0
commit
a8b8692016
|
@ -129,13 +129,6 @@ textarea {
|
|||
font-style: normal;
|
||||
}
|
||||
|
||||
.module-message__author-avatar {
|
||||
position: relative;
|
||||
margin-inline-end: 20px;
|
||||
padding-top: 5px;
|
||||
padding-inline-end: 4px;
|
||||
}
|
||||
|
||||
.module-message--incoming {
|
||||
margin-inline-start: 0;
|
||||
margin-inline-end: auto;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React, { useCallback } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import styled from 'styled-components';
|
||||
import { OpenGroupData } from '../../../../data/opengroups';
|
||||
import { MessageRenderingProps } from '../../../../models/messageType';
|
||||
import { findCachedBlindedMatchOrLookItUp } from '../../../../session/apis/open_group_api/sogsv3/knownBlindedkeys';
|
||||
|
@ -16,6 +17,13 @@ import {
|
|||
import { Avatar, AvatarSize, CrownIcon } from '../../../avatar/Avatar';
|
||||
// tslint:disable: use-simple-attributes
|
||||
|
||||
const StyledAvatar = styled.div`
|
||||
position: relative;
|
||||
margin-inline-end: 20px;
|
||||
padding-top: 5px;
|
||||
padding-inline-end: 4px;
|
||||
`;
|
||||
|
||||
export type MessageAvatarSelectorProps = Pick<
|
||||
MessageRenderingProps,
|
||||
| 'authorAvatarPath'
|
||||
|
@ -23,16 +31,14 @@ export type MessageAvatarSelectorProps = Pick<
|
|||
| 'sender'
|
||||
| 'authorProfileName'
|
||||
| 'isSenderAdmin'
|
||||
| 'conversationType'
|
||||
| 'direction'
|
||||
| 'isPublic'
|
||||
| 'lastMessageOfSeries'
|
||||
>;
|
||||
|
||||
type Props = { messageId: string };
|
||||
type Props = { messageId: string; noAvatar: boolean };
|
||||
|
||||
export const MessageAvatar = (props: Props) => {
|
||||
const { messageId } = props;
|
||||
const { messageId, noAvatar } = props;
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const avatarProps = useSelector(state => getMessageAvatarProps(state as any, messageId));
|
||||
|
@ -43,21 +49,21 @@ export const MessageAvatar = (props: Props) => {
|
|||
if (!avatarProps) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const {
|
||||
authorAvatarPath,
|
||||
authorName,
|
||||
sender,
|
||||
authorProfileName,
|
||||
conversationType,
|
||||
direction,
|
||||
isSenderAdmin,
|
||||
lastMessageOfSeries,
|
||||
isPublic,
|
||||
} = avatarProps;
|
||||
|
||||
if (conversationType !== 'group' || direction === 'outgoing') {
|
||||
if (noAvatar) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const userName = authorName || authorProfileName || sender;
|
||||
|
||||
const onMessageAvatarClick = useCallback(async () => {
|
||||
|
@ -122,9 +128,9 @@ export const MessageAvatar = (props: Props) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="module-message__author-avatar" key={`msg-avatar-${sender}`}>
|
||||
<StyledAvatar key={`msg-avatar-${sender}`}>
|
||||
<Avatar size={AvatarSize.S} onAvatarClick={onMessageAvatarClick} pubkey={sender} />
|
||||
{isSenderAdmin && <CrownIcon />}
|
||||
</div>
|
||||
</StyledAvatar>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -20,7 +20,7 @@ import { MessageStatus } from './MessageStatus';
|
|||
|
||||
export type MessageContentWithStatusSelectorProps = Pick<
|
||||
MessageRenderingProps,
|
||||
'direction' | 'isDeleted'
|
||||
'conversationType' | 'direction' | 'isDeleted'
|
||||
>;
|
||||
|
||||
type Props = {
|
||||
|
@ -40,7 +40,7 @@ const StyledMessageContentContainer = styled.div<{ direction: 'left' | 'right' }
|
|||
width: 100%;
|
||||
|
||||
${StyledMessageReactions} {
|
||||
margin-right: var(--margins-sm);
|
||||
margin-right: var(--margins-md);
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -88,11 +88,13 @@ export const MessageContentWithStatuses = (props: Props) => {
|
|||
};
|
||||
|
||||
const { messageId, ctxMenuID, isDetailView, dataTestId, enableReactions } = props;
|
||||
|
||||
if (!contentProps) {
|
||||
return null;
|
||||
}
|
||||
const { direction, isDeleted } = contentProps;
|
||||
const { conversationType, direction, isDeleted } = contentProps;
|
||||
const isIncoming = direction === 'incoming';
|
||||
const noAvatar = conversationType !== 'group' || direction === 'outgoing';
|
||||
|
||||
const [popupReaction, setPopupReaction] = useState('');
|
||||
|
||||
|
@ -118,7 +120,7 @@ export const MessageContentWithStatuses = (props: Props) => {
|
|||
onDoubleClickCapture={onDoubleClickReplyToMessage}
|
||||
data-testid={dataTestId}
|
||||
>
|
||||
<MessageAvatar messageId={messageId} />
|
||||
<MessageAvatar messageId={messageId} noAvatar={noAvatar} />
|
||||
<MessageStatus
|
||||
dataTestId="msg-status-incoming"
|
||||
messageId={messageId}
|
||||
|
@ -148,6 +150,7 @@ export const MessageContentWithStatuses = (props: Props) => {
|
|||
popupReaction={popupReaction}
|
||||
setPopupReaction={setPopupReaction}
|
||||
onPopupClick={handlePopupClick}
|
||||
noAvatar={noAvatar}
|
||||
/>
|
||||
)}
|
||||
</StyledMessageContentContainer>
|
||||
|
|
|
@ -15,15 +15,15 @@ import { useSelector } from 'react-redux';
|
|||
export const popupXDefault = -81;
|
||||
export const popupYDefault = -90;
|
||||
|
||||
const StyledMessageReactionsContainer = styled(Flex)<{ x: number; y: number }>`
|
||||
div:first-child {
|
||||
margin-left: 1.7rem;
|
||||
}
|
||||
const StyledMessageReactionsContainer = styled(Flex)<{ x: number; y: number; noAvatar: boolean }>`
|
||||
${StyledPopupContainer} {
|
||||
position: absolute;
|
||||
top: ${props => `${props.y}px;`};
|
||||
left: ${props => `${props.x}px;`};
|
||||
}
|
||||
|
||||
// MessageAvatar width + margin-inline-end
|
||||
${props => !props.noAvatar && 'margin-inline-start: calc(36px + 20px);'}
|
||||
`;
|
||||
|
||||
export const StyledMessageReactions = styled(Flex)<{ fullWidth: boolean }>`
|
||||
|
@ -118,13 +118,13 @@ const CompressedReactions = (props: ExpandReactionsProps): ReactElement => {
|
|||
const ExpandedReactions = (props: ExpandReactionsProps): ReactElement => {
|
||||
const { handleExpand } = props;
|
||||
return (
|
||||
<>
|
||||
<Flex container={true} flexDirection={'column'} alignItems={'center'} margin="4px 0 0">
|
||||
<Reactions {...props} />
|
||||
<StyledReadLess onClick={handleExpand}>
|
||||
<SessionIcon iconType="chevron" iconSize="medium" iconRotation={180} />
|
||||
{window.i18n('expandedReactionsText')}
|
||||
</StyledReadLess>
|
||||
</>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -142,6 +142,7 @@ type Props = {
|
|||
onPopupClick?: () => void;
|
||||
inModal?: boolean;
|
||||
onSelected?: (emoji: string) => boolean;
|
||||
noAvatar: boolean;
|
||||
};
|
||||
|
||||
export const MessageReactions = (props: Props): ReactElement => {
|
||||
|
@ -154,6 +155,7 @@ export const MessageReactions = (props: Props): ReactElement => {
|
|||
onPopupClick,
|
||||
inModal = false,
|
||||
onSelected,
|
||||
noAvatar,
|
||||
} = props;
|
||||
const [reactions, setReactions] = useState<SortedReactionList>([]);
|
||||
|
||||
|
@ -211,6 +213,7 @@ export const MessageReactions = (props: Props): ReactElement => {
|
|||
alignItems={inModal ? 'flex-start' : 'center'}
|
||||
x={popupX}
|
||||
y={popupY}
|
||||
noAvatar={noAvatar}
|
||||
>
|
||||
{sortedReacts &&
|
||||
sortedReacts?.length !== 0 &&
|
||||
|
|
|
@ -329,6 +329,7 @@ export const ReactListModal = (props: Props): ReactElement => {
|
|||
inModal={true}
|
||||
onSelected={handleSelectedReaction}
|
||||
onClick={handleReactionClick}
|
||||
noAvatar={true}
|
||||
/>
|
||||
</StyledReactionsContainer>
|
||||
{reactionsMap && currentReact && (
|
||||
|
|
|
@ -1129,7 +1129,7 @@ export const getMessageContentWithStatusesSelectorProps = createSelector(
|
|||
}
|
||||
|
||||
const msgProps: MessageContentWithStatusSelectorProps = {
|
||||
...pick(props.propsForMessage, ['direction', 'isDeleted']),
|
||||
...pick(props.propsForMessage, ['conversationType', 'direction', 'isDeleted']),
|
||||
};
|
||||
|
||||
return msgProps;
|
||||
|
|
Loading…
Reference in New Issue