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

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

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

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

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

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

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

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

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

Для каждого действия вы указываете текст, который должен появиться в меню этого действия. Затем вы можете указать поле 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.
}