Migrate to private class properties/methods

This commit is contained in:
Jamie Kyle 2025-01-14 11:11:52 -08:00 committed by GitHub
commit aa9f53df57
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
100 changed files with 3795 additions and 3944 deletions

View file

@ -34,29 +34,24 @@ export type LeftPaneArchivePropsType =
| (LeftPaneArchiveBasePropsType & LeftPaneSearchPropsType);
export class LeftPaneArchiveHelper extends LeftPaneHelper<LeftPaneArchivePropsType> {
private readonly archivedConversations: ReadonlyArray<ConversationListItemPropsType>;
private readonly isSearchingGlobally: boolean;
private readonly searchConversation: undefined | ConversationType;
private readonly searchTerm: string;
private readonly searchHelper: undefined | LeftPaneSearchHelper;
private readonly startSearchCounter: number;
readonly #archivedConversations: ReadonlyArray<ConversationListItemPropsType>;
readonly #isSearchingGlobally: boolean;
readonly #searchConversation: undefined | ConversationType;
readonly #searchTerm: string;
readonly #searchHelper: undefined | LeftPaneSearchHelper;
readonly #startSearchCounter: number;
constructor(props: Readonly<LeftPaneArchivePropsType>) {
super();
this.archivedConversations = props.archivedConversations;
this.isSearchingGlobally = props.isSearchingGlobally;
this.searchConversation = props.searchConversation;
this.searchTerm = props.searchTerm;
this.startSearchCounter = props.startSearchCounter;
this.#archivedConversations = props.archivedConversations;
this.#isSearchingGlobally = props.isSearchingGlobally;
this.#searchConversation = props.searchConversation;
this.#searchTerm = props.searchTerm;
this.#startSearchCounter = props.startSearchCounter;
if ('conversationResults' in props) {
this.searchHelper = new LeftPaneSearchHelper(props);
this.#searchHelper = new LeftPaneSearchHelper(props);
}
}
@ -100,7 +95,7 @@ export class LeftPaneArchiveHelper extends LeftPaneHelper<LeftPaneArchivePropsTy
updateSearchTerm: (searchTerm: string) => unknown;
showConversation: ShowConversationType;
}>): ReactChild | null {
if (!this.searchConversation) {
if (!this.#searchConversation) {
return null;
}
@ -111,11 +106,11 @@ export class LeftPaneArchiveHelper extends LeftPaneHelper<LeftPaneArchivePropsTy
endConversationSearch={endConversationSearch}
endSearch={endSearch}
i18n={i18n}
isSearchingGlobally={this.isSearchingGlobally}
searchConversation={this.searchConversation}
searchTerm={this.searchTerm}
isSearchingGlobally={this.#isSearchingGlobally}
searchConversation={this.#searchConversation}
searchTerm={this.#searchTerm}
showConversation={showConversation}
startSearchCounter={this.startSearchCounter}
startSearchCounter={this.#startSearchCounter}
updateSearchTerm={updateSearchTerm}
/>
);
@ -128,8 +123,8 @@ export class LeftPaneArchiveHelper extends LeftPaneHelper<LeftPaneArchivePropsTy
override getPreRowsNode({
i18n,
}: Readonly<{ i18n: LocalizerType }>): ReactChild | null {
if (this.searchHelper) {
return this.searchHelper.getPreRowsNode({ i18n });
if (this.#searchHelper) {
return this.#searchHelper.getPreRowsNode({ i18n });
}
return (
@ -143,16 +138,16 @@ export class LeftPaneArchiveHelper extends LeftPaneHelper<LeftPaneArchivePropsTy
getRowCount(): number {
return (
this.searchHelper?.getRowCount() ?? this.archivedConversations.length
this.#searchHelper?.getRowCount() ?? this.#archivedConversations.length
);
}
getRow(rowIndex: number): undefined | Row {
if (this.searchHelper) {
return this.searchHelper.getRow(rowIndex);
if (this.#searchHelper) {
return this.#searchHelper.getRow(rowIndex);
}
const conversation = this.archivedConversations[rowIndex];
const conversation = this.#archivedConversations[rowIndex];
return conversation
? {
type: RowType.Conversation,
@ -164,14 +159,14 @@ export class LeftPaneArchiveHelper extends LeftPaneHelper<LeftPaneArchivePropsTy
override getRowIndexToScrollTo(
selectedConversationId: undefined | string
): undefined | number {
if (this.searchHelper) {
return this.searchHelper.getRowIndexToScrollTo(selectedConversationId);
if (this.#searchHelper) {
return this.#searchHelper.getRowIndexToScrollTo(selectedConversationId);
}
if (!selectedConversationId) {
return undefined;
}
const result = this.archivedConversations.findIndex(
const result = this.#archivedConversations.findIndex(
conversation => conversation.id === selectedConversationId
);
return result === -1 ? undefined : result;
@ -180,7 +175,8 @@ export class LeftPaneArchiveHelper extends LeftPaneHelper<LeftPaneArchivePropsTy
getConversationAndMessageAtIndex(
conversationIndex: number
): undefined | { conversationId: string } {
const { archivedConversations, searchHelper } = this;
const searchHelper = this.#searchHelper;
const archivedConversations = this.#archivedConversations;
if (searchHelper) {
return searchHelper.getConversationAndMessageAtIndex(conversationIndex);
@ -196,8 +192,8 @@ export class LeftPaneArchiveHelper extends LeftPaneHelper<LeftPaneArchivePropsTy
selectedConversationId: undefined | string,
targetedMessageId: unknown
): undefined | { conversationId: string } {
if (this.searchHelper) {
return this.searchHelper.getConversationAndMessageInDirection(
if (this.#searchHelper) {
return this.#searchHelper.getConversationAndMessageInDirection(
toFind,
selectedConversationId,
targetedMessageId
@ -205,7 +201,7 @@ export class LeftPaneArchiveHelper extends LeftPaneHelper<LeftPaneArchivePropsTy
}
return getConversationInDirection(
this.archivedConversations,
this.#archivedConversations,
toFind,
selectedConversationId
);
@ -213,13 +209,13 @@ export class LeftPaneArchiveHelper extends LeftPaneHelper<LeftPaneArchivePropsTy
shouldRecomputeRowHeights(old: Readonly<LeftPaneArchivePropsType>): boolean {
const hasSearchingChanged =
'conversationResults' in old !== Boolean(this.searchHelper);
'conversationResults' in old !== Boolean(this.#searchHelper);
if (hasSearchingChanged) {
return true;
}
if ('conversationResults' in old && this.searchHelper) {
return this.searchHelper.shouldRecomputeRowHeights(old);
if ('conversationResults' in old && this.#searchHelper) {
return this.#searchHelper.shouldRecomputeRowHeights(old);
}
return false;
@ -251,7 +247,9 @@ export class LeftPaneArchiveHelper extends LeftPaneHelper<LeftPaneArchivePropsTy
!commandAndCtrl &&
shiftKey &&
(key === 'f' || key === 'F') &&
this.archivedConversations.some(({ id }) => id === selectedConversationId)
this.#archivedConversations.some(
({ id }) => id === selectedConversationId
)
) {
searchInConversation(selectedConversationId);

View file

@ -42,31 +42,19 @@ export type LeftPaneChooseGroupMembersPropsType = {
};
export class LeftPaneChooseGroupMembersHelper extends LeftPaneHelper<LeftPaneChooseGroupMembersPropsType> {
private readonly candidateContacts: ReadonlyArray<ConversationType>;
private readonly isPhoneNumberChecked: boolean;
private readonly isUsernameChecked: boolean;
private readonly isShowingMaximumGroupSizeModal: boolean;
private readonly isShowingRecommendedGroupSizeModal: boolean;
private readonly groupSizeRecommendedLimit: number;
private readonly groupSizeHardLimit: number;
private readonly searchTerm: string;
private readonly phoneNumber: ParsedE164Type | undefined;
private readonly username: string | undefined;
private readonly selectedContacts: Array<ConversationType>;
private readonly selectedConversationIdsSet: Set<string>;
private readonly uuidFetchState: UUIDFetchStateType;
readonly #candidateContacts: ReadonlyArray<ConversationType>;
readonly #isPhoneNumberChecked: boolean;
readonly #isUsernameChecked: boolean;
readonly #isShowingMaximumGroupSizeModal: boolean;
readonly #isShowingRecommendedGroupSizeModal: boolean;
readonly #groupSizeRecommendedLimit: number;
readonly #groupSizeHardLimit: number;
readonly #searchTerm: string;
readonly #phoneNumber: ParsedE164Type | undefined;
readonly #username: string | undefined;
readonly #selectedContacts: Array<ConversationType>;
readonly #selectedConversationIdsSet: Set<string>;
readonly #uuidFetchState: UUIDFetchStateType;
constructor({
candidateContacts,
@ -84,27 +72,27 @@ export class LeftPaneChooseGroupMembersHelper extends LeftPaneHelper<LeftPaneCho
}: Readonly<LeftPaneChooseGroupMembersPropsType>) {
super();
this.uuidFetchState = uuidFetchState;
this.groupSizeRecommendedLimit = groupSizeRecommendedLimit - 1;
this.groupSizeHardLimit = groupSizeHardLimit - 1;
this.#uuidFetchState = uuidFetchState;
this.#groupSizeRecommendedLimit = groupSizeRecommendedLimit - 1;
this.#groupSizeHardLimit = groupSizeHardLimit - 1;
this.candidateContacts = candidateContacts;
this.isShowingMaximumGroupSizeModal = isShowingMaximumGroupSizeModal;
this.isShowingRecommendedGroupSizeModal =
this.#candidateContacts = candidateContacts;
this.#isShowingMaximumGroupSizeModal = isShowingMaximumGroupSizeModal;
this.#isShowingRecommendedGroupSizeModal =
isShowingRecommendedGroupSizeModal;
this.searchTerm = searchTerm;
this.#searchTerm = searchTerm;
const isUsernameVisible =
username !== undefined &&
username !== ourUsername &&
this.candidateContacts.every(contact => contact.username !== username);
this.#candidateContacts.every(contact => contact.username !== username);
if (isUsernameVisible) {
this.username = username;
this.#username = username;
}
this.isUsernameChecked = selectedContacts.some(
contact => contact.username === this.username
this.#isUsernameChecked = selectedContacts.some(
contact => contact.username === this.#username
);
const phoneNumber = parseAndFormatPhoneNumber(searchTerm, regionCode);
@ -114,22 +102,22 @@ export class LeftPaneChooseGroupMembersHelper extends LeftPaneHelper<LeftPaneCho
phoneNumber
) {
const { e164 } = phoneNumber;
this.isPhoneNumberChecked =
this.#isPhoneNumberChecked =
phoneNumber.isValid &&
selectedContacts.some(contact => contact.e164 === e164);
const isVisible =
e164 !== ourE164 &&
this.candidateContacts.every(contact => contact.e164 !== e164);
this.#candidateContacts.every(contact => contact.e164 !== e164);
if (isVisible) {
this.phoneNumber = phoneNumber;
this.#phoneNumber = phoneNumber;
}
} else {
this.isPhoneNumberChecked = false;
this.#isPhoneNumberChecked = false;
}
this.selectedContacts = selectedContacts;
this.#selectedContacts = selectedContacts;
this.selectedConversationIdsSet = new Set(
this.#selectedConversationIdsSet = new Set(
selectedContacts.map(contact => contact.id)
);
}
@ -183,7 +171,7 @@ export class LeftPaneChooseGroupMembersHelper extends LeftPaneHelper<LeftPaneCho
onChange={onChangeComposeSearchTerm}
placeholder={i18n('icu:contactSearchPlaceholder')}
ref={focusRef}
value={this.searchTerm}
value={this.#searchTerm}
/>
);
}
@ -200,20 +188,20 @@ export class LeftPaneChooseGroupMembersHelper extends LeftPaneHelper<LeftPaneCho
removeSelectedContact: (conversationId: string) => unknown;
}>): ReactChild {
let modalNode: undefined | ReactChild;
if (this.isShowingMaximumGroupSizeModal) {
if (this.#isShowingMaximumGroupSizeModal) {
modalNode = (
<AddGroupMemberErrorDialog
i18n={i18n}
maximumNumberOfContacts={this.groupSizeHardLimit}
maximumNumberOfContacts={this.#groupSizeHardLimit}
mode={AddGroupMemberErrorDialogMode.MaximumGroupSize}
onClose={closeMaximumGroupSizeModal}
/>
);
} else if (this.isShowingRecommendedGroupSizeModal) {
} else if (this.#isShowingRecommendedGroupSizeModal) {
modalNode = (
<AddGroupMemberErrorDialog
i18n={i18n}
recommendedMaximumNumberOfContacts={this.groupSizeRecommendedLimit}
recommendedMaximumNumberOfContacts={this.#groupSizeRecommendedLimit}
mode={AddGroupMemberErrorDialogMode.RecommendedMaximumGroupSize}
onClose={closeRecommendedGroupSizeModal}
/>
@ -222,9 +210,9 @@ export class LeftPaneChooseGroupMembersHelper extends LeftPaneHelper<LeftPaneCho
return (
<>
{Boolean(this.selectedContacts.length) && (
{Boolean(this.#selectedContacts.length) && (
<ContactPills>
{this.selectedContacts.map(contact => (
{this.#selectedContacts.map(contact => (
<ContactPill
key={contact.id}
acceptedMessageRequest={contact.acceptedMessageRequest}
@ -264,10 +252,10 @@ export class LeftPaneChooseGroupMembersHelper extends LeftPaneHelper<LeftPaneCho
}>): ReactChild {
return (
<Button
disabled={this.hasExceededMaximumNumberOfContacts()}
disabled={this.#hasExceededMaximumNumberOfContacts()}
onClick={startSettingGroupMetadata}
>
{this.selectedContacts.length
{this.#selectedContacts.length
? i18n('icu:chooseGroupMembers__next')
: i18n('icu:chooseGroupMembers__skip')}
</Button>
@ -278,18 +266,18 @@ export class LeftPaneChooseGroupMembersHelper extends LeftPaneHelper<LeftPaneCho
let rowCount = 0;
// Header + Phone Number
if (this.phoneNumber) {
if (this.#phoneNumber) {
rowCount += 2;
}
// Header + Username
if (this.username) {
if (this.#username) {
rowCount += 2;
}
// Header + Contacts
if (this.candidateContacts.length) {
rowCount += 1 + this.candidateContacts.length;
if (this.#candidateContacts.length) {
rowCount += 1 + this.#candidateContacts.length;
}
// Footer
@ -301,7 +289,11 @@ export class LeftPaneChooseGroupMembersHelper extends LeftPaneHelper<LeftPaneCho
}
getRow(actualRowIndex: number): undefined | Row {
if (!this.candidateContacts.length && !this.phoneNumber && !this.username) {
if (
!this.#candidateContacts.length &&
!this.#phoneNumber &&
!this.#username
) {
return undefined;
}
@ -314,7 +306,7 @@ export class LeftPaneChooseGroupMembersHelper extends LeftPaneHelper<LeftPaneCho
let virtualRowIndex = actualRowIndex;
if (this.candidateContacts.length) {
if (this.#candidateContacts.length) {
if (virtualRowIndex === 0) {
return {
type: RowType.Header,
@ -322,12 +314,12 @@ export class LeftPaneChooseGroupMembersHelper extends LeftPaneHelper<LeftPaneCho
};
}
if (virtualRowIndex <= this.candidateContacts.length) {
const contact = this.candidateContacts[virtualRowIndex - 1];
if (virtualRowIndex <= this.#candidateContacts.length) {
const contact = this.#candidateContacts[virtualRowIndex - 1];
const isChecked = this.selectedConversationIdsSet.has(contact.id);
const isChecked = this.#selectedConversationIdsSet.has(contact.id);
const disabledReason =
!isChecked && this.hasSelectedMaximumNumberOfContacts()
!isChecked && this.#hasSelectedMaximumNumberOfContacts()
? ContactCheckboxDisabledReason.MaximumContactsSelected
: undefined;
@ -339,10 +331,10 @@ export class LeftPaneChooseGroupMembersHelper extends LeftPaneHelper<LeftPaneCho
};
}
virtualRowIndex -= 1 + this.candidateContacts.length;
virtualRowIndex -= 1 + this.#candidateContacts.length;
}
if (this.phoneNumber) {
if (this.#phoneNumber) {
if (virtualRowIndex === 0) {
return {
type: RowType.Header,
@ -352,18 +344,18 @@ export class LeftPaneChooseGroupMembersHelper extends LeftPaneHelper<LeftPaneCho
if (virtualRowIndex === 1) {
return {
type: RowType.PhoneNumberCheckbox,
isChecked: this.isPhoneNumberChecked,
isChecked: this.#isPhoneNumberChecked,
isFetching: isFetchingByE164(
this.uuidFetchState,
this.phoneNumber.e164
this.#uuidFetchState,
this.#phoneNumber.e164
),
phoneNumber: this.phoneNumber,
phoneNumber: this.#phoneNumber,
};
}
virtualRowIndex -= 2;
}
if (this.username) {
if (this.#username) {
if (virtualRowIndex === 0) {
return {
type: RowType.Header,
@ -373,9 +365,12 @@ export class LeftPaneChooseGroupMembersHelper extends LeftPaneHelper<LeftPaneCho
if (virtualRowIndex === 1) {
return {
type: RowType.UsernameCheckbox,
isChecked: this.isUsernameChecked,
isFetching: isFetchingByUsername(this.uuidFetchState, this.username),
username: this.username,
isChecked: this.#isUsernameChecked,
isFetching: isFetchingByUsername(
this.#uuidFetchState,
this.#username
),
username: this.#username,
};
}
virtualRowIndex -= 2;
@ -402,13 +397,13 @@ export class LeftPaneChooseGroupMembersHelper extends LeftPaneHelper<LeftPaneCho
return false;
}
private hasSelectedMaximumNumberOfContacts(): boolean {
return this.selectedContacts.length >= this.groupSizeHardLimit;
#hasSelectedMaximumNumberOfContacts(): boolean {
return this.#selectedContacts.length >= this.#groupSizeHardLimit;
}
private hasExceededMaximumNumberOfContacts(): boolean {
#hasExceededMaximumNumberOfContacts(): boolean {
// It should be impossible to reach this state. This is here as a failsafe.
return this.selectedContacts.length > this.groupSizeHardLimit;
return this.#selectedContacts.length > this.#groupSizeHardLimit;
}
}

View file

@ -35,21 +35,14 @@ enum TopButtons {
}
export class LeftPaneComposeHelper extends LeftPaneHelper<LeftPaneComposePropsType> {
private readonly composeContacts: ReadonlyArray<ContactListItemConversationType>;
private readonly composeGroups: ReadonlyArray<GroupListItemConversationType>;
private readonly uuidFetchState: UUIDFetchStateType;
private readonly searchTerm: string;
private readonly phoneNumber: ParsedE164Type | undefined;
private readonly isPhoneNumberVisible: boolean;
private readonly username: string | undefined;
private readonly isUsernameVisible: boolean;
readonly #composeContacts: ReadonlyArray<ContactListItemConversationType>;
readonly #composeGroups: ReadonlyArray<GroupListItemConversationType>;
readonly #uuidFetchState: UUIDFetchStateType;
readonly #searchTerm: string;
readonly #phoneNumber: ParsedE164Type | undefined;
readonly #isPhoneNumberVisible: boolean;
readonly #username: string | undefined;
readonly #isUsernameVisible: boolean;
constructor({
composeContacts,
@ -61,24 +54,24 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<LeftPaneComposePropsTy
}: Readonly<LeftPaneComposePropsType>) {
super();
this.composeContacts = composeContacts;
this.composeGroups = composeGroups;
this.searchTerm = searchTerm;
this.uuidFetchState = uuidFetchState;
this.#composeContacts = composeContacts;
this.#composeGroups = composeGroups;
this.#searchTerm = searchTerm;
this.#uuidFetchState = uuidFetchState;
this.username = username;
this.isUsernameVisible =
this.#username = username;
this.#isUsernameVisible =
Boolean(username) &&
this.composeContacts.every(contact => contact.username !== username);
this.#composeContacts.every(contact => contact.username !== username);
const phoneNumber = parseAndFormatPhoneNumber(searchTerm, regionCode);
if (!username && phoneNumber) {
this.phoneNumber = phoneNumber;
this.isPhoneNumberVisible = this.composeContacts.every(
this.#phoneNumber = phoneNumber;
this.#isPhoneNumberVisible = this.#composeContacts.every(
contact => contact.e164 !== phoneNumber.e164
);
} else {
this.isPhoneNumberVisible = false;
this.#isPhoneNumberVisible = false;
}
}
@ -125,7 +118,7 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<LeftPaneComposePropsTy
onChange={onChangeComposeSearchTerm}
placeholder={i18n('icu:contactSearchPlaceholder')}
ref={focusRef}
value={this.searchTerm}
value={this.#searchTerm}
/>
);
}
@ -143,20 +136,20 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<LeftPaneComposePropsTy
}
getRowCount(): number {
let result = this.composeContacts.length + this.composeGroups.length;
if (this.hasTopButtons()) {
let result = this.#composeContacts.length + this.#composeGroups.length;
if (this.#hasTopButtons()) {
result += 3;
}
if (this.hasContactsHeader()) {
if (this.#hasContactsHeader()) {
result += 1;
}
if (this.hasGroupsHeader()) {
if (this.#hasGroupsHeader()) {
result += 1;
}
if (this.isUsernameVisible) {
if (this.#isUsernameVisible) {
result += 2;
}
if (this.isPhoneNumberVisible) {
if (this.#isPhoneNumberVisible) {
result += 2;
}
@ -165,7 +158,7 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<LeftPaneComposePropsTy
getRow(actualRowIndex: number): undefined | Row {
let virtualRowIndex = actualRowIndex;
if (this.hasTopButtons()) {
if (this.#hasTopButtons()) {
if (virtualRowIndex === 0) {
return { type: RowType.CreateNewGroup };
}
@ -179,7 +172,7 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<LeftPaneComposePropsTy
virtualRowIndex -= 3;
}
if (this.hasContactsHeader()) {
if (this.#hasContactsHeader()) {
if (virtualRowIndex === 0) {
return {
type: RowType.Header,
@ -189,7 +182,7 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<LeftPaneComposePropsTy
virtualRowIndex -= 1;
const contact = this.composeContacts[virtualRowIndex];
const contact = this.#composeContacts[virtualRowIndex];
if (contact) {
return {
type: RowType.Contact,
@ -198,10 +191,10 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<LeftPaneComposePropsTy
};
}
virtualRowIndex -= this.composeContacts.length;
virtualRowIndex -= this.#composeContacts.length;
}
if (this.hasGroupsHeader()) {
if (this.#hasGroupsHeader()) {
if (virtualRowIndex === 0) {
return {
type: RowType.Header,
@ -211,7 +204,7 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<LeftPaneComposePropsTy
virtualRowIndex -= 1;
const group = this.composeGroups[virtualRowIndex];
const group = this.#composeGroups[virtualRowIndex];
if (group) {
return {
type: RowType.SelectSingleGroup,
@ -219,10 +212,10 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<LeftPaneComposePropsTy
};
}
virtualRowIndex -= this.composeGroups.length;
virtualRowIndex -= this.#composeGroups.length;
}
if (this.username && this.isUsernameVisible) {
if (this.#username && this.#isUsernameVisible) {
if (virtualRowIndex === 0) {
return {
type: RowType.Header,
@ -235,16 +228,16 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<LeftPaneComposePropsTy
if (virtualRowIndex === 0) {
return {
type: RowType.UsernameSearchResult,
username: this.username,
username: this.#username,
isFetchingUsername: isFetchingByUsername(
this.uuidFetchState,
this.username
this.#uuidFetchState,
this.#username
),
};
}
}
if (this.phoneNumber && this.isPhoneNumberVisible) {
if (this.#phoneNumber && this.#isPhoneNumberVisible) {
if (virtualRowIndex === 0) {
return {
type: RowType.Header,
@ -257,10 +250,10 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<LeftPaneComposePropsTy
if (virtualRowIndex === 0) {
return {
type: RowType.StartNewConversation,
phoneNumber: this.phoneNumber,
phoneNumber: this.#phoneNumber,
isFetching: isFetchingByE164(
this.uuidFetchState,
this.phoneNumber.e164
this.#uuidFetchState,
this.#phoneNumber.e164
),
};
}
@ -287,8 +280,8 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<LeftPaneComposePropsTy
exProps: Readonly<LeftPaneComposePropsType>
): boolean {
const prev = new LeftPaneComposeHelper(exProps);
const currHeaderIndices = this.getHeaderIndices();
const prevHeaderIndices = prev.getHeaderIndices();
const currHeaderIndices = this.#getHeaderIndices();
const prevHeaderIndices = prev.#getHeaderIndices();
return (
currHeaderIndices.top !== prevHeaderIndices.top ||
@ -299,26 +292,26 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<LeftPaneComposePropsTy
);
}
private getTopButtons(): TopButtons {
if (this.searchTerm) {
#getTopButtons(): TopButtons {
if (this.#searchTerm) {
return TopButtons.None;
}
return TopButtons.Visible;
}
private hasTopButtons(): boolean {
return this.getTopButtons() !== TopButtons.None;
#hasTopButtons(): boolean {
return this.#getTopButtons() !== TopButtons.None;
}
private hasContactsHeader(): boolean {
return Boolean(this.composeContacts.length);
#hasContactsHeader(): boolean {
return Boolean(this.#composeContacts.length);
}
private hasGroupsHeader(): boolean {
return Boolean(this.composeGroups.length);
#hasGroupsHeader(): boolean {
return Boolean(this.#composeGroups.length);
}
private getHeaderIndices(): {
#getHeaderIndices(): {
top?: number;
contact?: number;
group?: number;
@ -333,22 +326,22 @@ export class LeftPaneComposeHelper extends LeftPaneHelper<LeftPaneComposePropsTy
let rowCount = 0;
if (this.hasTopButtons()) {
if (this.#hasTopButtons()) {
top = 0;
rowCount += 3;
}
if (this.hasContactsHeader()) {
if (this.#hasContactsHeader()) {
contact = rowCount;
rowCount += this.composeContacts.length;
rowCount += this.#composeContacts.length;
}
if (this.hasGroupsHeader()) {
if (this.#hasGroupsHeader()) {
group = rowCount;
rowCount += this.composeContacts.length;
rowCount += this.#composeContacts.length;
}
if (this.phoneNumber) {
if (this.#phoneNumber) {
phoneNumber = rowCount;
}
if (this.username) {
if (this.#username) {
username = rowCount;
}

View file

@ -36,17 +36,12 @@ type DoLookupActionsType = Readonly<{
LookupConversationWithoutServiceIdActionsType;
export class LeftPaneFindByPhoneNumberHelper extends LeftPaneHelper<LeftPaneFindByPhoneNumberPropsType> {
private readonly searchTerm: string;
private readonly phoneNumber: ParsedE164Type | undefined;
private readonly regionCode: string | undefined;
private readonly uuidFetchState: UUIDFetchStateType;
private readonly countries: ReadonlyArray<CountryDataType>;
private readonly selectedRegion: string;
readonly #searchTerm: string;
readonly #phoneNumber: ParsedE164Type | undefined;
readonly #regionCode: string | undefined;
readonly #uuidFetchState: UUIDFetchStateType;
readonly #countries: ReadonlyArray<CountryDataType>;
readonly #selectedRegion: string;
constructor({
searchTerm,
@ -57,14 +52,14 @@ export class LeftPaneFindByPhoneNumberHelper extends LeftPaneHelper<LeftPaneFind
}: Readonly<LeftPaneFindByPhoneNumberPropsType>) {
super();
this.searchTerm = searchTerm;
this.uuidFetchState = uuidFetchState;
this.regionCode = regionCode;
this.countries = countries;
this.selectedRegion = selectedRegion;
this.#searchTerm = searchTerm;
this.#uuidFetchState = uuidFetchState;
this.#regionCode = regionCode;
this.#countries = countries;
this.#selectedRegion = selectedRegion;
this.phoneNumber = parseAndFormatPhoneNumber(
this.searchTerm,
this.#phoneNumber = parseAndFormatPhoneNumber(
this.#searchTerm,
selectedRegion || regionCode
);
}
@ -83,7 +78,7 @@ export class LeftPaneFindByPhoneNumberHelper extends LeftPaneHelper<LeftPaneFind
<button
aria-label={backButtonLabel}
className="module-left-pane__header__contents__back-button"
disabled={this.isFetching()}
disabled={this.#isFetching()}
onClick={this.getBackAction({ startComposing })}
title={backButtonLabel}
type="button"
@ -100,7 +95,7 @@ export class LeftPaneFindByPhoneNumberHelper extends LeftPaneHelper<LeftPaneFind
}: {
startComposing: () => void;
}): undefined | (() => void) {
return this.isFetching() ? undefined : startComposing;
return this.#isFetching() ? undefined : startComposing;
}
override getSearchInput({
@ -122,25 +117,25 @@ export class LeftPaneFindByPhoneNumberHelper extends LeftPaneHelper<LeftPaneFind
return (
<div className="LeftPaneFindByPhoneNumberHelper__container">
<CountryCodeSelect
countries={this.countries}
countries={this.#countries}
i18n={i18n}
defaultRegion={this.regionCode ?? ''}
value={this.selectedRegion}
defaultRegion={this.#regionCode ?? ''}
value={this.#selectedRegion}
onChange={onChangeComposeSelectedRegion}
/>
<SearchInput
hasSearchIcon={false}
disabled={this.isFetching()}
disabled={this.#isFetching()}
i18n={i18n}
moduleClassName="LeftPaneFindByPhoneNumberHelper__search-input"
onChange={onChangeComposeSearchTerm}
placeholder={placeholder}
ref={focusRef}
value={this.searchTerm}
value={this.#searchTerm}
onKeyDown={ev => {
if (ev.key === 'Enter') {
drop(this.doLookup(lookupActions));
drop(this.#doLookup(lookupActions));
}
}}
/>
@ -157,10 +152,10 @@ export class LeftPaneFindByPhoneNumberHelper extends LeftPaneHelper<LeftPaneFind
DoLookupActionsType): ReactChild {
return (
<Button
disabled={this.isLookupDisabled()}
onClick={() => drop(this.doLookup(lookupActions))}
disabled={this.#isLookupDisabled()}
onClick={() => drop(this.#doLookup(lookupActions))}
>
{this.isFetching() ? (
{this.#isFetching() ? (
<span aria-label={i18n('icu:loading')} role="status">
<Spinner size="20px" svgSize="small" direction="on-avatar" />
</span>
@ -198,14 +193,14 @@ export class LeftPaneFindByPhoneNumberHelper extends LeftPaneHelper<LeftPaneFind
return false;
}
private async doLookup({
async #doLookup({
lookupConversationWithoutServiceId,
showUserNotFoundModal,
setIsFetchingUUID,
showInbox,
showConversation,
}: DoLookupActionsType): Promise<void> {
if (!this.phoneNumber || this.isLookupDisabled()) {
if (!this.#phoneNumber || this.#isLookupDisabled()) {
return;
}
@ -213,8 +208,8 @@ export class LeftPaneFindByPhoneNumberHelper extends LeftPaneHelper<LeftPaneFind
showUserNotFoundModal,
setIsFetchingUUID,
type: 'e164',
e164: this.phoneNumber.e164,
phoneNumber: this.searchTerm,
e164: this.#phoneNumber.e164,
phoneNumber: this.#searchTerm,
});
if (conversationId != null) {
@ -223,20 +218,20 @@ export class LeftPaneFindByPhoneNumberHelper extends LeftPaneHelper<LeftPaneFind
}
}
private isFetching(): boolean {
if (this.phoneNumber != null) {
return isFetchingByE164(this.uuidFetchState, this.phoneNumber.e164);
#isFetching(): boolean {
if (this.#phoneNumber != null) {
return isFetchingByE164(this.#uuidFetchState, this.#phoneNumber.e164);
}
return false;
}
private isLookupDisabled(): boolean {
if (this.isFetching()) {
#isLookupDisabled(): boolean {
if (this.#isFetching()) {
return true;
}
return !this.phoneNumber?.isValid;
return !this.#phoneNumber?.isValid;
}
}

View file

@ -30,11 +30,9 @@ type DoLookupActionsType = Readonly<{
LookupConversationWithoutServiceIdActionsType;
export class LeftPaneFindByUsernameHelper extends LeftPaneHelper<LeftPaneFindByUsernamePropsType> {
private readonly searchTerm: string;
private readonly username: string | undefined;
private readonly uuidFetchState: UUIDFetchStateType;
readonly #searchTerm: string;
readonly #username: string | undefined;
readonly #uuidFetchState: UUIDFetchStateType;
constructor({
searchTerm,
@ -43,10 +41,10 @@ export class LeftPaneFindByUsernameHelper extends LeftPaneHelper<LeftPaneFindByU
}: Readonly<LeftPaneFindByUsernamePropsType>) {
super();
this.searchTerm = searchTerm;
this.uuidFetchState = uuidFetchState;
this.#searchTerm = searchTerm;
this.#uuidFetchState = uuidFetchState;
this.username = username;
this.#username = username;
}
override getHeaderContents({
@ -63,7 +61,7 @@ export class LeftPaneFindByUsernameHelper extends LeftPaneHelper<LeftPaneFindByU
<button
aria-label={backButtonLabel}
className="module-left-pane__header__contents__back-button"
disabled={this.isFetching()}
disabled={this.#isFetching()}
onClick={this.getBackAction({ startComposing })}
title={backButtonLabel}
type="button"
@ -80,7 +78,7 @@ export class LeftPaneFindByUsernameHelper extends LeftPaneHelper<LeftPaneFindByU
}: {
startComposing: () => void;
}): undefined | (() => void) {
return this.isFetching() ? undefined : startComposing;
return this.#isFetching() ? undefined : startComposing;
}
override getSearchInput({
@ -103,17 +101,17 @@ export class LeftPaneFindByUsernameHelper extends LeftPaneHelper<LeftPaneFindByU
return (
<SearchInput
hasSearchIcon={false}
disabled={this.isFetching()}
disabled={this.#isFetching()}
i18n={i18n}
moduleClassName="LeftPaneFindByUsernameHelper__search-input"
onChange={onChangeComposeSearchTerm}
placeholder={placeholder}
ref={focusRef}
value={this.searchTerm}
value={this.#searchTerm}
description={description}
onKeyDown={ev => {
if (ev.key === 'Enter') {
drop(this.doLookup(lookupActions));
drop(this.#doLookup(lookupActions));
}
}}
/>
@ -129,10 +127,10 @@ export class LeftPaneFindByUsernameHelper extends LeftPaneHelper<LeftPaneFindByU
DoLookupActionsType): ReactChild {
return (
<Button
disabled={this.isLookupDisabled()}
onClick={() => drop(this.doLookup(lookupActions))}
disabled={this.#isLookupDisabled()}
onClick={() => drop(this.#doLookup(lookupActions))}
>
{this.isFetching() ? (
{this.#isFetching() ? (
<span aria-label={i18n('icu:loading')} role="status">
<Spinner size="20px" svgSize="small" direction="on-avatar" />
</span>
@ -170,14 +168,14 @@ export class LeftPaneFindByUsernameHelper extends LeftPaneHelper<LeftPaneFindByU
return false;
}
private async doLookup({
async #doLookup({
lookupConversationWithoutServiceId,
showUserNotFoundModal,
setIsFetchingUUID,
showInbox,
showConversation,
}: DoLookupActionsType): Promise<void> {
if (!this.username || this.isLookupDisabled()) {
if (!this.#username || this.#isLookupDisabled()) {
return;
}
@ -185,7 +183,7 @@ export class LeftPaneFindByUsernameHelper extends LeftPaneHelper<LeftPaneFindByU
showUserNotFoundModal,
setIsFetchingUUID,
type: 'username',
username: this.username,
username: this.#username,
});
if (conversationId != null) {
@ -194,20 +192,20 @@ export class LeftPaneFindByUsernameHelper extends LeftPaneHelper<LeftPaneFindByU
}
}
private isFetching(): boolean {
if (this.username != null) {
return isFetchingByUsername(this.uuidFetchState, this.username);
#isFetching(): boolean {
if (this.#username != null) {
return isFetchingByUsername(this.#uuidFetchState, this.#username);
}
return false;
}
private isLookupDisabled(): boolean {
if (this.isFetching()) {
#isLookupDisabled(): boolean {
if (this.#isFetching()) {
return true;
}
return this.username == null;
return this.#username == null;
}
}

View file

@ -34,25 +34,16 @@ export type LeftPaneInboxPropsType = {
};
export class LeftPaneInboxHelper extends LeftPaneHelper<LeftPaneInboxPropsType> {
private readonly conversations: ReadonlyArray<ConversationListItemPropsType>;
private readonly archivedConversations: ReadonlyArray<ConversationListItemPropsType>;
private readonly pinnedConversations: ReadonlyArray<ConversationListItemPropsType>;
private readonly isAboutToSearch: boolean;
private readonly isSearchingGlobally: boolean;
private readonly startSearchCounter: number;
private readonly searchDisabled: boolean;
private readonly searchTerm: string;
private readonly searchConversation: undefined | ConversationType;
private readonly filterByUnread: boolean;
readonly #conversations: ReadonlyArray<ConversationListItemPropsType>;
readonly #archivedConversations: ReadonlyArray<ConversationListItemPropsType>;
readonly #pinnedConversations: ReadonlyArray<ConversationListItemPropsType>;
readonly #isAboutToSearch: boolean;
readonly #isSearchingGlobally: boolean;
readonly #startSearchCounter: number;
readonly #searchDisabled: boolean;
readonly #searchTerm: string;
readonly #searchConversation: undefined | ConversationType;
readonly #filterByUnread: boolean;
constructor({
conversations,
@ -68,25 +59,25 @@ export class LeftPaneInboxHelper extends LeftPaneHelper<LeftPaneInboxPropsType>
}: Readonly<LeftPaneInboxPropsType>) {
super();
this.conversations = conversations;
this.archivedConversations = archivedConversations;
this.pinnedConversations = pinnedConversations;
this.isAboutToSearch = isAboutToSearch;
this.isSearchingGlobally = isSearchingGlobally;
this.startSearchCounter = startSearchCounter;
this.searchDisabled = searchDisabled;
this.searchTerm = searchTerm;
this.searchConversation = searchConversation;
this.filterByUnread = filterByUnread;
this.#conversations = conversations;
this.#archivedConversations = archivedConversations;
this.#pinnedConversations = pinnedConversations;
this.#isAboutToSearch = isAboutToSearch;
this.#isSearchingGlobally = isSearchingGlobally;
this.#startSearchCounter = startSearchCounter;
this.#searchDisabled = searchDisabled;
this.#searchTerm = searchTerm;
this.#searchConversation = searchConversation;
this.#filterByUnread = filterByUnread;
}
getRowCount(): number {
const headerCount = this.hasPinnedAndNonpinned() ? 2 : 0;
const buttonCount = this.archivedConversations.length ? 1 : 0;
const headerCount = this.#hasPinnedAndNonpinned() ? 2 : 0;
const buttonCount = this.#archivedConversations.length ? 1 : 0;
return (
headerCount +
this.pinnedConversations.length +
this.conversations.length +
this.#pinnedConversations.length +
this.#conversations.length +
buttonCount
);
}
@ -116,17 +107,17 @@ export class LeftPaneInboxHelper extends LeftPaneHelper<LeftPaneInboxPropsType>
clearSearchQuery={clearSearchQuery}
endConversationSearch={endConversationSearch}
endSearch={endSearch}
disabled={this.searchDisabled}
disabled={this.#searchDisabled}
i18n={i18n}
isSearchingGlobally={this.isSearchingGlobally}
searchConversation={this.searchConversation}
searchTerm={this.searchTerm}
isSearchingGlobally={this.#isSearchingGlobally}
searchConversation={this.#searchConversation}
searchTerm={this.#searchTerm}
showConversation={showConversation}
startSearchCounter={this.startSearchCounter}
startSearchCounter={this.#startSearchCounter}
updateSearchTerm={updateSearchTerm}
onFilterClick={updateFilterByUnread}
filterButtonEnabled={!this.searchConversation}
filterPressed={this.filterByUnread}
filterButtonEnabled={!this.#searchConversation}
filterPressed={this.#filterByUnread}
/>
);
}
@ -149,11 +140,13 @@ export class LeftPaneInboxHelper extends LeftPaneHelper<LeftPaneInboxPropsType>
}
getRow(rowIndex: number): undefined | Row {
const { conversations, archivedConversations, pinnedConversations } = this;
const pinnedConversations = this.#pinnedConversations;
const archivedConversations = this.#archivedConversations;
const conversations = this.#conversations;
const archivedConversationsCount = archivedConversations.length;
if (this.hasPinnedAndNonpinned()) {
if (this.#hasPinnedAndNonpinned()) {
switch (rowIndex) {
case 0:
return {
@ -226,9 +219,9 @@ export class LeftPaneInboxHelper extends LeftPaneHelper<LeftPaneInboxPropsType>
const isConversationSelected = (
conversation: Readonly<ConversationListItemPropsType>
) => conversation.id === selectedConversationId;
const hasHeaders = this.hasPinnedAndNonpinned();
const hasHeaders = this.#hasPinnedAndNonpinned();
const pinnedConversationIndex = this.pinnedConversations.findIndex(
const pinnedConversationIndex = this.#pinnedConversations.findIndex(
isConversationSelected
);
if (pinnedConversationIndex !== -1) {
@ -236,11 +229,11 @@ export class LeftPaneInboxHelper extends LeftPaneHelper<LeftPaneInboxPropsType>
return pinnedConversationIndex + headerOffset;
}
const conversationIndex = this.conversations.findIndex(
const conversationIndex = this.#conversations.findIndex(
isConversationSelected
);
if (conversationIndex !== -1) {
const pinnedOffset = this.pinnedConversations.length;
const pinnedOffset = this.#pinnedConversations.length;
const headerOffset = hasHeaders ? 2 : 0;
return conversationIndex + pinnedOffset + headerOffset;
}
@ -250,20 +243,21 @@ export class LeftPaneInboxHelper extends LeftPaneHelper<LeftPaneInboxPropsType>
override requiresFullWidth(): boolean {
const hasNoConversations =
!this.conversations.length &&
!this.pinnedConversations.length &&
!this.archivedConversations.length;
return hasNoConversations || this.isAboutToSearch;
!this.#conversations.length &&
!this.#pinnedConversations.length &&
!this.#archivedConversations.length;
return hasNoConversations || this.#isAboutToSearch;
}
shouldRecomputeRowHeights(old: Readonly<LeftPaneInboxPropsType>): boolean {
return old.pinnedConversations.length !== this.pinnedConversations.length;
return old.pinnedConversations.length !== this.#pinnedConversations.length;
}
getConversationAndMessageAtIndex(
conversationIndex: number
): undefined | { conversationId: string } {
const { conversations, pinnedConversations } = this;
const pinnedConversations = this.#pinnedConversations;
const conversations = this.#conversations;
const conversation =
pinnedConversations[conversationIndex] ||
conversations[conversationIndex - pinnedConversations.length] ||
@ -278,7 +272,7 @@ export class LeftPaneInboxHelper extends LeftPaneHelper<LeftPaneInboxPropsType>
_targetedMessageId: unknown
): undefined | { conversationId: string } {
return getConversationInDirection(
[...this.pinnedConversations, ...this.conversations],
[...this.#pinnedConversations, ...this.#conversations],
toFind,
selectedConversationId
);
@ -295,9 +289,9 @@ export class LeftPaneInboxHelper extends LeftPaneHelper<LeftPaneInboxPropsType>
handleKeydownForSearch(event, options);
}
private hasPinnedAndNonpinned(): boolean {
#hasPinnedAndNonpinned(): boolean {
return Boolean(
this.pinnedConversations.length && this.conversations.length
this.#pinnedConversations.length && this.#conversations.length
);
}
}

View file

@ -50,36 +50,24 @@ export type LeftPaneSearchPropsType = {
searchConversation: undefined | ConversationType;
};
const searchResultKeys: Array<
'conversationResults' | 'contactResults' | 'messageResults'
> = ['conversationResults', 'contactResults', 'messageResults'];
export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType> {
private readonly conversationResults: MaybeLoadedSearchResultsType<ConversationListItemPropsType>;
readonly #conversationResults: MaybeLoadedSearchResultsType<ConversationListItemPropsType>;
readonly #contactResults: MaybeLoadedSearchResultsType<ConversationListItemPropsType>;
readonly #isSearchingGlobally: boolean;
private readonly contactResults: MaybeLoadedSearchResultsType<ConversationListItemPropsType>;
private readonly isSearchingGlobally: boolean;
private readonly messageResults: MaybeLoadedSearchResultsType<{
readonly #messageResults: MaybeLoadedSearchResultsType<{
id: string;
conversationId: string;
type: string;
}>;
private readonly searchConversationName?: string;
private readonly primarySendsSms: boolean;
private readonly searchTerm: string;
private readonly startSearchCounter: number;
private readonly searchDisabled: boolean;
private readonly searchConversation: undefined | ConversationType;
private readonly filterByUnread: boolean;
readonly #searchConversationName?: string;
readonly #primarySendsSms: boolean;
readonly #searchTerm: string;
readonly #startSearchCounter: number;
readonly #searchDisabled: boolean;
readonly #searchConversation: undefined | ConversationType;
readonly #filterByUnread: boolean;
constructor({
contactResults,
@ -96,18 +84,17 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
}: Readonly<LeftPaneSearchPropsType>) {
super();
this.contactResults = contactResults;
this.conversationResults = conversationResults;
this.isSearchingGlobally = isSearchingGlobally;
this.messageResults = messageResults;
this.primarySendsSms = primarySendsSms;
this.searchConversation = searchConversation;
this.searchConversationName = searchConversationName;
this.searchDisabled = searchDisabled;
this.searchTerm = searchTerm;
this.startSearchCounter = startSearchCounter;
this.filterByUnread = filterByUnread;
this.onEnterKeyDown = this.onEnterKeyDown.bind(this);
this.#contactResults = contactResults;
this.#conversationResults = conversationResults;
this.#isSearchingGlobally = isSearchingGlobally;
this.#messageResults = messageResults;
this.#primarySendsSms = primarySendsSms;
this.#searchConversation = searchConversation;
this.#searchConversationName = searchConversationName;
this.#searchDisabled = searchDisabled;
this.#searchTerm = searchTerm;
this.#startSearchCounter = startSearchCounter;
this.#filterByUnread = filterByUnread;
}
override getSearchInput({
@ -135,17 +122,17 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
clearSearchQuery={clearSearchQuery}
endConversationSearch={endConversationSearch}
endSearch={endSearch}
disabled={this.searchDisabled}
disabled={this.#searchDisabled}
i18n={i18n}
isSearchingGlobally={this.isSearchingGlobally}
onEnterKeyDown={this.onEnterKeyDown}
searchConversation={this.searchConversation}
searchTerm={this.searchTerm}
isSearchingGlobally={this.#isSearchingGlobally}
onEnterKeyDown={this.#onEnterKeyDown}
searchConversation={this.#searchConversation}
searchTerm={this.#searchTerm}
showConversation={showConversation}
startSearchCounter={this.startSearchCounter}
startSearchCounter={this.#startSearchCounter}
updateSearchTerm={updateSearchTerm}
filterButtonEnabled={!this.searchConversation}
filterPressed={this.filterByUnread}
filterButtonEnabled={!this.#searchConversation}
filterPressed={this.#filterByUnread}
onFilterClick={updateFilterByUnread}
/>
);
@ -156,7 +143,7 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
}: Readonly<{
i18n: LocalizerType;
}>): ReactChild | null {
const mightHaveSearchResults = this.allResults().some(
const mightHaveSearchResults = this.#allResults().some(
searchResult => searchResult.isLoading || searchResult.results.length
);
@ -164,7 +151,9 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
return null;
}
const { searchConversationName, primarySendsSms, searchTerm } = this;
const searchTerm = this.#searchTerm;
const primarySendsSms = this.#primarySendsSms;
const searchConversationName = this.#searchConversationName;
let noResults: ReactChild;
if (searchConversationName) {
@ -182,11 +171,11 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
);
} else {
let noResultsMessage: string;
if (this.filterByUnread && this.searchTerm.length > 0) {
if (this.#filterByUnread && this.#searchTerm.length > 0) {
noResultsMessage = i18n('icu:noSearchResultsWithUnreadFilter', {
searchTerm,
});
} else if (this.filterByUnread) {
} else if (this.#filterByUnread) {
noResultsMessage = i18n('icu:noSearchResultsOnlyUnreadFilter');
} else {
noResultsMessage = i18n('icu:noSearchResults', {
@ -195,7 +184,7 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
}
noResults = (
<>
{this.filterByUnread && (
{this.#filterByUnread && (
<div
className="module-conversation-list__item--header module-left-pane__no-search-results__unread-header"
aria-label={i18n('icu:conversationsUnreadHeader')}
@ -218,7 +207,7 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
// We need this for Ctrl-T shortcut cycling through parts of app
tabIndex={-1}
className={
this.filterByUnread
this.#filterByUnread
? 'module-left-pane__no-search-results--withHeader'
: 'module-left-pane__no-search-results'
}
@ -230,19 +219,19 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
}
getRowCount(): number {
if (this.isLoading()) {
if (this.#isLoading()) {
// 1 for the header.
return 1 + SEARCH_RESULTS_FAKE_ROW_COUNT;
}
let count = this.allResults().reduce(
let count = this.#allResults().reduce(
(result: number, searchResults) =>
result + getRowCountForLoadedSearchResults(searchResults),
0
);
// The clear unread filter button adds an extra row
if (this.filterByUnread) {
if (this.#filterByUnread) {
count += 1;
}
@ -257,9 +246,11 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
}
getRow(rowIndex: number): undefined | Row {
const { conversationResults, contactResults, messageResults } = this;
const messageResults = this.#messageResults;
const contactResults = this.#contactResults;
const conversationResults = this.#conversationResults;
if (this.isLoading()) {
if (this.#isLoading()) {
if (rowIndex === 0) {
return { type: RowType.SearchResultsLoadingFakeHeader };
}
@ -273,7 +264,7 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
getRowCountForLoadedSearchResults(conversationResults);
const contactRowCount = getRowCountForLoadedSearchResults(contactResults);
const messageRowCount = getRowCountForLoadedSearchResults(messageResults);
const clearFilterButtonRowCount = this.filterByUnread ? 1 : 0;
const clearFilterButtonRowCount = this.#filterByUnread ? 1 : 0;
let rowOffset = 0;
@ -283,7 +274,7 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
return {
type: RowType.Header,
getHeaderText: i18n =>
this.filterByUnread
this.#filterByUnread
? i18n('icu:conversationsUnreadHeader')
: i18n('icu:conversationsHeader'),
};
@ -350,7 +341,7 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
if (rowIndex < rowOffset) {
return {
type: RowType.ClearFilterButton,
isOnNoResultsPage: this.allResults().every(
isOnNoResultsPage: this.#allResults().every(
searchResult =>
searchResult.isLoading || searchResult.results.length === 0
),
@ -361,24 +352,30 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
}
override isScrollable(): boolean {
return !this.isLoading();
return !this.#isLoading();
}
shouldRecomputeRowHeights(old: Readonly<LeftPaneSearchPropsType>): boolean {
const oldSearchPaneHelper = new LeftPaneSearchHelper(old);
const oldIsLoading = oldSearchPaneHelper.isLoading();
const newIsLoading = this.isLoading();
const oldIsLoading = oldSearchPaneHelper.#isLoading();
const newIsLoading = this.#isLoading();
if (oldIsLoading && newIsLoading) {
return false;
}
if (oldIsLoading !== newIsLoading) {
return true;
}
return searchResultKeys.some(
key =>
getRowCountForLoadedSearchResults(old[key]) !==
getRowCountForLoadedSearchResults(this[key])
);
const searchResultsByKey = [
{ current: this.#conversationResults, prev: old.conversationResults },
{ current: this.#contactResults, prev: old.contactResults },
{ current: this.#messageResults, prev: old.messageResults },
];
return searchResultsByKey.some(item => {
return (
getRowCountForLoadedSearchResults(item.prev) !==
getRowCountForLoadedSearchResults(item.current)
);
});
}
getConversationAndMessageAtIndex(
@ -388,7 +385,7 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
return undefined;
}
let pointer = conversationIndex;
for (const list of this.allResults()) {
for (const list of this.#allResults()) {
if (list.isLoading) {
continue;
}
@ -426,25 +423,29 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
handleKeydownForSearch(event, options);
}
private allResults() {
return [this.conversationResults, this.contactResults, this.messageResults];
#allResults() {
return [
this.#conversationResults,
this.#contactResults,
this.#messageResults,
];
}
private isLoading(): boolean {
return this.allResults().some(results => results.isLoading);
#isLoading(): boolean {
return this.#allResults().some(results => results.isLoading);
}
private onEnterKeyDown(
#onEnterKeyDown = (
clearSearchQuery: () => unknown,
showConversation: ShowConversationType
): void {
): void => {
const conversation = this.getConversationAndMessageAtIndex(0);
if (!conversation) {
return;
}
showConversation(conversation);
clearSearchQuery();
}
};
}
function getRowCountForLoadedSearchResults(

View file

@ -38,21 +38,14 @@ export type LeftPaneSetGroupMetadataPropsType = {
};
export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGroupMetadataPropsType> {
private readonly groupAvatar: undefined | Uint8Array;
private readonly groupName: string;
private readonly groupExpireTimer: DurationInSeconds;
private readonly hasError: boolean;
private readonly isCreating: boolean;
private readonly isEditingAvatar: boolean;
private readonly selectedContacts: ReadonlyArray<ContactListItemConversationType>;
private readonly userAvatarData: ReadonlyArray<AvatarDataType>;
readonly #groupAvatar: undefined | Uint8Array;
readonly #groupName: string;
readonly #groupExpireTimer: DurationInSeconds;
readonly #hasError: boolean;
readonly #isCreating: boolean;
readonly #isEditingAvatar: boolean;
readonly #selectedContacts: ReadonlyArray<ContactListItemConversationType>;
readonly #userAvatarData: ReadonlyArray<AvatarDataType>;
constructor({
groupAvatar,
@ -66,14 +59,14 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGr
}: Readonly<LeftPaneSetGroupMetadataPropsType>) {
super();
this.groupAvatar = groupAvatar;
this.groupName = groupName;
this.groupExpireTimer = groupExpireTimer;
this.hasError = hasError;
this.isCreating = isCreating;
this.isEditingAvatar = isEditingAvatar;
this.selectedContacts = selectedContacts;
this.userAvatarData = userAvatarData;
this.#groupAvatar = groupAvatar;
this.#groupName = groupName;
this.#groupExpireTimer = groupExpireTimer;
this.#hasError = hasError;
this.#isCreating = isCreating;
this.#isEditingAvatar = isEditingAvatar;
this.#selectedContacts = selectedContacts;
this.#userAvatarData = userAvatarData;
}
override getHeaderContents({
@ -90,7 +83,7 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGr
<button
aria-label={backButtonLabel}
className="module-left-pane__header__contents__back-button"
disabled={this.isCreating}
disabled={this.#isCreating}
onClick={this.getBackAction({ showChooseGroupMembers })}
title={backButtonLabel}
type="button"
@ -107,7 +100,7 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGr
}: {
showChooseGroupMembers: () => void;
}): undefined | (() => void) {
return this.isCreating ? undefined : showChooseGroupMembers;
return this.#isCreating ? undefined : showChooseGroupMembers;
}
override getPreRowsNode({
@ -134,7 +127,7 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGr
toggleComposeEditingAvatar: () => unknown;
}>): ReactChild {
const [avatarColor] = AvatarColors;
const disabled = this.isCreating;
const disabled = this.#isCreating;
return (
<form
@ -143,14 +136,14 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGr
event.preventDefault();
event.stopPropagation();
if (!this.canCreateGroup()) {
if (!this.#canCreateGroup()) {
return;
}
createGroup();
}}
>
{this.isEditingAvatar && (
{this.#isEditingAvatar && (
<Modal
modalName="LeftPaneSetGroupMetadataHelper.AvatarEditor"
hasXButton
@ -162,7 +155,7 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGr
>
<AvatarEditor
avatarColor={avatarColor}
avatarValue={this.groupAvatar}
avatarValue={this.#groupAvatar}
deleteAvatarFromDisk={composeDeleteAvatarFromDisk}
i18n={i18n}
isGroup
@ -171,7 +164,7 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGr
setComposeGroupAvatar(newAvatar);
toggleComposeEditingAvatar();
}}
userAvatarData={this.userAvatarData}
userAvatarData={this.#userAvatarData}
replaceAvatar={composeReplaceAvatar}
saveAvatarToDisk={composeSaveAvatarToDisk}
/>
@ -179,7 +172,7 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGr
)}
<AvatarPreview
avatarColor={avatarColor}
avatarValue={this.groupAvatar}
avatarValue={this.#groupAvatar}
i18n={i18n}
isEditable
isGroup
@ -196,7 +189,7 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGr
i18n={i18n}
onChangeValue={setComposeGroupName}
ref={focusRef}
value={this.groupName}
value={this.#groupName}
/>
</div>
@ -206,12 +199,12 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGr
</div>
<DisappearingTimerSelect
i18n={i18n}
value={this.groupExpireTimer}
value={this.#groupExpireTimer}
onChange={setComposeGroupExpireTimer}
/>
</section>
{this.hasError && (
{this.#hasError && (
<Alert
body={i18n('icu:setGroupMetadata__error-message')}
i18n={i18n}
@ -231,12 +224,12 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGr
}>): ReactChild {
return (
<Button
disabled={!this.canCreateGroup()}
disabled={!this.#canCreateGroup()}
onClick={() => {
createGroup();
}}
>
{this.isCreating ? (
{this.#isCreating ? (
<span aria-label={i18n('icu:loading')} role="status">
<Spinner size="20px" svgSize="small" direction="on-avatar" />
</span>
@ -248,14 +241,14 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGr
}
getRowCount(): number {
if (!this.selectedContacts.length) {
if (!this.#selectedContacts.length) {
return 0;
}
return this.selectedContacts.length + 2;
return this.#selectedContacts.length + 2;
}
getRow(rowIndex: number): undefined | Row {
if (!this.selectedContacts.length) {
if (!this.#selectedContacts.length) {
return undefined;
}
@ -267,11 +260,11 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGr
}
// This puts a blank row for the footer.
if (rowIndex === this.selectedContacts.length + 1) {
if (rowIndex === this.#selectedContacts.length + 1) {
return { type: RowType.Blank };
}
const contact = this.selectedContacts[rowIndex - 1];
const contact = this.#selectedContacts[rowIndex - 1];
return contact
? {
type: RowType.Contact,
@ -299,8 +292,8 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGr
return false;
}
private canCreateGroup(): boolean {
return !this.isCreating && Boolean(this.groupName.trim());
#canCreateGroup(): boolean {
return !this.#isCreating && Boolean(this.#groupName.trim());
}
}