More permissive username search

This commit is contained in:
Fedor Indutny 2024-02-14 10:18:49 -08:00 committed by GitHub
parent 89525d3e16
commit 4a41e87173
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 121 additions and 31 deletions

View file

@ -111,9 +111,6 @@ window.SignalContext = {
platform: '', platform: '',
release: '', release: '',
}, },
usernames: {
hash: input => Buffer.from(input),
} as any,
config: {} as any, config: {} as any,
getHourCyclePreference: () => HourCyclePreference.UnknownPreference, getHourCyclePreference: () => HourCyclePreference.UnknownPreference,

View file

@ -5,7 +5,6 @@
const chai = require('chai'); const chai = require('chai');
const chaiAsPromised = require('chai-as-promised'); const chaiAsPromised = require('chai-as-promised');
const { usernames } = require('@signalapp/libsignal-client');
const { Crypto } = require('../ts/context/Crypto'); const { Crypto } = require('../ts/context/Crypto');
const { setEnvironment, Environment } = require('../ts/environment'); const { setEnvironment, Environment } = require('../ts/environment');
@ -23,7 +22,6 @@ global.window = {
performance, performance,
SignalContext: { SignalContext: {
crypto: new Crypto(), crypto: new Crypto(),
usernames,
log: { log: {
info: (...args) => console.log(...args), info: (...args) => console.log(...args),
warn: (...args) => console.warn(...args), warn: (...args) => console.warn(...args),

View file

@ -660,6 +660,7 @@ export function ComposeNoResults(): JSX.Element {
uuidFetchState: {}, uuidFetchState: {},
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
username: undefined,
}, },
})} })}
/> />
@ -677,6 +678,7 @@ export function ComposeSomeContactsNoSearchTerm(): JSX.Element {
uuidFetchState: {}, uuidFetchState: {},
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
username: undefined,
}, },
})} })}
/> />
@ -694,6 +696,7 @@ export function ComposeSomeContactsWithASearchTerm(): JSX.Element {
uuidFetchState: {}, uuidFetchState: {},
regionCode: 'US', regionCode: 'US',
searchTerm: 'ar', searchTerm: 'ar',
username: undefined,
}, },
})} })}
/> />
@ -711,6 +714,7 @@ export function ComposeSomeGroupsNoSearchTerm(): JSX.Element {
uuidFetchState: {}, uuidFetchState: {},
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
username: undefined,
}, },
})} })}
/> />
@ -728,6 +732,7 @@ export function ComposeSomeGroupsWithSearchTerm(): JSX.Element {
uuidFetchState: {}, uuidFetchState: {},
regionCode: 'US', regionCode: 'US',
searchTerm: 'ar', searchTerm: 'ar',
username: undefined,
}, },
})} })}
/> />
@ -745,6 +750,7 @@ export function ComposeSearchIsValidUsername(): JSX.Element {
uuidFetchState: {}, uuidFetchState: {},
regionCode: 'US', regionCode: 'US',
searchTerm: 'someone', searchTerm: 'someone',
username: 'someone',
}, },
})} })}
/> />
@ -764,6 +770,7 @@ export function ComposeSearchIsValidUsernameFetchingUsername(): JSX.Element {
}, },
regionCode: 'US', regionCode: 'US',
searchTerm: 'someone', searchTerm: 'someone',
username: 'someone',
}, },
})} })}
/> />
@ -781,6 +788,7 @@ export function ComposeSearchIsValidPhoneNumber(): JSX.Element {
uuidFetchState: {}, uuidFetchState: {},
regionCode: 'US', regionCode: 'US',
searchTerm: '2125555454', searchTerm: '2125555454',
username: undefined,
}, },
})} })}
/> />
@ -800,6 +808,7 @@ export function ComposeSearchIsValidPhoneNumberFetchingPhoneNumber(): JSX.Elemen
}, },
regionCode: 'US', regionCode: 'US',
searchTerm: '(212)5555454', searchTerm: '(212)5555454',
username: undefined,
}, },
})} })}
/> />
@ -817,6 +826,7 @@ export function ComposeAllKindsOfResultsNoSearchTerm(): JSX.Element {
uuidFetchState: {}, uuidFetchState: {},
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
username: undefined,
}, },
})} })}
/> />
@ -834,6 +844,7 @@ export function ComposeAllKindsOfResultsWithASearchTerm(): JSX.Element {
uuidFetchState: {}, uuidFetchState: {},
regionCode: 'US', regionCode: 'US',
searchTerm: 'someone', searchTerm: 'someone',
username: 'someone',
}, },
})} })}
/> />
@ -912,6 +923,7 @@ export function ChooseGroupMembersPartialPhoneNumber(): JSX.Element {
ourE164: undefined, ourE164: undefined,
ourUsername: undefined, ourUsername: undefined,
searchTerm: '+1(212) 555', searchTerm: '+1(212) 555',
username: undefined,
regionCode: 'US', regionCode: 'US',
selectedContacts: [], selectedContacts: [],
}, },
@ -937,6 +949,7 @@ export function ChooseGroupMembersValidPhoneNumber(): JSX.Element {
searchTerm: '+1(212) 555 5454', searchTerm: '+1(212) 555 5454',
regionCode: 'US', regionCode: 'US',
selectedContacts: [], selectedContacts: [],
username: undefined,
}, },
})} })}
/> />
@ -957,9 +970,10 @@ export function ChooseGroupMembersUsername(): JSX.Element {
isShowingMaximumGroupSizeModal: false, isShowingMaximumGroupSizeModal: false,
ourE164: undefined, ourE164: undefined,
ourUsername: undefined, ourUsername: undefined,
searchTerm: '@signal', searchTerm: 'signal.01',
regionCode: 'US', regionCode: 'US',
selectedContacts: [], selectedContacts: [],
username: 'signal.01',
}, },
})} })}
/> />

