Do not populate left pane on initial link
This commit is contained in:
parent
f456bbd3db
commit
5e2d48cc2f
25 changed files with 791 additions and 277 deletions
|
@ -35,6 +35,25 @@ const defaultConversations: Array<ConversationListItemPropsType> = [
|
|||
},
|
||||
];
|
||||
|
||||
const defaultGroups: Array<ConversationListItemPropsType> = [
|
||||
{
|
||||
id: 'biking-group',
|
||||
isSelected: false,
|
||||
lastUpdated: Date.now(),
|
||||
markedUnread: false,
|
||||
title: 'Mtn Biking Arizona 🚵☀️⛰',
|
||||
type: 'group',
|
||||
},
|
||||
{
|
||||
id: 'dance-group',
|
||||
isSelected: false,
|
||||
lastUpdated: Date.now(),
|
||||
markedUnread: false,
|
||||
title: 'Are we dancers? 💃',
|
||||
type: 'group',
|
||||
},
|
||||
];
|
||||
|
||||
const defaultArchivedConversations: Array<ConversationListItemPropsType> = [
|
||||
{
|
||||
id: 'michelle-archive-convo',
|
||||
|
@ -352,12 +371,13 @@ story.add('Archive: archived conversations', () => (
|
|||
|
||||
// Compose stories
|
||||
|
||||
story.add('Compose: no contacts', () => (
|
||||
story.add('Compose: no contacts or groups', () => (
|
||||
<LeftPane
|
||||
{...createProps({
|
||||
modeSpecificProps: {
|
||||
mode: LeftPaneMode.Compose,
|
||||
composeContacts: [],
|
||||
composeGroups: [],
|
||||
regionCode: 'US',
|
||||
searchTerm: '',
|
||||
},
|
||||
|
@ -365,12 +385,13 @@ story.add('Compose: no contacts', () => (
|
|||
/>
|
||||
));
|
||||
|
||||
story.add('Compose: some contacts, no search term', () => (
|
||||
story.add('Compose: some contacts, no groups, no search term', () => (
|
||||
<LeftPane
|
||||
{...createProps({
|
||||
modeSpecificProps: {
|
||||
mode: LeftPaneMode.Compose,
|
||||
composeContacts: defaultConversations,
|
||||
composeGroups: [],
|
||||
regionCode: 'US',
|
||||
searchTerm: '',
|
||||
},
|
||||
|
@ -378,14 +399,71 @@ story.add('Compose: some contacts, no search term', () => (
|
|||
/>
|
||||
));
|
||||
|
||||
story.add('Compose: some contacts with a search term', () => (
|
||||
story.add('Compose: some contacts, no groups, with a search term', () => (
|
||||
<LeftPane
|
||||
{...createProps({
|
||||
modeSpecificProps: {
|
||||
mode: LeftPaneMode.Compose,
|
||||
composeContacts: defaultConversations,
|
||||
composeGroups: [],
|
||||
regionCode: 'US',
|
||||
searchTerm: 'foo bar',
|
||||
searchTerm: 'ar',
|
||||
},
|
||||
})}
|
||||
/>
|
||||
));
|
||||
|
||||
story.add('Compose: some groups, no contacts, no search term', () => (
|
||||
<LeftPane
|
||||
{...createProps({
|
||||
modeSpecificProps: {
|
||||
mode: LeftPaneMode.Compose,
|
||||
composeContacts: [],
|
||||
composeGroups: defaultGroups,
|
||||
regionCode: 'US',
|
||||
searchTerm: '',
|
||||
},
|
||||
})}
|
||||
/>
|
||||
));
|
||||
|
||||
story.add('Compose: some groups, no contacts, with search term', () => (
|
||||
<LeftPane
|
||||
{...createProps({
|
||||
modeSpecificProps: {
|
||||
mode: LeftPaneMode.Compose,
|
||||
composeContacts: [],
|
||||
composeGroups: defaultGroups,
|
||||
regionCode: 'US',
|
||||
searchTerm: 'ar',
|
||||
},
|
||||
})}
|
||||
/>
|
||||
));
|
||||
|
||||
story.add('Compose: some contacts, some groups, no search term', () => (
|
||||
<LeftPane
|
||||
{...createProps({
|
||||
modeSpecificProps: {
|
||||
mode: LeftPaneMode.Compose,
|
||||
composeContacts: defaultConversations,
|
||||
composeGroups: defaultGroups,
|
||||
regionCode: 'US',
|
||||
searchTerm: '',
|
||||
},
|
||||
})}
|
||||
/>
|
||||
));
|
||||
|
||||
story.add('Compose: some contacts, some groups, with a search term', () => (
|
||||
<LeftPane
|
||||
{...createProps({
|
||||
modeSpecificProps: {
|
||||
mode: LeftPaneMode.Compose,
|
||||
composeContacts: defaultConversations,
|
||||
composeGroups: defaultGroups,
|
||||
regionCode: 'US',
|
||||
searchTerm: 'ar',
|
||||
},
|
||||
})}
|
||||
/>
|
||||
|
|
|
@ -14,7 +14,7 @@ import { LocalizerType } from '../../../../types/Util';
|
|||
import { assert } from '../../../../util/assert';
|
||||
import { getOwn } from '../../../../util/getOwn';
|
||||
import { missingCaseError } from '../../../../util/missingCaseError';
|
||||
import { filterAndSortContacts } from '../../../../util/filterAndSortContacts';
|
||||
import { filterAndSortConversations } from '../../../../util/filterAndSortConversations';
|
||||
import { ConversationType } from '../../../../state/ducks/conversations';
|
||||
import { ModalHost } from '../../../ModalHost';
|
||||
import { ContactPills } from '../../../ContactPills';
|
||||
|
@ -72,13 +72,13 @@ export const ChooseGroupMembersModal: FunctionComponent<PropsType> = ({
|
|||
const canContinue = Boolean(selectedContacts.length);
|
||||
|
||||
const [filteredContacts, setFilteredContacts] = useState(
|
||||
filterAndSortContacts(candidateContacts, '')
|
||||
filterAndSortConversations(candidateContacts, '')
|
||||
);
|
||||
const normalizedSearchTerm = searchTerm.trim();
|
||||
useEffect(() => {
|
||||
const timeout = setTimeout(() => {
|
||||
setFilteredContacts(
|
||||
filterAndSortContacts(candidateContacts, normalizedSearchTerm)
|
||||
filterAndSortConversations(candidateContacts, normalizedSearchTerm)
|
||||
);
|
||||
}, 200);
|
||||
return () => {
|
||||
|
|
|
@ -7,6 +7,7 @@ import { PhoneNumber } from 'google-libphonenumber';
|
|||
import { LeftPaneHelper } from './LeftPaneHelper';
|
||||
import { Row, RowType } from '../ConversationList';
|
||||
import { PropsDataType as ContactListItemPropsType } from '../conversationList/ContactListItem';
|
||||
import { PropsData as ConversationListItemPropsType } from '../conversationList/ConversationListItem';
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
import {
|
||||
instance as phoneNumberInstance,
|
||||
|
@ -18,6 +19,7 @@ import { isStorageWriteFeatureEnabled } from '../../storage/isFeatureEnabled';
|
|||
|
||||
export type LeftPaneComposePropsType = {
|
||||
composeContacts: ReadonlyArray<ContactListItemPropsType>;
|
||||
composeGroups: ReadonlyArray<ContactListItemPropsType>;
|
||||
regionCode: string;
|
||||
searchTerm: string;
|
||||
};
|
||||
|
@ -35,20 +37,24 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<
|
|||
> {
|
||||
private readonly composeContacts: ReadonlyArray<ContactListItemPropsType>;
|
||||
|
||||
private readonly composeGroups: ReadonlyArray<ConversationListItemPropsType>;
|
||||
|
||||
private readonly searchTerm: string;
|
||||
|
||||
private readonly phoneNumber: undefined | PhoneNumber;
|
||||
|
||||
constructor({
|
||||
composeContacts,
|
||||
composeGroups,
|
||||
regionCode,
|
||||
searchTerm,
|
||||
}: Readonly<LeftPaneComposePropsType>) {
|
||||
super();
|
||||
|
||||
this.composeContacts = composeContacts;
|
||||
this.searchTerm = searchTerm;
|
||||
this.phoneNumber = parsePhoneNumber(searchTerm, regionCode);
|
||||
this.composeGroups = composeGroups;
|
||||
this.composeContacts = composeContacts;
|
||||
}
|
||||
|
||||
getHeaderContents({
|
||||
|
@ -103,7 +109,7 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<
|
|||
|
||||
{this.getRowCount() ? null : (
|
||||
<div className="module-left-pane__compose-no-contacts">
|
||||
{i18n('noContactsFound')}
|
||||
{i18n('noConversationsFound')}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
@ -111,62 +117,89 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<
|
|||
}
|
||||
|
||||
getRowCount(): number {
|
||||
let result = this.composeContacts.length;
|
||||
let result = this.composeContacts.length + this.composeGroups.length;
|
||||
if (this.hasTopButton()) {
|
||||
result += 1;
|
||||
}
|
||||
if (this.hasContactsHeader()) {
|
||||
result += 1;
|
||||
}
|
||||
if (this.hasGroupsHeader()) {
|
||||
result += 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
getRow(rowIndex: number): undefined | Row {
|
||||
if (rowIndex === 0) {
|
||||
const topButton = this.getTopButton();
|
||||
switch (topButton) {
|
||||
case TopButton.None:
|
||||
break;
|
||||
case TopButton.StartNewConversation:
|
||||
assert(
|
||||
this.phoneNumber,
|
||||
'LeftPaneComposeHelper: we should have a phone number if the top button is "Start new conversation"'
|
||||
);
|
||||
return {
|
||||
type: RowType.StartNewConversation,
|
||||
phoneNumber: phoneNumberInstance.format(
|
||||
getRow(actualRowIndex: number): undefined | Row {
|
||||
let virtualRowIndex = actualRowIndex;
|
||||
if (this.hasTopButton()) {
|
||||
if (virtualRowIndex === 0) {
|
||||
const topButton = this.getTopButton();
|
||||
switch (topButton) {
|
||||
case TopButton.None:
|
||||
break;
|
||||
case TopButton.StartNewConversation:
|
||||
assert(
|
||||
this.phoneNumber,
|
||||
PhoneNumberFormat.E164
|
||||
),
|
||||
};
|
||||
case TopButton.CreateNewGroup:
|
||||
return { type: RowType.CreateNewGroup };
|
||||
default:
|
||||
throw missingCaseError(topButton);
|
||||
'LeftPaneComposeHelper: we should have a phone number if the top button is "Start new conversation"'
|
||||
);
|
||||
return {
|
||||
type: RowType.StartNewConversation,
|
||||
phoneNumber: phoneNumberInstance.format(
|
||||
this.phoneNumber,
|
||||
PhoneNumberFormat.E164
|
||||
),
|
||||
};
|
||||
case TopButton.CreateNewGroup:
|
||||
return { type: RowType.CreateNewGroup };
|
||||
default:
|
||||
throw missingCaseError(topButton);
|
||||
}
|
||||
}
|
||||
|
||||
virtualRowIndex -= 1;
|
||||
}
|
||||
|
||||
if (rowIndex === 1 && this.hasContactsHeader()) {
|
||||
if (this.hasContactsHeader()) {
|
||||
if (virtualRowIndex === 0) {
|
||||
return {
|
||||
type: RowType.Header,
|
||||
i18nKey: 'contactsHeader',
|
||||
};
|
||||
}
|
||||
|
||||
virtualRowIndex -= 1;
|
||||
|
||||
const contact = this.composeContacts[virtualRowIndex];
|
||||
if (contact) {
|
||||
return {
|
||||
type: RowType.Contact,
|
||||
contact,
|
||||
};
|
||||
}
|
||||
|
||||
virtualRowIndex -= this.composeContacts.length;
|
||||
}
|
||||
|
||||
if (this.hasGroupsHeader()) {
|
||||
if (virtualRowIndex === 0) {
|
||||
return {
|
||||
type: RowType.Header,
|
||||
i18nKey: 'groupsHeader',
|
||||
};
|
||||
}
|
||||
|
||||
virtualRowIndex -= 1;
|
||||
|
||||
const group = this.composeGroups[virtualRowIndex];
|
||||
return {
|
||||
type: RowType.Header,
|
||||
i18nKey: 'contactsHeader',
|
||||
type: RowType.Conversation,
|
||||
conversation: group,
|
||||
};
|
||||
}
|
||||
|
||||
let contactIndex: number;
|
||||
if (this.hasTopButton()) {
|
||||
contactIndex = rowIndex - 2;
|
||||
} else {
|
||||
contactIndex = rowIndex;
|
||||
}
|
||||
|
||||
const contact = this.composeContacts[contactIndex];
|
||||
return contact
|
||||
? {
|
||||
type: RowType.Contact,
|
||||
contact,
|
||||
}
|
||||
: undefined;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// This is deliberately unimplemented because these keyboard shortcuts shouldn't work in
|
||||
|
@ -183,10 +216,17 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<
|
|||
return undefined;
|
||||
}
|
||||
|
||||
shouldRecomputeRowHeights(old: Readonly<LeftPaneComposePropsType>): boolean {
|
||||
shouldRecomputeRowHeights(
|
||||
exProps: Readonly<LeftPaneComposePropsType>
|
||||
): boolean {
|
||||
const prev = new LeftPaneComposeHelper(exProps);
|
||||
const currHeaderIndices = this.getHeaderIndices();
|
||||
const prevHeaderIndices = prev.getHeaderIndices();
|
||||
|
||||
return (
|
||||
this.hasContactsHeader() !==
|
||||
new LeftPaneComposeHelper(old).hasContactsHeader()
|
||||
currHeaderIndices.top !== prevHeaderIndices.top ||
|
||||
currHeaderIndices.contact !== prevHeaderIndices.contact ||
|
||||
currHeaderIndices.group !== prevHeaderIndices.group
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -205,7 +245,39 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<
|
|||
}
|
||||
|
||||
private hasContactsHeader(): boolean {
|
||||
return this.hasTopButton() && Boolean(this.composeContacts.length);
|
||||
return Boolean(this.composeContacts.length);
|
||||
}
|
||||
|
||||
private hasGroupsHeader(): boolean {
|
||||
return Boolean(this.composeGroups.length);
|
||||
}
|
||||
|
||||
private getHeaderIndices(): {
|
||||
top?: number;
|
||||
contact?: number;
|
||||
group?: number;
|
||||
} {
|
||||
let top: number | undefined;
|
||||
let contact: number | undefined;
|
||||
let group: number | undefined;
|
||||
let rowCount = 0;
|
||||
if (this.hasTopButton()) {
|
||||
top = 0;
|
||||
rowCount += 1;
|
||||
}
|
||||
if (this.composeContacts.length) {
|
||||
contact = rowCount;
|
||||
rowCount += this.composeContacts.length;
|
||||
}
|
||||
if (this.composeGroups.length) {
|
||||
group = rowCount;
|
||||
}
|
||||
|
||||
return {
|
||||
top,
|
||||
contact,
|
||||
group,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,11 +2,14 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { last } from 'lodash';
|
||||
import React, { ReactChild } from 'react';
|
||||
|
||||
import { Intl } from '../Intl';
|
||||
import { LeftPaneHelper, ToFindType } from './LeftPaneHelper';
|
||||
import { getConversationInDirection } from './getConversationInDirection';
|
||||
import { Row, RowType } from '../ConversationList';
|
||||
import { PropsData as ConversationListItemPropsType } from '../conversationList/ConversationListItem';
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
|
||||
export type LeftPaneInboxPropsType = {
|
||||
conversations: ReadonlyArray<ConversationListItemPropsType>;
|
||||
|
@ -56,6 +59,33 @@ export class LeftPaneInboxHelper extends LeftPaneHelper<
|
|||
);
|
||||
}
|
||||
|
||||
getPreRowsNode({
|
||||
i18n,
|
||||
}: Readonly<{ i18n: LocalizerType }>): null | ReactChild {
|
||||
if (this.getRowCount() === 0) {
|
||||
return (
|
||||
<div className="module-left-pane__empty">
|
||||
<div>
|
||||
<Intl
|
||||
i18n={i18n}
|
||||
id="emptyInboxMessage"
|
||||
components={[
|
||||
<span>
|
||||
<strong>{i18n('composeIcon')}</strong>
|
||||
<span className="module-left-pane__empty--composer_icon">
|
||||
<i className="module-left-pane__empty--composer_icon--icon" />
|
||||
</span>
|
||||
</span>,
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
getRow(rowIndex: number): undefined | Row {
|
||||
const { conversations, archivedConversations, pinnedConversations } = this;
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue