add the leftpane overlay as reusable from subsections

pull/712/head
Audric Ackermann 5 years ago
parent 571af6c654
commit af22bd7b33

@ -2424,5 +2424,8 @@
}, },
"createGroup": { "createGroup": {
"message": "Create Group" "message": "Create Group"
},
"yourPublicKey": {
"message": "Your Public Key"
} }
} }

@ -139,6 +139,10 @@ div,
span, span,
label { label {
user-select: none; user-select: none;
&::selection {
background: $session-shade-17;
}
} }
$session-gradient-green: linear-gradient( $session-gradient-green: linear-gradient(

@ -114,11 +114,6 @@
padding-top: 2em; padding-top: 2em;
} }
&__unique-session-id {
@include registration-label-mixin;
padding-top: 3em;
}
&__entry-fields { &__entry-fields {
margin: 0px; margin: 0px;
padding-bottom: 30px; padding-bottom: 30px;
@ -229,6 +224,7 @@
padding: 20px 5px 20px 5px; padding: 20px 5px 20px 5px;
display: inline-block; display: inline-block;
font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
user-select: all;
} }
} }

@ -190,6 +190,7 @@ $session-compose-margin: 20px;
margin: 0px 20px; margin: 0px 20px;
width: -webkit-fill-available; width: -webkit-fill-available;
flex-shrink: 0; flex-shrink: 0;
user-select: all;
} }
.session-button { .session-button {
@ -278,7 +279,6 @@ $session-compose-margin: 20px;
font-weight: bold; font-weight: bold;
} }
.left-pane-contact { .left-pane-contact {
&-section, &-section,
&-content { &-content {
@ -299,3 +299,19 @@ $session-compose-margin: 20px;
} }
} }
} }
.panel-text-divider {
width: 100%;
text-align: center;
border-bottom: 1px solid $session-color-dark-grey;
line-height: 0.1em;
margin: 50px 0 50px;
span {
padding: 5px 10px;
border-radius: 50px;
background-color: $session-shade-18;
color: $session-color-light-grey;
border: 1px solid $session-color-dark-grey;
}
}

