בנוסף לממשק מבוסס-כרטיסים שמוצג כשמשתמש קורא הודעה ב-Gmail, תוספים ל-Google Workspace שמרחיבים את Gmail יכולים לספק ממשק נוסף כשמשתמש כותב הודעות חדשות או משיב להודעות קיימות. כך תוספים ל-Google Workspace יכולים לבצע אוטומציה של משימת כתיבת האימיילים עבור המשתמש.
גישה לממשק המשתמש של התוסף לכתיבת הודעות
יש שתי דרכים להציג את ממשק המשתמש של כתיבת הודעות בתוסף. הדרך הראשונה היא להתחיל לכתוב טיוטה חדשה או תשובה בזמן שהתוסף כבר פתוח. הדרך השנייה היא להפעיל את התוסף בזמן כתיבת טיוטה.
בכל אחד מהמקרים האלה, התוסף מפעיל את פונקציית הטריגר של יצירת ההודעה המתאימה, שמוגדרת במניפסט של התוסף. פונקציית ההפעלה של הכתיבה יוצרת את ממשק המשתמש של הכתיבה לפעולת הכתיבה הזו, ו-Gmail מציג אותו למשתמש.
יצירת תוסף לכתיבת הודעות
כדי להוסיף לתוסף פונקציונליות של כתיבת הודעות, פועלים לפי השלבים הכלליים הבאים:
- מוסיפים את השדה
gmail.composeTriggerלמניפסט של פרויקט הסקריפט של התוסף ומעדכנים את ההיקפים של המניפסט כך שיכללו את ההיקפים שנדרשים לפעולות של כתיבת הודעות. - הטמעה של פונקציית טריגר ליצירת הודעה שיוצרת ממשק משתמש ליצירת הודעה כשהטריגר מופעל. פונקציות של טריגר יצירת הודעה מחזירות אובייקט
Cardיחיד או מערך של אובייקטיםCardשמרכיבים את ממשק המשתמש של פעולת יצירת ההודעה. - מטמיעים פונקציות קריאה חוזרת שקשורות לזה, שנדרשות כדי להגיב לאינטראקציות של המשתמש עם ממשק המשתמש של כתיבת ההודעה. הפונקציות האלה הן לא פעולת הכתיבה עצמה (שגורמת רק להצגת ממשק הכתיבה), אלא הפונקציות האישיות שקובעות מה קורה כשבוחרים רכיבים שונים בממשק הכתיבה. לדוגמה, לכרטיס בממשק משתמש שמכיל לחצן בדרך כלל משויכת פונקציית קריאה חוזרת שמופעלת כשמשתמש לוחץ על הלחצן הזה. פונקציית הקריאה החוזרת של ווידג'טים שמעדכנים את תוכן הטיוטה של ההודעה צריכה להחזיר אובייקט
UpdateDraftActionResponse.
הרכבת פונקציית טריגר
ממשק המשתמש של התוסף לכתיבת הודעות בנוי באותו אופן כמו ממשק המשתמש של התוסף להודעות – באמצעות שירות הכרטיסים של Apps Script כדי ליצור כרטיסים ולמלא אותם בווידג'טים.
צריך להטמיע את התג gmail.composeTrigger.selectActions[].runFunction שמוגדר במניפסט. פונקציית הטריגר של ה-Compose חייבת להחזיר אובייקט Card יחיד או מערך של אובייקטים Card שמרכיבים את ממשק המשתמש של ה-Compose עבור הפעולה הזו. הפונקציות האלה דומות מאוד לפונקציות הפעלה לפי הקשר, והן אמורות ליצור כרטיסים באותו אופן.
הרכבת אובייקטים של אירועים שמפעילים טריגר
כשבוחרים פעולת יצירה, מופעלת פונקציית הטריגר המתאימה ליצירה, ומועבר לפונקציה אובייקט אירוע כפרמטר. אובייקט האירוע יכול להעביר מידע על ההקשר של התוסף ועל הטיוטה שנכתבת לפונקציית ההפעלה.
במאמר בנושא מבנה אובייקט האירוע מוסבר איך המידע מסודר באובייקט האירוע. המידע שכלול באובייקט האירוע נשלט באופן חלקי על ידי הערך של שדה המניפסט gmail.composeTrigger.draftAccess:
אם שדה המניפסט
gmail.composeTrigger.draftAccessהואNONEאו לא נכלל, אובייקט האירוע מכיל רק מידע מינימלי.אם הערך של
gmail.composeTrigger.draftAccessמוגדר כ-METADATA, אובייקט האירוע שמועבר לפונקציית הטריגר של יצירת ההודעה מאוכלס ברשימות של הנמענים של האימייל שנכתב.
הוספת תוכן לטיוטות פעילות
בדרך כלל, ממשק המשתמש של תוסף לחיבור הודעות ב-Google Workspace מספק למשתמש אפשרויות ושליטה שעוזרות לו לכתוב הודעה. בתרחישי השימוש האלה, אחרי שהמשתמש בוחר אפשרויות בממשק המשתמש, התוסף מפרש את הבחירות ומעדכן את טיוטת האימייל הנוכחית בהתאם.
כדי להקל על עדכון טיוטת האימייל הנוכחית, שירות הכרטיסים הורחב עם המחלקות הבאות:
-
ContentType– סוג enum שקובע אם להוסיף HTML שניתן לשינוי, HTML שלא ניתן לשינוי (שמשתמשי Gmail לא יכולים לערוך) או תוכן טקסט פשוט. -
UpdateDraftActionResponse– מייצג תשובה לפעולה שמעדכנת את טיוטת האימייל הנוכחית. -
UpdateDraftActionResponseBuilder– כלי ליצירת אובייקטים שלUpdateDraftActionResponse. -
UpdateDraftBodyAction– מייצג פעולה שמעדכנת את גוף הטיוטה הנוכחית של האימייל. -
UpdateDraftBodyType– סוג enum שמגדיר איך הגוף משתנה. -
UpdateDraftSubjectAction– מייצג פעולה שמעדכנת את שדה הנושא של טיוטת האימייל הנוכחית. -
UpdateDraftToRecipientsAction– מייצג פעולה שמעדכנת את הנמענים של טיוטת האימייל הנוכחית. -
UpdateDraftCcRecipientsAction– מייצג פעולה שמעדכנת את הנמענים בשדה 'עותק' של טיוטת האימייל הנוכחית. -
UpdateDraftBccRecipientsAction– מייצג פעולה שמעדכנת את הנמענים בשדה 'עותק מוסתר' של טיוטת האימייל הנוכחית.
בדרך כלל, ממשק המשתמש של תוסף לכתיבת אימייל כולל ווידג'ט של 'שמירה' או 'הוספה' שהמשתמש יכול ללחוץ עליו כדי לציין שהוא סיים לבחור בממשק המשתמש ושהוא רוצה שהבחירות שלו יתווספו לאימייל שהוא כותב. כדי להוסיף אינטראקטיביות, הווידג'ט צריך לכלול אובייקט Action משויך שמורה לתוסף להפעיל פונקציית קריאה חוזרת ספציפית כשמקישים על הווידג'ט. חובה להטמיע את פונקציות הקריאה החוזרת האלה. כל פונקציית קריאה חוזרת צריכה להחזיר אובייקט UpdateDraftActionResponse בנוי שמפרט את השינויים שצריך לבצע בטיוטה הנוכחית של האימייל.
דוגמה 1
בקטע הקוד הבא אפשר לראות איך ליצור ממשק משתמש לכתיבת אימייל שמעדכן את הנושא ואת הנמענים בשדות 'אל', 'עותק' ו'עותק מוסתר' של טיוטת האימייל הנוכחית.
/**
* 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 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;
}