View file

@ -70,6 +70,7 @@ const createProps = (
i18n={i18n} i18n={i18n}
lookupConversationWithoutServiceId={lookupConversationWithoutServiceId} lookupConversationWithoutServiceId={lookupConversationWithoutServiceId}
showUserNotFoundModal={action('showUserNotFoundModal')} showUserNotFoundModal={action('showUserNotFoundModal')}
username={undefined}
/> />
); );
}, },

View file

@ -12,7 +12,6 @@ import { omit } from 'lodash';
import type { ListRowProps } from 'react-virtualized'; import type { ListRowProps } from 'react-virtualized';
import type { LocalizerType, ThemeType } from '../../../../types/Util'; import type { LocalizerType, ThemeType } from '../../../../types/Util';
import { getUsernameFromSearch } from '../../../../types/Username';
import { strictAssert, assertDev } from '../../../../util/assert'; import { strictAssert, assertDev } from '../../../../util/assert';
import { refMerger } from '../../../../util/refMerger'; import { refMerger } from '../../../../util/refMerger';
import { useRestoreFocus } from '../../../../hooks/useRestoreFocus'; import { useRestoreFocus } from '../../../../hooks/useRestoreFocus';
@ -59,6 +58,7 @@ export type StatePropsType = {
ourUsername: string | undefined; ourUsername: string | undefined;
searchTerm: string; searchTerm: string;
selectedContacts: ReadonlyArray<ConversationType>; selectedContacts: ReadonlyArray<ConversationType>;
username: string | undefined;
confirmAdds: () => void; confirmAdds: () => void;
onClose: () => void; onClose: () => void;
@ -96,11 +96,10 @@ export function ChooseGroupMembersModal({
toggleSelectedContact, toggleSelectedContact,
lookupConversationWithoutServiceId, lookupConversationWithoutServiceId,
showUserNotFoundModal, showUserNotFoundModal,
username,
}: PropsType): JSX.Element { }: PropsType): JSX.Element {
const [focusRef] = useRestoreFocus(); const [focusRef] = useRestoreFocus();
const username = getUsernameFromSearch(searchTerm);
const isUsernameChecked = selectedContacts.some( const isUsernameChecked = selectedContacts.some(
contact => contact.username === username contact => contact.username === username
); );

View file

@ -126,6 +126,7 @@ const createProps = (
ourE164={undefined} ourE164={undefined}
ourUsername={undefined} ourUsername={undefined}
showUserNotFoundModal={action('showUserNotFoundModal')} showUserNotFoundModal={action('showUserNotFoundModal')}
username={undefined}
/> />
); );
}, },

View file

