add conversations with working search on leftpanel
This commit is contained in:
parent
3893a26251
commit
225f002648
|
@ -2387,5 +2387,8 @@
|
|||
},
|
||||
"completeSignUp": {
|
||||
"message": "Complete Sign Up"
|
||||
},
|
||||
"compose": {
|
||||
"message": "Compose"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -435,6 +435,10 @@ label {
|
|||
visibility: hidden;
|
||||
}
|
||||
|
||||
.session-button div[role='button'] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.input-with-label-container {
|
||||
height: 46.5px;
|
||||
width: 280px;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
// Messages
|
||||
.dark-theme {
|
||||
.conversation {
|
||||
background: none !important;
|
||||
}
|
||||
.module-conversation-header {
|
||||
border-bottom: none;
|
||||
background-color: $session-shade-4;
|
||||
}
|
||||
.discussion-container {
|
||||
background-image: $session-gradient-black;
|
||||
}
|
||||
|
||||
.module-message {
|
||||
&__author,
|
||||
|
@ -53,4 +53,15 @@
|
|||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.inbox {
|
||||
background-image: $session-gradient-black;
|
||||
}
|
||||
}
|
||||
.conversation {
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
.discussion-container {
|
||||
background: none !important;
|
||||
}
|
||||
|
|
|
@ -5,11 +5,21 @@
|
|||
background-color: $session-shade-11;
|
||||
}
|
||||
}
|
||||
.gutter {
|
||||
width: 380px;
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
|
||||
.inbox {
|
||||
background: linear-gradient(90deg, $session-shade-2 100%, #171717 0%);
|
||||
}
|
||||
|
||||
.module-left-pane {
|
||||
border-right: none !important;
|
||||
width: 300px;
|
||||
height: -webkit-fill-available;
|
||||
background: none !important;
|
||||
|
||||
&-session {
|
||||
display: flex;
|
||||
|
@ -20,7 +30,6 @@
|
|||
width: 80px;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
background: $session-shade-2;
|
||||
|
||||
.module-avatar,
|
||||
.session-icon-button {
|
||||
|
@ -30,8 +39,50 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 28px 7px 28px 0px;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-family: $session-font-family;
|
||||
color: $session-color-white;
|
||||
font-size: 25px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.gutter {
|
||||
width: 380px;
|
||||
padding-right: 5px;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.session-search-input {
|
||||
height: 34px;
|
||||
width: 100%;
|
||||
margin-right: 1px;
|
||||
margin-bottom: 10px;
|
||||
background: $session-shade-4;
|
||||
color: $session-color-white;
|
||||
display: inline-flex;
|
||||
|
||||
.session-icon-button {
|
||||
margin: auto 10px;
|
||||
}
|
||||
|
||||
input {
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
background: $session-shade-4;
|
||||
color: $session-color-white;
|
||||
border: none;
|
||||
flex-grow: 1;
|
||||
|
||||
&:focus {
|
||||
outline: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,27 +1,21 @@
|
|||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { AutoSizer, List } from 'react-virtualized';
|
||||
|
||||
import {
|
||||
ConversationListItem,
|
||||
PropsData as ConversationListItemPropsType,
|
||||
} from './ConversationListItem';
|
||||
import {
|
||||
PropsData as SearchResultsProps,
|
||||
SearchResults,
|
||||
} from './SearchResults';
|
||||
import { LocalizerType } from '../types/Util';
|
||||
import { LeftPaneSections, SectionType } from './session/LeftPaneSections';
|
||||
import { LeftPaneMessageSection } from './session/LeftPaneMessageSection';
|
||||
|
||||
import { LeftPaneSections, SectionType } from './LeftPaneSections';
|
||||
import { PropsData as ConversationListItemPropsType } from './ConversationListItem';
|
||||
import { PropsData as SearchResultsProps } from './SearchResults';
|
||||
import { SearchOptions } from '../types/Search';
|
||||
|
||||
export interface Props {
|
||||
interface State {
|
||||
selectedSection: SectionType;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
conversations?: Array<ConversationListItemPropsType>;
|
||||
friends?: Array<ConversationListItemPropsType>;
|
||||
archivedConversations?: Array<ConversationListItemPropsType>;
|
||||
searchResults?: SearchResultsProps;
|
||||
showArchived?: boolean;
|
||||
|
||||
i18n: LocalizerType;
|
||||
searchTerm: string;
|
||||
isSecondaryDevice: boolean;
|
||||
|
||||
// Action Creators
|
||||
startNewConversation: (
|
||||
|
@ -30,255 +24,26 @@ export interface Props {
|
|||
) => void;
|
||||
|
||||
openConversationInternal: (id: string, messageId?: string) => void;
|
||||
showArchivedConversations: () => void;
|
||||
showInbox: () => void;
|
||||
|
||||
// Render Props
|
||||
renderMainHeader: () => JSX.Element;
|
||||
updateSearchTerm: (searchTerm: string) => void;
|
||||
search: (query: string, options: SearchOptions) => void;
|
||||
clearSearch: () => void;
|
||||
}
|
||||
|
||||
// from https://github.com/bvaughn/react-virtualized/blob/fb3484ed5dcc41bffae8eab029126c0fb8f7abc0/source/List/types.js#L5
|
||||
type RowRendererParamsType = {
|
||||
index: number;
|
||||
isScrolling: boolean;
|
||||
isVisible: boolean;
|
||||
key: string;
|
||||
parent: Object;
|
||||
style: Object;
|
||||
};
|
||||
|
||||
export class LeftPane extends React.Component<Props> {
|
||||
export class LeftPane extends React.Component<Props, State> {
|
||||
public state = {
|
||||
currentTab: 'conversations',
|
||||
selectedSection: SectionType.Message,
|
||||
};
|
||||
public constructor(props: Props) {
|
||||
|
||||
public constructor(props: any) {
|
||||
super(props);
|
||||
this.handleSectionSelected = this.handleSectionSelected.bind(this);
|
||||
}
|
||||
|
||||
public getCurrentConversations():
|
||||
| Array<ConversationListItemPropsType>
|
||||
| undefined {
|
||||
const { conversations, friends } = this.props;
|
||||
const { currentTab } = this.state;
|
||||
|
||||
let conversationList =
|
||||
currentTab === 'conversations' ? conversations : friends;
|
||||
if (conversationList !== undefined) {
|
||||
conversationList = conversationList.filter(
|
||||
conversation => !conversation.isSecondary
|
||||
);
|
||||
}
|
||||
|
||||
return conversationList;
|
||||
}
|
||||
|
||||
public renderTabs(): JSX.Element {
|
||||
const { i18n } = this.props;
|
||||
const { currentTab } = this.state;
|
||||
const tabs = [
|
||||
{
|
||||
id: 'conversations',
|
||||
name: i18n('conversationsTab'),
|
||||
},
|
||||
{
|
||||
id: 'friends',
|
||||
name: i18n('friendsTab'),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="module-left-pane__tabs" key="tabs">
|
||||
{tabs.map(tab => (
|
||||
<div
|
||||
role="button"
|
||||
className={classNames('tab', tab.id === currentTab && 'selected')}
|
||||
key={tab.id}
|
||||
onClick={() => {
|
||||
this.setState({ currentTab: tab.id });
|
||||
}}
|
||||
>
|
||||
{tab.name}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
public renderRow = ({
|
||||
index,
|
||||
key,
|
||||
style,
|
||||
}: RowRendererParamsType): JSX.Element => {
|
||||
const {
|
||||
archivedConversations,
|
||||
i18n,
|
||||
openConversationInternal,
|
||||
showArchived,
|
||||
} = this.props;
|
||||
|
||||
const { currentTab } = this.state;
|
||||
|
||||
const conversations = this.getCurrentConversations();
|
||||
|
||||
if (!conversations || !archivedConversations) {
|
||||
throw new Error(
|
||||
'renderRow: Tried to render without conversations or archivedConversations'
|
||||
);
|
||||
}
|
||||
|
||||
if (!showArchived && index === conversations.length) {
|
||||
return this.renderArchivedButton({ key, style });
|
||||
}
|
||||
|
||||
const conversation = showArchived
|
||||
? archivedConversations[index]
|
||||
: conversations[index];
|
||||
|
||||
return (
|
||||
<ConversationListItem
|
||||
key={key}
|
||||
style={style}
|
||||
{...conversation}
|
||||
onClick={openConversationInternal}
|
||||
i18n={i18n}
|
||||
isFriendItem={currentTab !== 'conversations'}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
public renderArchivedButton({
|
||||
key,
|
||||
style,
|
||||
}: {
|
||||
key: string;
|
||||
style: Object;
|
||||
}): JSX.Element {
|
||||
const {
|
||||
archivedConversations,
|
||||
i18n,
|
||||
showArchivedConversations,
|
||||
} = this.props;
|
||||
|
||||
if (!archivedConversations || !archivedConversations.length) {
|
||||
throw new Error(
|
||||
'renderArchivedButton: Tried to render without archivedConversations'
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
key={key}
|
||||
className="module-left-pane__archived-button"
|
||||
style={style}
|
||||
role="button"
|
||||
onClick={showArchivedConversations}
|
||||
>
|
||||
{i18n('archivedConversations')}{' '}
|
||||
<span className="module-left-pane__archived-button__archived-count">
|
||||
{archivedConversations.length}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
public renderList(): JSX.Element | Array<JSX.Element | null> {
|
||||
const {
|
||||
archivedConversations,
|
||||
i18n,
|
||||
openConversationInternal,
|
||||
startNewConversation,
|
||||
searchResults,
|
||||
showArchived,
|
||||
} = this.props;
|
||||
|
||||
if (searchResults) {
|
||||
return (
|
||||
<SearchResults
|
||||
{...searchResults}
|
||||
openConversation={openConversationInternal}
|
||||
startNewConversation={startNewConversation}
|
||||
i18n={i18n}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const conversations = this.getCurrentConversations();
|
||||
|
||||
if (!conversations || !archivedConversations) {
|
||||
throw new Error(
|
||||
'render: must provided conversations and archivedConverstions if no search results are provided'
|
||||
);
|
||||
}
|
||||
|
||||
// That extra 1 element added to the list is the 'archived converastions' button
|
||||
const length = showArchived
|
||||
? archivedConversations.length
|
||||
: conversations.length + (archivedConversations.length ? 1 : 0);
|
||||
|
||||
const archived = showArchived ? (
|
||||
<div className="module-left-pane__archive-helper-text" key={0}>
|
||||
{i18n('archiveHelperText')}
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
// We ensure that the listKey differs between inbox and archive views, which ensures
|
||||
// that AutoSizer properly detects the new size of its slot in the flexbox. The
|
||||
// archive explainer text at the top of the archive view causes problems otherwise.
|
||||
// It also ensures that we scroll to the top when switching views.
|
||||
const listKey = showArchived ? 1 : 0;
|
||||
|
||||
// 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
|
||||
// on startup and scroll.
|
||||
const list = (
|
||||
<div className="module-left-pane__list" key={listKey}>
|
||||
<AutoSizer>
|
||||
{({ height, width }) => (
|
||||
<List
|
||||
className="module-left-pane__virtual-list"
|
||||
conversations={conversations}
|
||||
height={height}
|
||||
rowCount={length}
|
||||
rowHeight={64}
|
||||
rowRenderer={this.renderRow}
|
||||
width={width}
|
||||
autoHeight={true}
|
||||
/>
|
||||
)}
|
||||
</AutoSizer>
|
||||
</div>
|
||||
);
|
||||
|
||||
return [this.renderTabs(), archived, list];
|
||||
}
|
||||
|
||||
public renderArchivedHeader(): JSX.Element {
|
||||
const { i18n, showInbox } = this.props;
|
||||
|
||||
return (
|
||||
<div className="module-left-pane__archive-header">
|
||||
<div
|
||||
role="button"
|
||||
onClick={showInbox}
|
||||
className="module-left-pane__to-inbox-button"
|
||||
/>
|
||||
<div className="module-left-pane__archive-header-text">
|
||||
{i18n('archivedConversations')}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
public handleSectionSelected(section: SectionType) {
|
||||
console.log('section switch to:', section);
|
||||
this.setState({ selectedSection: section });
|
||||
}
|
||||
|
||||
public render(): JSX.Element {
|
||||
const { renderMainHeader, showArchived } = this.props;
|
||||
|
||||
return (
|
||||
<div className="module-left-pane-session">
|
||||
<LeftPaneSections
|
||||
|
@ -286,12 +51,38 @@ export class LeftPane extends React.Component<Props> {
|
|||
onSectionSelected={this.handleSectionSelected}
|
||||
/>
|
||||
<div className="module-left-pane">
|
||||
<div className="module-left-pane__header">
|
||||
{showArchived ? this.renderArchivedHeader() : renderMainHeader()}
|
||||
</div>
|
||||
{this.renderList()}
|
||||
{this.state.selectedSection === SectionType.Message &&
|
||||
this.renderMessageSection()}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private renderMessageSection() {
|
||||
const {
|
||||
startNewConversation,
|
||||
openConversationInternal,
|
||||
conversations,
|
||||
searchResults,
|
||||
searchTerm,
|
||||
isSecondaryDevice,
|
||||
updateSearchTerm,
|
||||
search,
|
||||
clearSearch,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<LeftPaneMessageSection
|
||||
startNewConversation={startNewConversation}
|
||||
openConversationInternal={openConversationInternal}
|
||||
conversations={conversations}
|
||||
searchResults={searchResults}
|
||||
searchTerm={searchTerm}
|
||||
isSecondaryDevice={isSecondaryDevice}
|
||||
updateSearchTerm={updateSearchTerm}
|
||||
search={search}
|
||||
clearSearch={clearSearch}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,234 @@
|
|||
import React from 'react';
|
||||
import { AutoSizer, List } from 'react-virtualized';
|
||||
|
||||
import {
|
||||
ConversationListItem,
|
||||
PropsData as ConversationListItemPropsType,
|
||||
} from '../ConversationListItem';
|
||||
import {
|
||||
PropsData as SearchResultsProps,
|
||||
SearchResults,
|
||||
} from '../SearchResults';
|
||||
import { SessionButton } from './SessionButton';
|
||||
import { SessionConversationSearch } from './SessionConversationSearch';
|
||||
import { debounce } from 'lodash';
|
||||
import { cleanSearchTerm } from '../../util/cleanSearchTerm';
|
||||
import { SearchOptions } from '../../types/Search';
|
||||
|
||||
export interface Props {
|
||||
searchTerm: string;
|
||||
isSecondaryDevice: boolean;
|
||||
|
||||
conversations?: Array<ConversationListItemPropsType>;
|
||||
|
||||
friends?: Array<ConversationListItemPropsType>;
|
||||
searchResults?: SearchResultsProps;
|
||||
|
||||
// Action Creators
|
||||
startNewConversation: (
|
||||
query: string,
|
||||
options: { regionCode: string }
|
||||
) => void;
|
||||
updateSearchTerm: (searchTerm: string) => void;
|
||||
search: (query: string, options: SearchOptions) => void;
|
||||
openConversationInternal: (id: string, messageId?: string) => void;
|
||||
clearSearch: () => void;
|
||||
}
|
||||
|
||||
// from https://github.com/bvaughn/react-virtualized/blob/fb3484ed5dcc41bffae8eab029126c0fb8f7abc0/source/List/types.js#L5
|
||||
type RowRendererParamsType = {
|
||||
index: number;
|
||||
isScrolling: boolean;
|
||||
isVisible: boolean;
|
||||
key: string;
|
||||
parent: Object;
|
||||
style: Object;
|
||||
};
|
||||
|
||||
export class LeftPaneMessageSection extends React.Component<Props, any> {
|
||||
private readonly updateSearchBound: (searchedString: string) => void;
|
||||
private readonly debouncedSearch: (searchTerm: string) => void;
|
||||
|
||||
public constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
showComposeView: false,
|
||||
};
|
||||
|
||||
this.updateSearchBound = this.updateSearch.bind(this);
|
||||
this.debouncedSearch = debounce(this.search.bind(this), 20);
|
||||
}
|
||||
|
||||
public getCurrentConversations():
|
||||
| Array<ConversationListItemPropsType>
|
||||
| undefined {
|
||||
const { conversations } = this.props;
|
||||
|
||||
let conversationList = conversations;
|
||||
if (conversationList !== undefined) {
|
||||
conversationList = conversationList.filter(
|
||||
conversation => !conversation.isSecondary
|
||||
);
|
||||
}
|
||||
|
||||
return conversationList;
|
||||
}
|
||||
|
||||
public renderRow = ({
|
||||
index,
|
||||
key,
|
||||
style,
|
||||
}: RowRendererParamsType): JSX.Element => {
|
||||
const { openConversationInternal } = this.props;
|
||||
|
||||
const conversations = this.getCurrentConversations();
|
||||
|
||||
if (!conversations) {
|
||||
throw new Error('renderRow: Tried to render without conversations');
|
||||
}
|
||||
|
||||
const conversation = conversations[index];
|
||||
|
||||
return (
|
||||
<ConversationListItem
|
||||
key={key}
|
||||
style={style}
|
||||
{...conversation}
|
||||
onClick={openConversationInternal}
|
||||
i18n={window.i18n}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
public renderList(): JSX.Element | Array<JSX.Element | null> {
|
||||
const {
|
||||
openConversationInternal,
|
||||
startNewConversation,
|
||||
searchResults,
|
||||
} = this.props;
|
||||
|
||||
if (searchResults) {
|
||||
return (
|
||||
<SearchResults
|
||||
{...searchResults}
|
||||
openConversation={openConversationInternal}
|
||||
startNewConversation={startNewConversation}
|
||||
i18n={window.i18n}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const conversations = this.getCurrentConversations();
|
||||
|
||||
if (!conversations) {
|
||||
throw new Error(
|
||||
'render: must provided conversations if no search results are provided'
|
||||
);
|
||||
}
|
||||
|
||||
// That extra 1 element added to the list is the 'archived conversations' button
|
||||
const length = conversations.length;
|
||||
|
||||
// We ensure that the listKey differs between inbox and archive views, which ensures
|
||||
// that AutoSizer properly detects the new size of its slot in the flexbox. The
|
||||
// archive explainer text at the top of the archive view causes problems otherwise.
|
||||
// It also ensures that we scroll to the top when switching views.
|
||||
const listKey = 0;
|
||||
|
||||
// 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
|
||||
// on startup and scroll.
|
||||
const list = (
|
||||
<div className="module-left-pane__list" key={listKey}>
|
||||
<AutoSizer>
|
||||
{({ height, width }) => (
|
||||
<List
|
||||
className="module-left-pane__virtual-list"
|
||||
conversations={conversations}
|
||||
height={height}
|
||||
rowCount={length}
|
||||
rowHeight={64}
|
||||
rowRenderer={this.renderRow}
|
||||
width={width}
|
||||
autoHeight={true}
|
||||
/>
|
||||
)}
|
||||
</AutoSizer>
|
||||
</div>
|
||||
);
|
||||
|
||||
return [list];
|
||||
}
|
||||
|
||||
public renderHeader(): JSX.Element {
|
||||
return (
|
||||
<div className="module-left-pane__header">
|
||||
<div className="module-left-pane__title">
|
||||
{window.i18n('messagesHeader')}
|
||||
</div>
|
||||
<SessionButton text={window.i18n('compose')} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
public render(): JSX.Element {
|
||||
return (
|
||||
<div className="module-left-pane-session">
|
||||
<div className="module-left-pane">
|
||||
{this.renderHeader()}
|
||||
<SessionConversationSearch
|
||||
searchString={this.props.searchTerm}
|
||||
onChange={this.updateSearchBound}
|
||||
/>
|
||||
{this.renderList()}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
public updateSearch(searchTerm: string) {
|
||||
const { updateSearchTerm, clearSearch } = this.props;
|
||||
|
||||
if (!searchTerm) {
|
||||
clearSearch();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (updateSearchTerm) {
|
||||
updateSearchTerm(searchTerm);
|
||||
}
|
||||
|
||||
if (searchTerm.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cleanedTerm = cleanSearchTerm(searchTerm);
|
||||
if (!cleanedTerm) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.debouncedSearch(cleanedTerm);
|
||||
}
|
||||
|
||||
public clearSearch() {
|
||||
const { clearSearch } = this.props;
|
||||
|
||||
clearSearch();
|
||||
//this.setFocus();
|
||||
}
|
||||
|
||||
public search() {
|
||||
const { search } = this.props;
|
||||
const { searchTerm, isSecondaryDevice } = this.props;
|
||||
|
||||
if (search) {
|
||||
search(searchTerm, {
|
||||
noteToSelf: window.i18n('noteToSelf').toLowerCase(),
|
||||
ourNumber: window.textsecure.storage.user.getNumber(),
|
||||
regionCode: '',
|
||||
isSecondaryDevice,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,6 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
SessionIconButton,
|
||||
SessionIconSize,
|
||||
SessionIconType,
|
||||
} from './session/icon';
|
||||
import { Avatar } from './Avatar';
|
||||
import { SessionIconButton, SessionIconSize, SessionIconType } from './icon';
|
||||
import { Avatar } from '../Avatar';
|
||||
|
||||
export enum SectionType {
|
||||
Profile,
|
|
@ -0,0 +1,30 @@
|
|||
import React from 'react';
|
||||
import { SessionIconButton, SessionIconSize, SessionIconType } from './icon';
|
||||
|
||||
interface Props {
|
||||
searchString: string;
|
||||
onChange: any;
|
||||
}
|
||||
|
||||
export class SessionConversationSearch extends React.Component<Props> {
|
||||
public constructor(props: Props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { searchString } = this.props;
|
||||
|
||||
return (
|
||||
<div className="session-search-input">
|
||||
<SessionIconButton
|
||||
iconSize={SessionIconSize.Medium}
|
||||
iconType={SessionIconType.Search}
|
||||
/>
|
||||
<input
|
||||
value={searchString}
|
||||
onChange={e => this.props.onChange(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,18 +1,19 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { mapDispatchToProps } from '../actions';
|
||||
import { LeftPane } from '../../components/LeftPane';
|
||||
import { StateType } from '../reducer';
|
||||
|
||||
import { getSearchResults, isSearching } from '../selectors/search';
|
||||
import { getIntl } from '../selectors/user';
|
||||
import { getQuery, getSearchResults, isSearching } from '../selectors/search';
|
||||
import {
|
||||
getIntl,
|
||||
getIsSecondaryDevice,
|
||||
getRegionCode,
|
||||
getUserNumber,
|
||||
} from '../selectors/user';
|
||||
import { getLeftPaneLists, getShowArchived } from '../selectors/conversations';
|
||||
|
||||
import { SmartMainHeader } from './MainHeader';
|
||||
|
||||
// Workaround: A react component's required properties are filtering up through connect()
|
||||
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/31363
|
||||
const FilteredSmartMainHeader = SmartMainHeader as any;
|
||||
|
||||
const mapStateToProps = (state: StateType) => {
|
||||
const showSearch = isSearching(state);
|
||||
|
@ -22,10 +23,13 @@ const mapStateToProps = (state: StateType) => {
|
|||
|
||||
return {
|
||||
...lists,
|
||||
searchTerm: getQuery(state),
|
||||
regionCode: getRegionCode(state),
|
||||
ourNumber: getUserNumber(state),
|
||||
isSecondaryDevice: getIsSecondaryDevice(state),
|
||||
searchResults,
|
||||
showArchived: getShowArchived(state),
|
||||
i18n: getIntl(state),
|
||||
renderMainHeader: () => <FilteredSmartMainHeader />,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue