fix: improved reaction alignment based on avatar visibility

pull/2612/head
William Grant 2 years ago
parent 828f1923a0
commit a8b8692016

@ -129,13 +129,6 @@ textarea {
font-style: normal; font-style: normal;
} }
.module-message__author-avatar {
position: relative;
margin-inline-end: 20px;
padding-top: 5px;
padding-inline-end: 4px;
}
.module-message--incoming { .module-message--incoming {
margin-inline-start: 0; margin-inline-start: 0;
margin-inline-end: auto; margin-inline-end: auto;

@ -1,5 +1,6 @@
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import styled from 'styled-components';
import { OpenGroupData } from '../../../../data/opengroups'; import { OpenGroupData } from '../../../../data/opengroups';
import { MessageRenderingProps } from '../../../../models/messageType'; import { MessageRenderingProps } from '../../../../models/messageType';
import { findCachedBlindedMatchOrLookItUp } from '../../../../session/apis/open_group_api/sogsv3/knownBlindedkeys'; import { findCachedBlindedMatchOrLookItUp } from '../../../../session/apis/open_group_api/sogsv3/knownBlindedkeys';
@ -16,6 +17,13 @@ import {
import { Avatar, AvatarSize, CrownIcon } from '../../../avatar/Avatar'; import { Avatar, AvatarSize, CrownIcon } from '../../../avatar/Avatar';
// tslint:disable: use-simple-attributes // 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< export type MessageAvatarSelectorProps = Pick<
MessageRenderingProps, MessageRenderingProps,
| 'authorAvatarPath' | 'authorAvatarPath'
@ -23,16 +31,14 @@ export type MessageAvatarSelectorProps = Pick<
| 'sender' | 'sender'
| 'authorProfileName' | 'authorProfileName'
| 'isSenderAdmin' | 'isSenderAdmin'
| 'conversationType'
| 'direction'
| 'isPublic' | 'isPublic'
| 'lastMessageOfSeries' | 'lastMessageOfSeries'
>; >;
type Props = { messageId: string }; type Props = { messageId: string; noAvatar: boolean };
export const MessageAvatar = (props: Props) => { export const MessageAvatar = (props: Props) => {
const { messageId } = props; const { messageId, noAvatar } = props;
const dispatch = useDispatch(); const dispatch = useDispatch();
const avatarProps = useSelector(state => getMessageAvatarProps(state as any, messageId)); const avatarProps = useSelector(state => getMessageAvatarProps(state as any, messageId));
@ -43,21 +49,21 @@ export const MessageAvatar = (props: Props) => {
if (!avatarProps) { if (!avatarProps) {
return null; return null;
} }
const { const {
authorAvatarPath, authorAvatarPath,
authorName, authorName,
sender, sender,
authorProfileName, authorProfileName,
conversationType,
direction,
isSenderAdmin, isSenderAdmin,
lastMessageOfSeries, lastMessageOfSeries,
isPublic, isPublic,
} = avatarProps; } = avatarProps;
if (conversationType !== 'group' || direction === 'outgoing') { if (noAvatar) {
return null; return null;
} }
const userName = authorName || authorProfileName || sender; const userName = authorName || authorProfileName || sender;
const onMessageAvatarClick = useCallback(async () => { const onMessageAvatarClick = useCallback(async () => {
@ -122,9 +128,9 @@ export const MessageAvatar = (props: Props) => {
} }
return ( return (
<div className="module-message__author-avatar" key={`msg-avatar-${sender}`}> <StyledAvatar key={`msg-avatar-${sender}`}>
<Avatar size={AvatarSize.S} onAvatarClick={onMessageAvatarClick} pubkey={sender} /> <Avatar size={AvatarSize.S} onAvatarClick={onMessageAvatarClick} pubkey={sender} />
{isSenderAdmin && <CrownIcon />} {isSenderAdmin && <CrownIcon />}
</div> </StyledAvatar>
); );
}; };

@ -20,7 +20,7 @@ import { MessageStatus } from './MessageStatus';
export type MessageContentWithStatusSelectorProps = Pick< export type MessageContentWithStatusSelectorProps = Pick<
MessageRenderingProps, MessageRenderingProps,
'direction' | 'isDeleted' 'conversationType' | 'direction' | 'isDeleted'
>; >;
type Props = { type Props = {
@ -40,7 +40,7 @@ const StyledMessageContentContainer = styled.div<{ direction: 'left' | 'right' }
width: 100%; width: 100%;
${StyledMessageReactions} { ${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; const { messageId, ctxMenuID, isDetailView, dataTestId, enableReactions } = props;
if (!contentProps) { if (!contentProps) {
return null; return null;
} }
const { direction, isDeleted } = contentProps; const { conversationType, direction, isDeleted } = contentProps;
const isIncoming = direction === 'incoming'; const isIncoming = direction === 'incoming';
const noAvatar = conversationType !== 'group' || direction === 'outgoing';
const [popupReaction, setPopupReaction] = useState(''); const [popupReaction, setPopupReaction] = useState('');
@ -118,7 +120,7 @@ export const MessageContentWithStatuses = (props: Props) => {
onDoubleClickCapture={onDoubleClickReplyToMessage} onDoubleClickCapture={onDoubleClickReplyToMessage}
data-testid={dataTestId} data-testid={dataTestId}
> >
<MessageAvatar messageId={messageId} /> <MessageAvatar messageId={messageId} noAvatar={noAvatar} />
<MessageStatus <MessageStatus
dataTestId="msg-status-incoming" dataTestId="msg-status-incoming"
messageId={messageId} messageId={messageId}
@ -148,6 +150,7 @@ export const MessageContentWithStatuses = (props: Props) => {
popupReaction={popupReaction} popupReaction={popupReaction}
setPopupReaction={setPopupReaction} setPopupReaction={setPopupReaction}
onPopupClick={handlePopupClick} onPopupClick={handlePopupClick}
noAvatar={noAvatar}
/> />
)} )}
</StyledMessageContentContainer> </StyledMessageContentContainer>

@ -15,15 +15,15 @@ import { useSelector } from 'react-redux';
export const popupXDefault = -81; export const popupXDefault = -81;
export const popupYDefault = -90; export const popupYDefault = -90;
const StyledMessageReactionsContainer = styled(Flex)<{ x: number; y: number }>` const StyledMessageReactionsContainer = styled(Flex)<{ x: number; y: number; noAvatar: boolean }>`
div:first-child {
margin-left: 1.7rem;
}
${StyledPopupContainer} { ${StyledPopupContainer} {
position: absolute; position: absolute;
top: ${props => `${props.y}px;`}; top: ${props => `${props.y}px;`};
left: ${props => `${props.x}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 }>` export const StyledMessageReactions = styled(Flex)<{ fullWidth: boolean }>`
@ -118,13 +118,13 @@ const CompressedReactions = (props: ExpandReactionsProps): ReactElement => {
const ExpandedReactions = (props: ExpandReactionsProps): ReactElement => { const ExpandedReactions = (props: ExpandReactionsProps): ReactElement => {
const { handleExpand } = props; const { handleExpand } = props;
return ( return (
<> <Flex container={true} flexDirection={'column'} alignItems={'center'} margin="4px 0 0">
<Reactions {...props} /> <Reactions {...props} />
<StyledReadLess onClick={handleExpand}> <StyledReadLess onClick={handleExpand}>
<SessionIcon iconType="chevron" iconSize="medium" iconRotation={180} /> <SessionIcon iconType="chevron" iconSize="medium" iconRotation={180} />
{window.i18n('expandedReactionsText')} {window.i18n('expandedReactionsText')}
</StyledReadLess> </StyledReadLess>
</> </Flex>
); );
}; };
@ -142,6 +142,7 @@ type Props = {
onPopupClick?: () => void; onPopupClick?: () => void;
inModal?: boolean; inModal?: boolean;
onSelected?: (emoji: string) => boolean; onSelected?: (emoji: string) => boolean;
noAvatar: boolean;
}; };
export const MessageReactions = (props: Props): ReactElement => { export const MessageReactions = (props: Props): ReactElement => {
@ -154,6 +155,7 @@ export const MessageReactions = (props: Props): ReactElement => {
onPopupClick, onPopupClick,
inModal = false, inModal = false,
onSelected, onSelected,
noAvatar,
} = props; } = props;
const [reactions, setReactions] = useState<SortedReactionList>([]); const [reactions, setReactions] = useState<SortedReactionList>([]);
@ -211,6 +213,7 @@ export const MessageReactions = (props: Props): ReactElement => {
alignItems={inModal ? 'flex-start' : 'center'} alignItems={inModal ? 'flex-start' : 'center'}
x={popupX} x={popupX}
y={popupY} y={popupY}
noAvatar={noAvatar}
> >
{sortedReacts && {sortedReacts &&
sortedReacts?.length !== 0 && sortedReacts?.length !== 0 &&

@ -329,6 +329,7 @@ export const ReactListModal = (props: Props): ReactElement => {
inModal={true} inModal={true}
onSelected={handleSelectedReaction} onSelected={handleSelectedReaction}
onClick={handleReactionClick} onClick={handleReactionClick}
noAvatar={true}
/> />
</StyledReactionsContainer> </StyledReactionsContainer>
{reactionsMap && currentReact && ( {reactionsMap && currentReact && (

@ -1129,7 +1129,7 @@ export const getMessageContentWithStatusesSelectorProps = createSelector(
} }
const msgProps: MessageContentWithStatusSelectorProps = { const msgProps: MessageContentWithStatusSelectorProps = {
...pick(props.propsForMessage, ['direction', 'isDeleted']), ...pick(props.propsForMessage, ['conversationType', 'direction', 'isDeleted']),
}; };
return msgProps; return msgProps;

Loading…
Cancel
Save