Mở rộng giao diện người dùng soạn bằng tác vụ soạn

Ngoài việc cung cấp giao diện dựa trên thẻ khi người dùng đang đọc thư trên Gmail, Tiện ích bổ sung của Google Workspace giúp mở rộng Gmail còn có thể cung cấp một giao diện khác khi người dùng soạn thư mới hoặc trả lời thư hiện có. Điều này cho phép Tiện ích bổ sung của Google Workspace tự động hoá tác vụ soạn email cho người dùng.

Truy cập vào giao diện người dùng Compose của tiện ích bổ sung

Có hai cách để xem giao diện người dùng Compose của tiện ích bổ sung. Cách đầu tiên là bắt đầu soạn một bản nháp hoặc thư trả lời mới trong khi tiện ích bổ sung đang mở. Cách thứ hai là bắt đầu tiện ích bổ sung trong khi soạn bản nháp.

Cả hai trường hợp đều khiến tiện ích bổ sung thực thi hàm kích hoạt Compose tương ứng, được xác định trong tệp kê khai của tiện ích bổ sung. Hàm kích hoạt Compose tạo giao diện người dùng Compose cho thao tác soạn đó. Sau đó, Gmail sẽ hiển thị giao diện này cho người dùng.

Xây dựng tiện ích bổ sung Compose

Bạn có thể thêm chức năng Compose vào một tiện ích bổ sung bằng cách làm theo các bước chung sau:

  1. Thêm trường gmail.composeTrigger vào tệp kê khai của dự án tập lệnh tiện ích bổ sung và cập nhật phạm vi tệp kê khai để bao gồm những phạm vi cần thiết cho các thao tác soạn.
  2. Triển khai hàm của điều kiện kích hoạt Compose để tạo giao diện người dùng trong Compose khi điều kiện kích hoạt kích hoạt. Các hàm kích hoạt Compose trả về một đối tượng Card hoặc một mảng các đối tượng Card có chứa giao diện người dùng Compose cho thao tác soạn thư.
  3. Triển khai các hàm callback liên kết cần thiết để phản ứng với các hoạt động tương tác trên giao diện người dùng Compose của người dùng. Các hàm này không phải là chính thao tác Compose (chỉ khiến giao diện người dùng Compose xuất hiện); thay vào đó, đây là các hàm riêng lẻ chi phối điều gì sẽ xảy ra khi các thành phần khác nhau của giao diện người dùng Compose được chọn. Ví dụ: Thẻ giao diện người dùng chứa một nút thường có hàm callback được liên kết. Hàm này sẽ thực thi khi người dùng nhấp vào nút đó. Hàm callback cho các tiện ích cập nhật nội dung thông báo nháp sẽ trả về một đối tượng UpdateDraftActionResponse.

Hàm kích hoạt Compose

Giao diện người dùng soạn thư của tiện ích bổ sung được xây dựng tương tự như giao diện người dùng thông báo của tiện ích bổ sung — sử dụng dịch vụ Thẻ Apps Script để tạo thẻ và điền các tiện ích vào chúng.

Bạn phải triển khai gmail.composeTrigger.selectActions[].runFunction mà bạn xác định trong tệp kê khai. Hàm kích hoạt Compose phải trả về một đối tượng Card hoặc một mảng các đối tượng Card bao gồm giao diện người dùng Compose cho thao tác đó. Các hàm này rất giống với hàm kích hoạt theo ngữ cảnh và nên tạo thẻ theo cách tương tự.

Đối tượng sự kiện kích hoạt Compose

Khi được chọn, thao tác Compose sẽ thực thi hàm kích hoạt Compose tương ứng và truyền cho hàm một đối tượng sự kiện dưới dạng thông số. Đối tượng sự kiện có thể mang thông tin về ngữ cảnh tiện ích bổ sung và bản nháp đang được soạn cho hàm kích hoạt.

Xem bài viết Cấu trúc đối tượng sự kiện để biết thông tin chi tiết về cách sắp xếp thông tin trong đối tượng sự kiện. Thông tin có trong đối tượng sự kiện một phần được kiểm soát bởi giá trị của trường tệp kê khai gmail.composeTrigger.draftAccess:

  • Nếu trường tệp kê khai gmail.composeTrigger.draftAccessNONE hoặc không được đưa vào, thì đối tượng sự kiện sẽ chỉ có rất ít thông tin.

  • Nếu bạn đặt gmail.composeTrigger.draftAccess thành METADATA, thì đối tượng sự kiện được chuyển đến hàm kích hoạt soạn thư sẽ được điền sẵn danh sách người nhận email đang được soạn.

https://www.googleapis.com/auth/gmail.addons.current.message.metadata

Chèn nội dung vào các bản nháp đang hoạt động

Thông thường, giao diện người dùng soạn tin nhắn của Tiện ích bổ sung của Google Workspace cung cấp các tuỳ chọn và chế độ kiểm soát cho người dùng để giúp soạn tin nhắn. Đối với những trường hợp sử dụng này, sau khi người dùng đã lựa chọn trong giao diện người dùng, tiện ích bổ sung sẽ diễn giải các lựa chọn và cập nhật bản nháp email hiện tại cho phù hợp.

Để giúp bạn cập nhật email nháp hiện tại dễ dàng hơn, Dịch vụ thẻ đã được mở rộng với các lớp sau:

Thông thường, một tiện ích bổ sung trên Compose bao gồm một tiện ích "Lưu" hoặc "Chèn" mà người dùng có thể nhấp vào để cho biết họ đã chọn xong giao diện người dùng và muốn thêm lựa chọn vào email họ đang soạn. Để thêm hoạt động tương tác này, tiện ích phải có một đối tượng Action được liên kết để hướng dẫn tiện ích bổ sung chạy một hàm callback cụ thể khi người dùng nhấp vào tiện ích. Bạn phải triển khai các hàm callback này. Mỗi hàm callback sẽ trả về một đối tượng UpdateDraftActionResponse đã tạo cho biết thông tin chi tiết về những thay đổi cần thực hiện đối với email nháp hiện tại.

Ví dụ 1

Đoạn mã sau đây cho biết cách xây dựng giao diện người dùng khi soạn thư để cập nhật tiêu đề và người nhận đến, Cc, Bcc của thư nháp hiện tại.

    /**
     * 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;
    }

Ví dụ 2

Đoạn mã sau đây cho biết cách tạo giao diện người dùng soạn thư để chèn hình ảnh vào email nháp hiện tại.

    /**
     * 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;
    }