cleanedup redux action openConversationExternal

pull/1783/head
Audric Ackermann 4 years ago
parent 7f76ab274c
commit ee4a0b9b1e
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -16,15 +16,15 @@ import { OutgoingMessageStatus } from './conversation/message/OutgoingMessageSta
import { useTheme } from 'styled-components'; import { useTheme } from 'styled-components';
import { PubKey } from '../session/types'; import { PubKey } from '../session/types';
import { import {
ConversationType,
LastMessageType, LastMessageType,
openConversationExternal, openConversationExternal,
ReduxConversationType,
} from '../state/ducks/conversations'; } from '../state/ducks/conversations';
import _ from 'underscore'; import _ from 'underscore';
import { useMembersAvatars } from '../hooks/useMembersAvatar'; import { useMembersAvatars } from '../hooks/useMembersAvatar';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
export interface ConversationListItemProps extends ConversationType {} export interface ConversationListItemProps extends ReduxConversationType {}
type PropsHousekeeping = { type PropsHousekeeping = {
style?: Object; style?: Object;

@ -1,9 +1,8 @@
import React, { useState } from 'react'; import React from 'react';
import { ActionsPanel, SectionType } from './session/ActionsPanel'; import { ActionsPanel, SectionType } from './session/ActionsPanel';
import { LeftPaneMessageSection } from './session/LeftPaneMessageSection'; import { LeftPaneMessageSection } from './session/LeftPaneMessageSection';
import { openConversationExternal } from '../state/ducks/conversations';
import { LeftPaneContactSection } from './session/LeftPaneContactSection'; import { LeftPaneContactSection } from './session/LeftPaneContactSection';
import { LeftPaneSettingSection } from './session/LeftPaneSettingSection'; import { LeftPaneSettingSection } from './session/LeftPaneSettingSection';
import { SessionTheme } from '../state/ducks/SessionTheme'; import { SessionTheme } from '../state/ducks/SessionTheme';
@ -13,6 +12,7 @@ import { useDispatch, useSelector } from 'react-redux';
import { getLeftPaneLists } from '../state/selectors/conversations'; import { getLeftPaneLists } from '../state/selectors/conversations';
import { getQuery, getSearchResults, isSearching } from '../state/selectors/search'; import { getQuery, getSearchResults, isSearching } from '../state/selectors/search';
import { clearSearch, search, updateSearchTerm } from '../state/ducks/search'; import { clearSearch, search, updateSearchTerm } from '../state/ducks/search';
import { useTheme } from 'styled-components';
import { getTheme } from '../state/selectors/theme'; import { getTheme } from '../state/selectors/theme';
// from https://github.com/bvaughn/react-virtualized/blob/fb3484ed5dcc41bffae8eab029126c0fb8f7abc0/source/List/types.js#L5 // from https://github.com/bvaughn/react-virtualized/blob/fb3484ed5dcc41bffae8eab029126c0fb8f7abc0/source/List/types.js#L5
@ -30,57 +30,29 @@ type Props = {
}; };
const InnerLeftPaneMessageSection = (props: { isExpired: boolean }) => { const InnerLeftPaneMessageSection = (props: { isExpired: boolean }) => {
const dispatch = useDispatch();
const showSearch = useSelector(isSearching); const showSearch = useSelector(isSearching);
const searchTerm = useSelector(getQuery); const searchTerm = useSelector(getQuery);
const searchResults = showSearch ? useSelector(getSearchResults) : undefined; const searchResults = showSearch ? useSelector(getSearchResults) : undefined;
const lists = showSearch ? undefined : useSelector(getLeftPaneLists); const lists = showSearch ? undefined : useSelector(getLeftPaneLists);
const theme = useSelector(getTheme);
// tslint:disable: use-simple-attributes // tslint:disable: use-simple-attributes
return ( return (
<> <>
{props.isExpired && <SessionExpiredWarning />} {props.isExpired && <SessionExpiredWarning />}
<LeftPaneMessageSection <LeftPaneMessageSection
theme={theme}
openConversationExternal={(id, messageId) =>
dispatch(openConversationExternal(id, messageId))
}
conversations={lists?.conversations || []} conversations={lists?.conversations || []}
contacts={lists?.contacts || []} contacts={lists?.contacts || []}
searchResults={searchResults} searchResults={searchResults}
searchTerm={searchTerm} searchTerm={searchTerm}
updateSearchTerm={query => dispatch(updateSearchTerm(query))}
search={(query, options) => dispatch(search(query, options))}
clearSearch={() => dispatch(clearSearch())}
/> />
</> </>
); );
}; };
const InnerLeftPaneContactSection = () => { const InnerLeftPaneContactSection = () => {
const dispatch = useDispatch(); return <LeftPaneContactSection />;
const theme = useSelector(getTheme);
const showSearch = useSelector(isSearching);
const lists = showSearch ? undefined : useSelector(getLeftPaneLists);
const directContacts = lists?.contacts || [];
return (
<>
<LeftPaneContactSection
openConversationExternal={(id, messageId) =>
dispatch(openConversationExternal(id, messageId))
}
directContacts={directContacts}
theme={theme}
/>
</>
);
}; };
const LeftPaneSection = (props: { isExpired: boolean }) => { const LeftPaneSection = (props: { isExpired: boolean }) => {
@ -96,23 +68,21 @@ const LeftPaneSection = (props: { isExpired: boolean }) => {
if (focusedSection === SectionType.Settings) { if (focusedSection === SectionType.Settings) {
return <LeftPaneSettingSection />; return <LeftPaneSettingSection />;
} }
return <></>; return null;
}; };
export const LeftPane = (props: Props) => { export const LeftPane = (props: Props) => {
const theme = useSelector(getTheme); const theme = useSelector(getTheme);
return ( return (
<> <SessionTheme theme={theme}>
<SessionTheme theme={theme}> <div className="module-left-pane-session">
<div className="module-left-pane-session"> <ActionsPanel />
<ActionsPanel />
<div className="module-left-pane"> <div className="module-left-pane">
<LeftPaneSection isExpired={props.isExpired} /> <LeftPaneSection isExpired={props.isExpired} />
</div>
</div> </div>
</SessionTheme> </div>
</> </SessionTheme>
); );
}; };

@ -14,70 +14,58 @@ export type SearchResultsProps = {
searchTerm: string; searchTerm: string;
}; };
type PropsHousekeeping = { const ContactsItem = (props: { header: string; items: Array<ConversationListItemProps> }) => {
openConversationExternal: (id: string, messageId?: string) => void; return (
<div className="module-search-results__contacts">
<div className="module-search-results__contacts-header">{props.header}</div>
{props.items.map(contact => (
<MemoConversationListItemWithDetails {...contact} />
))}
</div>
);
}; };
type Props = SearchResultsProps & PropsHousekeeping; export const SearchResults = (props: SearchResultsProps) => {
const { conversations, contacts, hideMessagesHeader, messages, searchTerm } = props;
export class SearchResults extends React.Component<Props> { const haveConversations = conversations && conversations.length;
public render() { const haveContacts = contacts && contacts.length;
const { const haveMessages = messages && messages.length;
conversations, const noResults = !haveConversations && !haveContacts && !haveMessages;
contacts,
hideMessagesHeader,
messages,
openConversationExternal,
searchTerm,
} = this.props;
const haveConversations = conversations && conversations.length; return (
const haveContacts = contacts && contacts.length; <div className="module-search-results">
const haveMessages = messages && messages.length; {noResults ? (
const noResults = !haveConversations && !haveContacts && !haveMessages; <div className="module-search-results__no-results">
{window.i18n('noSearchResults', [searchTerm])}
return ( </div>
<div className="module-search-results"> ) : null}
{noResults ? ( {haveConversations ? (
<div className="module-search-results__no-results"> <div className="module-search-results__conversations">
{window.i18n('noSearchResults', [searchTerm])} <div className="module-search-results__conversations-header">
</div> {window.i18n('conversationsHeader')}
) : null}
{haveConversations ? (
<div className="module-search-results__conversations">
<div className="module-search-results__conversations-header">
{window.i18n('conversationsHeader')}
</div>
{conversations.map(conversation => (
<MemoConversationListItemWithDetails {...conversation} />
))}
</div> </div>
) : null} {conversations.map(conversation => (
{haveContacts ? this.renderContacts(window.i18n('contactsHeader'), contacts) : null} <MemoConversationListItemWithDetails {...conversation} />
))}
</div>
) : null}
{haveContacts ? (
<ContactsItem header={window.i18n('contactsHeader')} items={contacts} />
) : null}
{haveMessages ? ( {haveMessages ? (
<div className="module-search-results__messages"> <div className="module-search-results__messages">
{hideMessagesHeader ? null : ( {hideMessagesHeader ? null : (
<div className="module-search-results__messages-header"> <div className="module-search-results__messages-header">
{window.i18n('messagesHeader')} {window.i18n('messagesHeader')}
</div> </div>
)} )}
{messages.map(message => ( {messages.map(message => (
<MessageSearchResult key={message.id} {...message} /> <MessageSearchResult key={message.id} {...message} />
))} ))}
</div> </div>
) : null} ) : null}
</div> </div>
); );
} };
private renderContacts(header: string, items: Array<ConversationListItemProps>) {
return (
<div className="module-search-results__contacts">
<div className="module-search-results__contacts-header">{header}</div>
{items.map(contact => (
<MemoConversationListItemWithDetails {...contact} />
))}
</div>
);
}
}

@ -3,70 +3,58 @@ import React from 'react';
import { MemoConversationListItemWithDetails } from '../ConversationListItem'; import { MemoConversationListItemWithDetails } from '../ConversationListItem';
import { RowRendererParamsType } from '../LeftPane'; import { RowRendererParamsType } from '../LeftPane';
import { AutoSizer, List } from 'react-virtualized'; import { AutoSizer, List } from 'react-virtualized';
import { ConversationType as ReduxConversationType } from '../../state/ducks/conversations';
import { DefaultTheme } from 'styled-components';
import { LeftPaneSectionHeader } from './LeftPaneSectionHeader'; import { LeftPaneSectionHeader } from './LeftPaneSectionHeader';
import autoBind from 'auto-bind'; import { useSelector } from 'react-redux';
import { getDirectContacts, getLeftPaneLists } from '../../state/selectors/conversations';
import { isSearching } from '../../state/selectors/search';
export interface Props { const renderRow = ({ index, key, style }: RowRendererParamsType): JSX.Element | undefined => {
directContacts: Array<ReduxConversationType>; const showSearch = useSelector(isSearching);
theme: DefaultTheme;
openConversationExternal: (id: string, messageId?: string) => void;
}
export class LeftPaneContactSection extends React.Component<Props> { const lists = showSearch ? undefined : useSelector(getLeftPaneLists);
public constructor(props: Props) {
super(props);
autoBind(this);
}
public renderHeader(): JSX.Element | undefined {
return <LeftPaneSectionHeader label={window.i18n('contactsHeader')} theme={this.props.theme} />;
}
public render(): JSX.Element { const directContacts = lists?.contacts || [];
return ( const item = directContacts[index];
<div className="left-pane-contact-section">
{this.renderHeader()}
{this.renderContacts()}
</div>
);
}
public renderRow = ({ index, key, style }: RowRendererParamsType): JSX.Element | undefined => { return <MemoConversationListItemWithDetails style={style} key={key} {...item} />;
const { directContacts } = this.props; };
const item = directContacts[index];
return <MemoConversationListItemWithDetails style={style} {...item} />; const ContactListItemSection = () => {
}; const directContacts = useSelector(getDirectContacts);
private renderContacts() { if (!directContacts) {
return <div className="left-pane-contact-content">{this.renderList()}</div>; return null;
} }
const length = Number(directContacts.length);
private renderList() {
const { directContacts } = this.props; return (
const length = Number(directContacts.length); <div className="module-left-pane__list" key={0}>
<AutoSizer>
const list = ( {({ height, width }) => (
<div className="module-left-pane__list" key={0}> <List
<AutoSizer> className="module-left-pane__virtual-list"
{({ height, width }) => ( height={height}
<List directContacts={directContacts} // needed for change in props refresh
className="module-left-pane__virtual-list" rowCount={length}
height={height} rowHeight={64}
directContacts={directContacts} // needed for change in props refresh rowRenderer={renderRow}
rowCount={length} width={width}
rowHeight={64} autoHeight={false}
rowRenderer={this.renderRow} />
width={width} )}
autoHeight={false} </AutoSizer>
/> </div>
)} );
</AutoSizer> };
export const LeftPaneContactSection = () => {
debugger;
return (
<div className="left-pane-contact-section">
<LeftPaneSectionHeader label={window.i18n('contactsHeader')} />
<div className="left-pane-contact-content">
<ContactListItemSection />
</div> </div>
); </div>
);
return [list]; };
}
}

@ -7,7 +7,7 @@ import {
ConversationListItemProps, ConversationListItemProps,
MemoConversationListItemWithDetails, MemoConversationListItemWithDetails,
} from '../ConversationListItem'; } from '../ConversationListItem';
import { ConversationType as ReduxConversationType } from '../../state/ducks/conversations'; import { openConversationExternal, ReduxConversationType } from '../../state/ducks/conversations';
import { SearchResults, SearchResultsProps } from '../SearchResults'; import { SearchResults, SearchResultsProps } from '../SearchResults';
import { SessionSearchInput } from './SessionSearchInput'; import { SessionSearchInput } from './SessionSearchInput';
import { debounce } from 'lodash'; import { debounce } from 'lodash';
@ -29,8 +29,7 @@ import { joinOpenGroupV2WithUIEvents } from '../../opengroup/opengroupV2/JoinOpe
import autoBind from 'auto-bind'; import autoBind from 'auto-bind';
import { onsNameRegex } from '../../session/snode_api/SNodeAPI'; import { onsNameRegex } from '../../session/snode_api/SNodeAPI';
import { SNodeAPI } from '../../session/snode_api'; import { SNodeAPI } from '../../session/snode_api';
import { clearSearch, search, updateSearchTerm } from '../../state/ducks/search';
import { createClosedGroup } from '../../receiver/closedGroups';
export interface Props { export interface Props {
searchTerm: string; searchTerm: string;
@ -38,12 +37,6 @@ export interface Props {
contacts: Array<ReduxConversationType>; contacts: Array<ReduxConversationType>;
conversations?: Array<ConversationListItemProps>; conversations?: Array<ConversationListItemProps>;
searchResults?: SearchResultsProps; searchResults?: SearchResultsProps;
updateSearchTerm: (searchTerm: string) => void;
search: (query: string, options: SearchOptions) => void;
openConversationExternal: (id: string, messageId?: string) => void;
clearSearch: () => void;
theme: DefaultTheme;
} }
export enum SessionComposeToType { export enum SessionComposeToType {
@ -81,7 +74,7 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
} }
public renderRow = ({ index, key, style }: RowRendererParamsType): JSX.Element => { public renderRow = ({ index, key, style }: RowRendererParamsType): JSX.Element => {
const { conversations, openConversationExternal } = this.props; const { conversations } = this.props;
if (!conversations) { if (!conversations) {
throw new Error('renderRow: Tried to render without conversations'); throw new Error('renderRow: Tried to render without conversations');
@ -89,21 +82,15 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
const conversation = conversations[index]; const conversation = conversations[index];
return <MemoConversationListItemWithDetails style={style} {...conversation} />; return <MemoConversationListItemWithDetails key={key} style={style} {...conversation} />;
}; };
public renderList(): JSX.Element | Array<JSX.Element | null> { public renderList(): JSX.Element | Array<JSX.Element | null> {
const { conversations, openConversationExternal, searchResults } = this.props; const { conversations, searchResults } = this.props;
const contacts = searchResults?.contacts || []; const contacts = searchResults?.contacts || [];
if (searchResults) { if (searchResults) {
return ( return <SearchResults {...searchResults} contacts={contacts} />;
<SearchResults
{...searchResults}
contacts={contacts}
openConversationExternal={openConversationExternal}
/>
);
} }
if (!conversations) { if (!conversations) {
@ -147,7 +134,6 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
return ( return (
<LeftPaneSectionHeader <LeftPaneSectionHeader
label={window.i18n('messagesHeader')} label={window.i18n('messagesHeader')}
theme={this.props.theme}
buttonIcon={SessionIconType.Plus} buttonIcon={SessionIconType.Plus}
buttonClicked={this.handleNewSessionButtonClick} buttonClicked={this.handleNewSessionButtonClick}
/> />
@ -172,7 +158,6 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
searchString={this.props.searchTerm} searchString={this.props.searchTerm}
onChange={this.updateSearch} onChange={this.updateSearch}
placeholder={window.i18n('searchFor...')} placeholder={window.i18n('searchFor...')}
theme={this.props.theme}
/> />
{this.renderList()} {this.renderList()}
{this.renderBottomButtons()} {this.renderBottomButtons()}
@ -181,10 +166,8 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
} }
public updateSearch(searchTerm: string) { public updateSearch(searchTerm: string) {
const { updateSearchTerm, clearSearch } = this.props;
if (!searchTerm) { if (!searchTerm) {
clearSearch(); window.inboxStore?.dispatch(clearSearch());
return; return;
} }
@ -192,9 +175,7 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
// reset our pubKeyPasted, we can either have a pasted sessionID or a sessionID got from a search // reset our pubKeyPasted, we can either have a pasted sessionID or a sessionID got from a search
this.setState({ valuePasted: '' }); this.setState({ valuePasted: '' });
if (updateSearchTerm) { window.inboxStore?.dispatch(updateSearchTerm(searchTerm));
updateSearchTerm(searchTerm);
}
if (searchTerm.length < 2) { if (searchTerm.length < 2) {
return; return;
@ -209,19 +190,17 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
} }
public clearSearch() { public clearSearch() {
this.props.clearSearch(); window.inboxStore?.dispatch(clearSearch());
} }
public search() { public search() {
const { search } = this.props;
const { searchTerm } = this.props; const { searchTerm } = this.props;
window.inboxStore?.dispatch(
if (search) {
search(searchTerm, { search(searchTerm, {
noteToSelf: window.i18n('noteToSelf').toLowerCase(), noteToSelf: window.i18n('noteToSelf').toLowerCase(),
ourNumber: UserUtils.getOurPubKeyStrFromCache(), ourNumber: UserUtils.getOurPubKeyStrFromCache(),
}); })
} );
} }
private renderClosableOverlay(overlay: SessionComposeToType) { private renderClosableOverlay(overlay: SessionComposeToType) {
@ -239,7 +218,6 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
searchTerm={searchTerm} searchTerm={searchTerm}
updateSearch={this.updateSearch} updateSearch={this.updateSearch}
showSpinner={loading} showSpinner={loading}
theme={this.props.theme}
/> />
); );
@ -257,7 +235,6 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
searchTerm={searchTerm} searchTerm={searchTerm}
updateSearch={this.updateSearch} updateSearch={this.updateSearch}
showSpinner={loading} showSpinner={loading}
theme={this.props.theme}
/> />
); );
@ -273,7 +250,6 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
searchResults={searchResults} searchResults={searchResults}
showSpinner={loading} showSpinner={loading}
updateSearch={this.updateSearch} updateSearch={this.updateSearch}
theme={this.props.theme}
/> />
); );
@ -332,8 +308,6 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
} }
private async handleMessageButtonClick() { private async handleMessageButtonClick() {
const { openConversationExternal } = this.props;
if (!this.state.valuePasted && !this.props.searchTerm) { if (!this.state.valuePasted && !this.props.searchTerm) {
ToastUtils.pushToastError('invalidPubKey', window.i18n('invalidNumberError')); // or ons name ToastUtils.pushToastError('invalidPubKey', window.i18n('invalidNumberError')); // or ons name
return; return;
@ -349,7 +323,7 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
pubkeyorOns, pubkeyorOns,
ConversationTypeEnum.PRIVATE ConversationTypeEnum.PRIVATE
); );
openConversationExternal(pubkeyorOns); window.inboxStore?.dispatch(openConversationExternal(pubkeyorOns));
this.handleToggleOverlay(undefined); this.handleToggleOverlay(undefined);
} else { } else {
// this might be an ONS, validate the regex first // this might be an ONS, validate the regex first
@ -369,7 +343,7 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
resolvedSessionID, resolvedSessionID,
ConversationTypeEnum.PRIVATE ConversationTypeEnum.PRIVATE
); );
openConversationExternal(resolvedSessionID); window.inboxStore?.dispatch(openConversationExternal(resolvedSessionID));
this.handleToggleOverlay(undefined); this.handleToggleOverlay(undefined);
} catch (e) { } catch (e) {
window?.log?.warn('failed to resolve ons name', pubkeyorOns, e); window?.log?.warn('failed to resolve ons name', pubkeyorOns, e);

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { SessionIcon, SessionIconSize, SessionIconType } from './icon'; import { SessionIcon, SessionIconSize, SessionIconType } from './icon';
import { DefaultTheme } from 'styled-components'; import { DefaultTheme, useTheme } from 'styled-components';
import { SessionButton } from './SessionButton'; import { SessionButton } from './SessionButton';
const Tab = ({ const Tab = ({
@ -36,22 +36,23 @@ type Props = {
label?: string; label?: string;
buttonIcon?: SessionIconType; buttonIcon?: SessionIconType;
buttonClicked?: any; buttonClicked?: any;
theme: DefaultTheme;
}; };
export const LeftPaneSectionHeader = (props: Props) => { export const LeftPaneSectionHeader = (props: Props) => {
const { label, buttonIcon, buttonClicked } = props; const { label, buttonIcon, buttonClicked } = props;
const theme = useTheme();
return ( return (
<div className="module-left-pane__header"> <div className="module-left-pane__header">
{label && <Tab label={label} type={0} isSelected={true} key={label} />} {label && <Tab label={label} type={0} isSelected={true} key={label} />}
{buttonIcon && ( {buttonIcon && (
<SessionButton onClick={buttonClicked} key="compose" theme={props.theme}> <SessionButton onClick={buttonClicked} key="compose" theme={theme}>
<SessionIcon <SessionIcon
iconType={buttonIcon} iconType={buttonIcon}
iconSize={SessionIconSize.Small} iconSize={SessionIconSize.Small}
iconColor="white" iconColor="white"
theme={props.theme} theme={theme}
/> />
</SessionButton> </SessionButton>
)} )}

@ -154,7 +154,7 @@ export const LeftPaneSettingSection = () => {
const theme = useSelector(getTheme); const theme = useSelector(getTheme);
return ( return (
<div className="left-pane-setting-section"> <div className="left-pane-setting-section">
<LeftPaneSectionHeader label={window.i18n('settingsHeader')} theme={theme} /> <LeftPaneSectionHeader label={window.i18n('settingsHeader')} />
<div className="left-pane-setting-content"> <div className="left-pane-setting-content">
<LeftPaneSettingsCategories /> <LeftPaneSettingsCategories />
<LeftPaneBottomButtons /> <LeftPaneBottomButtons />

@ -4,7 +4,7 @@ import { SessionIconButton, SessionIconSize, SessionIconType } from './icon';
import { SessionIdEditable } from './SessionIdEditable'; import { SessionIdEditable } from './SessionIdEditable';
import { UserSearchDropdown } from './UserSearchDropdown'; import { UserSearchDropdown } from './UserSearchDropdown';
import { ContactType, SessionMemberListItem } from './SessionMemberListItem'; import { ContactType, SessionMemberListItem } from './SessionMemberListItem';
import { ConversationType } from '../../state/ducks/conversations'; import { ReduxConversationType } from '../../state/ducks/conversations';
import { SessionButton, SessionButtonColor, SessionButtonType } from './SessionButton'; import { SessionButton, SessionButtonColor, SessionButtonType } from './SessionButton';
import { SessionSpinner } from './SessionSpinner'; import { SessionSpinner } from './SessionSpinner';
import { DefaultTheme } from 'styled-components'; import { DefaultTheme } from 'styled-components';
@ -23,12 +23,11 @@ interface Props {
onChangeSessionID: any; onChangeSessionID: any;
onCloseClick: any; onCloseClick: any;
onButtonClick: any; onButtonClick: any;
contacts?: Array<ConversationType>; contacts?: Array<ReduxConversationType>;
searchTerm?: string; searchTerm?: string;
searchResults?: any; searchResults?: any;
updateSearch?: any; updateSearch?: any;
showSpinner?: boolean; showSpinner?: boolean;
theme: DefaultTheme;
} }
interface State { interface State {
@ -159,7 +158,6 @@ export class SessionClosableOverlay extends React.Component<Props, State> {
iconSize={SessionIconSize.Small} iconSize={SessionIconSize.Small}
iconType={SessionIconType.Exit} iconType={SessionIconType.Exit}
onClick={onCloseClick} onClick={onCloseClick}
theme={this.props.theme}
/> />
</div> </div>
@ -226,7 +224,6 @@ export class SessionClosableOverlay extends React.Component<Props, State> {
updateSearch={updateSearch} updateSearch={updateSearch}
placeholder={window.i18n('searchFor...')} placeholder={window.i18n('searchFor...')}
searchResults={searchResults} searchResults={searchResults}
theme={this.props.theme}
/> />
)} )}

@ -8,7 +8,6 @@ interface Props {
onChange: any; onChange: any;
handleNavigation?: any; handleNavigation?: any;
placeholder: string; placeholder: string;
theme: DefaultTheme;
} }
export class SessionSearchInput extends React.Component<Props> { export class SessionSearchInput extends React.Component<Props> {
@ -32,11 +31,7 @@ export class SessionSearchInput extends React.Component<Props> {
}); });
}} }}
> >
<SessionIconButton <SessionIconButton iconSize={SessionIconSize.Medium} iconType={SessionIconType.Search} />
iconSize={SessionIconSize.Medium}
iconType={SessionIconType.Search}
theme={this.props.theme}
/>
<input <input
value={searchString} value={searchString}
onChange={e => this.props.onChange(e.target.value)} onChange={e => this.props.onChange(e.target.value)}

@ -11,7 +11,6 @@ export interface Props {
placeholder: string; placeholder: string;
searchResults?: SearchResultsProps; searchResults?: SearchResultsProps;
updateSearch: (searchTerm: string) => void; updateSearch: (searchTerm: string) => void;
theme: DefaultTheme;
} }
interface State { interface State {
@ -68,7 +67,6 @@ export class UserSearchDropdown extends React.Component<Props, State> {
onChange={this.updateSearchBound} onChange={this.updateSearchBound}
placeholder={placeholder} placeholder={placeholder}
handleNavigation={this.handleNavigation} handleNavigation={this.handleNavigation}
theme={this.props.theme}
/> />
{searchResults && ( {searchResults && (
<UserSearchResults <UserSearchResults

@ -28,7 +28,7 @@ import { Mention, MentionsInput } from 'react-mentions';
import { CaptionEditor } from '../../CaptionEditor'; import { CaptionEditor } from '../../CaptionEditor';
import { DefaultTheme } from 'styled-components'; import { DefaultTheme } from 'styled-components';
import { getConversationController } from '../../../session/conversations'; import { getConversationController } from '../../../session/conversations';
import { ConversationType } from '../../../state/ducks/conversations'; import { ReduxConversationType } from '../../../state/ducks/conversations';
import { SessionMemberListItem } from '../SessionMemberListItem'; import { SessionMemberListItem } from '../SessionMemberListItem';
import autoBind from 'auto-bind'; import autoBind from 'auto-bind';
import { SectionType } from '../ActionsPanel'; import { SectionType } from '../ActionsPanel';
@ -72,7 +72,7 @@ interface Props {
isKickedFromGroup: boolean; isKickedFromGroup: boolean;
left: boolean; left: boolean;
selectedConversationKey: string; selectedConversationKey: string;
selectedConversation: ConversationType | undefined; selectedConversation: ReduxConversationType | undefined;
isPublic: boolean; isPublic: boolean;
quotedMessageProps?: ReplyingToMessageProps; quotedMessageProps?: ReplyingToMessageProps;

@ -23,7 +23,7 @@ import { ToastUtils, UserUtils } from '../../../session/utils';
import * as MIME from '../../../types/MIME'; import * as MIME from '../../../types/MIME';
import { SessionFileDropzone } from './SessionFileDropzone'; import { SessionFileDropzone } from './SessionFileDropzone';
import { import {
ConversationType, ReduxConversationType,
PropsForMessage, PropsForMessage,
SortedMessageModelProps, SortedMessageModelProps,
} from '../../../state/ducks/conversations'; } from '../../../state/ducks/conversations';
@ -40,6 +40,7 @@ import { updateMentionsMembers } from '../../../state/ducks/mentionsInput';
import { sendDataExtractionNotification } from '../../../session/messages/outgoing/controlMessage/DataExtractionNotificationMessage'; import { sendDataExtractionNotification } from '../../../session/messages/outgoing/controlMessage/DataExtractionNotificationMessage';
import { SessionButtonColor } from '../SessionButton'; import { SessionButtonColor } from '../SessionButton';
import { updateConfirmModal } from '../../../state/ducks/modalDialog';
interface State { interface State {
unreadCount: number; unreadCount: number;
selectedMessages: Array<string>; selectedMessages: Array<string>;
@ -70,10 +71,9 @@ export interface LightBoxOptions {
interface Props { interface Props {
ourNumber: string; ourNumber: string;
selectedConversationKey: string; selectedConversationKey: string;
selectedConversation?: ConversationType; selectedConversation?: ReduxConversationType;
theme: DefaultTheme; theme: DefaultTheme;
messagesProps: Array<SortedMessageModelProps>; messagesProps: Array<SortedMessageModelProps>;
actions: any;
} }
export class SessionConversation extends React.Component<Props, State> { export class SessionConversation extends React.Component<Props, State> {
@ -199,7 +199,7 @@ export class SessionConversation extends React.Component<Props, State> {
} = this.state; } = this.state;
const selectionMode = !!selectedMessages.length; const selectionMode = !!selectedMessages.length;
const { selectedConversation, selectedConversationKey, messagesProps, actions } = this.props; const { selectedConversation, selectedConversationKey, messagesProps } = this.props;
if (!selectedConversation || !messagesProps) { if (!selectedConversation || !messagesProps) {
// return an empty message view // return an empty message view
@ -227,9 +227,6 @@ export class SessionConversation extends React.Component<Props, State> {
}; };
const showMessageDetails = !!messageDetailShowProps; const showMessageDetails = !!messageDetailShowProps;
const isPublic = selectedConversation.isPublic || false;
const isPrivate = selectedConversation.type === ConversationTypeEnum.PRIVATE;
return ( return (
<SessionTheme theme={this.props.theme}> <SessionTheme theme={this.props.theme}>
<div className="conversation-header">{this.renderHeader()}</div> <div className="conversation-header">{this.renderHeader()}</div>
@ -257,8 +254,8 @@ export class SessionConversation extends React.Component<Props, State> {
isBlocked={selectedConversation.isBlocked} isBlocked={selectedConversation.isBlocked}
left={selectedConversation.left} left={selectedConversation.left}
isKickedFromGroup={selectedConversation.isKickedFromGroup} isKickedFromGroup={selectedConversation.isKickedFromGroup}
isPrivate={isPrivate} isPrivate={selectedConversation.isPrivate}
isPublic={isPublic} isPublic={selectedConversation.isPublic}
selectedConversationKey={selectedConversationKey} selectedConversationKey={selectedConversationKey}
selectedConversation={selectedConversation} selectedConversation={selectedConversation}
sendMessage={sendMessageFn} sendMessage={sendMessageFn}
@ -307,10 +304,12 @@ export class SessionConversation extends React.Component<Props, State> {
Constants.CONVERSATION.DEFAULT_MESSAGE_FETCH_COUNT, Constants.CONVERSATION.DEFAULT_MESSAGE_FETCH_COUNT,
unreadCount unreadCount
); );
this.props.actions.fetchMessagesForConversation({ window.inboxStore?.dispatch(
conversationKey: selectedConversationKey, fetchMessagesForConversation({
count: messagesToFetch, conversationKey: selectedConversationKey,
}); count: messagesToFetch,
})
);
} }
public getHeaderProps(): ConversationHeaderNonReduxProps { public getHeaderProps(): ConversationHeaderNonReduxProps {
@ -337,6 +336,9 @@ export class SessionConversation extends React.Component<Props, State> {
const { selectedConversation, selectedConversationKey, ourNumber, messagesProps } = this.props; const { selectedConversation, selectedConversationKey, ourNumber, messagesProps } = this.props;
const { quotedMessageTimestamp, selectedMessages } = this.state; const { quotedMessageTimestamp, selectedMessages } = this.state;
if (!selectedConversation) {
throw new Error();
}
return { return {
selectedMessages, selectedMessages,
ourPrimary: ourNumber, ourPrimary: ourNumber,
@ -344,7 +346,7 @@ export class SessionConversation extends React.Component<Props, State> {
messagesProps, messagesProps,
resetSelection: this.resetSelection, resetSelection: this.resetSelection,
quotedMessageTimestamp, quotedMessageTimestamp,
conversation: selectedConversation as ConversationType, conversation: selectedConversation,
selectMessage: this.selectMessage, selectMessage: this.selectMessage,
deleteMessage: this.deleteMessage, deleteMessage: this.deleteMessage,
replyToMessage: this.replyToMessage, replyToMessage: this.replyToMessage,
@ -490,18 +492,19 @@ export class SessionConversation extends React.Component<Props, State> {
if (askUserForConfirmation) { if (askUserForConfirmation) {
const onClickClose = () => { const onClickClose = () => {
this.props.actions.updateConfirmModal(null); window.inboxStore?.dispatch(updateConfirmModal(null));
}; };
this.props.actions.updateConfirmModal({ window.inboxStore?.dispatch(
title, updateConfirmModal({
message: warningMessage, title,
okText, message: warningMessage,
okTheme: SessionButtonColor.Danger, okText,
onClickOk: doDelete, okTheme: SessionButtonColor.Danger,
onClickClose, onClickOk: doDelete,
closeAfterClick: true, onClickClose,
}); })
);
} else { } else {
void doDelete(); void doDelete();
} }
@ -988,3 +991,6 @@ export class SessionConversation extends React.Component<Props, State> {
window.inboxStore?.dispatch(updateMentionsMembers(allMembers)); window.inboxStore?.dispatch(updateMentionsMembers(allMembers));
} }
} }
function fetchMessagesForConversation(arg0: { conversationKey: string; count: number }): any {
throw new Error('Function not implemented.');
}

@ -10,11 +10,7 @@ import { contextMenu } from 'react-contexify';
import { AttachmentType } from '../../../types/Attachment'; import { AttachmentType } from '../../../types/Attachment';
import { GroupNotification } from '../../conversation/GroupNotification'; import { GroupNotification } from '../../conversation/GroupNotification';
import { GroupInvitation } from '../../conversation/GroupInvitation'; import { GroupInvitation } from '../../conversation/GroupInvitation';
import { import { ReduxConversationType, SortedMessageModelProps } from '../../../state/ducks/conversations';
ConversationType,
MessageModelProps,
SortedMessageModelProps,
} from '../../../state/ducks/conversations';
import { SessionLastSeenIndicator } from './SessionLastSeenIndicator'; import { SessionLastSeenIndicator } from './SessionLastSeenIndicator';
import { ToastUtils } from '../../../session/utils'; import { ToastUtils } from '../../../session/utils';
import { TypingBubble } from '../../conversation/TypingBubble'; import { TypingBubble } from '../../conversation/TypingBubble';
@ -36,7 +32,7 @@ interface Props {
selectedMessages: Array<string>; selectedMessages: Array<string>;
conversationKey: string; conversationKey: string;
messagesProps: Array<SortedMessageModelProps>; messagesProps: Array<SortedMessageModelProps>;
conversation: ConversationType; conversation: ReduxConversationType;
ourPrimary: string; ourPrimary: string;
messageContainerRef: React.RefObject<any>; messageContainerRef: React.RefObject<any>;
selectMessage: (messageId: string) => void; selectMessage: (messageId: string) => void;
@ -129,7 +125,7 @@ export class SessionMessagesList extends React.Component<Props, State> {
} }
public render() { public render() {
const { conversationKey, conversation, messagesProps } = this.props; const { conversationKey, conversation } = this.props;
const { showScrollButton } = this.state; const { showScrollButton } = this.state;
let displayedName = null; let displayedName = null;

@ -11,7 +11,7 @@ import { HexKeyPair } from '../receiver/keypairs';
import { getSodium } from '../session/crypto'; import { getSodium } from '../session/crypto';
import { PubKey } from '../session/types'; import { PubKey } from '../session/types';
import { fromArrayBufferToBase64, fromBase64ToArrayBuffer } from '../session/utils/String'; import { fromArrayBufferToBase64, fromBase64ToArrayBuffer } from '../session/utils/String';
import { ConversationType } from '../state/ducks/conversations'; import { ReduxConversationType } from '../state/ducks/conversations';
import { channels } from './channels'; import { channels } from './channels';
import { channelsToMake as channelstoMakeOpenGroupV2 } from './opengroups'; import { channelsToMake as channelstoMakeOpenGroupV2 } from './opengroups';
@ -511,7 +511,7 @@ export async function removeAllClosedGroupEncryptionKeyPairs(
} }
// Conversation // Conversation
export async function saveConversation(data: ConversationType): Promise<void> { export async function saveConversation(data: ReduxConversationType): Promise<void> {
const cleaned = _.omit(data, 'isOnline'); const cleaned = _.omit(data, 'isOnline');
await channels.saveConversation(cleaned); await channels.saveConversation(cleaned);
} }
@ -524,7 +524,7 @@ export async function getConversationById(id: string): Promise<ConversationModel
return undefined; return undefined;
} }
export async function updateConversation(data: ConversationType): Promise<void> { export async function updateConversation(data: ReduxConversationType): Promise<void> {
await channels.updateConversation(data); await channels.updateConversation(data);
} }

@ -2,9 +2,9 @@ import _ from 'lodash';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { getConversationController } from '../session/conversations'; import { getConversationController } from '../session/conversations';
import { UserUtils } from '../session/utils'; import { UserUtils } from '../session/utils';
import { ConversationType } from '../state/ducks/conversations'; import { ReduxConversationType } from '../state/ducks/conversations';
export function useMembersAvatars(conversation: ConversationType | undefined) { export function useMembersAvatars(conversation: ReduxConversationType | undefined) {
const [membersAvatars, setMembersAvatars] = useState< const [membersAvatars, setMembersAvatars] = useState<
| Array<{ | Array<{
avatarPath: string | undefined; avatarPath: string | undefined;

@ -24,9 +24,9 @@ import {
import { fromArrayBufferToBase64, fromBase64ToArrayBuffer } from '../session/utils/String'; import { fromArrayBufferToBase64, fromBase64ToArrayBuffer } from '../session/utils/String';
import { import {
actions as conversationActions, actions as conversationActions,
ConversationType as ReduxConversationType,
LastMessageStatusType, LastMessageStatusType,
MessageModelProps, MessageModelProps,
ReduxConversationType,
} from '../state/ducks/conversations'; } from '../state/ducks/conversations';
import { ExpirationTimerUpdateMessage } from '../session/messages/outgoing/controlMessage/ExpirationTimerUpdateMessage'; import { ExpirationTimerUpdateMessage } from '../session/messages/outgoing/controlMessage/ExpirationTimerUpdateMessage';
import { TypingMessage } from '../session/messages/outgoing/controlMessage/TypingMessage'; import { TypingMessage } from '../session/messages/outgoing/controlMessage/TypingMessage';

@ -168,7 +168,7 @@ export type LastMessageType = {
text: string | null; text: string | null;
}; };
export interface ConversationType { export interface ReduxConversationType {
id: string; id: string;
name?: string; name?: string;
profileName?: string; profileName?: string;
@ -202,7 +202,7 @@ export interface ConversationType {
} }
export type ConversationLookupType = { export type ConversationLookupType = {
[key: string]: ConversationType; [key: string]: ReduxConversationType;
}; };
export type ConversationsStateType = { export type ConversationsStateType = {
@ -322,14 +322,14 @@ type ConversationAddedActionType = {
type: 'CONVERSATION_ADDED'; type: 'CONVERSATION_ADDED';
payload: { payload: {
id: string; id: string;
data: ConversationType; data: ReduxConversationType;
}; };
}; };
type ConversationChangedActionType = { type ConversationChangedActionType = {
type: 'CONVERSATION_CHANGED'; type: 'CONVERSATION_CHANGED';
payload: { payload: {
id: string; id: string;
data: ConversationType; data: ReduxConversationType;
}; };
}; };
type ConversationRemovedActionType = { type ConversationRemovedActionType = {
@ -425,7 +425,7 @@ export const actions = {
openConversationExternal, openConversationExternal,
}; };
function conversationAdded(id: string, data: ConversationType): ConversationAddedActionType { function conversationAdded(id: string, data: ReduxConversationType): ConversationAddedActionType {
return { return {
type: 'CONVERSATION_ADDED', type: 'CONVERSATION_ADDED',
payload: { payload: {
@ -434,7 +434,10 @@ function conversationAdded(id: string, data: ConversationType): ConversationAdde
}, },
}; };
} }
function conversationChanged(id: string, data: ConversationType): ConversationChangedActionType { function conversationChanged(
id: string,
data: ReduxConversationType
): ConversationChangedActionType {
return { return {
type: 'CONVERSATION_CHANGED', type: 'CONVERSATION_CHANGED',
payload: { payload: {

@ -6,9 +6,9 @@ import { searchConversations, searchMessages } from '../../../ts/data/data';
import { makeLookup } from '../../util/makeLookup'; import { makeLookup } from '../../util/makeLookup';
import { import {
ConversationType,
MessageExpiredActionType, MessageExpiredActionType,
PropsForSearchResults, PropsForSearchResults,
ReduxConversationType,
RemoveAllConversationsActionType, RemoveAllConversationsActionType,
SelectedConversationChangedActionType, SelectedConversationChangedActionType,
} from './conversations'; } from './conversations';
@ -242,7 +242,7 @@ async function queryConversationsAndContacts(providedQuery: string, options: Sea
const { ourNumber, noteToSelf } = options; const { ourNumber, noteToSelf } = options;
const query = providedQuery.replace(/[+-.()]*/g, ''); const query = providedQuery.replace(/[+-.()]*/g, '');
const searchResults: Array<ConversationType> = await searchConversations(query); const searchResults: Array<ReduxConversationType> = await searchConversations(query);
// Split into two groups - active conversations and items just from address book // Split into two groups - active conversations and items just from address book
let conversations: Array<string> = []; let conversations: Array<string> = [];

@ -4,8 +4,7 @@ import { StateType } from '../reducer';
import { import {
ConversationLookupType, ConversationLookupType,
ConversationsStateType, ConversationsStateType,
ConversationType, ReduxConversationType,
MessageModelProps,
SortedMessageModelProps, SortedMessageModelProps,
} from '../ducks/conversations'; } from '../ducks/conversations';
@ -36,7 +35,7 @@ export const getSelectedConversationKey = createSelector(
export const getSelectedConversation = createSelector( export const getSelectedConversation = createSelector(
getConversations, getConversations,
(state: ConversationsStateType): ConversationType | undefined => { (state: ConversationsStateType): ReduxConversationType | undefined => {
return state.selectedConversation return state.selectedConversation
? state.conversationLookup[state.selectedConversation] ? state.conversationLookup[state.selectedConversation]
: undefined; : undefined;
@ -45,7 +44,7 @@ export const getSelectedConversation = createSelector(
export const getOurPrimaryConversation = createSelector( export const getOurPrimaryConversation = createSelector(
getConversations, getConversations,
(state: ConversationsStateType): ConversationType => (state: ConversationsStateType): ReduxConversationType =>
state.conversationLookup[window.storage.get('primaryDevicePubKey')] state.conversationLookup[window.storage.get('primaryDevicePubKey')]
); );
@ -54,7 +53,10 @@ export const getMessagesOfSelectedConversation = createSelector(
(state: ConversationsStateType): Array<SortedMessageModelProps> => state.messages (state: ConversationsStateType): Array<SortedMessageModelProps> => state.messages
); );
function getConversationTitle(conversation: ConversationType, testingi18n?: LocalizerType): string { function getConversationTitle(
conversation: ReduxConversationType,
testingi18n?: LocalizerType
): string {
if (conversation.name) { if (conversation.name) {
return conversation.name; return conversation.name;
} }
@ -68,7 +70,7 @@ function getConversationTitle(conversation: ConversationType, testingi18n?: Loca
const collator = new Intl.Collator(); const collator = new Intl.Collator();
export const _getConversationComparator = (testingi18n?: LocalizerType) => { export const _getConversationComparator = (testingi18n?: LocalizerType) => {
return (left: ConversationType, right: ConversationType): number => { return (left: ReduxConversationType, right: ReduxConversationType): number => {
const leftActiveAt = left.activeAt; const leftActiveAt = left.activeAt;
const rightActiveAt = right.activeAt; const rightActiveAt = right.activeAt;
if (leftActiveAt && !rightActiveAt) { if (leftActiveAt && !rightActiveAt) {
@ -91,18 +93,18 @@ export const getConversationComparator = createSelector(getIntl, _getConversatio
// export only because we use it in some of our tests // export only because we use it in some of our tests
export const _getLeftPaneLists = ( export const _getLeftPaneLists = (
lookup: ConversationLookupType, lookup: ConversationLookupType,
comparator: (left: ConversationType, right: ConversationType) => number, comparator: (left: ReduxConversationType, right: ReduxConversationType) => number,
selectedConversation?: string selectedConversation?: string
): { ): {
conversations: Array<ConversationType>; conversations: Array<ReduxConversationType>;
contacts: Array<ConversationType>; contacts: Array<ReduxConversationType>;
unreadCount: number; unreadCount: number;
} => { } => {
const values = Object.values(lookup); const values = Object.values(lookup);
const sorted = values.sort(comparator); const sorted = values.sort(comparator);
const conversations: Array<ConversationType> = []; const conversations: Array<ReduxConversationType> = [];
const directConversations: Array<ConversationType> = []; const directConversations: Array<ReduxConversationType> = [];
let index = 0; let index = 0;
@ -172,11 +174,20 @@ export const getLeftPaneLists = createSelector(
export const getMe = createSelector( export const getMe = createSelector(
[getConversationLookup, getOurNumber], [getConversationLookup, getOurNumber],
(lookup: ConversationLookupType, ourNumber: string): ConversationType => { (lookup: ConversationLookupType, ourNumber: string): ReduxConversationType => {
return lookup[ourNumber]; return lookup[ourNumber];
} }
); );
export const getDirectContacts = createSelector(
getLeftPaneLists,
(state: {
conversations: Array<ReduxConversationType>;
contacts: Array<ReduxConversationType>;
unreadCount: number;
}) => state.contacts
);
export const getUnreadMessageCount = createSelector(getLeftPaneLists, (state): number => { export const getUnreadMessageCount = createSelector(getLeftPaneLists, (state): number => {
return state.unreadCount; return state.unreadCount;
}); });

Loading…
Cancel
Save