使用撰寫動作擴充撰寫 UI

除了在使用者閱讀 Gmail 郵件時提供以資訊卡為基礎的介面,擴充 Gmail 的 Google Workspace 外掛程式還能在使用者撰寫新郵件或回覆現有郵件時,提供其他介面。這樣一來,Google Workspace 外掛程式就能自動為使用者撰寫電子郵件。

存取外掛程式撰寫 UI

你可以透過兩種方式查看外掛程式的撰寫 UI。第一種方法是先開啟外掛程式,然後開始撰寫新草稿或回覆郵件。第二種方式是在撰寫草稿時啟動外掛程式。

無論是哪一種情況,外掛程式都會執行外掛程式資訊清單中定義的對應撰寫觸發函式。撰寫觸發函式會為該撰寫動作建構撰寫 UI,然後 Gmail 會向使用者顯示該 UI。

建立撰寫外掛程式

如要為外掛程式新增撰寫功能,請按照下列一般步驟操作:

  1. gmail.composeTrigger 欄位新增至外掛程式指令碼專案的資訊清單,並更新資訊清單範圍,加入撰寫動作所需的範圍。
  2. 實作撰寫觸發函式,在觸發條件觸發時建構撰寫 UI。Compose 觸發函式會傳回單一 Card 物件,或包含 Card 物件的陣列,這些物件構成撰寫動作的 Compose UI。
  3. 實作相關聯的回呼函式,以便對使用者的 Compose UI 互動做出反應。這些函式並非 Compose 動作本身 (只會導致 Compose UI 顯示),而是管理選取 Compose UI 不同元素時所發生情況的個別函式。舉例來說,含有按鈕的 UI 資訊卡通常會具備相關聯的回呼函式,使用者點選該按鈕時就會執行該函式。更新草稿訊息內容的小工具回呼函式應傳回 UpdateDraftActionResponse 物件。

撰寫觸發函式

外掛程式的 Compose UI 建構方式與外掛程式的訊息 UI 相同,都是使用 Apps Script Card 服務建構資訊卡,並在其中填入小工具

您必須實作在資訊清單中定義的 gmail.composeTrigger.selectActions[].runFunction。撰寫觸發函式必須傳回單一 Card 物件,或是包含該動作撰寫 UI 的 Card 物件陣列。這些函式與情境觸發函式非常相似,應以相同方式建構資訊卡。

編寫觸發事件物件

選取撰寫動作時,系統會執行對應的撰寫觸發函式,並將事件物件做為參數傳遞至函式。事件物件可將外掛程式環境和正在撰寫的草稿資訊傳送至觸發函式。

如要瞭解事件物件中的資訊排列方式,請參閱「事件物件結構」。事件物件中包含的資訊部分由 gmail.composeTrigger.draftAccess 資訊清單欄位的值控制:

在進行中的草稿中插入內容

一般來說,Google Workspace 外掛程式撰寫 UI 會提供使用者選項和控制項,協助撰寫郵件。在這些使用案例中,使用者在 UI 中選取項目後,外掛程式會解讀選取項目,並據此更新目前的工作電子郵件草稿。

為方便更新目前的草稿電子郵件,我們已使用下列類別擴充 Card 服務

一般來說,外掛程式的撰寫 UI 會包含「儲存」或「插入」小工具,使用者可以點選這些小工具,表示已在 UI 中完成選取,並希望將所選內容新增至正在撰寫的電子郵件。如要新增這項互動性,小工具應具備相關聯的 Action 物件,指示外掛程式在點選小工具時執行特定回呼函式。您必須實作這些回呼函式。每個回呼函式都應傳回已建構的 UpdateDraftActionResponse 物件,詳細說明要對目前草稿電子郵件進行的變更。

範例 1

下列程式碼片段說明如何建構 Compose UI,以更新目前電子郵件草稿的主旨,以及「收件者」、「副本」和「密件副本」收件者。

    /**
     * Compose trigger function that fires when the compose UI is
     * requested. Builds and returns a compose UI for inserting images.
     *
     * @param {event} e The compose trigger event object. Not used in
     *         this example.
     * @return {Card[]}
     */
    function getComposeUI(e) {
      return [buildComposeCard()];
    }

    /**
     * Build a card to display interactive buttons to allow the user to
     * update the subject, and To, Cc, Bcc recipients.
     *
     * @return {Card}
     */
    function buildComposeCard() {

      var card = CardService.newCardBuilder();
      var cardSection = CardService.newCardSection().setHeader('Update email');
      cardSection.addWidget(
          CardService.newTextButton()
              .setText('Update subject')
              .setOnClickAction(CardService.newAction()
                  .setFunctionName('applyUpdateSubjectAction')));
      cardSection.addWidget(
          CardService.newTextButton()
              .setText('Update To recipients')
              .setOnClickAction(CardService.newAction()
                  .setFunctionName('updateToRecipients')));
      cardSection.addWidget(
          CardService.newTextButton()
              .setText('Update Cc recipients')
              .setOnClickAction(CardService.newAction()
                  .setFunctionName('updateCcRecipients')));
      cardSection.addWidget(
          CardService.newTextButton()
              .setText('Update Bcc recipients')
              .setOnClickAction(CardService.newAction()
                  .setFunctionName('updateBccRecipients')));
      return card.addSection(cardSection).build();
    }

    /**
     * Updates the subject field of the current email when the user clicks
     * on "Update subject" in the compose UI.
     *
     * Note: This is not the compose action that builds a compose UI, but
     * rather an action taken when the user interacts with the compose UI.
     *
     * @return {UpdateDraftActionResponse}
     */
    function applyUpdateSubjectAction() {
      // Get the new subject field of the email.
      // This function is not shown in this example.
      var subject = getSubject();
      var response = CardService.newUpdateDraftActionResponseBuilder()
          .setUpdateDraftSubjectAction(CardService.newUpdateDraftSubjectAction()
              .addUpdateSubject(subject))
          .build();
      return response;
    }

    /**
     * Updates the To recipients of the current email when the user clicks
     * on "Update To recipients" in the compose UI.
     *
     * Note: This is not the compose action that builds a compose UI, but
     * rather an action taken when the user interacts with the compose UI.
     *
     * @return {UpdateDraftActionResponse}
     */
    function applyUpdateToRecipientsAction() {
      // Get the new To recipients of the email.
      // This function is not shown in this example.
      var toRecipients = getToRecipients();
      var response = CardService.newUpdateDraftActionResponseBuilder()
          .setUpdateDraftToRecipientsAction(CardService.newUpdateDraftToRecipientsAction()
              .addUpdateToRecipients(toRecipients))
          .build();
      return response;
    }

    /**
     * Updates the Cc recipients  of the current email when the user clicks
     * on "Update Cc recipients" in the compose UI.
     *
     * Note: This is not the compose action that builds a compose UI, but
     * rather an action taken when the user interacts with the compose UI.
     *
     * @return {UpdateDraftActionResponse}
     */
    function applyUpdateCcRecipientsAction() {
      // Get the new Cc recipients of the email.
      // This function is not shown in this example.
      var ccRecipients = getCcRecipients();
      var response = CardService.newUpdateDraftActionResponseBuilder()
          .setUpdateDraftCcRecipientsAction(CardService.newUpdateDraftCcRecipientsAction()
              .addUpdateToRecipients(ccRecipients))
          .build();
      return response;
    }

    /**
     * Updates the Bcc recipients  of the current email when the user clicks
     * on "Update Bcc recipients" in the compose UI.
     *
     * Note: This is not the compose action that builds a compose UI, but
     * rather an action taken when the user interacts with the compose UI.
     *
     * @return {UpdateDraftActionResponse}
     */
    function applyUpdateBccRecipientsAction() {
      // Get the new Bcc recipients of the email.
      // This function is not shown in this example.
      var bccRecipients = getBccRecipients();
      var response = CardService.newUpdateDraftActionResponseBuilder()
          .setUpdateDraftBccRecipientsAction(CardService.newUpdateDraftBccRecipientsAction()
              .addUpdateToRecipients(bccRecipients))
          .build();
      return response;
    }

範例 2

下列程式碼片段說明如何建構 Compose UI,將圖片插入目前的草稿電子郵件。

    /**
     * Compose trigger function that fires when the compose UI is
     * requested. Builds and returns a compose UI for inserting images.
     *
     * @param {event} e The compose trigger event object. Not used in
     *         this example.
     * @return {Card[]}
     */
    function getInsertImageComposeUI(e) {
      return [buildImageComposeCard()];
    }

    /**
     * Build a card to display images from a third-party source.
     *
     * @return {Card}
     */
    function buildImageComposeCard() {
      // Get a short list of image URLs to display in the UI.
      // This function is not shown in this example.
      var imageUrls = getImageUrls();

      var card = CardService.newCardBuilder();
      var cardSection = CardService.newCardSection().setHeader('My Images');
      for (var i = 0; i < imageUrls.length; i++) {
        var imageUrl = imageUrls[i];
        cardSection.addWidget(
            CardService.newImage()
                .setImageUrl(imageUrl)
                .setOnClickAction(CardService.newAction()
                      .setFunctionName('applyInsertImageAction')
                      .setParameters({'url' : imageUrl})));
      }
      return card.addSection(cardSection).build();
    }

    /**
     * Adds an image to the current draft email when the image is clicked
     * in the compose UI. The image is inserted at the current cursor
     * location. If any content of the email draft is currently selected,
     * it is deleted and replaced with the image.
     *
     * Note: This is not the compose action that builds a compose UI, but
     * rather an action taken when the user interacts with the compose UI.
     *
     * @param {event} e The incoming event object.
     * @return {UpdateDraftActionResponse}
     */
    function applyInsertImageAction(e) {
      var imageUrl = e.parameters.url;
      var imageHtmlContent = '<img style=\"display: block\" src=\"'
           + imageUrl + '\"/>';
      var response = CardService.newUpdateDraftActionResponseBuilder()
          .setUpdateDraftBodyAction(CardService.newUpdateDraftBodyAction()
              .addUpdateContent(
                  imageHtmlContent,
                  CardService.ContentType.MUTABLE_HTML)
              .setUpdateType(
                  CardService.UpdateDraftBodyType.IN_PLACE_INSERT))
          .build();
      return response;
    }