feat: wrap up the new Join Community overlay

pull/2410/head
Audric Ackermann 3 years ago
parent 282e631f73
commit 374b71630a

@ -28,9 +28,9 @@
"viewMenuToggleFullScreen": "Toggle Full Screen", "viewMenuToggleFullScreen": "Toggle Full Screen",
"viewMenuToggleDevTools": "Toggle Developer Tools", "viewMenuToggleDevTools": "Toggle Developer Tools",
"contextMenuNoSuggestions": "No Suggestions", "contextMenuNoSuggestions": "No Suggestions",
"openGroupInvitation": "Open group invitation", "openGroupInvitation": "Community invitation",
"joinOpenGroupAfterInvitationConfirmationTitle": "Join $roomName$?", "joinOpenGroupAfterInvitationConfirmationTitle": "Join $roomName$?",
"joinOpenGroupAfterInvitationConfirmationDesc": "Are you sure you want to join the $roomName$ open group?", "joinOpenGroupAfterInvitationConfirmationDesc": "Are you sure you want to join the $roomName$ community?",
"couldntFindServerMatching": "Couldn't find the corresponding opengroup server", "couldntFindServerMatching": "Couldn't find the corresponding opengroup server",
"enterSessionIDOrONSName": "Enter Session ID or ONS name", "enterSessionIDOrONSName": "Enter Session ID or ONS name",
"loading": "Loading...", "loading": "Loading...",
@ -138,10 +138,10 @@
"typingIndicatorsSettingDescription": "See and share when messages are being typed (applies to all sessions).", "typingIndicatorsSettingDescription": "See and share when messages are being typed (applies to all sessions).",
"typingIndicatorsSettingTitle": "Typing Indicators", "typingIndicatorsSettingTitle": "Typing Indicators",
"zoomFactorSettingTitle": "Zoom Factor", "zoomFactorSettingTitle": "Zoom Factor",
"pruneSettingTitle": "Prune Old Open Group Messages", "pruneSettingTitle": "Prune Old Community Messages",
"pruneSettingDescription": "Prune messages older than 6 months from Open Groups on start", "pruneSettingDescription": "Prune messages older than 6 months from Communities on start",
"pruningOpengroupDialogTitle": "Open group pruning", "pruningOpengroupDialogTitle": "Community pruning",
"pruningOpengroupDialogMessage": "Pruning old open group messages improves performance. Enable pruning for open group messages older than 6 months?", "pruningOpengroupDialogMessage": "Pruning old communities messages improves performance. Enable pruning for communities messages older than 6 months?",
"pruningOpengroupDialogSubMessage": "You can change this setting in the Session settings menu", "pruningOpengroupDialogSubMessage": "You can change this setting in the Session settings menu",
"enable": "Enable", "enable": "Enable",
"keepDisabled": "Keep disabled", "keepDisabled": "Keep disabled",
@ -281,10 +281,10 @@
"setPasswordToastDescription": "Your password has been set. Please keep it safe.", "setPasswordToastDescription": "Your password has been set. Please keep it safe.",
"changePasswordToastDescription": "Your password has been changed. Please keep it safe.", "changePasswordToastDescription": "Your password has been changed. Please keep it safe.",
"removePasswordToastDescription": "You have removed your password.", "removePasswordToastDescription": "You have removed your password.",
"publicChatExists": "You are already connected to this open group", "publicChatExists": "You are already connected to this community",
"connectToServerFail": "Couldn't join group", "connectToServerFail": "Couldn't join group",
"connectingToServer": "Connecting...", "connectingToServer": "Connecting...",
"connectToServerSuccess": "Successfully connected to open group", "connectToServerSuccess": "Successfully connected to community",
"setPasswordFail": "Failed to set password", "setPasswordFail": "Failed to set password",
"passwordLengthError": "Password must be between 6 and 64 characters long", "passwordLengthError": "Password must be between 6 and 64 characters long",
"passwordTypeError": "Password must be a string", "passwordTypeError": "Password must be a string",
@ -337,12 +337,13 @@
"recoveryPhraseEmpty": "Enter your recovery phrase", "recoveryPhraseEmpty": "Enter your recovery phrase",
"displayNameEmpty": "Please enter a display name", "displayNameEmpty": "Please enter a display name",
"members": "$count$ members", "members": "$count$ members",
"join": "Join",
"joinOpenGroup": "Join Community", "joinOpenGroup": "Join Community",
"createGroup": "Create Group", "createGroup": "Create Group",
"createClosedGroupNamePrompt": "Group Name", "createClosedGroupNamePrompt": "Group Name",
"createClosedGroupPlaceholder": "Enter a group name", "createClosedGroupPlaceholder": "Enter a group name",
"openGroupURL": "Open Group URL", "openGroupURL": "Community URL",
"enterAnOpenGroupURL": "Enter an open group URL", "enterAnOpenGroupURL": "Enter a community URL",
"next": "Next", "next": "Next",
"invalidGroupNameTooShort": "Please enter a group name", "invalidGroupNameTooShort": "Please enter a group name",
"invalidGroupNameTooLong": "Please enter a shorter group name", "invalidGroupNameTooLong": "Please enter a shorter group name",

@ -1278,13 +1278,6 @@
height: 100%; height: 100%;
} }
.module-left-pane__list {
flex-grow: 1;
flex-shrink: 1;
overflow-y: auto;
overflow-x: hidden;
}
.module-left-pane__virtual-list { .module-left-pane__virtual-list {
outline: none; outline: none;
} }

@ -119,10 +119,6 @@ $session-compose-margin: 20px;
flex-grow: 1; flex-grow: 1;
} }
&__list {
height: -webkit-fill-available;
}
&-overlay { &-overlay {
background: var(--color-left-pane-overlay-background); background: var(--color-left-pane-overlay-background);
@ -262,35 +258,6 @@ $session-compose-margin: 20px;
} }
} }
.left-pane-contact {
&-section,
&-content {
display: flex;
flex-direction: column;
overflow: hidden;
flex: 1;
.module-conversation-list-item {
&__header__date,
&__message {
display: none;
}
&__buttons {
display: flex;
.session-button {
font-size: 11px;
padding: 6px;
height: auto;
margin: 0px;
line-height: 14px;
}
}
}
}
}
.left-pane-setting { .left-pane-setting {
&-bottom-buttons { &-bottom-buttons {
@include bottom-buttons(); @include bottom-buttons();

@ -120,18 +120,6 @@ const Section = (props: { type: SectionType }) => {
isSelected={isSelected} isSelected={isSelected}
/> />
); );
case SectionType.Contact:
return (
<SessionIconButton
iconSize="medium"
dataTestId="contact-section"
iconType={'users'}
iconColor={undefined}
notificationCount={unreadToShow}
onClick={handleClick}
isSelected={isSelected}
/>
);
case SectionType.Settings: case SectionType.Settings:
return ( return (
<SessionIconButton <SessionIconButton
@ -357,7 +345,6 @@ export const ActionsPanel = () => {
<LeftPaneSectionContainer data-testid="leftpane-section-container"> <LeftPaneSectionContainer data-testid="leftpane-section-container">
<Section type={SectionType.Profile} /> <Section type={SectionType.Profile} />
<Section type={SectionType.Message} /> <Section type={SectionType.Message} />
<Section type={SectionType.Contact} />
<Section type={SectionType.Settings} /> <Section type={SectionType.Settings} />
<SessionToastContainer /> <SessionToastContainer />

@ -8,20 +8,9 @@ import { getSearchResults, isSearching } from '../../state/selectors/search';
import { getFocusedSection, getOverlayMode } from '../../state/selectors/section'; import { getFocusedSection, getOverlayMode } from '../../state/selectors/section';
import { getHideMessageRequestBanner } from '../../state/selectors/userConfig'; import { getHideMessageRequestBanner } from '../../state/selectors/userConfig';
import { ActionsPanel } from './ActionsPanel'; import { ActionsPanel } from './ActionsPanel';
import { LeftPaneContactSection } from './LeftPaneContactSection';
import { LeftPaneMessageSection } from './LeftPaneMessageSection'; import { LeftPaneMessageSection } from './LeftPaneMessageSection';
import { LeftPaneSettingSection } from './LeftPaneSettingSection'; import { LeftPaneSettingSection } from './LeftPaneSettingSection';
// from https://github.com/bvaughn/react-virtualized/blob/fb3484ed5dcc41bffae8eab029126c0fb8f7abc0/source/List/types.js#L5
export type RowRendererParamsType = {
index: number;
isScrolling: boolean;
isVisible: boolean;
key: string;
parent: Object;
style: Object;
};
const InnerLeftPaneMessageSection = () => { const InnerLeftPaneMessageSection = () => {
const showSearch = useSelector(isSearching); const showSearch = useSelector(isSearching);
@ -43,10 +32,6 @@ const InnerLeftPaneMessageSection = () => {
); );
}; };
const InnerLeftPaneContactSection = () => {
return <LeftPaneContactSection />;
};
const LeftPaneSection = () => { const LeftPaneSection = () => {
const focusedSection = useSelector(getFocusedSection); const focusedSection = useSelector(getFocusedSection);
@ -54,9 +39,6 @@ const LeftPaneSection = () => {
return <InnerLeftPaneMessageSection />; return <InnerLeftPaneMessageSection />;
} }
if (focusedSection === SectionType.Contact) {
return <InnerLeftPaneContactSection />;
}
if (focusedSection === SectionType.Settings) { if (focusedSection === SectionType.Settings) {
return <LeftPaneSettingSection />; return <LeftPaneSettingSection />;
} }

@ -1,62 +0,0 @@
import React from 'react';
import { MemoConversationListItemWithDetails } from './conversation-list-item/ConversationListItem';
import { AutoSizer, List } from 'react-virtualized';
import { LeftPaneSectionHeader } from './LeftPaneSectionHeader';
import { useSelector } from 'react-redux';
import { getDirectContacts } from '../../state/selectors/conversations';
import { RowRendererParamsType } from './LeftPane';
const renderRow = (props: RowRendererParamsType) => {
const { index, key, style } = props;
const directContacts = (props.parent as any)?.props?.directContacts || [];
const item = directContacts?.[index];
if (!item) {
return null;
}
return <MemoConversationListItemWithDetails style={style} key={key} {...item} />;
};
const ContactListItemSection = () => {
const directContacts = useSelector(getDirectContacts);
if (!directContacts) {
return null;
}
const length = Number(directContacts.length);
return (
<div className="module-left-pane__list" key={0}>
<AutoSizer>
{({ height, width }) => (
<List
className="module-left-pane__virtual-list"
height={height}
directContacts={directContacts} // needed for change in props refresh
rowCount={length}
rowHeight={64}
rowRenderer={renderRow}
width={width}
autoHeight={false}
/>
)}
</AutoSizer>
</div>
);
};
export const LeftPaneContactSection = () => {
return (
<div className="left-pane-contact-section">
<LeftPaneSectionHeader />
<div className="left-pane-contact-content">
<ContactListItemSection />
</div>
</div>
);
};

@ -0,0 +1,9 @@
import styled from 'styled-components';
export const StyledLeftPaneList = styled.div`
height: -webkit-fill-available;
flex-grow: 1;
flex-shrink: 1;
overflow-y: auto;
overflow-x: hidden;
`;

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { AutoSizer, List } from 'react-virtualized'; import { AutoSizer, List, ListRowProps } from 'react-virtualized';
import { import {
ConversationListItemProps, ConversationListItemProps,
MemoConversationListItemWithDetails, MemoConversationListItemWithDetails,
@ -12,14 +12,16 @@ import _ from 'lodash';
import { MessageRequestsBanner } from './MessageRequestsBanner'; import { MessageRequestsBanner } from './MessageRequestsBanner';
import { SessionSearchInput } from '../SessionSearchInput'; import { SessionSearchInput } from '../SessionSearchInput';
import { RowRendererParamsType } from './LeftPane'; import { OverlayCommunity } from './overlay/OverlayCommunity';
import { OverlayOpenGroup } from './overlay/OverlayOpenGroup';
import { OverlayMessageRequest } from './overlay/OverlayMessageRequest'; import { OverlayMessageRequest } from './overlay/OverlayMessageRequest';
import { OverlayMessage } from './overlay/OverlayMessage'; import { OverlayMessage } from './overlay/OverlayMessage';
import { OverlayClosedGroup } from './overlay/OverlayClosedGroup'; import { OverlayClosedGroup } from './overlay/OverlayClosedGroup';
import { OverlayMode, setOverlayMode } from '../../state/ducks/section'; import { OverlayMode, setOverlayMode } from '../../state/ducks/section';
import { OverlayChooseAction } from './overlay/OverlayChooseAction'; import { OverlayChooseAction } from './overlay/choose-action/OverlayChooseAction';
import styled from 'styled-components'; import styled from 'styled-components';
import { useSelector } from 'react-redux';
import { getOverlayMode } from '../../state/selectors/section';
import { StyledLeftPaneList } from './LeftPaneList';
export interface Props { export interface Props {
contacts: Array<ReduxConversationType>; contacts: Array<ReduxConversationType>;
@ -40,6 +42,25 @@ const StyledConversationListContent = styled.div`
background: var(--color-conversation-list); background: var(--color-conversation-list);
`; `;
const ClosableOverlay = () => {
const overlayMode = useSelector(getOverlayMode);
switch (overlayMode) {
case 'choose-action':
return <OverlayChooseAction />;
case 'open-group':
return <OverlayCommunity />;
case 'closed-group':
return <OverlayClosedGroup />;
case 'message':
return <OverlayMessage />;
case 'message-requests':
return <OverlayMessageRequest />;
default:
return null;
}
};
export class LeftPaneMessageSection extends React.Component<Props> { export class LeftPaneMessageSection extends React.Component<Props> {
public constructor(props: Props) { public constructor(props: Props) {
super(props); super(props);
@ -47,7 +68,7 @@ export class LeftPaneMessageSection extends React.Component<Props> {
autoBind(this); autoBind(this);
} }
public renderRow = ({ index, key, style }: RowRendererParamsType): JSX.Element | null => { public renderRow = ({ index, key, style }: ListRowProps): JSX.Element | null => {
const { conversations } = this.props; const { conversations } = this.props;
//assume conversations that have been marked unapproved should be filtered out by selector. //assume conversations that have been marked unapproved should be filtered out by selector.
@ -63,7 +84,7 @@ export class LeftPaneMessageSection extends React.Component<Props> {
return <MemoConversationListItemWithDetails key={key} style={style} {...conversation} />; return <MemoConversationListItemWithDetails key={key} style={style} {...conversation} />;
}; };
public renderList(): JSX.Element | Array<JSX.Element | null> { public renderList(): JSX.Element {
const { conversations, searchResults } = this.props; const { conversations, searchResults } = this.props;
if (searchResults) { if (searchResults) {
@ -76,12 +97,12 @@ export class LeftPaneMessageSection extends React.Component<Props> {
const length = conversations.length; const length = conversations.length;
const listKey = 0;
// Note: conversations is not a known prop for List, but it is required to ensure that // Note: conversations is not a known prop for List, but it is required to ensure that
// it re-renders when our conversation data changes. Otherwise it would just render // it re-renders when our conversation data changes. Otherwise it would just render
// on startup and scroll. // on startup and scroll.
const list = (
<div className="module-left-pane__list" key={listKey}> return (
<StyledLeftPaneList key={0}>
<AutoSizer> <AutoSizer>
{({ height, width }) => ( {({ height, width }) => (
<List <List
@ -96,10 +117,8 @@ export class LeftPaneMessageSection extends React.Component<Props> {
/> />
)} )}
</AutoSizer> </AutoSizer>
</div> </StyledLeftPaneList>
); );
return [list];
} }
public render(): JSX.Element { public render(): JSX.Element {
@ -108,7 +127,7 @@ export class LeftPaneMessageSection extends React.Component<Props> {
return ( return (
<div className="session-left-pane-section-content"> <div className="session-left-pane-section-content">
<LeftPaneSectionHeader /> <LeftPaneSectionHeader />
{overlayMode ? this.renderClosableOverlay() : this.renderConversations()} {overlayMode ? <ClosableOverlay /> : this.renderConversations()}
</div> </div>
); );
} }
@ -126,23 +145,4 @@ export class LeftPaneMessageSection extends React.Component<Props> {
</StyledConversationListContent> </StyledConversationListContent>
); );
} }
private renderClosableOverlay() {
const { overlayMode } = this.props;
switch (overlayMode) {
case 'choose-action':
return <OverlayChooseAction />;
case 'open-group':
return <OverlayOpenGroup />;
case 'closed-group':
return <OverlayClosedGroup />;
case 'message':
return <OverlayMessage />;
case 'message-requests':
return <OverlayMessageRequest />;
default:
return null;
}
}
} }

@ -32,9 +32,6 @@ export const LeftPaneSectionHeader = () => {
const showBackButton = isMessageRequestOverlay && isMessageSection; const showBackButton = isMessageRequestOverlay && isMessageSection;
switch (focusedSection) { switch (focusedSection) {
case SectionType.Contact:
label = window.i18n('contactsHeader');
break;
case SectionType.Settings: case SectionType.Settings:
label = window.i18n('settingsHeader'); label = window.i18n('settingsHeader');
break; break;

@ -15,6 +15,7 @@ import { SessionButton, SessionButtonColor, SessionButtonType } from '../basic/S
import { SessionIcon } from '../icon'; import { SessionIcon } from '../icon';
import { SessionSettingCategory } from '../settings/SessionSettings'; import { SessionSettingCategory } from '../settings/SessionSettings';
import { resetConversationExternal } from '../../state/ducks/conversations'; import { resetConversationExternal } from '../../state/ducks/conversations';
import { StyledLeftPaneList } from './LeftPaneList';
const getCategories = () => { const getCategories = () => {
return [ return [
@ -89,13 +90,13 @@ const LeftPaneSettingsCategories = () => {
const categories = getCategories(); const categories = getCategories();
return ( return (
<div className="module-left-pane__list" key={0}> <StyledLeftPaneList key={0}>
<div className="left-pane-setting-category-list"> <div className="left-pane-setting-category-list">
{categories.map(item => { {categories.map(item => {
return <LeftPaneSettingsCategoryRow key={item.id} item={item} />; return <LeftPaneSettingsCategoryRow key={item.id} item={item} />;
})} })}
</div> </div>
</div> </StyledLeftPaneList>
); );
}; };

@ -26,7 +26,7 @@ async function joinOpenGroup(serverUrl: string) {
} }
} }
export const OverlayOpenGroup = () => { export const OverlayCommunity = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [groupUrl, setGroupUrl] = useState(''); const [groupUrl, setGroupUrl] = useState('');
@ -56,7 +56,7 @@ export const OverlayOpenGroup = () => {
useKey('Escape', closeOverlay); useKey('Escape', closeOverlay);
const title = window.i18n('joinOpenGroup'); const title = window.i18n('joinOpenGroup');
const buttonText = window.i18n('next'); const buttonText = window.i18n('join');
const subtitle = window.i18n('openGroupURL'); const subtitle = window.i18n('openGroupURL');
const placeholder = window.i18n('enterAnOpenGroupURL'); const placeholder = window.i18n('enterAnOpenGroupURL');
@ -78,12 +78,14 @@ export const OverlayOpenGroup = () => {
<SessionSpinner loading={loading} /> <SessionSpinner loading={loading} />
<SessionJoinableRooms onRoomClicked={closeOverlay} /> <SessionJoinableRooms onRoomClicked={closeOverlay} />
<SessionButton {groupUrl && (
buttonColor={SessionButtonColor.Green} <SessionButton
buttonType={SessionButtonType.BrandOutline} buttonColor={SessionButtonColor.White}
text={buttonText} buttonType={SessionButtonType.BrandOutline}
onClick={onEnterPressed} text={buttonText}
/> onClick={onEnterPressed}
/>
)}
</div> </div>
); );
}; };

@ -114,7 +114,12 @@ export const OverlayMessage = () => {
<YourSessionIDPill /> <YourSessionIDPill />
<SpacerMD /> <SpacerMD />
</Flex> </Flex>
<Flex container={true} justifyContent="space-between" alignItems="center"> <Flex
container={true}
justifyContent="space-between"
alignItems="center"
padding="0 15px 0 0 " // YourSessionIDSelectable already has a left margin of 15px
>
<YourSessionIDSelectable /> <YourSessionIDSelectable />
<SessionIconButton iconSize="small" iconType="copy" onClick={copyOurSessionID} /> <SessionIconButton iconSize="small" iconType="copy" onClick={copyOurSessionID} />
</Flex> </Flex>

@ -0,0 +1,100 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { AutoSizer, List, ListRowProps } from 'react-virtualized';
import styled from 'styled-components';
import {
getDirectContacts,
getDirectContactsCount,
} from '../../../../state/selectors/conversations';
import { MemoConversationListItemWithDetails } from '../../conversation-list-item/ConversationListItem';
import { StyledLeftPaneList } from '../../LeftPaneList';
import { StyledChooseActionTitle } from './OverlayChooseAction';
// tslint:disable: use-simple-attributes no-submodule-imports
const renderRow = (props: ListRowProps) => {
const { index, key, style, parent } = props;
// ugly, but it seems react-viurtualized do not support very well functional components just yet
// https://stackoverflow.com/questions/54488954/how-to-pass-prop-into-rowrender-of-react-virtualized
const directContacts = (parent as any).props.directContacts;
const item = directContacts?.[index];
if (!item) {
return null;
}
return <MemoConversationListItemWithDetails style={style} key={key} {...item} />;
};
const ContactListItemSection = () => {
const directContacts = useSelector(getDirectContacts);
if (!directContacts) {
return null;
}
const length = Number(directContacts.length);
return (
<StyledLeftPaneList key={0} style={{ width: '100%' }}>
<AutoSizer>
{({ height }) => {
return (
<List
className="module-left-pane__virtual-list"
height={height}
rowCount={length}
rowHeight={64}
directContacts={directContacts}
rowRenderer={renderRow}
width={300} // the same as session-left-pane-width
autoHeight={false}
/>
);
}}
</AutoSizer>
</StyledLeftPaneList>
);
};
const StyledContactSection = styled.div`
display: flex;
flex-direction: column;
overflow: hidden;
flex: 1;
width: 100%;
.module-conversation-list-item __header__date,
.module-conversation-list-item __message {
display: none;
}
.module-conversation-list-item __buttons {
display: flex;
.session-button {
font-size: 11px;
padding: 6px;
height: auto;
margin: 0px;
line-height: 14px;
}
}
`;
const ContactsTitle = () => {
const contactsCount = useSelector(getDirectContactsCount);
if (contactsCount <= 0) {
return null;
}
return <StyledChooseActionTitle>{window.i18n('contactsHeader')}</StyledChooseActionTitle>;
};
export const ContactsListWithBreaks = () => {
return (
<StyledContactSection>
<ContactsTitle />
<ContactListItemSection />
</StyledContactSection>
);
};

@ -2,18 +2,19 @@ import React from 'react';
// tslint:disable: use-simple-attributes no-submodule-imports // tslint:disable: use-simple-attributes no-submodule-imports
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { resetOverlayMode, setOverlayMode } from '../../../state/ducks/section'; import { resetOverlayMode, setOverlayMode } from '../../../../state/ducks/section';
import useKey from 'react-use/lib/useKey'; import useKey from 'react-use/lib/useKey';
import styled from 'styled-components'; import styled from 'styled-components';
import { SessionIcon, SessionIconType } from '../../icon'; import { SessionIcon, SessionIconType } from '../../../icon';
import { ContactsListWithBreaks } from './ContactsListWithBreaks';
const StyledActionRow = styled.button` const StyledActionRow = styled.button`
border: none; border: none;
width: 100%;
display: flex; display: flex;
align-items: center; align-items: center;
border-bottom: 1px var(--color-session-border) solid; border-bottom: 1px var(--color-session-border) solid;
transition-duration: 0.25s; transition-duration: 0.25s;
width: 100%;
&:first-child { &:first-child {
border-top: 1px var(--color-session-border) solid; border-top: 1px var(--color-session-border) solid;
@ -24,7 +25,7 @@ const StyledActionRow = styled.button`
} }
`; `;
const StyledActionText = styled.span` export const StyledChooseActionTitle = styled.span`
color: var(--color-text); color: var(--color-text);
font-size: 18px; font-size: 18px;
padding: 5px 0px 5px 10px; padding: 5px 0px 5px 10px;
@ -67,16 +68,17 @@ export const OverlayChooseAction = () => {
<div className="module-left-pane-overlay"> <div className="module-left-pane-overlay">
<StyledActionRow onClick={openNewMessage}> <StyledActionRow onClick={openNewMessage}>
<IconOnActionRow iconType="chatBubble" /> <IconOnActionRow iconType="chatBubble" />
<StyledActionText>{window.i18n('newMessage')}</StyledActionText> <StyledChooseActionTitle>{window.i18n('newMessage')}</StyledChooseActionTitle>
</StyledActionRow> </StyledActionRow>
<StyledActionRow onClick={openCreateGroup}> <StyledActionRow onClick={openCreateGroup}>
<IconOnActionRow iconType="group" /> <IconOnActionRow iconType="group" />
<StyledActionText>{window.i18n('createGroup')}</StyledActionText> <StyledChooseActionTitle>{window.i18n('createGroup')}</StyledChooseActionTitle>
</StyledActionRow> </StyledActionRow>
<StyledActionRow onClick={openJoinCommunity}> <StyledActionRow onClick={openJoinCommunity}>
<IconOnActionRow iconType="communities" /> <IconOnActionRow iconType="communities" />
<StyledActionText>{window.i18n('joinOpenGroup')}</StyledActionText> <StyledChooseActionTitle>{window.i18n('joinOpenGroup')}</StyledChooseActionTitle>
</StyledActionRow> </StyledActionRow>
<ContactsListWithBreaks />
</div> </div>
); );
}; };

@ -9,7 +9,6 @@ export const RESET_OVERLAY_MODE = 'RESET_OVERLAY_MODE';
export enum SectionType { export enum SectionType {
Profile, Profile,
Message, Message,
Contact,
Settings, Settings,
Moon, Moon,
PathIndicator, PathIndicator,
@ -95,7 +94,7 @@ export const initialSectionState: SectionStateType = {
focusedSection: SectionType.Message, focusedSection: SectionType.Message,
focusedSettingsSection: undefined, focusedSettingsSection: undefined,
isAppFocused: false, isAppFocused: false,
overlayMode: 'message', overlayMode: 'choose-action',
}; };
export type SectionStateType = { export type SectionStateType = {

@ -533,6 +533,11 @@ export const getDirectContacts = createSelector(
}) => state.contacts }) => state.contacts
); );
export const getDirectContactsCount = createSelector(
getDirectContacts,
(contacts: Array<ReduxConversationType>) => contacts.length
);
export const getUnreadMessageCount = createSelector(getLeftPaneLists, (state): number => { export const getUnreadMessageCount = createSelector(getLeftPaneLists, (state): number => {
return state.unreadCount; return state.unreadCount;
}); });

@ -391,6 +391,7 @@ export type LocalizerKeys =
| 'closedGroupMaxSize' | 'closedGroupMaxSize'
| 'messagesHeader' | 'messagesHeader'
| 'joinOpenGroup' | 'joinOpenGroup'
| 'join'
| 'callMediaPermissionsDialogContent' | 'callMediaPermissionsDialogContent'
| 'timerOption_1_day_abbreviated' | 'timerOption_1_day_abbreviated'
| 'about' | 'about'

Loading…
Cancel
Save