@ -8,6 +8,18 @@ import { PropsData as SearchResultsProps } from './SearchResults';
import { SearchOptions } from '../types/Search'; import { SearchOptions } from '../types/Search';
import { LeftPaneSectionHeader } from './session/LeftPaneSectionHeader'; import { LeftPaneSectionHeader } from './session/LeftPaneSectionHeader';
import { LeftPaneContactSection } from './session/LeftPaneContactSection'; import { LeftPaneContactSection } from './session/LeftPaneContactSection';
import {
SessionIconButton,
SessionIconSize,
SessionIconType,
} from './session/icon';
import { SessionIdEditable } from './session/SessionIdEditable';
import { UserSearchDropdown } from './session/UserSearchDropdown';
import {
SessionButton,
SessionButtonColor,
SessionButtonType,
} from './session/SessionButton';
// 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
export type RowRendererParamsType = { export type RowRendererParamsType = {
@ -19,7 +31,6 @@ export type RowRendererParamsType = {
style: Object; style: Object;
}; };
interface State { interface State {
selectedSection: SectionType; selectedSection: SectionType;
} }
@ -38,7 +49,7 @@ interface Props {
export class LeftPane extends React.Component<Props, State> { export class LeftPane extends React.Component<Props, State> {
public state = { public state = {
selectedSection: SectionType.Message, selectedSection: SectionType.Contact,
}; };
public constructor(props: any) { public constructor(props: any) {
@ -144,4 +155,79 @@ export class LeftPane extends React.Component<Props, State> {
/> />
); );
} }
static renderClosableOverlay(
isAddContactView: boolean,
onChangeSessionID: any,
onCloseClick: any,
onButtonClick: any,
searchTerm: string,
searchResults?: any,
updateSearch?: any
): JSX.Element {
const title = isAddContactView
? window.i18n('addContact')
: window.i18n('enterRecipient');
const buttonText = isAddContactView
? window.i18n('addContact')
: window.i18n('message');
const ourSessionID = window.textsecure.storage.user.getNumber();
return (
<div className="module-left-pane-compose">
<div className="exit">
<SessionIconButton
iconSize={SessionIconSize.Small}
iconType={SessionIconType.Exit}
onClick={onCloseClick}
/>
</div>
<h2>{title}</h2>
<h3>{window.i18n('enterSessionID')}</h3>
<div className="module-left-pane-compose-border-container">
<hr className="white" />
<hr className="green" />
</div>
<SessionIdEditable
editable={true}
placeholder={window.i18n('pasteSessionIDRecipient')}
onChange={onChangeSessionID}
/>
<div className="session-description-long">
{window.i18n('usersCanShareTheir...')}
</div>
{isAddContactView || <h4>{window.i18n('or')}</h4>}
{isAddContactView || (
<UserSearchDropdown
searchTerm={searchTerm}
updateSearch={updateSearch}
placeholder={window.i18n('searchByIDOrDisplayName')}
searchResults={searchResults}
/>
)}
{isAddContactView && (
<div className="panel-text-divider">
<span>{window.i18n('yourPublicKey')}</span>
</div>
)}
{isAddContactView && (
<SessionIdEditable
editable={false}
placeholder=""
text={ourSessionID}
/>
)}
<SessionButton
buttonColor={SessionButtonColor.Green}
buttonType={SessionButtonType.BrandOutline}
text={buttonText}
onClick={onButtonClick}
/>
</div>
);
}
} }

@ -5,8 +5,12 @@ import { PropsData as SearchResultsProps } from '../SearchResults';
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import { cleanSearchTerm } from '../../util/cleanSearchTerm'; import { cleanSearchTerm } from '../../util/cleanSearchTerm';
import { SearchOptions } from '../../types/Search'; import { SearchOptions } from '../../types/Search';
import { LeftPane, RowRendererParamsType } from '../LeftPane'; import { LeftPane } from '../LeftPane';
import { SessionButton, SessionButtonType, SessionButtonColor } from './SessionButton'; import {
SessionButton,
SessionButtonType,
SessionButtonColor,
} from './SessionButton';
import { AutoSizer, List } from 'react-virtualized'; import { AutoSizer, List } from 'react-virtualized';
export interface Props { export interface Props {
@ -35,6 +39,7 @@ export class LeftPaneContactSection extends React.Component<Props, any> {
this.debouncedSearch = debounce(this.search.bind(this), 20); this.debouncedSearch = debounce(this.search.bind(this), 20);
this.handleTabSelected = this.handleTabSelected.bind(this); this.handleTabSelected = this.handleTabSelected.bind(this);
this.handleToggleOverlay = this.handleToggleOverlay.bind(this);
} }
public componentWillUnmount() { public componentWillUnmount() {
@ -42,29 +47,49 @@ export class LeftPaneContactSection extends React.Component<Props, any> {
} }
public handleTabSelected(tabType: number) { public handleTabSelected(tabType: number) {
this.setState({selectedTab: tabType}); this.setState({ selectedTab: tabType, showAddContactView: false });
} }
public renderHeader(): JSX.Element|undefined { public renderHeader(): JSX.Element | undefined {
const labels = [window.i18n('contactsHeader'), window.i18n('lists')]; const labels = [window.i18n('contactsHeader'), window.i18n('lists')];
return LeftPane.renderHeader(labels, this.handleTabSelected, undefined, null); return LeftPane.renderHeader(
labels,
this.handleTabSelected,
undefined,
null
);
} }
public render(): JSX.Element { public render(): JSX.Element {
return ( return (
<div className="left-pane-contact-section"> <div className="left-pane-contact-section">
{this.renderHeader()} {this.renderHeader()}
{this.state.showAddContactView || this.renderContacts()} {this.state.showAddContactView
? LeftPane.renderClosableOverlay(
true,
undefined,
this.handleToggleOverlay,
undefined,
''
)
: this.renderContacts()}
</div> </div>
); );
} }
private handleToggleOverlay() {
this.setState((prevState: { showAddContactView: any }) => ({
showAddContactView: !prevState.showAddContactView,
}));
}
private renderContacts() { private renderContacts() {
return ( return (
<div className="left-pane-contact-content"> <div className="left-pane-contact-content">
{this.renderList()} {this.renderList()}
{this.renderBottomButtons()} {this.renderBottomButtons()}
</div>); </div>
);
} }
private renderBottomButtons(): JSX.Element { private renderBottomButtons(): JSX.Element {
@ -74,11 +99,28 @@ export class LeftPaneContactSection extends React.Component<Props, any> {
const createGroup = window.i18n('createGroup'); const createGroup = window.i18n('createGroup');
return ( return (
<div className="left-pane-contact-bottom-buttons"> <div className="left-pane-contact-bottom-buttons">
<SessionButton text={edit} buttonType={SessionButtonType.SquareOutline} buttonColor={SessionButtonColor.White}/> <SessionButton
{selectedTab === 0 ? <SessionButton text={addContact} buttonType={SessionButtonType.SquareOutline} buttonColor={SessionButtonColor.Green}/> : text={edit}
<SessionButton text={createGroup} buttonType={SessionButtonType.Square} buttonColor={SessionButtonColor.Green}/>} buttonType={SessionButtonType.SquareOutline}
buttonColor={SessionButtonColor.White}
/>
{selectedTab === 0 ? (
<SessionButton
text={addContact}
buttonType={SessionButtonType.SquareOutline}
buttonColor={SessionButtonColor.Green}
onClick={this.handleToggleOverlay}
/>
) : (
<SessionButton
text={createGroup}
buttonType={SessionButtonType.SquareOutline}
buttonColor={SessionButtonColor.Green}
onClick={this.handleToggleOverlay}
/>
)}
</div> </div>
) );
} }
public getCurrentConversations(): public getCurrentConversations():
@ -97,47 +139,50 @@ export class LeftPaneContactSection extends React.Component<Props, any> {
} }
private renderList() { private renderList() {
// const conversations = this.getCurrentConversations(); const conversations = this.getCurrentConversations();
// if (!conversations) { if (!conversations) {
// throw new Error( throw new Error(
// 'render: must provided conversations if no search results are provided' 'render: must provided conversations if no search results are provided'
// ); );
// } }
// const length = conversations.length; console.log('conversations 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 = ( const list = (
<div className="module-left-pane__list" key={0}> <div className="module-left-pane__list" key={0}>
<AutoSizer> <AutoSizer>
{({ height, width }) => ( {({ height, width }) => (
<List <List
className="module-left-pane__virtual-list" className="module-left-pane__virtual-list"
height={height} height={height}
rowCount={length} rowCount={conversations.length}
rowHeight={64} rowHeight={64}
rowRenderer={this.renderRow} rowRenderer={this.renderRow}
width={width} width={width}
autoHeight={true} autoHeight={true}
/> />
)} )}
</AutoSizer> </AutoSizer>
</div> </div>
); );
return [list]; return [list];
} }
public renderRow() {
return undefined;
}
public renderRow = ({ // public renderRow = ({
// index, // ,
// key, // }: // index,
// style, // key,
}: RowRendererParamsType): JSX.Element|undefined => { // style,
// RowRendererParamsType): JSX.Element | undefined => {
// const { openConversationInternal } = this.props; // const { openConversationInternal } = this.props;
// const conversations = this.getCurrentConversations(); // const conversations = this.getCurrentConversations();
@ -157,10 +202,8 @@ export class LeftPaneContactSection extends React.Component<Props, any> {
// i18n={window.i18n} // i18n={window.i18n}
// /> // />
// ); // );
return undefined; // return undefined;
}; // };
public updateSearch(searchTerm: string) { public updateSearch(searchTerm: string) {
const { updateSearchTerm, clearSearch } = this.props; const { updateSearchTerm, clearSearch } = this.props;

@ -9,20 +9,12 @@ import {
PropsData as SearchResultsProps, PropsData as SearchResultsProps,
SearchResults, SearchResults,
} from '../SearchResults'; } from '../SearchResults';
import {
SessionButton,
SessionButtonColor,
SessionButtonType,
} from './SessionButton';
import { SessionSearchInput } from './SessionSearchInput'; import { SessionSearchInput } from './SessionSearchInput';
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import { cleanSearchTerm } from '../../util/cleanSearchTerm'; import { cleanSearchTerm } from '../../util/cleanSearchTerm';
import { SearchOptions } from '../../types/Search'; import { SearchOptions } from '../../types/Search';
import { SessionIconButton, SessionIconSize, SessionIconType } from './icon';
import { SessionIdEditable } from './SessionIdEditable';
import { UserSearchDropdown } from './UserSearchDropdown';
import { validateNumber } from '../../types/PhoneNumber'; import { validateNumber } from '../../types/PhoneNumber';
import { RowRendererParamsType, LeftPane } from '../LeftPane'; import { RowRendererParamsType, LeftPane } from '../LeftPane';
export interface Props { export interface Props {
searchTerm: string; searchTerm: string;
@ -38,8 +30,6 @@ export interface Props {
clearSearch: () => void; clearSearch: () => void;
} }
export class LeftPaneMessageSection extends React.Component<Props, any> { export class LeftPaneMessageSection extends React.Component<Props, any> {
private readonly updateSearchBound: (searchedString: string) => void; private readonly updateSearchBound: (searchedString: string) => void;
private readonly debouncedSearch: (searchTerm: string) => void; private readonly debouncedSearch: (searchTerm: string) => void;
@ -167,57 +157,20 @@ export class LeftPaneMessageSection extends React.Component<Props, any> {
<div> <div>
{this.renderHeader()} {this.renderHeader()}
{this.state.showComposeView {this.state.showComposeView
? this.renderCompose() ? LeftPane.renderClosableOverlay(
false,
this.handleOnPasteSessionID,
this.handleComposeClick,
this.handleMessageButtonClick,
this.props.searchTerm,
this.props.searchResults,
this.updateSearchBound
)
: this.renderConversations()} : this.renderConversations()}
</div> </div>
); );
} }
public renderCompose(): JSX.Element {
const { searchResults } = this.props;
return (
<div className="module-left-pane-compose">
<div className="exit">
<SessionIconButton
iconSize={SessionIconSize.Small}
iconType={SessionIconType.Exit}
onClick={this.handleComposeClick}
/>
</div>
<h2>{window.i18n('enterRecipient')}</h2>
<h3>{window.i18n('enterSessionID')}</h3>
<div className="module-left-pane-compose-border-container">
<hr className="white" />
<hr className="green" />
</div>
<SessionIdEditable
editable={true}
placeholder={window.i18n('pasteSessionIDRecipient')}
onChange={this.handleOnPasteSessionID}
/>
<div className="session-description-long">
{window.i18n('usersCanShareTheir...')}
</div>
<h4>{window.i18n('or')}</h4>
<UserSearchDropdown
searchTerm={this.props.searchTerm}
updateSearch={this.updateSearchBound}
placeholder={window.i18n('searchByIDOrDisplayName')}
searchResults={searchResults}
/>
<SessionButton
buttonColor={SessionButtonColor.Green}
buttonType={SessionButtonType.BrandOutline}
text={window.i18n('message')}
onClick={this.handleMessageButtonClick}
/>
</div>
);
}
public renderConversations() { public renderConversations() {
return ( return (
<div> <div>

@ -504,7 +504,10 @@ export class RegistrationTabs extends React.Component<{}, State> {
} }
private renderTermsConditionAgreement() { private renderTermsConditionAgreement() {
// FIXME link to our Terms and Conditions and privacy statement // FIXME
console.log(
'FIXME: add link to our Terms and Conditions and privacy statement'
);
return ( return (
<div className="session-terms-conditions-agreement"> <div className="session-terms-conditions-agreement">

@ -2,6 +2,7 @@ import React from 'react';
interface Props { interface Props {
placeholder: string; placeholder: string;
text?: string;
editable?: boolean; editable?: boolean;
onChange?: any; onChange?: any;
} }
@ -13,7 +14,7 @@ export class SessionIdEditable extends React.PureComponent<Props> {
} }
public render() { public render() {
const { placeholder, editable, onChange } = this.props; const { placeholder, editable, onChange, text } = this.props;
return ( return (
<div <div
@ -25,7 +26,9 @@ export class SessionIdEditable extends React.PureComponent<Props> {
onChange(e); onChange(e);
} }
}} }}
/> >
{text}
</div>
); );
} }
} }

Loading…
Cancel
Save