chromium/chrome/browser/resources/chromeos/emoji_picker/emoji_picker_api_proxy.ts

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {Url} from 'chrome://resources/mojo/url/mojom/url.mojom-webui.js';

import {Category, HistoryItem, PageHandlerFactory, PageHandlerRemote, Status, TenorGifResponse} from './emoji_picker.mojom-webui.js';
import {EmojiSearch} from './emoji_search.mojom-webui.js';
import {NewWindowProxy} from './new_window_proxy.mojom-webui.js';
import {EmojiVariants, GifSubcategoryData, VisualContent} from './types.js';

const HELP_CENTRE_URL = 'https://support.google.com/chrome?p=palette';

export class EmojiPickerApiProxy {
  private handler = new PageHandlerRemote();
  private newWindowProxy = NewWindowProxy.getRemote();
  // TODO(b/309343774): Once search is always on, remove function wrapper.
  private searchProxy = () => EmojiSearch.getRemote();
  static instance: EmojiPickerApiProxy|null = null;
  constructor() {
    const factory = PageHandlerFactory.getRemote();
    factory.createPageHandler(this.handler.$.bindNewPipeAndPassReceiver());
  }

  showUi() {
    this.handler.showUI();
  }

  insertEmoji(emoji: string, isVariant: boolean, searchLength: number) {
    this.handler.insertEmoji(emoji, isVariant, searchLength);
  }

  insertGif(gif: Url) {
    this.handler.insertGif(gif);
  }

  isIncognitoTextField() {
    return this.handler.isIncognitoTextField();
  }

  getFeatureList() {
    return this.handler.getFeatureList();
  }

  async getCategories(): Promise<{gifCategories: GifSubcategoryData[]}> {
    const {gifCategories} = await this.handler.getCategories();
    return {
      gifCategories: gifCategories.map((category) => ({name: category})),
    };
  }

  getFeaturedGifs(pos?: string):
      Promise<{status: Status, featuredGifs: TenorGifResponse}> {
    if (!navigator.onLine) {
      return Promise.resolve({
        status: Status.kNetError,
        featuredGifs: {
          next: '',
          results: [],
        },
      });
    }
    return this.handler.getFeaturedGifs(pos || null);
  }

  searchGifs(query: string, pos?: string):
      Promise<{status: Status, searchGifs: TenorGifResponse}> {
    if (!navigator.onLine) {
      return Promise.resolve({
        status: Status.kNetError,
        searchGifs: {
          next: '',
          results: [],
        },
      });
    }

    // Avoid sending blank queries to the backend.
    if (query.trim().length === 0) {
      return Promise.resolve({
        status: Status.kHttpOk,
        searchGifs: {
          next: '',
          results: [],
        },
      });
    }

    return this.handler.searchGifs(query, pos || null);
  }

  searchEmoji(query: string) {
    // TODO(b/346457889): Add multilingual search for emoji picker.
    // For now assume English.
    return this.searchProxy().searchEmoji(query, ['en']);
  }

  /** @override */
  getGifsByIds(ids: string[]):
      Promise<{status: Status, selectedGifs: VisualContent[]}> {
    return this.handler.getGifsByIds(ids);
  }

  openHelpCentreArticle(): void {
    this.newWindowProxy.openUrl({
      url: HELP_CENTRE_URL,
    });
  }

  getInitialCategory(): Promise<{category: Category}> {
    return this.handler.getInitialCategory();
  }

  getInitialQuery(): Promise<{query: string}> {
    return this.handler.getInitialQuery();
  }

  updateHistoryInPrefs(category: Category, history: HistoryItem[]): void {
    this.handler.updateHistoryInPrefs(category, history);
  }

  updatePreferredVariantsInPrefs(preferredVariants: Record<string, string>):
      void {
    this.handler.updatePreferredVariantsInPrefs(
        Object.keys(preferredVariants).map(base => ({
                                             'base': base,
                                             'variant': preferredVariants[base],
                                           })));
  }

  getHistoryFromPrefs(category: Category): Promise<{history: HistoryItem[]}> {
    return this.handler.getHistoryFromPrefs(category);
  }

  onUiFullyLoaded(): void {
    this.handler.onUiFullyLoaded();
  }

  convertTenorGifsToEmoji(gifs: TenorGifResponse): EmojiVariants[] {
    return gifs.results.map(({
                              id,
                              url,
                              previewSize,
                              contentDescription,
                            }) => ({
                              base: {
                                visualContent: {
                                  id,
                                  url,
                                  previewSize,
                                },
                                name: contentDescription,
                              },
                              alternates: [],
                            }));
  }

  static getInstance(): EmojiPickerApiProxy {
    if (EmojiPickerApiProxy.instance === null) {
      EmojiPickerApiProxy.instance = new EmojiPickerApiProxy();
    }
    return EmojiPickerApiProxy.instance;
  }

  static setInstance(instance: EmojiPickerApiProxy): void {
    EmojiPickerApiProxy.instance = instance;
  }
}