diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 15d48eebe..ff578d86e 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -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$" } diff --git a/ts/components/ConversationListItem.tsx b/ts/components/ConversationListItem.tsx index 93a0eb2c7..8098b6944 100644 --- a/ts/components/ConversationListItem.tsx +++ b/ts/components/ConversationListItem.tsx @@ -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 - case ('mentions_only'): - return + case 'disabled': + return ( + + ); + case 'mentions_only': + return ( + + ); default: return null; } - } + }; return (
@@ -137,7 +140,7 @@ const HeaderItem = (props: { {pinIcon} - + {unreadCountDiv} {atSymbol} diff --git a/ts/components/conversation/ConversationHeader.tsx b/ts/components/conversation/ConversationHeader.tsx index d9cc42b81..96c4dba1b 100644 --- a/ts/components/conversation/ConversationHeader.tsx +++ b/ts/components/conversation/ConversationHeader.tsx @@ -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()} />
@@ -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 }) = ); @@ -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 : ( - {text} - ); - + const notificationSetting = useSelector(getCurrentNotificationSettingText); + const notificationSubtitle = notificationSetting + ? window.i18n('notificationSubtitle', notificationSetting) + : null; const title = profileName || name || phoneNumber; return (
{title} - {textEl} + + {isKickedFromGroup ? null : } + +
); }; +/** + * 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 {text}; +}; + export const ConversationHeaderWithDetails = () => { const headerProps = useSelector(getConversationHeaderProps); diff --git a/ts/components/session/icon/Icons.tsx b/ts/components/session/icon/Icons.tsx index c5d6d64d7..e82f6866e 100644 --- a/ts/components/session/icon/Icons.tsx +++ b/ts/components/session/icon/Icons.tsx @@ -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, }, diff --git a/ts/components/session/settings/SessionSettings.tsx b/ts/components/session/settings/SessionSettings.tsx index 8b5d07e29..029a1d294 100644 --- a/ts/components/session/settings/SessionSettings.tsx +++ b/ts/components/session/settings/SessionSettings.tsx @@ -253,11 +253,13 @@ class SettingsViewInner extends React.Component { return (
v{window.versionInfo.version} - + + + {window.versionInfo.commitHash}
); diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts index f24683956..7be618d2d 100644 --- a/ts/state/selectors/conversations.ts +++ b/ts/state/selectors/conversations.ts @@ -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 => {