توسيع واجهة مستخدم الإنشاء باستخدام إجراءات الإنشاء

بالإضافة إلى توفير واجهة مستندة إلى البطاقات عندما يقرأ المستخدم رسالة Gmail، يمكن أن توفّر إضافات Google Workspace التي توسّع نطاق Gmail واجهة أخرى عندما ينشئ المستخدم رسائل جديدة أو يردّ على الرسائل الحالية. يتيح ذلك لإضافات Google Workspace تشغيل مهمة إنشاء الرسائل الإلكترونية للمستخدم آليًا.

الوصول إلى واجهة مستخدم إنشاء الإضافة

هناك طريقتان لعرض واجهة مستخدم إنشاء الإضافة. الطريقة الأولى هي بدء إنشاء مسودة جديدة أو ردّ بينما تكون الإضافة مفتوحة. الطريقة الثانية هي بدء الإضافة أثناء إنشاء مسودة.

في كلتا الحالتين، تنفّذ الإضافة وظيفة مشغّل الإنشاء المقابلة، والمحدّدة في بيان الإضافة. تنشئ وظيفة مشغّل الإنشاء واجهة مستخدم الإنشاء لإجراء الإنشاء هذا، ثم يعرضها Gmail للمستخدم.

إنشاء إضافة لإنشاء الرسائل

يمكنك إضافة وظيفة الإنشاء إلى إضافة باتّباع الخطوات العامة التالية:

  1. أضِف حقل gmail.composeTrigger إلى بيان مشروع نص برمجي للإضافة وعدِّل نطاقات البيان لتضمين النطاقات المطلوبة لإجراءات الإنشاء.
  2. تنفيذ وظيفة مشغّل إنشاء تنشئ واجهة مستخدم إنشاء عند تشغيل المشغّل تعرض دوال مشغّل الإنشاء إما كائن Card واحدًا أو مصفوفة من كائنات Card التي تتضمّن واجهة مستخدم الإنشاء لإجراء الإنشاء.
  3. نفِّذ دوال رد الاتصال المرتبطة اللازمة للتفاعل مع إجراءات المستخدم في واجهة Compose. هذه الدوال ليست إجراء الإنشاء نفسه (الذي يؤدي فقط إلى ظهور واجهة مستخدم الإنشاء)، بل هي الدوال الفردية التي تتحكّم في ما يحدث عند اختيار عناصر مختلفة من واجهة مستخدم الإنشاء. على سبيل المثال، تحتوي بطاقة واجهة المستخدم التي تتضمّن زرًا عادةً على دالة ردّ مرتبطة يتم تنفيذها عندما ينقر المستخدم على هذا الزر. يجب أن تعرض دالة رد الاتصال الخاصة بالأدوات التي تعدّل محتوى الرسالة المسوّدة كائن UpdateDraftActionResponse.

إنشاء دالة مشغّلة

يتم إنشاء واجهة مستخدم الإنشاء الخاصة بالإضافة بالطريقة نفسها التي يتم بها إنشاء واجهة مستخدم الرسالة الخاصة بالإضافة، أي باستخدام خدمة البطاقات في "برمجة تطبيقات Google" لإنشاء بطاقات وملؤها عناصر واجهة مستخدم.

يجب تنفيذ gmail.composeTrigger.selectActions[].runFunction الذي تحدّده في بيان التطبيق. يجب أن تعرض دالة مشغّل الإنشاء إما كائن Card واحدًا أو مصفوفة من كائنات Card التي تتضمّن واجهة مستخدم الإنشاء لهذا الإجراء. هذه الدوال تشبه إلى حد كبير دوال التشغيل السياقي ويجب أن تنشئ البطاقات بالطريقة نفسها.

إنشاء عناصر حدث التشغيل

عند تحديد إجراء إنشاء، يتم تنفيذ دالة مشغّل الإنشاء المقابلة، ويتم تمرير عنصر حدث إلى الدالة كمعلَمة. يمكن أن يحمل عنصر الحدث معلومات حول سياق الإضافة والمسودة التي يتم إنشاؤها إلى وظيفة المشغّل.

اطّلِع على بنية عنصر الحدث للحصول على تفاصيل حول كيفية ترتيب المعلومات في عنصر الحدث. تخضع المعلومات الواردة في عنصر الحدث جزئيًا لقيمة حقل gmail.composeTrigger.draftAccess في ملف البيان، وذلك على النحو التالي:

  • إذا كان حقل gmail.composeTrigger.draftAccess في ملف البيان هو NONE أو لم يتم تضمينه، سيحتوي عنصر الحدث على معلومات بسيطة فقط.

  • إذا تم ضبط gmail.composeTrigger.draftAccess على METADATA، سيتم ملء عنصر الحدث الذي تم تمريره إلى دالة مشغّل الإنشاء بقوائم المستلمين للرسالة الإلكترونية التي يتم إنشاؤها.

إدراج محتوى في مسودات نشطة

عادةً ما توفّر واجهة مستخدم إنشاء الإضافات في Google Workspace خيارات وعناصر تحكّم للمستخدم تساعده في إنشاء رسالة. في حالات الاستخدام هذه، بعد أن يحدّد المستخدم خيارات في واجهة المستخدم، تفسّر الإضافة هذه الخيارات وتعدّل مسودة الرسالة الإلكترونية الحالية وفقًا لذلك.

لتسهيل تعديل مسودة الرسالة الإلكترونية الحالية، تم توسيع نطاق خدمة البطاقات لتشمل الفئات التالية:

  • ContentType: هي قيمة تعداد تحدّد ما إذا كان سيتم إضافة محتوى HTML قابل للتعديل أو محتوى HTML غير قابل للتعديل (لا يمكن لمستخدمي Gmail تعديله) أو محتوى نصي عادي.
  • UpdateDraftActionResponse: يمثّل ردًا على إجراء يؤدي إلى تعديل مسودة الرسالة الإلكترونية الحالية.
  • UpdateDraftActionResponseBuilder: أداة إنشاء لكائنات UpdateDraftActionResponse.
  • UpdateDraftBodyAction: يمثّل إجراءً يعدّل نص مسودة الرسالة الإلكترونية الحالية.
  • UpdateDraftBodyType—قيمة تعداد تحدّد طريقة تغيير النص.
  • UpdateDraftSubjectAction: تمثّل هذه السمة إجراءً يعدّل حقل الموضوع في مسودة الرسالة الإلكترونية الحالية.
  • UpdateDraftToRecipientsAction: يمثّل هذا الإجراء تعديلًا على المستلمين في حقل "إلى" في الرسالة الإلكترونية الحالية المحفوظة كمسودة.
  • UpdateDraftCcRecipientsAction: يمثّل هذا الرمز إجراءً يعدّل المستلمين الذين تم إرسال نسخة إليهم من الرسالة الإلكترونية الحالية.
  • UpdateDraftBccRecipientsAction: يمثّل هذا الرمز إجراءً يعدّل مستلمي النسخة المخفية الوجهة من مسودة الرسالة الإلكترونية الحالية.

تتضمّن واجهة مستخدم الإضافة عادةً أداة "حفظ" أو "إدراج" يمكن للمستخدم النقر عليها للإشارة إلى أنّه انتهى من إجراء اختيارات في واجهة المستخدم ويريد إضافة خياراته إلى الرسالة الإلكترونية التي يكتبها. لإضافة هذه التفاعلية، يجب أن يتضمّن التطبيق المصغّر عنصر Action مرتبطًا به يطلب من الإضافة تنفيذ دالة رد اتصال معيّنة عند النقر على التطبيق المصغّر. يجب تنفيذ دوال رد الاتصال هذه. يجب أن تعرض كل دالة ردّ نداء كائن UpdateDraftActionResponse يتضمّن تفاصيل التغييرات التي يجب إجراؤها على مسودة الرسالة الإلكترونية الحالية.

مثال 1

يوضّح مقتطف الرمز التالي كيفية إنشاء واجهة مستخدم Compose تعدّل الموضوع والمستلمين في الحقول "إلى" و"نسخة طبق الأصل" و"نسخة مخفية الوجهة" لمسودة الرسالة الإلكترونية الحالية.

    /**
     * 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 تدرج الصور في مسودة الرسالة الإلكترونية الحالية.

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