گسترش رابط کاربری نوشتن با اقدامات نوشتن

علاوه بر ارائه رابط کاربری مبتنی بر کارت هنگام خواندن پیام جیمیل توسط کاربر، افزونه‌های Google Workspace که جیمیل را توسعه می‌دهند، می‌توانند رابط کاربری دیگری را هنگام نوشتن پیام‌های جدید یا پاسخ دادن به پیام‌های موجود توسط کاربر ارائه دهند. این امر به افزونه‌های Google Workspace اجازه می‌دهد تا وظیفه نوشتن ایمیل برای کاربر را خودکار کنند.

دسترسی به رابط کاربری افزونه برای نوشتن

دو راه برای مشاهده رابط کاربری نوشتن یک افزونه وجود دارد. راه اول این است که در حالی که افزونه از قبل باز است، شروع به نوشتن یک پیش‌نویس یا پاسخ جدید کنید. راه دوم این است که افزونه را هنگام نوشتن پیش‌نویس شروع کنید.

در هر صورت، افزونه تابع مربوط به compose trigger را که در فایل manifest افزونه تعریف شده است، اجرا می‌کند. تابع compose trigger رابط کاربری compose را برای آن عمل compose می‌سازد که سپس Gmail آن را به کاربر نمایش می‌دهد.

ساخت افزونه‌ی نوشتن

با دنبال کردن این مراحل کلی می‌توانید قابلیت نوشتن را به یک افزونه اضافه کنید:

  1. فیلد gmail.composeTrigger را به اسکریپت افزونه در مانیفست پروژه اضافه کنید و محدوده‌های مانیفست را به‌روزرسانی کنید تا موارد مورد نیاز برای اقدامات نوشتن را شامل شود.
  2. یک تابع ماشه نوشتن (compose trigger function) پیاده‌سازی کنید که هنگام فعال شدن ماشه، یک رابط کاربری نوشتن (compose UI) ایجاد کند. توابع ماشه نوشتن (Compose trigger functions) یا یک شیء Card واحد یا آرایه‌ای از اشیاء Card را برمی‌گردانند که رابط کاربری نوشتن (compose UI) را برای عمل نوشتن (compose action) تشکیل می‌دهند.
  3. توابع فراخوانی مرتبط مورد نیاز برای واکنش به تعاملات رابط کاربری نوشتن کاربر را پیاده‌سازی کنید. این توابع، خودِ عمل نوشتن نیستند (که فقط باعث نمایش رابط کاربری نوشتن می‌شود)؛ بلکه توابع منفردی هستند که تعیین می‌کنند هنگام انتخاب عناصر مختلف رابط کاربری نوشتن چه اتفاقی بیفتد. به عنوان مثال، یک کارت رابط کاربری حاوی یک دکمه معمولاً یک تابع فراخوانی مرتبط دارد که هنگام کلیک کاربر بر روی آن دکمه اجرا می‌شود. تابع فراخوانی برای ویجت‌هایی که محتوای پیام پیش‌نویس را به‌روزرسانی می‌کنند، باید یک شیء UpdateDraftActionResponse برگرداند.

تابع ماشه را بنویسید

رابط کاربری نوشتن یک افزونه به همان روشی ساخته می‌شود که رابط کاربری پیام افزونه ساخته می‌شود—با استفاده از سرویس Apps Script Card برای ساخت کارت‌ها و پر کردن آنها با ویجت‌ها .

شما باید gmail.composeTrigger.selectActions[].runFunction را که در مانیفست خود تعریف می‌کنید، پیاده‌سازی کنید. تابع ماشه compose باید یا یک شیء Card واحد یا آرایه‌ای از اشیاء Card را که رابط کاربری compose را برای آن اکشن تشکیل می‌دهند، برگرداند. این توابع بسیار شبیه به توابع ماشه متنی هستند و باید کارت‌ها را به همان روش بسازند.

اشیاء رویداد ماشه را بنویسید

وقتی یک عمل نوشتن انتخاب می‌شود، تابع ماشه نوشتن مربوطه را اجرا می‌کند و یک شیء رویداد را به عنوان پارامتر به تابع ارسال می‌کند. شیء رویداد می‌تواند اطلاعاتی در مورد زمینه افزونه و پیش‌نویس در حال نوشتن را به تابع ماشه منتقل کند.

برای جزئیات بیشتر در مورد نحوه چیدمان اطلاعات در شیء رویداد، به ساختار شیء رویداد مراجعه کنید. اطلاعات موجود در شیء رویداد تا حدی توسط مقدار فیلد مانیفست gmail.composeTrigger.draftAccess کنترل می‌شود:

  • اگر فیلد مانیفست gmail.composeTrigger.draftAccess NONE باشد یا شامل نشود، شیء رویداد فقط اطلاعات حداقلی را در خود جای می‌دهد.

  • اگر gmail.composeTrigger.draftAccess روی METADATA تنظیم شده باشد، شیء رویداد ارسالی به تابع تریگر compose با فهرست گیرندگان ایمیل در حال نگارش پر می‌شود.

درج محتوا در پیش‌نویس‌های فعال

معمولاً رابط کاربری نوشتن ایمیل افزونه‌ی Google Workspace، گزینه‌ها و کنترل‌هایی را در اختیار کاربر قرار می‌دهد که به نوشتن پیام کمک می‌کند. برای این موارد استفاده، پس از اینکه کاربر در رابط کاربری انتخاب‌هایی انجام داد، افزونه انتخاب‌ها را تفسیر کرده و پیش‌نویس ایمیل فعلی را بر اساس آن به‌روزرسانی می‌کند.

برای آسان‌تر کردن به‌روزرسانی ایمیل پیش‌نویس فعلی، سرویس کارت با کلاس‌های زیر گسترش یافته است:

  • ContentType ) — یک enum که مشخص می‌کند آیا محتوای HTML تغییرپذیر، HTML تغییرناپذیر (که کاربران Gmail نمی‌توانند آن را ویرایش کنند) یا متن ساده اضافه شود.
  • UpdateDraftActionResponse — نشان‌دهنده‌ی پاسخی به عملی است که پیش‌نویس ایمیل فعلی را به‌روزرسانی می‌کند.
  • UpdateDraftActionResponseBuilder — سازنده‌ای برای اشیاء UpdateDraftActionResponse .
  • UpdateDraftBodyAction — نشان دهنده عملی است که بدنه ایمیل پیش نویس فعلی را به روز می کند.
  • UpdateDraftBodyType — یک enum که نحوه تغییر بدنه را تعریف می‌کند.
  • UpdateDraftSubjectAction — نشان دهنده عملی است که فیلد موضوع ایمیل پیش نویس فعلی را به روز می کند.
  • UpdateDraftToRecipientsAction — نشان دهنده عملی است که گیرنده‌های To ایمیل پیش‌نویس فعلی را به‌روزرسانی می‌کند.
  • UpdateDraftCcRecipientsAction — نشان دهنده عملی است که گیرندگان Cc ایمیل پیش نویس فعلی را به روز می کند.
  • UpdateDraftBccRecipientsAction — نشان دهنده عملی است که گیرندگان Bcc ایمیل پیش نویس فعلی را به روز می کند.

معمولاً یک رابط کاربری افزونه برای نوشتن ایمیل شامل یک ویجت «ذخیره» یا «درج» است که کاربر می‌تواند با کلیک بر روی آن نشان دهد که انتخاب‌هایش در رابط کاربری تمام شده و می‌خواهد انتخاب‌هایش به ایمیلی که در حال نوشتن آن است اضافه شود. برای افزودن این تعامل ، ویجت باید یک شیء Action مرتبط داشته باشد که به افزونه دستور می‌دهد هنگام کلیک بر روی ویجت، یک تابع فراخوانی خاص را اجرا کند. شما باید این توابع فراخوانی را پیاده‌سازی کنید. هر تابع فراخوانی باید یک شیء UpdateDraftActionResponse ساخته شده را برگرداند که جزئیات تغییراتی را که باید در پیش‌نویس ایمیل فعلی ایجاد شود، شرح می‌دهد.

مثال ۱

قطعه کد زیر نحوه ساخت یک رابط کاربری نوشتن ایمیل را نشان می‌دهد که موضوع و گیرندگان To، Cc و Bcc پیش‌نویس ایمیل فعلی را به‌روزرسانی می‌کند.

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

مثال ۲

قطعه کد زیر نحوه ساخت یک رابط کاربری نوشتن ایمیل را نشان می‌دهد که تصاویر را در پیش‌نویس ایمیل فعلی درج می‌کند.

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