Универсальные действия

Универсальные действия — это элементы меню, которые позволяют пользователю открывать новую веб-страницу, отображать новые карточки пользовательского интерфейса или запускать определённую функцию Apps Script при выборе. По принципу действия они очень похожи на действия с карточками , за исключением того, что универсальные действия всегда применяются к каждой карточке в дополнении, независимо от текущего контекста дополнения.

Используя универсальные действия, вы можете гарантировать, что пользователь всегда будет иметь доступ к определённым функциям, независимо от того, с какой частью вашего дополнения он взаимодействует. Вот несколько примеров использования универсальных действий:

  • Откройте веб-страницу настроек (или отобразите карточку настроек).
  • Показывать пользователю справочную информацию.
  • Запустите новый рабочий процесс, например, «Добавить нового клиента».
  • Отобразить карточку, позволяющую пользователю отправить отзыв о дополнении.

Всякий раз, когда у вас есть действие, которое не зависит от текущего контекста, вам следует подумать о том, чтобы сделать его универсальным действием.

Использование универсальных действий

Универсальные действия настраиваются в манифесте проекта вашего дополнения. После настройки универсального действия оно всегда доступно пользователям вашего дополнения. Если пользователь просматривает карточку, заданный вами набор универсальных действий всегда отображается в меню карточки после всех действий , заданных для этой карточки. Универсальные действия отображаются в меню карточек в том же порядке, в котором они определены в манифесте дополнения.

Настройка универсальных действий

Универсальные действия настраиваются в манифесте вашего дополнения; более подробную информацию см. в разделе Манифесты .

Для каждого действия вы указываете текст, который должен отображаться в меню. Затем вы можете указать поле openLink , указывающее, что действие должно непосредственно открывать веб-страницу в новой вкладке. Кроме того, вы можете указать поле runFunction , которое определяет функцию обратного вызова Apps Script, которая будет выполняться при выборе универсального действия.

При использовании runFunction указанная функция обратного вызова обычно выполняет одно из следующих действий:

  • Создает карточки пользовательского интерфейса для немедленного отображения, возвращая созданный объект UniversalActionResponse .
  • Открывает URL, возможно, после выполнения других задач, возвращая построенный объект UniversalActionResponse .
  • Выполняет фоновые задачи, не переключаясь на новую карточку и не открывая URL. В этом случае функция обратного вызова ничего не возвращает.

При вызове функции обратного вызова передается объект события , содержащий информацию об открытой карточке и контексте дополнения.

Пример

В следующем фрагменте кода показан пример манифеста для дополнения Google Workspace, которое использует универсальные действия при расширении возможностей Gmail. Код явно задаёт область действия метаданных, чтобы дополнение могло определить, кто отправил открытое сообщение.

  "oauthScopes": [
    "https://www.googleapis.com/auth/gmail.addons.current.message.metadata"
  ],
  "addOns": {
    "common": {
      "name": "Universal Actions Only Addon",
      "logoUrl": "https://www.example.com/hosted/images/2x/my-icon.png",
      "openLinkUrlPrefixes": [
        "https://www.google.com",
        "https://www.example.com/urlbase"
      ],
      "universalActions": [{
          "label": "Open google.com",
          "openLink": "https://www.google.com"
        }, {
          "label": "Open contact URL",
          "runFunction": "openContactURL"
        }, {
          "label": "Open settings",
          "runFunction": "createSettingsResponse"
        }, {
          "label": "Run background sync",
          "runFunction": "runBackgroundSync"
      }],
      ...
    },
    "gmail": {
      "contextualTriggers": [
        {
          "unconditional": {},
          "onTriggerFunction": "getContextualAddOn"
        }
      ]
    },
    ...
  },
  ...

