通用動作

通用動作是選單項目元素,可讓使用者開啟新網頁、顯示新的 UI 資訊卡,或在選取時執行特定 Apps Script 函式。作業中的做法和資訊卡動作非常類似,但通用動作一律會放入外掛程式中的每張資訊卡,無論目前的外掛程式為何。

透過通用動作,您可以確保使用者隨時都能存取特定功能,無論外掛程式與哪個部分互動。以下是通用動作的幾個應用實例:

  • 開啟設定網頁 (或顯示設定資訊卡)。
  • 向使用者顯示說明資訊。
  • 開始新的工作流程,例如「新增客戶」。
  • 顯示資訊卡,讓使用者針對這個外掛程式提供意見。

每當您執行的動作並非取決於目前結構定義,都應考慮將其設為通用動作。

使用通用動作

通用動作是在外掛程式的專案資訊清單中設定。設定通用動作後,您外掛程式的使用者一律可以使用該動作。如果使用者正在查看資訊卡,您定義的通用動作組合一律會顯示在資訊卡選單中,且在您為該資訊卡定義的資訊卡動作之後。通用動作顯示在資訊卡選單中的順序,與在外掛程式資訊清單中定義的順序相同。

設定通用動作

您可以在外掛程式的資訊清單中設定通用動作,詳情請參閱「資訊清單」一文。

您也可以針對每個動作,指定該動作應在選單中顯示的文字。然後您可以指定 openLink 欄位,表示該動作應直接在新分頁中開啟網頁。或者,您可以指定 runFunction 欄位,指定在選取通用動作時要執行的 Apps Script 回呼函式。

使用 runFunction 時,指定的回呼函式通常會執行以下其中一項操作:

  • 傳回建構的 UniversalActionResponse 物件,建構要立即顯示的 UI 資訊卡。
  • 會在執行其他工作後,傳回建構的 UniversalActionResponse 物件來開啟網址。
  • 執行不會切換至新卡片或開啟網址的背景工作。 在這種情況下,回呼函式不會傳回任何內容。

呼叫回呼函式時,系統會傳遞事件物件,其中包含開啟資訊卡和外掛程式結構定義的相關資訊。

範例

下列程式碼片段為 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
  • 開啟聯絡人網址會執行函式,用於判斷要開啟的網址,然後使用 OpenLink 物件在新分頁中開啟。這個程式碼會使用寄件者的電子郵件地址建立網址。
  • 開啟設定會執行外掛程式指令碼專案中定義的 createSettingsCards() 函式。這個函式會傳回有效的 UniversalActionResponse 物件,其中包含一組具有外掛程式設定和其他資訊的資訊卡。函式完成建構這個物件後,UI 會顯示資訊卡清單 (請參閱傳回多張資訊卡)。
  • 執行背景同步處理會執行外掛程式指令碼專案中定義的 runBackgroundSync() 函式。這個函式不會建構資訊卡,而是執行其他不會變更 UI 的背景工作。由於函式不會傳回 UniversalActionResponse,因此當函式完成時,UI 不會顯示新資訊卡,而是在函式執行時顯示載入指標旋轉圖示。

以下範例說明如何建構 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.
}