即使再次打开电子邮件,Gmail附加组件onTriggerFunction也只会针对每封电子邮件运行一次

时间:2018-05-24 13:50:50

标签: google-apps-script gmail gmail-addons

我们正在构建Gmail Add-On但是我们希望在调用加载项onTriggerFunction时根据某些业务逻辑显示不同的卡。这在电子邮件打开时第一次运行该功能时工作正常。

我们有条件逻辑,但Gmail似乎会缓存返回第一张卡的初始调用的结果。转到另一封电子邮件并返回原始邮件时,onTriggerFunction不会再次调用,因此不运行条件逻辑来更改呈现的初始卡片。

无论如何,每次打开电子邮件时都会运行onTriggerFunction,而不是仅在第一次打开电子邮件时运行?

这是一个带有触发器功能的附加组件,它返回一张显示当前时间的卡片:

Code.js

function buildAddOn(e) {
  var card = CardService.newCardBuilder();
  card.setHeader(CardService.newCardHeader().setTitle(new Date().toLocaleTimeString()));  

  return [card.build()];
}

appsscript.json

{
  "timeZone": "GMT",
  "dependencies": {
  },
  "oauthScopes": ["https://www.googleapis.com/auth/gmail.addons.execute"],
  "gmail": {
    "name": "Minimal example",
    "logoUrl": "https://www.gstatic.com/images/icons/material/system/2x/bookmark_black_24dp.png",
    "contextualTriggers": [{
      "unconditional": {
      },
      "onTriggerFunction": "buildAddOn"
    }],
    "primaryColor": "#4285F4",
    "secondaryColor": "#4285F4",
    "openLinkUrlPrefixes": ["https://mail.google.com/"],
    "version": "TRUSTED_TESTER_V2"
  }
}

导航到较旧的对话时,会显示微调器,然后显示当前时间。但是,当导航回以前显示的对话时,会立即显示旧的时间值,表明正在进行一些缓存:

demo of the issue

加载项内的操作或我们应用中的其他活动会影响重新打开之前显示的对话时应显示的内容。这意味着重新显示卡的旧副本会导致用户意外行为。

2 个答案:

答案 0 :(得分:0)

不幸的是,目前没有办法(2019年7月)在每次打开电子邮件时强制触发器运行。您可以使用ActionResponseBuilder.setStateChanged(true)作为对按钮单击的响应,以指示Gmail清除缓存,但不能与普通卡响应一起发送。

答案 1 :(得分:0)

有几种方法可以重新加载卡的UI。两者都必须在ActionResponse中发生。

第一种是由于用户操作导致某些状态更改而要重新加载当前卡:

function buildCounterCard() {
  const card = CardService.newCardBuilder().setName('Counter');

  const count = CountApi.get(); // Or however you get this data

  const countWidget = CardService.newKeyValue().setTopLabel('Current Count').setContent(`${count}`);

  const incrementAction = CardService.newAction().setFunctionName('handleIncrement');
  const incrementButton = CardService.newTextButton().setText('Increment').setOnClickAction(incrementAction);

  const section = CardService.newCardSection().addWidget(countWidget).addWidget(incrementButton);

  card.addSection(section);

  return card.build();
}

function handleIncrement() {
  const actionResponse = CardService.newActionResponseBuilder();

  CountApi.update(); // Or however you update the data

  const nav = CardService.newNavigation().updateCard(buildCounterCard());
  actionResponse.setNavigation(nav);

  return actionResponse.build();
}

到目前为止,我发现的唯一其他方法是更新“导航”堆栈中的前一张卡。想象以下情况:

  1. 用户填写表格,然后单击“保存”
  2. 脚本将数据发布到API,并在成功后将“成功”卡推入堆栈。
  3. 用户看到“成功”卡,并显示一条消息,让他们知道数据已保存,并单击“返回”或“返回首页”按钮。

该按钮的动作处理程序可能如下所示:

function handleBackClick(event) {
  const actionResponse = CardService.newActionResponseBuilder();

  clearPreviousCardState() // Otherwise the user sees the same data they filled out previously when they go back to the form

  const nav = CardService.newNavigation()
    .popCard()
    .updateCard(buildPreviousCard(event))
    .popToRoot();
  actionResponse.setNavigation(nav);

  return actionResponse.build();
}

无论出于何种原因,这都行得通,但是通过链接导航步骤和updateCard()来更新多张卡片则无效。

似乎这些是目前唯一的选择。我发现有一个线性优化服务非常疯狂,但没有一种重新加载UI的方法。一位评论者提到ActionResponseBuilder.setStateChanged(true),它听起来像我们根据文档所想要的那样,但以我的经验,它绝对没有任何作用。