Add notification icon to conversation list item. Add notification subtitle to conversation header on conversation screen.

pull/1813/head
Warrick Corfe-Tan 4 years ago
parent 6e362098b2
commit 31118ae51f

@ -416,5 +416,9 @@
"pinConversationLimitToastDescription": "You can only pin $number$ conversations", "pinConversationLimitToastDescription": "You can only pin $number$ conversations",
"latestUnreadIsAbove": "First unread message is above", "latestUnreadIsAbove": "First unread message is above",
"sendRecoveryPhraseTitle": "Sending Recovery Phrase", "sendRecoveryPhraseTitle": "Sending Recovery Phrase",
"sendRecoveryPhraseMessage": "You are attempting to send your recovery phrase which can be used to access your account. Are you sure you want to send this message?" "sendRecoveryPhraseMessage": "You are attempting to send your recovery phrase which can be used to access your account. Are you sure you want to send this message?",
"all": "All",
"mentionsOnly": "Mentions only",
"disabled": "Disabled",
"notificationSubtitle": "Notifications - $setting$"
} }

@ -30,11 +30,11 @@ import { getFirstUnreadMessageIdInConversation } from '../data/data';
import { ConversationNotificationSettingType } from '../models/conversation'; import { ConversationNotificationSettingType } from '../models/conversation';
// tslint:disable-next-line: no-empty-interface // tslint:disable-next-line: no-empty-interface
export interface ConversationListItemProps extends ReduxConversationType { } export interface ConversationListItemProps extends ReduxConversationType {}
export const StyledConversationListItemIconWrapper = styled.div` export const StyledConversationListItemIconWrapper = styled.div`
svg { svg {
margin: 2px 2px; margin: 0px 2px;
} }
display: flex; display: flex;
@ -71,7 +71,7 @@ const HeaderItem = (props: {
conversationId, conversationId,
profileName, profileName,
name, name,
currentNotificationSetting currentNotificationSetting,
} = props; } = props;
const theme = useTheme(); const theme = useTheme();
@ -93,31 +93,34 @@ const HeaderItem = (props: {
/> />
) : null; ) : null;
const NotificationSettingIcon = () => { const NotificationSettingIcon = () => {
if (!isMessagesSection) { if (!isMessagesSection) {
return null; return null;
} }
switch (currentNotificationSetting) { switch (currentNotificationSetting) {
case ('all'): case 'all':
return null; return null;
case ('disabled'): case 'disabled':
return <SessionIcon return (
iconType={SessionIconType.Mute} <SessionIcon
iconColor={theme.colors.textColorSubtle} iconType={SessionIconType.Mute}
iconSize={SessionIconSize.Tiny} iconColor={theme.colors.textColorSubtle}
/> iconSize={SessionIconSize.Tiny}
case ('mentions_only'): />
return <SessionIcon );
iconType={SessionIconType.Bell} case 'mentions_only':
iconColor={theme.colors.textColorSubtle} return (
iconSize={SessionIconSize.Tiny} <SessionIcon
/> iconType={SessionIconType.Bell}
iconColor={theme.colors.textColorSubtle}
iconSize={SessionIconSize.Tiny}
/>
);
default: default:
return null; return null;
} }
} };
return ( return (
<div className="module-conversation-list-item__header"> <div className="module-conversation-list-item__header">
@ -137,7 +140,7 @@ const HeaderItem = (props: {
<StyledConversationListItemIconWrapper> <StyledConversationListItemIconWrapper>
{pinIcon} {pinIcon}
<NotificationSettingIcon></NotificationSettingIcon> <NotificationSettingIcon />
</StyledConversationListItemIconWrapper> </StyledConversationListItemIconWrapper>
{unreadCountDiv} {unreadCountDiv}
{atSymbol} {atSymbol}

@ -7,12 +7,13 @@ import { SessionIconButton, SessionIconSize, SessionIconType } from '../session/
import { SessionButton, SessionButtonColor, SessionButtonType } from '../session/SessionButton'; import { SessionButton, SessionButtonColor, SessionButtonType } from '../session/SessionButton';
import { ConversationAvatar } from '../session/usingClosedConversationDetails'; import { ConversationAvatar } from '../session/usingClosedConversationDetails';
import { MemoConversationHeaderMenu } from '../session/menu/ConversationHeaderMenu'; import { MemoConversationHeaderMenu } from '../session/menu/ConversationHeaderMenu';
import { contextMenu } from 'react-contexify'; import { contextMenu, theme } from 'react-contexify';
import { useTheme } from 'styled-components'; import styled, { useTheme } from 'styled-components';
import { ConversationNotificationSettingType } from '../../models/conversation'; import { ConversationNotificationSettingType } from '../../models/conversation';
import { import {
getConversationHeaderProps, getConversationHeaderProps,
getConversationHeaderTitleProps, getConversationHeaderTitleProps,
getCurrentNotificationSettingText,
getSelectedConversation, getSelectedConversation,
getSelectedMessageIds, getSelectedMessageIds,
isMessageDetailView, isMessageDetailView,
@ -74,7 +75,6 @@ const SelectionOverlay = (props: {
}) => { }) => {
const { onDeleteSelectedMessages, onCloseOverlay, isPublic } = props; const { onDeleteSelectedMessages, onCloseOverlay, isPublic } = props;
const { i18n } = window; const { i18n } = window;
const theme = useTheme();
const isServerDeletable = isPublic; const isServerDeletable = isPublic;
const deleteMessageButtonText = i18n(isServerDeletable ? 'deleteForEveryone' : 'delete'); const deleteMessageButtonText = i18n(isServerDeletable ? 'deleteForEveryone' : 'delete');
@ -86,7 +86,7 @@ const SelectionOverlay = (props: {
iconType={SessionIconType.Exit} iconType={SessionIconType.Exit}
iconSize={SessionIconSize.Medium} iconSize={SessionIconSize.Medium}
onClick={onCloseOverlay} onClick={onCloseOverlay}
theme={theme} theme={useTheme()}
/> />
</div> </div>
@ -104,7 +104,6 @@ const SelectionOverlay = (props: {
const TripleDotsMenu = (props: { triggerId: string; showBackButton: boolean }) => { const TripleDotsMenu = (props: { triggerId: string; showBackButton: boolean }) => {
const { showBackButton } = props; const { showBackButton } = props;
const theme = useTheme();
if (showBackButton) { if (showBackButton) {
return <></>; return <></>;
} }
@ -121,7 +120,7 @@ const TripleDotsMenu = (props: { triggerId: string; showBackButton: boolean }) =
<SessionIconButton <SessionIconButton
iconType={SessionIconType.Ellipses} iconType={SessionIconType.Ellipses}
iconSize={SessionIconSize.Medium} iconSize={SessionIconSize.Medium}
theme={theme} theme={useTheme()}
/> />
</div> </div>
); );
@ -175,7 +174,6 @@ const AvatarHeader = (props: {
const BackButton = (props: { onGoBack: () => void; showBackButton: boolean }) => { const BackButton = (props: { onGoBack: () => void; showBackButton: boolean }) => {
const { onGoBack, showBackButton } = props; const { onGoBack, showBackButton } = props;
const theme = useTheme();
if (!showBackButton) { if (!showBackButton) {
return null; return null;
} }
@ -186,11 +184,29 @@ const BackButton = (props: { onGoBack: () => void; showBackButton: boolean }) =>
iconSize={SessionIconSize.Large} iconSize={SessionIconSize.Large}
iconRotation={90} iconRotation={90}
onClick={onGoBack} onClick={onGoBack}
theme={theme} theme={useTheme()}
/> />
); );
}; };
interface StyledSubtitleContainerProps {
margin?: string;
}
export const StyledSubtitleContainer = styled.div`
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
span {
margin-bottom: ${(p: StyledSubtitleContainerProps) => p.margin || '5px'};
}
span:last-child {
margin-bottom: 0;
}
`;
export type ConversationHeaderTitleProps = { export type ConversationHeaderTitleProps = {
phoneNumber: string; phoneNumber: string;
profileName?: string; profileName?: string;
@ -201,6 +217,7 @@ export type ConversationHeaderTitleProps = {
subscriberCount?: number; subscriberCount?: number;
isKickedFromGroup: boolean; isKickedFromGroup: boolean;
name?: string; name?: string;
currentNotificationSetting?: ConversationNotificationSettingType;
}; };
const ConversationHeaderTitle = () => { const ConversationHeaderTitle = () => {
@ -245,21 +262,36 @@ const ConversationHeaderTitle = () => {
text = i18n('members', [count]); text = i18n('members', [count]);
} }
const textEl = const notificationSetting = useSelector(getCurrentNotificationSettingText);
text === '' || isKickedFromGroup ? null : ( const notificationSubtitle = notificationSetting
<span className="module-conversation-header__title-text">{text}</span> ? window.i18n('notificationSubtitle', notificationSetting)
); : null;
const title = profileName || name || phoneNumber; const title = profileName || name || phoneNumber;
return ( return (
<div className="module-conversation-header__title"> <div className="module-conversation-header__title">
<span className="module-contact-name__profile-name">{title}</span> <span className="module-contact-name__profile-name">{title}</span>
{textEl} <StyledSubtitleContainer margin={useTheme().common.margins.xs}>
{isKickedFromGroup ? null : <ConversationHeaderSubtitle text={text} />}
<ConversationHeaderSubtitle text={notificationSubtitle} />
</StyledSubtitleContainer>
</div> </div>
); );
}; };
/**
* The subtitle beneath a conversation title when looking at a conversation screen.
* @param props props for subtitle. Text to be displayed
* @returns JSX Element of the subtitle of conversation header
*/
export const ConversationHeaderSubtitle = (props: { text?: string | null }): JSX.Element | null => {
const { text } = props;
if (!text) {
return null;
}
return <span className="module-conversation-header__title-text">{text}</span>;
};
export const ConversationHeaderWithDetails = () => { export const ConversationHeaderWithDetails = () => {
const headerProps = useSelector(getConversationHeaderProps); const headerProps = useSelector(getConversationHeaderProps);

@ -1,7 +1,7 @@
export enum SessionIconType { export enum SessionIconType {
AddUser = 'addUser', AddUser = 'addUser',
Arrow = 'arrow', Arrow = 'arrow',
Bell= 'bell', Bell = 'bell',
Caret = 'caret', Caret = 'caret',
ChatBubble = 'chatBubble', ChatBubble = 'chatBubble',
Check = 'check', Check = 'check',
@ -83,7 +83,8 @@ export const icons = {
ratio: 1, ratio: 1,
}, },
[SessionIconType.Bell]: { [SessionIconType.Bell]: {
path: 'M68.16 6.889c18.129 3.653 31.889 19.757 31.889 38.921 0 22.594-2.146 39.585 20.592 54.716H0c22.8-15.173 20.647-32.49 20.647-54.716 0-19.267 13.91-35.439 32.182-38.979 1.054-9.14 14.345-9.096 15.331.058zm8.551 102.301c-1.398 7.785-8.205 13.688-16.392 13.688s-14.992-5.902-16.393-13.688h32.785z', path:
'M68.16 6.889c18.129 3.653 31.889 19.757 31.889 38.921 0 22.594-2.146 39.585 20.592 54.716H0c22.8-15.173 20.647-32.49 20.647-54.716 0-19.267 13.91-35.439 32.182-38.979 1.054-9.14 14.345-9.096 15.331.058zm8.551 102.301c-1.398 7.785-8.205 13.688-16.392 13.688s-14.992-5.902-16.393-13.688h32.785z',
viewBox: '0 0 120.641 122.878', viewBox: '0 0 120.641 122.878',
ratio: 1, ratio: 1,
}, },
@ -223,7 +224,7 @@ export const icons = {
}, },
[SessionIconType.Mute]: { [SessionIconType.Mute]: {
path: path:
"M7.02 28.81h28.65c.6 0 1.09.49 1.09 1.09v44.09L17.76 93H7c-3.85 0-7-3.15-7-7V35.83c0-3.86 3.16-7.02 7.02-7.02zM111.29 6.02l11.59 11.59-93.17 93.17-11.59-11.59 93.17-93.17zM42.33 27.67C59.03 18.51 75.73 9.35 92.42.19c1.6-.88 3.32 1.49 3.32 3.32v11.5L41.66 69.1V28.34c0-.37.35-.49.67-.67zm53.41 23.99v65.6c0 1.92-1.82 4.45-3.5 3.5L50.29 97.11l45.45-45.45z", 'M7.02 28.81h28.65c.6 0 1.09.49 1.09 1.09v44.09L17.76 93H7c-3.85 0-7-3.15-7-7V35.83c0-3.86 3.16-7.02 7.02-7.02zM111.29 6.02l11.59 11.59-93.17 93.17-11.59-11.59 93.17-93.17zM42.33 27.67C59.03 18.51 75.73 9.35 92.42.19c1.6-.88 3.32 1.49 3.32 3.32v11.5L41.66 69.1V28.34c0-.37.35-.49.67-.67zm53.41 23.99v65.6c0 1.92-1.82 4.45-3.5 3.5L50.29 97.11l45.45-45.45z',
viewBox: '0 0 122.88 120.97', viewBox: '0 0 122.88 120.97',
ratio: 1, ratio: 1,
}, },

@ -253,11 +253,13 @@ class SettingsViewInner extends React.Component<SettingsViewProps, State> {
return ( return (
<div className="session-settings__version-info"> <div className="session-settings__version-info">
<span className="text-selectable">v{window.versionInfo.version}</span> <span className="text-selectable">v{window.versionInfo.version}</span>
<span><SessionIconButton <span>
iconSize={SessionIconSize.Medium} <SessionIconButton
iconType={SessionIconType.Oxen} iconSize={SessionIconSize.Medium}
onClick={openOxenWebsite} iconType={SessionIconType.Oxen}
/></span> onClick={openOxenWebsite}
/>
</span>
<span className="text-selectable">{window.versionInfo.commitHash}</span> <span className="text-selectable">{window.versionInfo.commitHash}</span>
</div> </div>
); );

@ -238,9 +238,31 @@ export const getConversationHeaderTitleProps = createSelector(getSelectedConvers
name: state.name, name: state.name,
subscriberCount: state.subscriberCount, subscriberCount: state.subscriberCount,
isGroup: state.type === 'group', isGroup: state.type === 'group',
currentNotificationSetting: state.currentNotificationSetting,
}; };
}); });
/**
* Returns the formatted text for notification setting.
*/
export const getCurrentNotificationSettingText = createSelector(getSelectedConversation, (state):
| string
| undefined => {
if (!state) {
return undefined;
}
switch (state.currentNotificationSetting) {
case 'all':
return window.i18n('all');
case 'mentions_only':
return window.i18n('mentionsOnly');
case 'disabled':
return window.i18n('disabled');
default:
return window.i18n('all');
}
});
export const getConversationHeaderProps = createSelector(getSelectedConversation, (state): export const getConversationHeaderProps = createSelector(getSelectedConversation, (state):
| ConversationHeaderProps | ConversationHeaderProps
| undefined => { | undefined => {

Loading…
Cancel
Save