@ -18,7 +18,6 @@ import {
} from '../AddGroupMemberErrorDialog'; } from '../AddGroupMemberErrorDialog';
import { Button } from '../Button'; import { Button } from '../Button';
import type { LocalizerType } from '../../types/Util'; import type { LocalizerType } from '../../types/Util';
import { getUsernameFromSearch } from '../../types/Username';
import type { ParsedE164Type } from '../../util/libphonenumberInstance'; import type { ParsedE164Type } from '../../util/libphonenumberInstance';
import { parseAndFormatPhoneNumber } from '../../util/libphonenumberInstance'; import { parseAndFormatPhoneNumber } from '../../util/libphonenumberInstance';
import type { UUIDFetchStateType } from '../../util/uuidFetchState'; import type { UUIDFetchStateType } from '../../util/uuidFetchState';
@ -38,6 +37,7 @@ export type LeftPaneChooseGroupMembersPropsType = {
ourUsername: string | undefined; ourUsername: string | undefined;
searchTerm: string; searchTerm: string;
regionCode: string | undefined; regionCode: string | undefined;
username: string | undefined;
selectedContacts: Array<ConversationType>; selectedContacts: Array<ConversationType>;
}; };
@ -80,6 +80,7 @@ export class LeftPaneChooseGroupMembersHelper extends LeftPaneHelper<LeftPaneCho
regionCode, regionCode,
selectedContacts, selectedContacts,
uuidFetchState, uuidFetchState,
username,
}: Readonly<LeftPaneChooseGroupMembersPropsType>) { }: Readonly<LeftPaneChooseGroupMembersPropsType>) {
super(); super();
@ -93,7 +94,6 @@ export class LeftPaneChooseGroupMembersHelper extends LeftPaneHelper<LeftPaneCho
isShowingRecommendedGroupSizeModal; isShowingRecommendedGroupSizeModal;
this.searchTerm = searchTerm; this.searchTerm = searchTerm;
const username = getUsernameFromSearch(searchTerm);
const isUsernameVisible = const isUsernameVisible =
username !== undefined && username !== undefined &&
username !== ourUsername && username !== ourUsername &&

View file

@ -12,7 +12,6 @@ import { SearchInput } from '../SearchInput';
import type { LocalizerType } from '../../types/Util'; import type { LocalizerType } from '../../types/Util';
import type { ParsedE164Type } from '../../util/libphonenumberInstance'; import type { ParsedE164Type } from '../../util/libphonenumberInstance';
import { parseAndFormatPhoneNumber } from '../../util/libphonenumberInstance'; import { parseAndFormatPhoneNumber } from '../../util/libphonenumberInstance';
import { getUsernameFromSearch } from '../../types/Username';
import type { UUIDFetchStateType } from '../../util/uuidFetchState'; import type { UUIDFetchStateType } from '../../util/uuidFetchState';
import { import {
isFetchingByUsername, isFetchingByUsername,
@ -27,6 +26,7 @@ export type LeftPaneComposePropsType = {
regionCode: string | undefined; regionCode: string | undefined;
searchTerm: string; searchTerm: string;
uuidFetchState: UUIDFetchStateType; uuidFetchState: UUIDFetchStateType;
username: string | undefined;
}; };
enum TopButtons { enum TopButtons {
@ -57,6 +57,7 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<LeftPaneComposePropsTy
regionCode, regionCode,
searchTerm, searchTerm,
uuidFetchState, uuidFetchState,
username,
}: Readonly<LeftPaneComposePropsType>) { }: Readonly<LeftPaneComposePropsType>) {
super(); super();
@ -65,8 +66,6 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<LeftPaneComposePropsTy
this.searchTerm = searchTerm; this.searchTerm = searchTerm;
this.uuidFetchState = uuidFetchState; this.uuidFetchState = uuidFetchState;
const username = getUsernameFromSearch(this.searchTerm);
this.username = username; this.username = username;
this.isUsernameVisible = this.isUsernameVisible =
Boolean(username) && Boolean(username) &&

View file

@ -9,7 +9,6 @@ import type { Row } from '../ConversationList';
import { RowType } from '../ConversationList'; import { RowType } from '../ConversationList';
import { SearchInput } from '../SearchInput'; import { SearchInput } from '../SearchInput';
import type { LocalizerType } from '../../types/Util'; import type { LocalizerType } from '../../types/Util';
import { getUsernameFromSearch } from '../../types/Username';
import type { ShowConversationType } from '../../state/ducks/conversations'; import type { ShowConversationType } from '../../state/ducks/conversations';
import type { UUIDFetchStateType } from '../../util/uuidFetchState'; import type { UUIDFetchStateType } from '../../util/uuidFetchState';
import { isFetchingByUsername } from '../../util/uuidFetchState'; import { isFetchingByUsername } from '../../util/uuidFetchState';
@ -21,6 +20,7 @@ import { Button } from '../Button';
export type LeftPaneFindByUsernamePropsType = { export type LeftPaneFindByUsernamePropsType = {
searchTerm: string; searchTerm: string;
uuidFetchState: UUIDFetchStateType; uuidFetchState: UUIDFetchStateType;
username: string | undefined;
}; };
type DoLookupActionsType = Readonly<{ type DoLookupActionsType = Readonly<{
@ -39,13 +39,14 @@ export class LeftPaneFindByUsernameHelper extends LeftPaneHelper<LeftPaneFindByU
constructor({ constructor({
searchTerm, searchTerm,
uuidFetchState, uuidFetchState,
username,
}: Readonly<LeftPaneFindByUsernamePropsType>) { }: Readonly<LeftPaneFindByUsernamePropsType>) {
super(); super();
this.searchTerm = searchTerm; this.searchTerm = searchTerm;
this.uuidFetchState = uuidFetchState; this.uuidFetchState = uuidFetchState;
this.username = getUsernameFromSearch(this.searchTerm); this.username = username;
} }
override getHeaderContents({ override getHeaderContents({

View file

@ -7,6 +7,7 @@ import type { StateType } from '../reducer';
import { mapDispatchToProps } from '../actions'; import { mapDispatchToProps } from '../actions';
import { strictAssert } from '../../util/assert'; import { strictAssert } from '../../util/assert';
import { lookupConversationWithoutServiceId } from '../../util/lookupConversationWithoutServiceId'; import { lookupConversationWithoutServiceId } from '../../util/lookupConversationWithoutServiceId';
import { getUsernameFromSearch } from '../../util/Username';
import type { StatePropsType } from '../../components/conversation/conversation-details/AddGroupMembersModal/ChooseGroupMembersModal'; import type { StatePropsType } from '../../components/conversation/conversation-details/AddGroupMembersModal/ChooseGroupMembersModal';
import { ChooseGroupMembersModal } from '../../components/conversation/conversation-details/AddGroupMembersModal/ChooseGroupMembersModal'; import { ChooseGroupMembersModal } from '../../components/conversation/conversation-details/AddGroupMembersModal/ChooseGroupMembersModal';
@ -47,6 +48,8 @@ const mapStateToProps = (
return convo; return convo;
}); });
const { searchTerm } = props;
return { return {
...props, ...props,
regionCode: getRegionCode(state), regionCode: getRegionCode(state),
@ -58,6 +61,7 @@ const mapStateToProps = (
ourUsername: getMe(state).username, ourUsername: getMe(state).username,
selectedContacts, selectedContacts,
lookupConversationWithoutServiceId, lookupConversationWithoutServiceId,
username: getUsernameFromSearch(searchTerm),
}; };
}; };

View file

@ -14,6 +14,7 @@ import { missingCaseError } from '../../util/missingCaseError';
import { lookupConversationWithoutServiceId } from '../../util/lookupConversationWithoutServiceId'; import { lookupConversationWithoutServiceId } from '../../util/lookupConversationWithoutServiceId';
import { isDone as isRegistrationDone } from '../../util/registration'; import { isDone as isRegistrationDone } from '../../util/registration';
import { getCountryDataForLocale } from '../../util/getCountryData'; import { getCountryDataForLocale } from '../../util/getCountryData';
import { getUsernameFromSearch } from '../../util/Username';
import { LeftPaneMode } from '../../types/leftPane'; import { LeftPaneMode } from '../../types/leftPane';
import { ComposerStep, OneTimeModalState } from '../ducks/conversationsEnums'; import { ComposerStep, OneTimeModalState } from '../ducks/conversationsEnums';
@ -182,12 +183,18 @@ const getModeSpecificProps = (
regionCode: getRegionCode(state), regionCode: getRegionCode(state),
searchTerm: getComposerConversationSearchTerm(state), searchTerm: getComposerConversationSearchTerm(state),
uuidFetchState: getComposerUUIDFetchState(state), uuidFetchState: getComposerUUIDFetchState(state),
username: getUsernameFromSearch(
getComposerConversationSearchTerm(state)
),
}; };
case ComposerStep.FindByUsername: case ComposerStep.FindByUsername:
return { return {
mode: LeftPaneMode.FindByUsername, mode: LeftPaneMode.FindByUsername,
searchTerm: getComposerConversationSearchTerm(state), searchTerm: getComposerConversationSearchTerm(state),
uuidFetchState: getComposerUUIDFetchState(state), uuidFetchState: getComposerUUIDFetchState(state),
username: getUsernameFromSearch(
getComposerConversationSearchTerm(state)
),
}; };
case ComposerStep.FindByPhoneNumber: case ComposerStep.FindByPhoneNumber:
return { return {
@ -215,6 +222,9 @@ const getModeSpecificProps = (
searchTerm: getComposerConversationSearchTerm(state), searchTerm: getComposerConversationSearchTerm(state),
selectedContacts: getComposeSelectedContacts(state), selectedContacts: getComposeSelectedContacts(state),
uuidFetchState: getComposerUUIDFetchState(state), uuidFetchState: getComposerUUIDFetchState(state),
username: getUsernameFromSearch(
getComposerConversationSearchTerm(state)
),
}; };
case ComposerStep.SetGroupMetadata: case ComposerStep.SetGroupMetadata:
return { return {

View file

@ -3,15 +3,20 @@
import { assert } from 'chai'; import { assert } from 'chai';
import * as Username from '../../types/Username'; import * as Username from '../../util/Username';
describe('Username', () => { describe('Username', () => {
describe('getUsernameFromSearch', () => { describe('getUsernameFromSearch', () => {
const { getUsernameFromSearch } = Username; const { getUsernameFromSearch } = Username;
it('matches invalid username searches', () => { it('matches invalid username searches', () => {
assert.isUndefined(getUsernameFromSearch('use')); assert.isUndefined(getUsernameFromSearch('us'));
assert.isUndefined(getUsernameFromSearch('username9012345678901234567')); assert.isUndefined(getUsernameFromSearch('123'));
});
it('matches partial username searches without discriminator', () => {
assert.strictEqual(getUsernameFromSearch('use'), 'use');
assert.strictEqual(getUsernameFromSearch('use.'), 'use.');
}); });
it('matches valid username searches', () => { it('matches valid username searches', () => {

View file

@ -21,6 +21,7 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
groupSizeRecommendedLimit: 22, groupSizeRecommendedLimit: 22,
groupSizeHardLimit: 33, groupSizeHardLimit: 33,
searchTerm: '', searchTerm: '',
username: undefined,
regionCode: 'US', regionCode: 'US',
selectedContacts: [], selectedContacts: [],
}; };
@ -44,6 +45,7 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
...defaults, ...defaults,
candidateContacts: [], candidateContacts: [],
searchTerm: '', searchTerm: '',
username: undefined,
selectedContacts: [getDefaultConversation()], selectedContacts: [getDefaultConversation()],
}).getRowCount(), }).getRowCount(),
0 0
@ -53,6 +55,7 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
...defaults, ...defaults,
candidateContacts: [], candidateContacts: [],
searchTerm: 'foo bar', searchTerm: 'foo bar',
username: undefined,
selectedContacts: [getDefaultConversation()], selectedContacts: [getDefaultConversation()],
}).getRowCount(), }).getRowCount(),
0 0
@ -68,6 +71,7 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
getDefaultConversation(), getDefaultConversation(),
], ],
searchTerm: '', searchTerm: '',
username: undefined,
selectedContacts: [getDefaultConversation()], selectedContacts: [getDefaultConversation()],
}).getRowCount(), }).getRowCount(),
4 4
@ -82,6 +86,7 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
...defaults, ...defaults,
candidateContacts: [], candidateContacts: [],
searchTerm: '', searchTerm: '',
username: undefined,
selectedContacts: [getDefaultConversation()], selectedContacts: [getDefaultConversation()],
}).getRow(0) }).getRow(0)
); );
@ -90,6 +95,7 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
...defaults, ...defaults,
candidateContacts: [], candidateContacts: [],
searchTerm: '', searchTerm: '',
username: undefined,
selectedContacts: [getDefaultConversation()], selectedContacts: [getDefaultConversation()],
}).getRow(99) }).getRow(99)
); );
@ -98,6 +104,7 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
...defaults, ...defaults,
candidateContacts: [], candidateContacts: [],
searchTerm: 'foo bar', searchTerm: 'foo bar',
username: undefined,
selectedContacts: [getDefaultConversation()], selectedContacts: [getDefaultConversation()],
}).getRow(0) }).getRow(0)
); );
@ -112,6 +119,7 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
...defaults, ...defaults,
candidateContacts, candidateContacts,
searchTerm: 'foo bar', searchTerm: 'foo bar',
username: undefined,
selectedContacts: [candidateContacts[1]], selectedContacts: [candidateContacts[1]],
}); });
@ -137,6 +145,7 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
...defaults, ...defaults,
candidateContacts, candidateContacts,
searchTerm: 'foo bar', searchTerm: 'foo bar',
username: undefined,
selectedContacts: candidateContacts.slice(1, 33), selectedContacts: candidateContacts.slice(1, 33),
}); });
@ -159,6 +168,7 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
...defaults, ...defaults,
candidateContacts: [], candidateContacts: [],
searchTerm: '212 555', searchTerm: '212 555',
username: undefined,
selectedContacts: [], selectedContacts: [],
}); });
@ -184,6 +194,7 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
...defaults, ...defaults,
candidateContacts: [], candidateContacts: [],
searchTerm: 'signal.01', searchTerm: 'signal.01',
username: 'signal.01',
selectedContacts: [], selectedContacts: [],
}); });

