feat: added new togglable subtitle to header

pull/2660/head
William Grant 2 years ago
parent f825b74895
commit 26995e1873

@ -1,9 +1,9 @@
import React from 'react'; import React, { useState } from 'react';
import { Avatar, AvatarSize } from '../avatar/Avatar'; import { Avatar, AvatarSize } from '../avatar/Avatar';
import { contextMenu } from 'react-contexify'; import { contextMenu } from 'react-contexify';
import styled from 'styled-components'; import styled, { CSSProperties } from 'styled-components';
import { ConversationNotificationSettingType } from '../../models/conversationAttributes'; import { ConversationNotificationSettingType } from '../../models/conversationAttributes';
import { import {
getConversationHeaderTitleProps, getConversationHeaderTitleProps,
@ -48,7 +48,10 @@ import {
import { SessionIconButton } from '../icon'; import { SessionIconButton } from '../icon';
import { ConversationHeaderMenu } from '../menu/ConversationHeaderMenu'; import { ConversationHeaderMenu } from '../menu/ConversationHeaderMenu';
import { Flex } from '../basic/Flex'; import { Flex } from '../basic/Flex';
import { ExpirationTimerOptions } from '../../util/expiringMessages'; import {
DisappearingMessageConversationType,
ExpirationTimerOptions,
} from '../../util/expiringMessages';
export interface TimerOption { export interface TimerOption {
name: string; name: string;
@ -261,15 +264,53 @@ const CallButton = () => {
export const StyledSubtitleContainer = styled.div` export const StyledSubtitleContainer = styled.div`
display: flex; display: flex;
flex-direction: row; flex-direction: column;
align-items: center; align-items: center;
justify-content: space-between; justify-content: center;
min-width: 230px;
span:last-child { div:first-child {
margin-bottom: 0; span:last-child {
margin-bottom: 0;
}
} }
`; `;
const StyledSubtitleDot = styled.span<{ active: boolean }>`
border-radius: 50%;
background-color: ${props =>
props.active ? 'var(--text-primary-color)' : 'var(--text-secondary-color)'};
height: 6px;
width: 6px;
margin: 0 3px;
`;
const SubtitleDotMenu = ({
options,
selectedOptionIndex,
style,
}: {
options: Array<string | null>;
selectedOptionIndex: number;
style: CSSProperties;
}) => (
<Flex container={true} alignItems={'center'} style={style}>
{options.map((option, index) => {
if (!option) {
return null;
}
return (
<StyledSubtitleDot
key={`subtitleDotMenu-${index}`}
active={selectedOptionIndex === index}
/>
);
})}
</Flex>
);
export type ConversationHeaderTitleProps = { export type ConversationHeaderTitleProps = {
conversationKey: string; conversationKey: string;
isMe: boolean; isMe: boolean;
@ -279,19 +320,8 @@ export type ConversationHeaderTitleProps = {
subscriberCount?: number; subscriberCount?: number;
isKickedFromGroup: boolean; isKickedFromGroup: boolean;
currentNotificationSetting?: ConversationNotificationSettingType; currentNotificationSetting?: ConversationNotificationSettingType;
}; expirationType?: DisappearingMessageConversationType;
expireTimer?: number;
/**
* 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>;
}; };
const ConversationHeaderTitle = () => { const ConversationHeaderTitle = () => {
@ -301,17 +331,29 @@ const ConversationHeaderTitle = () => {
const convoName = useConversationUsername(headerTitleProps?.conversationKey); const convoName = useConversationUsername(headerTitleProps?.conversationKey);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [visibleTitleIndex, setVisibleTitleIndex] = useState(0);
if (!headerTitleProps) { if (!headerTitleProps) {
return null; return null;
} }
const { isGroup, isPublic, members, subscriberCount, isMe, isKickedFromGroup } = headerTitleProps; const {
isGroup,
isPublic,
members,
subscriberCount,
isMe,
isKickedFromGroup,
expirationType,
expireTimer,
} = headerTitleProps;
const { i18n } = window; const { i18n } = window;
if (isMe) { const notificationSubtitle = notificationSetting
return <div className="module-conversation-header__title">{i18n('noteToSelf')}</div>; ? i18n('notificationSubtitle', [notificationSetting])
} : null;
let memberCount = 0; let memberCount = 0;
if (isGroup) { if (isGroup) {
@ -322,37 +364,119 @@ const ConversationHeaderTitle = () => {
} }
} }
let memberCountText = ''; let memberCountSubtitle = null;
if (isGroup && memberCount > 0 && !isKickedFromGroup) { if (isGroup && memberCount > 0 && !isKickedFromGroup) {
const count = String(memberCount); const count = String(memberCount);
memberCountText = isPublic ? i18n('activeMembers', [count]) : i18n('members', [count]); memberCountSubtitle = isPublic ? i18n('activeMembers', [count]) : i18n('members', [count]);
} }
const notificationSubtitle = notificationSetting const disappearingMessageSettingText =
? window.i18n('notificationSubtitle', [notificationSetting]) expirationType === 'off'
? window.i18n('disappearingMessagesModeOff')
: expirationType === 'deleteAfterRead'
? window.i18n('disappearingMessagesModeAfterRead')
: window.i18n('disappearingMessagesModeAfterSend');
const abbreviatedExpireTime = Boolean(expireTimer)
? ExpirationTimerOptions.getAbbreviated(expireTimer)
: null; : null;
const fullTextSubtitle = memberCountText const disappearingMessageSubtitle = `${disappearingMessageSettingText}${
? `${memberCountText}${notificationSubtitle}` abbreviatedExpireTime ? ` - ${abbreviatedExpireTime}` : ''
: `${notificationSubtitle}`; }`;
const subtitles = [
notificationSubtitle && notificationSubtitle,
memberCountSubtitle && memberCountSubtitle,
disappearingMessageSubtitle && disappearingMessageSubtitle,
];
window.log.info(`WIP: subtitles`, subtitles);
// const fullTextSubtitle = memberCountText
// ? `${memberCountText} ● ${notificationSubtitle}`
// : `${notificationSubtitle}`;
const handleTitleCycle = (direction: 1 | -1) => {
let newIndex = visibleTitleIndex + direction;
if (newIndex > subtitles.length - 1) {
newIndex = 0;
}
if (newIndex < 0) {
newIndex = subtitles.length - 1;
}
if (subtitles[newIndex]) {
setVisibleTitleIndex(newIndex);
}
};
if (isMe) {
// TODO customise for new disappearing message system
return <div className="module-conversation-header__title">{i18n('noteToSelf')}</div>;
}
return ( return (
<div <div
className="module-conversation-header__title" className="module-conversation-header__title"
onClick={() => { // onClick={() => {
if (isRightPanelOn) { // if (isRightPanelOn) {
dispatch(closeRightPanel()); // dispatch(closeRightPanel());
} else { // } else {
dispatch(openRightPanel()); // dispatch(openRightPanel());
} // }
}} // }}
role="button" role="button"
> >
<span className="module-contact-name__profile-name" data-testid="header-conversation-name"> <span className="module-contact-name__profile-name" data-testid="header-conversation-name">
{convoName} {convoName}
</span> </span>
<StyledSubtitleContainer> {subtitles && (
<ConversationHeaderSubtitle text={fullTextSubtitle} /> <StyledSubtitleContainer>
</StyledSubtitleContainer> <Flex
container={true}
flexDirection={'row'}
justifyContent={'space-between'}
alignItems={'center'}
width={'100%'}
>
<SessionIconButton
iconColor={'var(--button-icon-stroke-selected-color)'}
iconSize={'medium'}
iconType="chevron"
iconRotation={90}
margin={'0 var(--margins-xs) 0 0'}
onClick={() => {
handleTitleCycle(-1);
}}
/>
{visibleTitleIndex === 2 && (
<SessionIconButton
iconColor={'var(--button-icon-stroke-selected-color)'}
iconSize={'tiny'}
iconType="timer50"
margin={'0 var(--margins-xs) 0 0'}
/>
)}
<span className="module-conversation-header__title-text">
{subtitles[visibleTitleIndex]}
</span>
<SessionIconButton
iconColor={'var(--button-icon-stroke-selected-color)'}
iconSize={'medium'}
iconType="chevron"
iconRotation={270}
margin={'0 0 0 var(--margins-xs)'}
onClick={() => {
handleTitleCycle(1);
}}
/>
</Flex>
<SubtitleDotMenu
options={subtitles}
selectedOptionIndex={visibleTitleIndex}
style={{ margin: 'var(--margins-xs) 0' }}
/>
</StyledSubtitleContainer>
)}
</div> </div>
); );
}; };

@ -563,6 +563,8 @@ export const getConversationHeaderTitleProps = createSelector(getSelectedConvers
subscriberCount: state.subscriberCount, subscriberCount: state.subscriberCount,
isGroup: state.type === 'group', isGroup: state.type === 'group',
currentNotificationSetting: state.currentNotificationSetting, currentNotificationSetting: state.currentNotificationSetting,
expirationType: state.expirationType,
expireTimer: state.expireTimer,
}; };
}); });

Loading…
Cancel
Save