Ações universais

As ações universais são elementos de item de menu que permitem ao usuário abrir uma nova página da Web, mostrar novos cards de IU ou executar uma função específica do Apps Script quando selecionada. Em operação, elas são muito semelhantes às ações de cartão, exceto pelo fato de que as ações universais são sempre colocadas em todos os cartões do complemento, independente do contexto atual do complemento.

Ao usar ações universais, você garante que o usuário sempre tenha acesso a certas funcionalidades, independentemente da parte do complemento com que ele interage. Confira alguns exemplos de casos de uso para ações universais:

  • Abra uma página da Web de configurações (ou exiba um card de configurações).
  • Mostre informações de ajuda ao usuário.
  • Inicie um novo fluxo de trabalho, como "Adicionar novo cliente".
  • Mostre um card que permite que um usuário envie feedback sobre o complemento.

Sempre que você tiver uma ação que não depende do contexto atual, considere torná-la uma ação universal.

Como usar ações universais

As ações universais são configuradas no manifesto do projeto do complemento. Depois de configurar uma ação universal, ela estará sempre disponível para os usuários do seu complemento. Se o usuário estiver visualizando um card, o conjunto de ações universais definido por você sempre aparecerá no menu do card, após todas as ações definidas para o card. As ações universais aparecem nos menus dos cards na mesma ordem em que são definidas no manifesto do complemento.

Como configurar ações universais

Você configura ações universais no manifesto do complemento. Consulte Manifestos para mais detalhes.

Para cada ação, especifique o texto que aparece no menu dela. Em seguida, você pode especificar um campo openLink indicando que a ação abrirá diretamente uma página da Web em uma nova guia. Outra opção é definir um campo runFunction com uma função de callback do Apps Script a ser executada quando a ação universal for selecionada.

Quando runFunction é usado, a função de callback especificada geralmente realiza uma das seguintes ações:

  • Cria cards de IU para serem exibidos imediatamente retornando um objeto UniversalActionResponse criado.
  • Abre um URL, talvez depois de realizar outras tarefas, retornando um objeto UniversalActionResponse criado.
  • Executa tarefas em segundo plano que não abrem um URL nem para um novo card. Nesse caso, a função de callback não retorna nada.

Quando chamada, a função de callback recebe um objeto de evento contendo informações sobre o cartão aberto e o contexto do complemento.

Exemplo

O snippet de código a seguir mostra um exemplo de trecho do manifesto de um complemento do Google Workspace que usa ações universais ao estender o Gmail. O código define explicitamente um escopo de metadados para que o complemento possa determinar quem enviou a mensagem aberta.

  "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"
        }
      ]
    },
    ...
  },
  ...

As três ações universais definidas no exemplo anterior fazem o seguinte:

  • Abrir google.com abre https://www.google.com em uma nova guia.
  • Open Contact URL executa uma função que determina qual URL será aberto e, em seguida, o abre em uma nova guia usando um objeto OpenLink. O código cria o URL usando o endereço de e-mail do remetente.
  • Abrir configurações executa a função createSettingsCards() definida no projeto de script de complemento. Essa função retorna um objeto UniversalActionResponse válido que contém um conjunto de cartões com configuração de complemento e outras informações. Depois que a função terminar de criar esse objeto, a interface exibirá a lista de cards. Consulte Como retornar vários cartões.
  • Executar a sincronização em segundo plano executa a função runBackgroundSync() definida no projeto de script do complemento. Essa função não cria cards. Em vez disso, ela executa algumas outras tarefas em segundo plano que não mudam a interface. Como a função não retorna um UniversalActionResponse, a interface não mostra um novo card quando a função é concluída. Em vez disso, a interface mostra um ícone de carregamento indicador de carregamento enquanto a função está em execução.

Veja um exemplo de como você pode construir as funções openContactURL(), createSettingsResponse() e 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.
}