Три универсальных действия, определенных в предыдущем примере, выполняют следующее:

  • Открыть google.com открывает https://www.google.com в новой вкладке.
  • URL-адрес открытого контакта запускает функцию, которая определяет URL-адрес для открытия, а затем открывает его в новой вкладке с помощью объекта OpenLink . Код формирует URL-адрес на основе адреса электронной почты отправителя.
  • Открытие настроек запускает функцию createSettingsCards() , определённую в проекте скрипта дополнения. Эта функция возвращает допустимый объект UniversalActionResponse , содержащий набор карточек с настройками дополнения и другой информацией. После завершения создания этого объекта пользовательский интерфейс отображает список карточек (см. раздел Возврат нескольких карточек ).
  • Запуск фоновой синхронизации запускает функцию runBackgroundSync() определённую в проекте скрипта дополнения. Эта функция не создаёт карточки; вместо этого она выполняет другие фоновые задачи, не изменяющие пользовательский интерфейс. Поскольку функция не возвращает UniversalActionResponse , пользовательский интерфейс не отображает новую карточку после завершения функции. Вместо этого во время выполнения функции отображается индикатор загрузки.

Вот пример того, как можно создать функции openContactURL() , createSettingsResponse() и runBackgroundSync() :

/**
 * Open a contact URL.
 * @param {Object} e an event object
 * @return {UniversalActionResponse}
 */
function openContactURL(e) {
  // Activate temporary Gmail scopes, in this case so that the
  // open message metadata can be read.
  var accessToken = e.gmail.accessToken;
  GmailApp.setCurrentMessageAccessToken(accessToken);

  // Build URL to open based on a base URL and the sender's email.
  // This URL must be included in the openLinkUrlPrefixes whitelist.
  var messageId = e.gmail.messageId;
  var message = GmailApp.getMessageById(messageId);
  var sender = message.getFrom();
  var url = "https://www.example.com/urlbase/" + sender;
  return CardService.newUniversalActionResponseBuilder()
      .setOpenLink(CardService.newOpenLink()
          .setUrl(url))
      .build();
}

/**
 * Create a collection of cards to control the add-on settings and
 * present other information. These cards are displayed in a list when
 * the user selects the associated "Open settings" universal action.
 *
 * @param {Object} e an event object
 * @return {UniversalActionResponse}
 */
function createSettingsResponse(e) {
  return CardService.newUniversalActionResponseBuilder()
      .displayAddOnCards(
          [createSettingCard(), createAboutCard()])
      .build();
}

/**
 * Create and return a built settings card.
 * @return {Card}
 */
function createSettingCard() {
  return CardService.newCardBuilder()
      .setHeader(CardService.newCardHeader().setTitle('Settings'))
      .addSection(CardService.newCardSection()
          .addWidget(CardService.newSelectionInput()
              .setType(CardService.SelectionInputType.CHECK_BOX)
              .addItem("Ask before deleting contact", "contact", false)
              .addItem("Ask before deleting cache", "cache", false)
              .addItem("Preserve contact ID after deletion", "contactId", false))
          // ... continue adding widgets or other sections here ...
      ).build();   // Don't forget to build the card!
}

/**
 * Create and return a built 'About' informational card.
 * @return {Card}
 */
function createAboutCard() {
  return CardService.newCardBuilder()
      .setHeader(CardService.newCardHeader().setTitle('About'))
      .addSection(CardService.newCardSection()
          .addWidget(CardService.newTextParagraph()
              .setText('This add-on manages contact information. For more '
                  + 'details see the <a href="https://www.example.com/help">'
                  + 'help page</a>.'))
      // ... add other information widgets or sections here ...
      ).build();  // Don't forget to build the card!
}

/**
 * Run background tasks, none of which should alter the UI.
 * Also records the time of sync in the script properties.
 *
 * @param {Object} e an event object
 */
function runBackgroundSync(e) {
  var props = PropertiesService.getUserProperties();
  props.setProperty("syncTime", new Date().toString());

  syncWithContacts();  // Not shown.
  updateCache();       // Not shown.
  validate();          // Not shown.

  // no return value tells the UI to keep showing the current card.
}