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

This commit is contained in:
Warrick Corfe-Tan 2021-07-30 15:07:52 +10:00
parent 6e362098b2
commit 31118ae51f
6 changed files with 106 additions and 42 deletions

View File

@ -416,5 +416,9 @@
"pinConversationLimitToastDescription": "You can only pin $number$ conversations",
"latestUnreadIsAbove": "First unread message is above",
"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$"
}

View File

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

View File

@ -7,12 +7,13 @@ import { SessionIconButton, SessionIconSize, SessionIconType } from '../session/
import { SessionButton, SessionButtonColor, SessionButtonType } from '../session/SessionButton';
import { ConversationAvatar } from '../session/usingClosedConversationDetails';
import { MemoConversationHeaderMenu } from '../session/menu/ConversationHeaderMenu';
import { contextMenu } from 'react-contexify';
import { useTheme } from 'styled-components';
import { contextMenu, theme } from 'react-contexify';
import styled, { useTheme } from 'styled-components';
import { ConversationNotificationSettingType } from '../../models/conversation';
import {
getConversationHeaderProps,
getConversationHeaderTitleProps,
getCurrentNotificationSettingText,
getSelectedConversation,
getSelectedMessageIds,
isMessageDetailView,
@ -74,7 +75,6 @@ const SelectionOverlay = (props: {
}) => {
const { onDeleteSelectedMessages, onCloseOverlay, isPublic } = props;
const { i18n } = window;
const theme = useTheme();
const isServerDeletable = isPublic;
const deleteMessageButtonText = i18n(isServerDeletable ? 'deleteForEveryone' : 'delete');
@ -86,7 +86,7 @@ const SelectionOverlay = (props: {
iconType={SessionIconType.Exit}
iconSize={SessionIconSize.Medium}
onClick={onCloseOverlay}
theme={theme}
theme={useTheme()}
/>
</div>
@ -104,7 +104,6 @@ const SelectionOverlay = (props: {
const TripleDotsMenu = (props: { triggerId: string; showBackButton: boolean }) => {
const { showBackButton } = props;
const theme = useTheme();
if (showBackButton) {
return <></>;
}
@ -121,7 +120,7 @@ const TripleDotsMenu = (props: { triggerId: string; showBackButton: boolean }) =
<SessionIconButton
iconType={SessionIconType.Ellipses}
iconSize={SessionIconSize.Medium}
theme={theme}
theme={useTheme()}
/>
</div>
);
@ -175,7 +174,6 @@ const AvatarHeader = (props: {
const BackButton = (props: { onGoBack: () => void; showBackButton: boolean }) => {
const { onGoBack, showBackButton } = props;
const theme = useTheme();
if (!showBackButton) {
return null;
}
@ -186,11 +184,29 @@ const BackButton = (props: { onGoBack: () => void; showBackButton: boolean }) =>
iconSize={SessionIconSize.Large}
iconRotation={90}
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 = {
phoneNumber: string;
profileName?: string;
@ -201,6 +217,7 @@ export type ConversationHeaderTitleProps = {
subscriberCount?: number;
isKickedFromGroup: boolean;
name?: string;
currentNotificationSetting?: ConversationNotificationSettingType;
};
const ConversationHeaderTitle = () => {
@ -245,21 +262,36 @@ const ConversationHeaderTitle = () => {
text = i18n('members', [count]);
}
const textEl =
text === '' || isKickedFromGroup ? null : (
<span className="module-conversation-header__title-text">{text}</span>
);
const notificationSetting = useSelector(getCurrentNotificationSettingText);
const notificationSubtitle = notificationSetting
? window.i18n('notificationSubtitle', notificationSetting)
: null;
const title = profileName || name || phoneNumber;
return (
<div className="module-conversation-header__title">
<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>
);
};
/**
* 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 = () => {
const headerProps = useSelector(getConversationHeaderProps);

View File

@ -1,7 +1,7 @@
export enum SessionIconType {
AddUser = 'addUser',
Arrow = 'arrow',
Bell= 'bell',
Bell = 'bell',
Caret = 'caret',
ChatBubble = 'chatBubble',
Check = 'check',
@ -83,7 +83,8 @@ export const icons = {
ratio: 1,
},
[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',
ratio: 1,
},
@ -223,7 +224,7 @@ export const icons = {
},
[SessionIconType.Mute]: {
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',
ratio: 1,
},

View File

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

View File

@ -238,9 +238,31 @@ export const getConversationHeaderTitleProps = createSelector(getSelectedConvers
name: state.name,
subscriberCount: state.subscriberCount,
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):
| ConversationHeaderProps
| undefined => {