刷新另一个小部件时重新加载/刷新一个小部件

大家好,

我们创建了一个名为“topic-timeline-bookmark”的小部件,它在 topic-timeline 小部件之后显示主题级别的书签按钮。

现在,当我们点击 topic-timeline 书签按钮时,会显示一个模态框以设置书签。保存书签后,它会更新 first-post-menu 按钮和 topic-footer-button 下的书签按钮,但除非刷新 topic-timeline 小部件(即滚动页面),否则它自身不会更新,反之亦然。

first-post-menu

image


topic-footer-button

image

我发现,每当设置或取消设置书签时,post-stream 小部件会被刷新,因此 post-menu 和 topic-footer-button 的书签按钮能够同步工作。

那么,我该如何在设置或取消设置书签时,或者在 post-stream 小部件刷新时,刷新我的“topic-timeline-bookmark”小部件呢?以下是我的代码:

<script type="text/discourse-plugin" version="0.8">
  const { h } = require('virtual-dom');
  const { getOwner } = require("discourse-common/lib/get-owner");
  const topicController = getOwner(this).lookup("controller:topic");

  api.createWidget("topic-timeline-bookmark", {  
      tagName: 'div.discourse-bookmark-button-wrapper',
      buildKey: () => `topic-timeline-bookmark`,
      toggleBookmark() {
        topicController.send('toggleBookmark');
      },
      html(attrs, state) { 
        let contents = [];
        const user = api.getCurrentUser();
        if (user) {
            let tooltip = 'bookmarked.help.bookmark';
            let label = 'bookmarked.title';
            let buttonClass = 'btn btn-default bookmark';
            let icon = "bookmark";  
            let bookmarkedPosts = topicController.model.bookmarked_posts;
            let bookmarkCount = 0;

            if(bookmarkedPosts && bookmarkedPosts.length > 0){
              bookmarkCount =  bookmarkedPosts.length;
              
              //图标
              if (bookmarkedPosts.some((bookmark) => bookmark.reminder_at))
                icon = "discourse-bookmark-clock";
              else
                icon = "bookmark";

              //标签
              if (bookmarkCount === 0)               
                  label = "bookmarked.title";          
              else if (bookmarkCount === 1)
                  label = "bookmarked.edit_bookmark"; 
              else 
                  label = "bookmarked.clear_bookmarks";

              //工具提示
              if (bookmarkedPosts.length === 1)
                  tooltip = 'bookmarked.help.edit_bookmark';
              else if (bookmarkedPosts.find((x) => x.reminder_at))
                  tooltip = 'bookmarked.help.unbookmark_with_reminder';
              
              //如果已设置书签,则追加 CSS 类
              if (bookmarkCount > 0) { buttonClass += ' bookmarked' }
            }
    
            contents.push(
            this.attach('button', {
              action: 'toggleBookmark',
              title: tooltip,
              label: label,
              icon: icon,
              className: buttonClass
            })
          );
        }
        return contents;
      }, 
    });
 
  api.decorateWidget('topic-timeline:after', function(helper) {
    return helper.attach('topic-timeline-bookmark');
  });
</script>

感谢您联系我们,我们的其中一名开发人员将对此进行调查,并反馈一些有用的信息。

您好,

我尚未在本地测试过,但以下方法可能有效:

在你的主脚本中添加此 API 调用:

api.dispatchWidgetAppEvent('topic-timeline-bookmark', 'force-refresh', 'post-stream:refresh');

在你的小部件代码中声明此函数:

api.createWidget("topic-timeline-bookmark", {  
  // 代码省略

  // 或许可以直接在 API 调用中将其命名为 schedule-rerender
  // 而不是 force-refresh
  // 从而避免定义此函数
  forceRefresh() {
    this.scheduleRerender();
  }
});

我认为这应该能起作用。如果不行,请告诉我,我将在本地尝试构建一个可工作的示例。

感谢 @joffreyjaffeux 的回复。

我们尝试了您建议的代码,但无法正常工作。

  1. 添加了以下 API 调用:
    api.dispatchWidgetAppEvent('topic-timeline-bookmark', 'force-refresh', 'post-stream:refresh');
    然后在 “topic-timeline-bookmark” 组件中添加了 forceRefresh() 方法。
    但这不起作用。

  2. 我还尝试将 dispatchWidgetAppEvent 方法的第二个参数重命名为 “schedule-rerender”,并从组件中移除了 forceRefresh 函数。这也无法工作。

我查看了 api.dispatchWidgetAppEvent 方法的实现,它接受 3 个参数,其中第二个是 widgetKey,我认为它应该是组件的 buildKey() 函数返回的值。
第三个参数是 appEvent,它会被转换为驼峰命名法,并作为方法名供我们使用。

https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/lib/plugin-api.js#L1448

我们是否遗漏了什么?

我将在本地尝试,我可能犯了一个错误。

@saurabhmasc 我在本地让它运行起来了,但我需要修复核心中的一个 bug,并在核心中添加一个新功能。待这一切合并后,我会更新该主题。

谢谢,@j.jaffeux

@j.jaffeux

请问这些更改预计何时会合并?

你好,是的,我刚合并了它(所以你需要先部署它):DEV: adds a topic level bookmark toggle (#14471) · discourse/discourse@20e70d0 · GitHub

此外,这是我为此制作的一个示例组件:

如果有任何问题,请告诉我。

你好 @j.jaffeux

  1. 我们注意到,之前当我们从 topic-footer-buttons 添加书签时,第一篇文章也会被标记为已收藏,但现在第一篇文章不再被标记为已收藏。这是正确的吗?

  2. 我们已测试您的组件,所有情况均正常运行,仅“清除书签”功能未同步工作。
    为使该功能正常运行,我们添加了以下代码行,现在“清除书签”功能也已正常工作。

  api.dispatchWidgetAppEvent(
    "topic-timeline",
    "topic-timeline-bookmark",
    "post-stream:refresh"
  );

谢谢。

将查看第一点。关于第二点,是的,有可能我遗漏了一种情况。书签功能的主要作者目前不在,我想修改一些内容,但需要等他回来。您的修复应该是可以的。

经过多次测试,我认为这是预期的行为(且与该组件无关)。

感谢 @j.jaffeux 的反馈。

我们将创建一个新的工单,请求将这些核心更改部署到我们的测试环境和生产环境。这样我们就可以在测试环境中进行测试。