// Copyright 2024 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import type { ReactChild } from 'react'; import React from 'react'; import { LeftPaneHelper } from './LeftPaneHelper'; import type { Row } from '../ConversationList'; import { RowType } from '../ConversationList'; import { SearchInput } from '../SearchInput'; import type { LocalizerType } from '../../types/Util'; import type { ShowConversationType } from '../../state/ducks/conversations'; import type { UUIDFetchStateType } from '../../util/uuidFetchState'; import { isFetchingByUsername } from '../../util/uuidFetchState'; import { drop } from '../../util/drop'; import type { LookupConversationWithoutServiceIdActionsType } from '../../util/lookupConversationWithoutServiceId'; import { Spinner } from '../Spinner'; import { Button } from '../Button'; export type LeftPaneFindByUsernamePropsType = { searchTerm: string; uuidFetchState: UUIDFetchStateType; username: string | undefined; }; type DoLookupActionsType = Readonly<{ showInbox: () => void; showConversation: ShowConversationType; }> & LookupConversationWithoutServiceIdActionsType; export class LeftPaneFindByUsernameHelper extends LeftPaneHelper { private readonly searchTerm: string; private readonly username: string | undefined; private readonly uuidFetchState: UUIDFetchStateType; constructor({ searchTerm, uuidFetchState, username, }: Readonly) { super(); this.searchTerm = searchTerm; this.uuidFetchState = uuidFetchState; this.username = username; } override getHeaderContents({ i18n, startComposing, }: Readonly<{ i18n: LocalizerType; startComposing: () => void; }>): ReactChild { const backButtonLabel = i18n('icu:setGroupMetadata__back-button'); return (
); } override getBackAction({ startComposing, }: { startComposing: () => void; }): undefined | (() => void) { return this.isFetching() ? undefined : startComposing; } override getSearchInput({ i18n, onChangeComposeSearchTerm, ...lookupActions }: Readonly<{ i18n: LocalizerType; onChangeComposeSearchTerm: ( event: React.ChangeEvent ) => unknown; }> & DoLookupActionsType): ReactChild { const placeholder = i18n( 'icu:LeftPaneFindByHelper__placeholder--findByUsername' ); const description = i18n( 'icu:LeftPaneFindByHelper__description--findByUsername' ); return ( { if (ev.key === 'Enter') { drop(this.doLookup(lookupActions)); } }} /> ); } override getFooterContents({ i18n, ...lookupActions }: Readonly<{ i18n: LocalizerType; }> & DoLookupActionsType): ReactChild { return ( ); } getRowCount(): number { return 1; } getRow(): Row { // This puts a blank row for the footer. return { type: RowType.Blank }; } // This is deliberately unimplemented because these keyboard shortcuts shouldn't work in // the composer. The same is true for the "in direction" function below. getConversationAndMessageAtIndex( ..._args: ReadonlyArray ): undefined { return undefined; } getConversationAndMessageInDirection( ..._args: ReadonlyArray ): undefined { return undefined; } shouldRecomputeRowHeights(_old: unknown): boolean { return false; } private async doLookup({ lookupConversationWithoutServiceId, showUserNotFoundModal, setIsFetchingUUID, showInbox, showConversation, }: DoLookupActionsType): Promise { if (!this.username || this.isLookupDisabled()) { return; } const conversationId = await lookupConversationWithoutServiceId({ showUserNotFoundModal, setIsFetchingUUID, type: 'username', username: this.username, }); if (conversationId != null) { showConversation({ conversationId }); showInbox(); } } private isFetching(): boolean { if (this.username != null) { return isFetchingByUsername(this.uuidFetchState, this.username); } return false; } private isLookupDisabled(): boolean { if (this.isFetching()) { return true; } return this.username == null; } } function focusRef(el: HTMLElement | null) { if (el) { el.focus(); } }