255 lines
		
	
	
	
		
			5.8 KiB
			
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			255 lines
		
	
	
	
		
			5.8 KiB
			
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import React from 'react';
 | 
						|
import classNames from 'classnames';
 | 
						|
import { debounce } from 'lodash';
 | 
						|
 | 
						|
import { Avatar } from './Avatar';
 | 
						|
import { LocalizerType } from '../types/Util';
 | 
						|
 | 
						|
export interface PropsType {
 | 
						|
  searchTerm: string;
 | 
						|
  searchConversationName?: string;
 | 
						|
  searchConversationId?: string;
 | 
						|
 | 
						|
  // To be used as an ID
 | 
						|
  ourNumber: string;
 | 
						|
  regionCode: string;
 | 
						|
 | 
						|
  // For display
 | 
						|
  phoneNumber: string;
 | 
						|
  isMe: boolean;
 | 
						|
  name?: string;
 | 
						|
  color: string;
 | 
						|
  verified: boolean;
 | 
						|
  profileName?: string;
 | 
						|
  avatarPath?: string;
 | 
						|
 | 
						|
  i18n: LocalizerType;
 | 
						|
  updateSearchTerm: (searchTerm: string) => void;
 | 
						|
  searchMessages: (
 | 
						|
    query: string,
 | 
						|
    options: {
 | 
						|
      searchConversationId?: string;
 | 
						|
      regionCode: string;
 | 
						|
    }
 | 
						|
  ) => void;
 | 
						|
  searchDiscussions: (
 | 
						|
    query: string,
 | 
						|
    options: {
 | 
						|
      ourNumber: string;
 | 
						|
      noteToSelf: string;
 | 
						|
    }
 | 
						|
  ) => void;
 | 
						|
 | 
						|
  clearConversationSearch: () => void;
 | 
						|
  clearSearch: () => void;
 | 
						|
}
 | 
						|
 | 
						|
