use OutgoingMessageStatus in ConversationListItem too

also, enable back the delivered/read status on message metadata
pull/1381/head
Audric Ackermann 5 years ago
parent 7f5515cf6b
commit 15ae97e0a7
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -428,32 +428,6 @@
color: $color-white; color: $color-white;
} }
.module-message__metadata__status-icon {
width: 12px;
height: 12px;
display: inline-block;
margin-inline-start: 6px;
margin-bottom: 2px;
margin-inline-start: 5px;
}
.module-message__metadata__status-icon--sent {
@include color-svg('../images/check-circle-outline.svg', $color-gray-60);
}
.module-message__metadata__status-icon--delivered {
@include color-svg('../images/double-check.svg', $color-gray-60);
width: 18px;
}
.module-message__metadata__status-icon--read {
@include color-svg('../images/read.svg', $color-gray-60);
width: 18px;
}
// When status indicators are overlaid on top of an image, they use different colors
.module-message__metadata__status-icon--with-image-no-caption {
background-color: $color-white;
}
.module-message__author-avatar { .module-message__author-avatar {
flex-direction: column-reverse; flex-direction: column-reverse;
display: inline-flex; display: inline-flex;
@ -1486,31 +1460,6 @@
color: $color-gray-05; color: $color-gray-05;
} }
.module-conversation-list-item__message__status-icon {
flex-shrink: 0;
margin-top: 1px;
width: 12px;
height: 13px;
display: inline-block;
margin-inline-start: 6px;
}
.module-conversation-list-item__message__status-icon--sent {
@include color-svg('../images/check-circle-outline.svg', $color-light-35);
}
.module-conversation-list-item__message__status-icon--delivered {
@include color-svg('../images/double-check.svg', $color-light-35);
width: 18px;
}
.module-conversation-list-item__message__status-icon--read {
@include color-svg('../images/read.svg', $color-light-35);
width: 18px;
}
.module-conversation-list-item__message__status-icon--error {
@include color-svg('../images/error.svg', $session-color-danger);
}
// Module: Main Header // Module: Main Header
.module-main-header__search__input { .module-main-header__search__input {

@ -20,8 +20,10 @@ import {
PropsContextConversationItem, PropsContextConversationItem,
} from './session/menu/ConversationListItemContextMenu'; } from './session/menu/ConversationListItemContextMenu';
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { OutgoingMessageStatus } from './conversation/message/OutgoingMessageStatus';
import { DefaultTheme, withTheme } from 'styled-components';
export type PropsData = { export type ConversationListItemProps = {
id: string; id: string;
phoneNumber: string; phoneNumber: string;
color?: string; color?: string;
@ -67,9 +69,10 @@ type PropsHousekeeping = {
onUnblockContact?: () => void; onUnblockContact?: () => void;
onInviteContacts?: () => void; onInviteContacts?: () => void;
onClearNickname?: () => void; onClearNickname?: () => void;
theme: DefaultTheme;
}; };
type Props = PropsData & PropsHousekeeping; type Props = ConversationListItemProps & PropsHousekeeping;
const Portal = ({ children }: { children: any }) => { const Portal = ({ children }: { children: any }) => {
return createPortal( return createPortal(
@ -200,11 +203,10 @@ class ConversationListItem extends React.PureComponent<Props> {
)} )}
</div> </div>
{lastMessage && lastMessage.status ? ( {lastMessage && lastMessage.status ? (
<div <OutgoingMessageStatus
className={classNames( status={lastMessage.status}
'module-conversation-list-item__message__status-icon', iconColor={this.props.theme.colors.textColorSubtle}
`module-conversation-list-item__message__status-icon--${lastMessage.status}` theme={this.props.theme}
)}
/> />
) : null} ) : null}
</div> </div>
@ -303,5 +305,5 @@ class ConversationListItem extends React.PureComponent<Props> {
} }
export const ConversationListItemWithDetails = usingClosedConversationDetails( export const ConversationListItemWithDetails = usingClosedConversationDetails(
ConversationListItem withTheme(ConversationListItem)
); );

@ -3,8 +3,8 @@ import React from 'react';
import { ActionsPanel, SectionType } from './session/ActionsPanel'; import { ActionsPanel, SectionType } from './session/ActionsPanel';
import { LeftPaneMessageSection } from './session/LeftPaneMessageSection'; import { LeftPaneMessageSection } from './session/LeftPaneMessageSection';
import { PropsData as ConversationListItemPropsType } from './ConversationListItem'; import { ConversationListItemProps } from './ConversationListItem';
import { PropsData as SearchResultsProps } from './SearchResults'; import { SearchResultsProps } from './SearchResults';
import { SearchOptions } from '../types/Search'; import { SearchOptions } from '../types/Search';
import { LeftPaneSectionHeader } from './session/LeftPaneSectionHeader'; import { LeftPaneSectionHeader } from './session/LeftPaneSectionHeader';
@ -30,7 +30,7 @@ export type RowRendererParamsType = {
interface Props { interface Props {
ourPrimaryConversation: ConversationType; ourPrimaryConversation: ConversationType;
conversations: Array<ConversationListItemPropsType>; conversations: Array<ConversationListItemProps>;
contacts: Array<ConversationType>; contacts: Array<ConversationType>;
unreadMessageCount: number; unreadMessageCount: number;

@ -8,7 +8,7 @@ import { ContactName } from './conversation/ContactName';
import { LocalizerType } from '../types/Util'; import { LocalizerType } from '../types/Util';
export type PropsData = { export type MessageSearchResultProps = {
id: string; id: string;
conversationId: string; conversationId: string;
receivedAt: number; receivedAt: number;
@ -40,7 +40,7 @@ type PropsHousekeeping = {
onClick: (conversationId: string, messageId?: string) => void; onClick: (conversationId: string, messageId?: string) => void;
}; };
type Props = PropsData & PropsHousekeeping; type Props = MessageSearchResultProps & PropsHousekeeping;
export class MessageSearchResult extends React.PureComponent<Props> { export class MessageSearchResult extends React.PureComponent<Props> {
public renderFromName() { public renderFromName() {

@ -1,20 +1,20 @@
import React from 'react'; import React from 'react';
import { import {
ConversationListItemProps,
ConversationListItemWithDetails, ConversationListItemWithDetails,
PropsData as ConversationListItemPropsType,
} from './ConversationListItem'; } from './ConversationListItem';
import { import {
MessageSearchResult, MessageSearchResult,
PropsData as MessageSearchResultPropsType, MessageSearchResultProps,
} from './MessageSearchResult'; } from './MessageSearchResult';
import { LocalizerType } from '../types/Util'; import { LocalizerType } from '../types/Util';
export type PropsData = { export type SearchResultsProps = {
contacts: Array<ConversationListItemPropsType>; contacts: Array<ConversationListItemProps>;
conversations: Array<ConversationListItemPropsType>; conversations: Array<ConversationListItemProps>;
hideMessagesHeader: boolean; hideMessagesHeader: boolean;
messages: Array<MessageSearchResultPropsType>; messages: Array<MessageSearchResultProps>;
regionCode: string; regionCode: string;
searchTerm: string; searchTerm: string;
}; };
@ -24,7 +24,7 @@ type PropsHousekeeping = {
openConversationExternal: (id: string, messageId?: string) => void; openConversationExternal: (id: string, messageId?: string) => void;
}; };
type Props = PropsData & PropsHousekeeping; type Props = SearchResultsProps & PropsHousekeeping;
export class SearchResults extends React.Component<Props> { export class SearchResults extends React.Component<Props> {
public render() { public render() {
@ -91,7 +91,7 @@ export class SearchResults extends React.Component<Props> {
} }
private renderContacts( private renderContacts(
header: string, header: string,
items: Array<ConversationListItemPropsType> items: Array<ConversationListItemProps>
) { ) {
const { i18n, openConversationExternal } = this.props; const { i18n, openConversationExternal } = this.props;

@ -1,10 +1,10 @@
import React from 'react'; import React from 'react';
import { PropsData as ConversationListItemPropsType } from './ConversationListItem'; import { ConversationListItemProps } from './ConversationListItem';
import classNames from 'classnames'; import classNames from 'classnames';
export type Props = { export type Props = {
contacts: Array<ConversationListItemPropsType>; contacts: Array<ConversationListItemProps>;
regionCode: string; regionCode: string;
searchTerm: string; searchTerm: string;
selectedContact: number; selectedContact: number;
@ -34,7 +34,7 @@ export class UserSearchResults extends React.Component<Props> {
); );
} }
private renderContacts(items: Array<ConversationListItemPropsType>) { private renderContacts(items: Array<ConversationListItemProps>) {
return ( return (
<div className="contacts-dropdown"> <div className="contacts-dropdown">
{items.map((contact, index) => this.renderContact(contact, index))} {items.map((contact, index) => this.renderContact(contact, index))}
@ -42,7 +42,7 @@ export class UserSearchResults extends React.Component<Props> {
); );
} }
private renderContact(contact: ConversationListItemPropsType, index: Number) { private renderContact(contact: ConversationListItemProps, index: Number) {
const { profileName, phoneNumber } = contact; const { profileName, phoneNumber } = contact;
const { selectedContact } = this.props; const { selectedContact } = this.props;

@ -28,6 +28,9 @@ type Props = {
theme: DefaultTheme; theme: DefaultTheme;
}; };
/**
* This is a component to display the message of an Incoming or Outgoing message.
*/
export const MessageMetadata = (props: Props) => { export const MessageMetadata = (props: Props) => {
const { const {
id, id,
@ -55,6 +58,9 @@ export const MessageMetadata = (props: Props) => {
const showError = status === 'error' && isOutgoing; const showError = status === 'error' && isOutgoing;
const showStatus = Boolean(!bodyPending && status?.length && isOutgoing); const showStatus = Boolean(!bodyPending && status?.length && isOutgoing);
const messageStatusColor = withImageNoCaption
? 'white'
: props.theme.colors.sentMessageText;
return ( return (
<div <div
className={classNames( className={classNames(
@ -106,9 +112,11 @@ export const MessageMetadata = (props: Props) => {
<MetadataSpacer /> <MetadataSpacer />
{showStatus ? ( {showStatus ? (
<OutgoingMessageStatus <OutgoingMessageStatus
withImageNoCaption={withImageNoCaption} iconColor={messageStatusColor}
theme={theme} theme={theme}
status={status} status={status}
// do not show the error status, another component is shown on the right of the message itself here
hideErrors={true}
/> />
) : null} ) : null}
</div> </div>

@ -1,28 +1,5 @@
import styled, { ThemeContext } from 'styled-components'; import styled from 'styled-components';
import React, { useContext } from 'react';
import {
SessionIcon,
SessionIconSize,
SessionIconType,
} from '../../session/icon';
export const MetadataSpacer = styled.span` export const MetadataSpacer = styled.span`
flex-grow: 1; flex-grow: 1;
`; `;
const MessageReadReceiptContainer = styled.div`
margin-inline-start: 5px;
`;
export const MessageReadReceipt = () => {
const theme = useContext(ThemeContext);
return (
<MessageReadReceiptContainer>
<SessionIcon
iconType={SessionIconType.Check}
iconSize={SessionIconSize.Small}
theme={theme}
/>
</MessageReadReceiptContainer>
);
};

@ -7,10 +7,6 @@ import {
} from '../../session/icon'; } from '../../session/icon';
const MessageStatusSendingContainer = styled.div` const MessageStatusSendingContainer = styled.div`
min-width: 12px;
min-height: 12px;
width: 12px;
height: 12px;
display: inline-block; display: inline-block;
margin-bottom: 2px; margin-bottom: 2px;
margin-inline-start: 5px; margin-inline-start: 5px;
@ -18,14 +14,13 @@ const MessageStatusSendingContainer = styled.div`
const MessageStatusSending = (props: { const MessageStatusSending = (props: {
theme: DefaultTheme; theme: DefaultTheme;
withImageNoCaption: boolean; iconColor: string;
}) => { }) => {
const iconColor = props.withImageNoCaption ? 'white' : undefined;
return ( return (
<MessageStatusSendingContainer> <MessageStatusSendingContainer>
<SessionIcon <SessionIcon
rotateDuration={2} rotateDuration={2}
iconColor={iconColor} iconColor={props.iconColor}
theme={props.theme} theme={props.theme}
iconType={SessionIconType.Sending} iconType={SessionIconType.Sending}
iconSize={SessionIconSize.Tiny} iconSize={SessionIconSize.Tiny}
@ -36,17 +31,15 @@ const MessageStatusSending = (props: {
const MessageStatusSent = (props: { const MessageStatusSent = (props: {
theme: DefaultTheme; theme: DefaultTheme;
withImageNoCaption: boolean; iconColor: string;
}) => { }) => {
const iconColor = props.withImageNoCaption ? 'white' : undefined;
return ( return (
<MessageStatusSendingContainer> <MessageStatusSendingContainer>
<SessionIcon <SessionIcon
iconColor={iconColor} iconColor={props.iconColor}
theme={props.theme} theme={props.theme}
iconType={SessionIconType.CircleCheck} iconType={SessionIconType.CircleCheck}
iconSize={SessionIconSize.Small} iconSize={SessionIconSize.Tiny}
/> />
</MessageStatusSendingContainer> </MessageStatusSendingContainer>
); );
@ -54,16 +47,15 @@ const MessageStatusSent = (props: {
const MessageStatusDelivered = (props: { const MessageStatusDelivered = (props: {
theme: DefaultTheme; theme: DefaultTheme;
withImageNoCaption: boolean; iconColor: string;
}) => { }) => {
const iconColor = props.withImageNoCaption ? 'white' : undefined;
return ( return (
<MessageStatusSendingContainer> <MessageStatusSendingContainer>
<SessionIcon <SessionIcon
iconColor={iconColor} iconColor={props.iconColor}
theme={props.theme} theme={props.theme}
iconType={SessionIconType.DoubleCheck} iconType={SessionIconType.DoubleCheckCircle}
iconSize={SessionIconSize.Small} iconSize={SessionIconSize.Tiny}
/> />
</MessageStatusSendingContainer> </MessageStatusSendingContainer>
); );
@ -71,33 +63,28 @@ const MessageStatusDelivered = (props: {
const MessageStatusRead = (props: { const MessageStatusRead = (props: {
theme: DefaultTheme; theme: DefaultTheme;
withImageNoCaption: boolean; iconColor: string;
}) => { }) => {
const iconColor = props.withImageNoCaption ? 'white' : undefined;
return ( return (
<MessageStatusSendingContainer> <MessageStatusSendingContainer>
<SessionIcon <SessionIcon
iconColor={iconColor} iconColor={props.iconColor}
theme={props.theme} theme={props.theme}
iconType={SessionIconType.Read} iconType={SessionIconType.DoubleCheckCircleFilled}
iconSize={SessionIconSize.Small} iconSize={SessionIconSize.Tiny}
/> />
</MessageStatusSendingContainer> </MessageStatusSendingContainer>
); );
}; };
const MessageStatusError = (props: { const MessageStatusError = (props: { theme: DefaultTheme }) => {
theme: DefaultTheme;
withImageNoCaption: boolean;
}) => {
return ( return (
<MessageStatusSendingContainer> <MessageStatusSendingContainer>
<SessionIcon <SessionIcon
iconColor={props.theme.colors.destructive} iconColor={props.theme.colors.destructive}
theme={props.theme} theme={props.theme}
iconType={SessionIconType.Error} iconType={SessionIconType.Error}
iconSize={SessionIconSize.Small} iconSize={SessionIconSize.Tiny}
/> />
</MessageStatusSendingContainer> </MessageStatusSendingContainer>
); );
@ -106,7 +93,8 @@ const MessageStatusError = (props: {
export const OutgoingMessageStatus = (props: { export const OutgoingMessageStatus = (props: {
status?: 'sending' | 'sent' | 'delivered' | 'read' | 'error' | 'pow'; status?: 'sending' | 'sent' | 'delivered' | 'read' | 'error' | 'pow';
theme: DefaultTheme; theme: DefaultTheme;
withImageNoCaption: boolean; iconColor: string;
hideErrors?: boolean;
}) => { }) => {
switch (props.status) { switch (props.status) {
case 'pow': case 'pow':
@ -119,6 +107,9 @@ export const OutgoingMessageStatus = (props: {
case 'read': case 'read':
return <MessageStatusRead {...props} />; return <MessageStatusRead {...props} />;
case 'error': case 'error':
if (props.hideErrors) {
return null;
}
return <MessageStatusError {...props} />; return <MessageStatusError {...props} />;
default: default:
return null; return null;

@ -4,14 +4,11 @@ import { AutoSizer, List } from 'react-virtualized';
import { MainViewController } from '../MainViewController'; import { MainViewController } from '../MainViewController';
import { import {
ConversationListItemProps,
ConversationListItemWithDetails, ConversationListItemWithDetails,
PropsData as ConversationListItemPropsType,
} from '../ConversationListItem'; } from '../ConversationListItem';
import { ConversationType } from '../../state/ducks/conversations'; import { ConversationType } from '../../state/ducks/conversations';
import { import { SearchResults, SearchResultsProps } from '../SearchResults';
PropsData as SearchResultsProps,
SearchResults,
} from '../SearchResults';
import { SessionSearchInput } from './SessionSearchInput'; import { SessionSearchInput } from './SessionSearchInput';
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import { cleanSearchTerm } from '../../util/cleanSearchTerm'; import { cleanSearchTerm } from '../../util/cleanSearchTerm';
@ -38,7 +35,7 @@ export interface Props {
isSecondaryDevice: boolean; isSecondaryDevice: boolean;
contacts: Array<ConversationType>; contacts: Array<ConversationType>;
conversations?: Array<ConversationListItemPropsType>; conversations?: Array<ConversationListItemProps>;
searchResults?: SearchResultsProps; searchResults?: SearchResultsProps;
updateSearchTerm: (searchTerm: string) => void; updateSearchTerm: (searchTerm: string) => void;

@ -3,7 +3,7 @@ import React from 'react';
import { UserSearchResults } from '../UserSearchResults'; import { UserSearchResults } from '../UserSearchResults';
import { SessionSearchInput } from './SessionSearchInput'; import { SessionSearchInput } from './SessionSearchInput';
import { PropsData as SearchResultsProps } from '../SearchResults'; import { SearchResultsProps } from '../SearchResults';
import { DefaultTheme } from 'styled-components'; import { DefaultTheme } from 'styled-components';
export interface Props { export interface Props {

File diff suppressed because one or more lines are too long

@ -18,19 +18,19 @@ const getIconDimensionFromIconSize = (iconSize: SessionIconSize | number) => {
} else { } else {
switch (iconSize) { switch (iconSize) {
case SessionIconSize.Tiny: case SessionIconSize.Tiny:
return '12'; return 12;
case SessionIconSize.Small: case SessionIconSize.Small:
return '15'; return 15;
case SessionIconSize.Medium: case SessionIconSize.Medium:
return '20'; return 20;
case SessionIconSize.Large: case SessionIconSize.Large:
return '25'; return 25;
case SessionIconSize.Huge: case SessionIconSize.Huge:
return '30'; return 30;
case SessionIconSize.Max: case SessionIconSize.Max:
return '80'; return 80;
default: default:
return '20'; return 20;
} }
} }
}; };
@ -64,7 +64,6 @@ const animation = (props: any) => {
//tslint:disable no-unnecessary-callback-wrapper //tslint:disable no-unnecessary-callback-wrapper
const Svg = styled.svg<StyledSvgProps>` const Svg = styled.svg<StyledSvgProps>`
width: ${props => props.width}; width: ${props => props.width};
height: ${props => props.height};
animation: ${props => animation(props)}; animation: ${props => animation(props)};
transform: ${props => `rotate(${props.iconRotation}deg)`}; transform: ${props => `rotate(${props.iconRotation}deg)`};
`; `;
@ -97,7 +96,7 @@ export const SessionIcon = (props: SessionIconProps) => {
const iconDimensions = getIconDimensionFromIconSize(iconSize); const iconDimensions = getIconDimensionFromIconSize(iconSize);
const iconDef = icons[iconType]; const iconDef = icons[iconType];
const ratio = iconDef?.ratio || 1;
if (!theme) { if (!theme) {
window.log.error('Missing theme props in SessionIcon'); window.log.error('Missing theme props in SessionIcon');
} }
@ -106,7 +105,7 @@ export const SessionIcon = (props: SessionIconProps) => {
<SessionSvg <SessionSvg
viewBox={iconDef.viewBox} viewBox={iconDef.viewBox}
path={iconDef.path} path={iconDef.path}
width={iconDimensions} width={iconDimensions * ratio}
height={iconDimensions} height={iconDimensions}
rotateDuration={rotateDuration} rotateDuration={rotateDuration}
iconRotation={iconRotation} iconRotation={iconRotation}

@ -10,7 +10,7 @@ import {
} from '../ducks/conversations'; } from '../ducks/conversations';
import { getIntl, getRegionCode, getUserNumber } from './user'; import { getIntl, getRegionCode, getUserNumber } from './user';
import { PropsData as ConversationListItemPropsType } from '../../components/ConversationListItem'; import { ConversationListItemProps } from '../../components/ConversationListItem';
import { BlockedNumberController } from '../../util'; import { BlockedNumberController } from '../../util';
export const getConversations = (state: StateType): ConversationsStateType => export const getConversations = (state: StateType): ConversationsStateType =>
@ -162,9 +162,9 @@ export const _getLeftPaneLists = (
} }
const filterToPrimary = < const filterToPrimary = <
T extends Array<ConversationType | ConversationListItemPropsType> T extends Array<ConversationType | ConversationListItemProps>
>( >(
group: Array<ConversationType | ConversationListItemPropsType> group: Array<ConversationType | ConversationListItemProps>
): T => { ): T => {
const secondariesToRemove: Array<string> = []; const secondariesToRemove: Array<string> = [];

Loading…
Cancel
Save