From 80da8bb47b7b30e5f086ddb771bb2c2401850b04 Mon Sep 17 00:00:00 2001 From: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com> Date: Wed, 19 May 2021 09:14:35 -0700 Subject: [PATCH] Display SMS/MMS disclaimer in empty search results --- _locales/en/messages.json | 4 ++ protos/SignalStorage.proto | 1 + stylesheets/_modules.scss | 10 ++++ ts/components/LeftPane.stories.tsx | 21 ++++++++ .../leftPane/LeftPaneSearchHelper.tsx | 49 +++++++++++++------ ts/services/storageRecordOps.ts | 10 ++++ ts/state/selectors/search.ts | 2 +- ts/state/smart/LeftPane.tsx | 6 +++ .../leftPane/LeftPaneSearchHelper_test.ts | 25 ++++++++++ ts/textsecure.d.ts | 1 + 10 files changed, 113 insertions(+), 16 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 22ca24c4f74..9f39196cdbb 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -739,6 +739,10 @@ } } }, + "noSearchResults--sms-only": { + "message": "SMS/MMS contacts are not available on Desktop.", + "description": "Shown in the search left pane when no results were found and primary device has SMS/MMS handling enabled" + }, "noSearchResultsInConversation": { "message": "No results for \"$searchTerm$\" in $conversationName$", "description": "Shown in the search left pane when no results were found", diff --git a/protos/SignalStorage.proto b/protos/SignalStorage.proto index b615c2593b5..d54ed9aba42 100644 --- a/protos/SignalStorage.proto +++ b/protos/SignalStorage.proto @@ -129,4 +129,5 @@ message AccountRecord { optional PhoneNumberSharingMode phoneNumberSharingMode = 12; optional bool notDiscoverableByPhoneNumber = 13; repeated PinnedConversation pinnedConversations = 14; + optional bool primarySendsSms = 18; } diff --git a/stylesheets/_modules.scss b/stylesheets/_modules.scss index 4bfd06bbe74..1274e44f35e 100644 --- a/stylesheets/_modules.scss +++ b/stylesheets/_modules.scss @@ -7331,6 +7331,16 @@ button.module-image__border-overlay:focus { outline: none; } +.module-left-pane__no-search-results__sms-only { + margin-top: 12px; + @include light-theme { + color: $color-gray-60; + } + @include dark-theme { + color: $color-gray-25; + } +} + .module-left-pane__compose-search-form { &__input { flex-grow: 1; diff --git a/ts/components/LeftPane.stories.tsx b/ts/components/LeftPane.stories.tsx index 3bb407e3c1d..eb20100ddb8 100644 --- a/ts/components/LeftPane.stories.tsx +++ b/ts/components/LeftPane.stories.tsx @@ -249,6 +249,22 @@ story.add('Search: no results when searching everywhere', () => ( contactResults: emptySearchResultsGroup, messageResults: emptySearchResultsGroup, searchTerm: 'foo bar', + primarySendsSms: false, + }, + })} + /> +)); + +story.add('Search: no results when searching everywhere (SMS)', () => ( + @@ -264,6 +280,7 @@ story.add('Search: no results when searching in a conversation', () => ( messageResults: emptySearchResultsGroup, searchConversationName: 'Bing Bong', searchTerm: 'foo bar', + primarySendsSms: false, }, })} /> @@ -278,6 +295,7 @@ story.add('Search: all results loading', () => ( contactResults: { isLoading: true }, messageResults: { isLoading: true }, searchTerm: 'foo bar', + primarySendsSms: false, }, })} /> @@ -295,6 +313,7 @@ story.add('Search: some results loading', () => ( contactResults: { isLoading: true }, messageResults: { isLoading: true }, searchTerm: 'foo bar', + primarySendsSms: false, }, })} /> @@ -312,6 +331,7 @@ story.add('Search: has conversations and contacts, but not messages', () => ( contactResults: { isLoading: false, results: defaultConversations }, messageResults: { isLoading: false, results: [] }, searchTerm: 'foo bar', + primarySendsSms: false, }, })} /> @@ -335,6 +355,7 @@ story.add('Search: all results', () => ( ], }, searchTerm: 'foo bar', + primarySendsSms: false, }, })} /> diff --git a/ts/components/leftPane/LeftPaneSearchHelper.tsx b/ts/components/leftPane/LeftPaneSearchHelper.tsx index e1871018690..680f9016b7a 100644 --- a/ts/components/leftPane/LeftPaneSearchHelper.tsx +++ b/ts/components/leftPane/LeftPaneSearchHelper.tsx @@ -31,6 +31,7 @@ export type LeftPaneSearchPropsType = { conversationId: string; }>; searchConversationName?: string; + primarySendsSms: boolean; searchTerm: string; }; @@ -50,6 +51,8 @@ export class LeftPaneSearchHelper extends LeftPaneHelper) { super(); @@ -65,6 +69,7 @@ export class LeftPaneSearchHelper extends LeftPaneHelper + ), + }} + /> + ); + } else { + noResults = ( + <> +
{i18n('noSearchResults', [searchTerm])}
+ {primarySendsSms && ( +
+ {i18n('noSearchResults--sms-only')} +
+ )} + + ); + } return !searchConversationName || searchTerm ? (
- {searchConversationName ? ( - - ), - }} - /> - ) : ( - i18n('noSearchResults', [searchTerm]) - )} + {noResults}
) : null; } diff --git a/ts/services/storageRecordOps.ts b/ts/services/storageRecordOps.ts index 38e4e830891..e172c4f620a 100644 --- a/ts/services/storageRecordOps.ts +++ b/ts/services/storageRecordOps.ts @@ -177,6 +177,11 @@ export async function toAccountRecord( ); accountRecord.linkPreviews = Boolean(window.storage.get('linkPreviews')); + const primarySendsSms = window.storage.get('primarySendsSms'); + if (primarySendsSms !== undefined) { + accountRecord.primarySendsSms = Boolean(primarySendsSms); + } + const PHONE_NUMBER_SHARING_MODE_ENUM = window.textsecure.protobuf.AccountRecord.PhoneNumberSharingMode; const phoneNumberSharingMode = parsePhoneNumberSharingMode( @@ -805,6 +810,7 @@ export async function mergeAccountRecord( readReceipts, sealedSenderIndicators, typingIndicators, + primarySendsSms, } = accountRecord; window.storage.put('read-receipt-setting', readReceipts); @@ -821,6 +827,10 @@ export async function mergeAccountRecord( window.storage.put('linkPreviews', linkPreviews); } + if (typeof primarySendsSms === 'boolean') { + window.storage.put('primarySendsSms', primarySendsSms); + } + const PHONE_NUMBER_SHARING_MODE_ENUM = window.textsecure.protobuf.AccountRecord.PhoneNumberSharingMode; let phoneNumberSharingModeToStore: PhoneNumberSharingMode; diff --git a/ts/state/selectors/search.ts b/ts/state/selectors/search.ts index 65c40c4ad79..51c656e6e83 100644 --- a/ts/state/selectors/search.ts +++ b/ts/state/selectors/search.ts @@ -72,7 +72,7 @@ export const getSearchResults = createSelector( ( state: SearchStateType, conversationLookup: ConversationLookupType - ): LeftPaneSearchPropsType => { + ): Omit => { const { contactIds, conversationIds, diff --git a/ts/state/smart/LeftPane.tsx b/ts/state/smart/LeftPane.tsx index e42c02fd35f..2f7bac723ed 100644 --- a/ts/state/smart/LeftPane.tsx +++ b/ts/state/smart/LeftPane.tsx @@ -3,6 +3,7 @@ import React, { CSSProperties } from 'react'; import { connect } from 'react-redux'; +import { get } from 'lodash'; import { mapDispatchToProps } from '../actions'; import { LeftPane, @@ -88,8 +89,13 @@ const getModeSpecificProps = ( }; } if (isSearching(state)) { + const primarySendsSms = Boolean( + get(state.items, ['primarySendsSms'], false) + ); + return { mode: LeftPaneMode.Search, + primarySendsSms, ...getSearchResults(state), }; } diff --git a/ts/test-node/components/leftPane/LeftPaneSearchHelper_test.ts b/ts/test-node/components/leftPane/LeftPaneSearchHelper_test.ts index 9554aa4c7b3..a8c7e5f0dbb 100644 --- a/ts/test-node/components/leftPane/LeftPaneSearchHelper_test.ts +++ b/ts/test-node/components/leftPane/LeftPaneSearchHelper_test.ts @@ -22,6 +22,7 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: false, results: [] }, messageResults: { isLoading: false, results: [] }, searchTerm: 'foo', + primarySendsSms: false, }); assert.isUndefined( @@ -42,6 +43,7 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: true }, messageResults: { isLoading: true }, searchTerm: 'foo', + primarySendsSms: false, }).getRowCount(), 100 ); @@ -54,6 +56,7 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: true }, messageResults: { isLoading: true }, searchTerm: 'foo', + primarySendsSms: false, }).getRowCount(), 100 ); @@ -63,6 +66,7 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: true }, messageResults: { isLoading: false, results: [fakeMessage()] }, searchTerm: 'foo', + primarySendsSms: false, }).getRowCount(), 100 ); @@ -74,6 +78,7 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: false, results: [] }, messageResults: { isLoading: false, results: [] }, searchTerm: 'foo', + primarySendsSms: false, }); assert.strictEqual(helper.getRowCount(), 0); @@ -88,6 +93,7 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: false, results: [] }, messageResults: { isLoading: false, results: [fakeMessage()] }, searchTerm: 'foo', + primarySendsSms: false, }); assert.strictEqual(helper.getRowCount(), 5); @@ -102,6 +108,7 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: true }, messageResults: { isLoading: true }, searchTerm: 'foo', + primarySendsSms: false, }), new LeftPaneSearchHelper({ conversationResults: { @@ -111,12 +118,14 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: true }, messageResults: { isLoading: true }, searchTerm: 'foo', + primarySendsSms: false, }), new LeftPaneSearchHelper({ conversationResults: { isLoading: true }, contactResults: { isLoading: true }, messageResults: { isLoading: false, results: [fakeMessage()] }, searchTerm: 'foo', + primarySendsSms: false, }), ]; @@ -149,6 +158,7 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: false, results: contacts }, messageResults: { isLoading: false, results: messages }, searchTerm: 'foo', + primarySendsSms: false, }); assert.deepEqual(helper.getRow(0), { @@ -197,6 +207,7 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: false, results: contacts }, messageResults: { isLoading: false, results: messages }, searchTerm: 'foo', + primarySendsSms: false, }); assert.deepEqual(helper.getRow(0), { @@ -236,6 +247,7 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: false, results: [] }, messageResults: { isLoading: false, results: messages }, searchTerm: 'foo', + primarySendsSms: false, }); assert.deepEqual(helper.getRow(0), { @@ -277,6 +289,7 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: false, results: contacts }, messageResults: { isLoading: false, results: [] }, searchTerm: 'foo', + primarySendsSms: false, }); assert.deepEqual(helper.getRow(0), { @@ -310,6 +323,7 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: true }, messageResults: { isLoading: true }, searchTerm: 'foo', + primarySendsSms: false, }), new LeftPaneSearchHelper({ conversationResults: { @@ -319,12 +333,14 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: true }, messageResults: { isLoading: true }, searchTerm: 'foo', + primarySendsSms: false, }), new LeftPaneSearchHelper({ conversationResults: { isLoading: true }, contactResults: { isLoading: true }, messageResults: { isLoading: false, results: [fakeMessage()] }, searchTerm: 'foo', + primarySendsSms: false, }), ]; @@ -345,6 +361,7 @@ describe('LeftPaneSearchHelper', () => { results: [fakeMessage(), fakeMessage(), fakeMessage()], }, searchTerm: 'foo', + primarySendsSms: false, }); assert.isTrue(helper.isScrollable()); }); @@ -363,6 +380,7 @@ describe('LeftPaneSearchHelper', () => { results: [fakeMessage(), fakeMessage(), fakeMessage()], }, searchTerm: 'foo', + primarySendsSms: false, }); assert.isFalse( @@ -377,6 +395,7 @@ describe('LeftPaneSearchHelper', () => { results: [fakeMessage(), fakeMessage(), fakeMessage()], }, searchTerm: 'bar', + primarySendsSms: false, }) ); }); @@ -387,6 +406,7 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: true }, messageResults: { isLoading: true }, searchTerm: 'foo', + primarySendsSms: false, }); assert.isFalse( @@ -398,6 +418,7 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: true }, messageResults: { isLoading: true }, searchTerm: 'bar', + primarySendsSms: false, }) ); }); @@ -408,6 +429,7 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: true }, messageResults: { isLoading: false, results: [fakeMessage()] }, searchTerm: 'foo', + primarySendsSms: false, }); assert.isTrue( @@ -419,6 +441,7 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: false, results: [] }, messageResults: { isLoading: false, results: [fakeMessage()] }, searchTerm: 'foo', + primarySendsSms: false, }) ); }); @@ -432,6 +455,7 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: false, results: [] }, messageResults: { isLoading: false, results: [] }, searchTerm: 'foo', + primarySendsSms: false, }); assert.isTrue( @@ -443,6 +467,7 @@ describe('LeftPaneSearchHelper', () => { contactResults: { isLoading: true }, messageResults: { isLoading: true }, searchTerm: 'bar', + primarySendsSms: false, }) ); }); diff --git a/ts/textsecure.d.ts b/ts/textsecure.d.ts index 73ecd1ba576..5cbac4280b3 100644 --- a/ts/textsecure.d.ts +++ b/ts/textsecure.d.ts @@ -1060,6 +1060,7 @@ export declare class AccountRecordClass { notDiscoverableByPhoneNumber?: boolean; pinnedConversations?: PinnedConversationClass[]; noteToSelfMarkedUnread?: boolean; + primarySendsSms?: boolean; __unknownFields?: ArrayBuffer; }