export class MainHeader extends React.Component<PropsType> {
 | 
						|
  private readonly inputRef: React.RefObject<HTMLInputElement>;
 | 
						|
 | 
						|
  constructor(props: PropsType) {
 | 
						|
    super(props);
 | 
						|
 | 
						|
    this.inputRef = React.createRef();
 | 
						|
  }
 | 
						|
 | 
						|
  public componentDidUpdate(prevProps: PropsType) {
 | 
						|
    const { searchConversationId } = this.props;
 | 
						|
 | 
						|
    // When user chooses to search in a given conversation we focus the field for them
 | 
						|
    if (
 | 
						|
      searchConversationId &&
 | 
						|
      searchConversationId !== prevProps.searchConversationId
 | 
						|
    ) {
 | 
						|
      this.setFocus();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // tslint:disable-next-line member-ordering
 | 
						|
  public search = debounce((searchTerm: string) => {
 | 
						|
    const {
 | 
						|
      i18n,
 | 
						|
      ourNumber,
 | 
						|
      regionCode,
 | 
						|
      searchDiscussions,
 | 
						|
      searchMessages,
 | 
						|
      searchConversationId,
 | 
						|
    } = this.props;
 | 
						|
 | 
						|
    if (searchDiscussions && !searchConversationId) {
 | 
						|
      searchDiscussions(searchTerm, {
 | 
						|
        noteToSelf: i18n('noteToSelf').toLowerCase(),
 | 
						|
        ourNumber,
 | 
						|
      });
 | 
						|
    }
 | 
						|
 | 
						|
    if (searchMessages) {
 | 
						|
      searchMessages(searchTerm, {
 | 
						|
        searchConversationId,
 | 
						|
        regionCode,
 | 
						|
      });
 | 
						|
    }
 | 
						|
  }, 200);
 | 
						|
 | 
						|
  public updateSearch = (event: React.FormEvent<HTMLInputElement>) => {
 | 
						|
    const {
 | 
						|
      updateSearchTerm,
 | 
						|
      clearConversationSearch,
 | 
						|
      clearSearch,
 | 
						|
      searchConversationId,
 | 
						|
    } = this.props;
 | 
						|
    const searchTerm = event.currentTarget.value;
 | 
						|
 | 
						|
    if (!searchTerm) {
 | 
						|
      if (searchConversationId) {
 | 
						|
        clearConversationSearch();
 | 
						|
      } else {
 | 
						|
        clearSearch();
 | 
						|
      }
 | 
						|
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (updateSearchTerm) {
 | 
						|
      updateSearchTerm(searchTerm);
 | 
						|
    }
 | 
						|
 | 
						|
    if (searchTerm.length < 2) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    this.search(searchTerm);
 | 
						|
  };
 | 
						|
 | 
						|
  public clearSearch = () => {
 | 
						|
    const { clearSearch } = this.props;
 | 
						|
 | 
						|
    clearSearch();
 | 
						|
    this.setFocus();
 | 
						|
  };
 | 
						|
 | 
						|
  public clearConversationSearch = () => {
 | 
						|
    const { clearConversationSearch } = this.props;
 | 
						|
 | 
						|
    clearConversationSearch();
 | 
						|
    this.setFocus();
 | 
						|
  };
 | 
						|
 | 
						|
  public handleKeyUp = (event: React.KeyboardEvent<HTMLInputElement>) => {
 | 
						|
    const {
 | 
						|
      clearConversationSearch,
 | 
						|
      clearSearch,
 | 
						|
      searchConversationId,
 | 
						|
      searchTerm,
 | 
						|
    } = this.props;
 | 
						|
 | 
						|
    if (event.key !== 'Escape') {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (searchConversationId && searchTerm) {
 | 
						|
      clearConversationSearch();
 | 
						|
    } else {
 | 
						|
      clearSearch();
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  public handleXButton = () => {
 | 
						|
    const {
 | 
						|
      searchConversationId,
 | 
						|
      clearConversationSearch,
 | 
						|
      clearSearch,
 | 
						|
    } = this.props;
 | 
						|
 | 
						|
    if (searchConversationId) {
 | 
						|
      clearConversationSearch();
 | 
						|
    } else {
 | 
						|
      clearSearch();
 | 
						|
    }
 | 
						|
 | 
						|
    this.setFocus();
 | 
						|
  };
 | 
						|
 | 
						|
  public setFocus = () => {
 | 
						|
    if (this.inputRef.current) {
 | 
						|
      // @ts-ignore
 | 
						|
      this.inputRef.current.focus();
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  public render() {
 | 
						|
    const {
 | 
						|
      avatarPath,
 | 
						|
      color,
 | 
						|
      i18n,
 | 
						|
      name,
 | 
						|
      phoneNumber,
 | 
						|
      profileName,
 | 
						|
      searchConversationId,
 | 
						|
      searchConversationName,
 | 
						|
      searchTerm,
 | 
						|
    } = this.props;
 | 
						|
 | 
						|
    const placeholder = searchConversationName
 | 
						|
      ? i18n('searchIn', [searchConversationName])
 | 
						|
      : i18n('search');
 | 
						|
 | 
						|
    return (
 | 
						|
      <div className="module-main-header">
 | 
						|
        <Avatar
 | 
						|
          avatarPath={avatarPath}
 | 
						|
          color={color}
 | 
						|
          conversationType="direct"
 | 
						|
          i18n={i18n}
 | 
						|
          name={name}
 | 
						|
          phoneNumber={phoneNumber}
 | 
						|
          profileName={profileName}
 | 
						|
          size={28}
 | 
						|
        />
 | 
						|
        <div className="module-main-header__search">
 | 
						|
          {searchConversationId ? (
 | 
						|
            <button
 | 
						|
              className="module-main-header__search__in-conversation-pill"
 | 
						|
              onClick={this.clearSearch}
 | 
						|
            >
 | 
						|
              <div className="module-main-header__search__in-conversation-pill__avatar-container">
 | 
						|
                <div className="module-main-header__search__in-conversation-pill__avatar" />
 | 
						|
              </div>
 | 
						|
              <div className="module-main-header__search__in-conversation-pill__x-button" />
 | 
						|
            </button>
 | 
						|
          ) : (
 | 
						|
            <button
 | 
						|
              className="module-main-header__search__icon"
 | 
						|
              onClick={this.setFocus}
 | 
						|
            />
 | 
						|
          )}
 | 
						|
          <input
 | 
						|
            type="text"
 | 
						|
            ref={this.inputRef}
 | 
						|
            className={classNames(
 | 
						|
              'module-main-header__search__input',
 | 
						|
              searchTerm
 | 
						|
                ? 'module-main-header__search__input--with-text'
 | 
						|
                : null,
 | 
						|
              searchConversationId
 | 
						|
                ? 'module-main-header__search__input--in-conversation'
 | 
						|
                : null
 | 
						|
            )}
 | 
						|
            placeholder={placeholder}
 | 
						|
            dir="auto"
 | 
						|
            onKeyUp={this.handleKeyUp}
 | 
						|
            value={searchTerm}
 | 
						|
            onChange={this.updateSearch}
 | 
						|
          />
 | 
						|
          {searchTerm ? (
 | 
						|
            <div
 | 
						|
              role="button"
 | 
						|
              className="module-main-header__search__cancel-icon"
 | 
						|
              onClick={this.handleXButton}
 | 
						|
            />
 | 
						|
          ) : null}
 | 
						|
        </div>
 | 
						|
      </div>
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 |