View file

@ -32,6 +32,7 @@ describe('LeftPaneComposeHelper', () => {
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
uuidFetchState: {}, uuidFetchState: {},
username: undefined,
}); });
assert.strictEqual(helper.getBackAction({ showInbox }), showInbox); assert.strictEqual(helper.getBackAction({ showInbox }), showInbox);
@ -46,6 +47,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
username: undefined,
uuidFetchState: {}, uuidFetchState: {},
}).getRowCount(), }).getRowCount(),
3 3
@ -60,6 +62,7 @@ describe('LeftPaneComposeHelper', () => {
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
uuidFetchState: {}, uuidFetchState: {},
username: undefined,
}).getRowCount(), }).getRowCount(),
6 6
); );
@ -73,6 +76,7 @@ describe('LeftPaneComposeHelper', () => {
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
uuidFetchState: {}, uuidFetchState: {},
username: undefined,
}).getRowCount(), }).getRowCount(),
9 9
); );
@ -86,6 +90,7 @@ describe('LeftPaneComposeHelper', () => {
regionCode: 'US', regionCode: 'US',
searchTerm: 'someone.01', searchTerm: 'someone.01',
uuidFetchState: {}, uuidFetchState: {},
username: 'someone.01',
}).getRowCount(), }).getRowCount(),
8 8
); );
@ -99,6 +104,7 @@ describe('LeftPaneComposeHelper', () => {
regionCode: 'US', regionCode: 'US',
searchTerm: 'foobar.01', searchTerm: 'foobar.01',
uuidFetchState: {}, uuidFetchState: {},
username: 'foobar.01',
}).getRowCount(), }).getRowCount(),
2 2
); );
@ -109,6 +115,7 @@ describe('LeftPaneComposeHelper', () => {
regionCode: 'US', regionCode: 'US',
searchTerm: 'foobar.01', searchTerm: 'foobar.01',
uuidFetchState: {}, uuidFetchState: {},
username: 'foobar.01',
}).getRowCount(), }).getRowCount(),
5 5
); );
@ -119,6 +126,7 @@ describe('LeftPaneComposeHelper', () => {
regionCode: 'US', regionCode: 'US',
searchTerm: 'foobar.01', searchTerm: 'foobar.01',
uuidFetchState: {}, uuidFetchState: {},
username: 'foobar.01',
}).getRowCount(), }).getRowCount(),
7 7
); );
@ -132,6 +140,7 @@ describe('LeftPaneComposeHelper', () => {
regionCode: 'US', regionCode: 'US',
searchTerm: '+16505551234', searchTerm: '+16505551234',
uuidFetchState: {}, uuidFetchState: {},
username: undefined,
}).getRowCount(), }).getRowCount(),
2 2
); );
@ -145,6 +154,7 @@ describe('LeftPaneComposeHelper', () => {
regionCode: 'US', regionCode: 'US',
searchTerm: 'someone.02', searchTerm: 'someone.02',
uuidFetchState: {}, uuidFetchState: {},
username: 'someone.02',
}).getRowCount(), }).getRowCount(),
2 2
); );
@ -158,6 +168,7 @@ describe('LeftPaneComposeHelper', () => {
regionCode: 'US', regionCode: 'US',
searchTerm: '+16505551234', searchTerm: '+16505551234',
uuidFetchState: {}, uuidFetchState: {},
username: undefined,
}).getRowCount(), }).getRowCount(),
5 5
); );
@ -172,6 +183,7 @@ describe('LeftPaneComposeHelper', () => {
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
uuidFetchState: {}, uuidFetchState: {},
username: undefined,
}); });
assert.deepEqual(helper.getRow(0), { assert.deepEqual(helper.getRow(0), {
@ -197,6 +209,7 @@ describe('LeftPaneComposeHelper', () => {
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
uuidFetchState: {}, uuidFetchState: {},
username: undefined,
}); });
assert.deepEqual(helper.getRow(0), { assert.deepEqual(helper.getRow(0), {
@ -236,6 +249,7 @@ describe('LeftPaneComposeHelper', () => {
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
uuidFetchState: {}, uuidFetchState: {},
username: undefined,
}); });
assert.deepEqual(helper.getRow(0), { assert.deepEqual(helper.getRow(0), {
@ -280,6 +294,7 @@ describe('LeftPaneComposeHelper', () => {
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
uuidFetchState: {}, uuidFetchState: {},
username: undefined,
}); });
assert.deepEqual(helper.getRow(1), { assert.deepEqual(helper.getRow(1), {
@ -301,6 +316,7 @@ describe('LeftPaneComposeHelper', () => {
regionCode: 'US', regionCode: 'US',
searchTerm: '+1(650) 555 12 34', searchTerm: '+1(650) 555 12 34',
uuidFetchState: {}, uuidFetchState: {},
username: undefined,
}); });
assert.deepEqual( assert.deepEqual(
@ -327,6 +343,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: username, searchTerm: username,
username,
uuidFetchState: { uuidFetchState: {
[`username:${username}`]: true, [`username:${username}`]: true,
}, },
@ -354,6 +371,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: '+1(650) 555 12 34', searchTerm: '+1(650) 555 12 34',
username: undefined,
uuidFetchState: {}, uuidFetchState: {},
}); });
@ -391,6 +409,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
username: undefined,
uuidFetchState: {}, uuidFetchState: {},
}); });
@ -405,6 +424,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
username: undefined,
uuidFetchState: {}, uuidFetchState: {},
}); });
@ -425,6 +445,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
username: undefined,
uuidFetchState: {}, uuidFetchState: {},
}); });
@ -434,6 +455,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: 'different search', searchTerm: 'different search',
username: undefined,
uuidFetchState: {}, uuidFetchState: {},
}) })
); );
@ -443,6 +465,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: 'last search', searchTerm: 'last search',
username: undefined,
uuidFetchState: {}, uuidFetchState: {},
}) })
); );
@ -454,6 +477,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
username: undefined,
uuidFetchState: {}, uuidFetchState: {},
}); });
@ -463,6 +487,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
username: undefined,
uuidFetchState: {}, uuidFetchState: {},
}) })
); );
@ -474,6 +499,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
username: undefined,
uuidFetchState: {}, uuidFetchState: {},
}); });
@ -483,6 +509,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
username: undefined,
uuidFetchState: {}, uuidFetchState: {},
}) })
); );
@ -492,6 +519,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: '+16505551234', searchTerm: '+16505551234',
username: undefined,
uuidFetchState: {}, uuidFetchState: {},
}) })
); );
@ -503,6 +531,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
username: undefined,
uuidFetchState: {}, uuidFetchState: {},
}); });
@ -512,6 +541,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
username: undefined,
uuidFetchState: {}, uuidFetchState: {},
}) })
); );
@ -523,6 +553,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
username: undefined,
uuidFetchState: {}, uuidFetchState: {},
}); });
@ -532,6 +563,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [getDefaultGroupListItem(), getDefaultGroupListItem()], composeGroups: [getDefaultGroupListItem(), getDefaultGroupListItem()],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
username: undefined,
uuidFetchState: {}, uuidFetchState: {},
}) })
); );
@ -541,6 +573,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [getDefaultGroupListItem(), getDefaultGroupListItem()], composeGroups: [getDefaultGroupListItem(), getDefaultGroupListItem()],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
username: undefined,
uuidFetchState: {}, uuidFetchState: {},
}); });
@ -550,6 +583,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
username: undefined,
uuidFetchState: {}, uuidFetchState: {},
}) })
); );
@ -561,6 +595,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [getDefaultGroupListItem()], composeGroups: [getDefaultGroupListItem()],
regionCode: 'US', regionCode: 'US',
searchTerm: 'soup', searchTerm: 'soup',
username: 'soup',
uuidFetchState: {}, uuidFetchState: {},
}); });
@ -570,6 +605,7 @@ describe('LeftPaneComposeHelper', () => {
composeGroups: [getDefaultGroupListItem(), getDefaultGroupListItem()], composeGroups: [getDefaultGroupListItem(), getDefaultGroupListItem()],
regionCode: 'US', regionCode: 'US',
searchTerm: 'soup', searchTerm: 'soup',
username: 'soup',
uuidFetchState: {}, uuidFetchState: {},
}) })
); );

View file

@ -27,15 +27,6 @@ export enum ConfirmUsernameResult {
ConflictOrGone = 'ConflictOrGone', ConflictOrGone = 'ConflictOrGone',
} }
export function getUsernameFromSearch(searchTerm: string): string | undefined {
try {
window.SignalContext.usernames.hash(searchTerm);
return searchTerm;
} catch {
return undefined;
}
}
export function getNickname(username: string): string | undefined { export function getNickname(username: string): string | undefined {
const match = username.match(/^(.*?)(?:\.|$)/); const match = username.match(/^(.*?)(?:\.|$)/);
if (!match) { if (!match) {

View file

@ -1,7 +1,10 @@
// Copyright 2021 Signal Messenger, LLC // Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import { usernames } from '@signalapp/libsignal-client';
import * as RemoteConfig from '../RemoteConfig'; import * as RemoteConfig from '../RemoteConfig';
import { getNickname } from '../types/Username';
import { parseIntWithFallback } from './parseIntWithFallback'; import { parseIntWithFallback } from './parseIntWithFallback';
export function getMaxNickname(): number { export function getMaxNickname(): number {
@ -13,3 +16,26 @@ export function getMaxNickname(): number {
export function getMinNickname(): number { export function getMinNickname(): number {
return parseIntWithFallback(RemoteConfig.getValue('global.nicknames.min'), 3); return parseIntWithFallback(RemoteConfig.getValue('global.nicknames.min'), 3);
} }
export function getUsernameFromSearch(searchTerm: string): string | undefined {
const nickname = getNickname(searchTerm);
if (nickname == null || nickname.length < getMinNickname()) {
return undefined;
}
let modifiedTerm = searchTerm;
if (searchTerm.endsWith('.')) {
// Allow nicknames without full discriminator
modifiedTerm = `${searchTerm}01`;
} else if (!/\.\d*$/.test(searchTerm)) {
// Allow nicknames without discriminator
modifiedTerm = `${searchTerm}.01`;
}
try {
usernames.hash(modifiedTerm);
return searchTerm;
} catch {
return undefined;
}
}

View file

@ -3,7 +3,6 @@
import { ipcRenderer } from 'electron'; import { ipcRenderer } from 'electron';
import type { MenuItemConstructorOptions } from 'electron'; import type { MenuItemConstructorOptions } from 'electron';
import { usernames } from '@signalapp/libsignal-client';
import type { MenuOptionsType } from '../types/menu'; import type { MenuOptionsType } from '../types/menu';
import type { IPCEventsValuesType } from '../util/createIPCEvents'; import type { IPCEventsValuesType } from '../util/createIPCEvents';
@ -71,7 +70,6 @@ export type MinimalSignalContextType = {
export type SignalContextType = { export type SignalContextType = {
bytes: Bytes; bytes: Bytes;
crypto: Crypto; crypto: Crypto;
usernames: typeof usernames;
i18n: LocalizerType; i18n: LocalizerType;
log: LoggerType; log: LoggerType;
renderWindow?: () => void; renderWindow?: () => void;
@ -83,7 +81,6 @@ export const SignalContext: SignalContextType = {
...MinimalSignalContext, ...MinimalSignalContext,
bytes: new Bytes(), bytes: new Bytes(),
crypto: new Crypto(), crypto: new Crypto(),
usernames,
i18n, i18n,
log: window.SignalContext.log, log: window.SignalContext.log,
setIsCallActive(isCallActive: boolean): void { setIsCallActive(isCallActive: boolean): void {