다른 위젯 새로고침 시 위젯을 다시 로드/새로고침

안녕하세요,

우리는 topic-timeline 위젯 뒤에 토픽 수준의 북마크 버튼을 표시하는 topic-timeline-bookmark 위젯을 만들었습니다.

현재 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;
              
              //Icon
              if (bookmarkedPosts.some((bookmark) => bookmark.reminder_at))
                icon = "discourse-bookmark-clock";
              else
                icon = "bookmark";

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

              //Tooltip
              if (bookmarkedPosts.length === 1)
                  tooltip = 'bookmarked.help.edit_bookmark';
              else if (bookmarkedPosts.find((x) => x.reminder_at))
                  tooltip = 'bookmarked.help.unbookmark_with_reminder';
              
              //Append CSS class if bookmark is set
              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", {  
  // 코드 생략

  // force-refresh 대신 schedule-rerender로
  // 직접 이름을 붙이고 이 함수를 생략할 수도 있습니다
  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로, camelCase로 변환되어 메서드 이름으로 사용됩니다.

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

무엇을 놓치고 있는 걸까요?

로컬에서 시도해 볼게요. 아마 제가 실수를 한 것 같아요.

@saurabhmasc 로컬에서는 작동하게 만들었지만, 코어에서 버그를 수정하고 새로운 기능을 추가해야 했습니다. 모든 것이 병합되면 이 주제를 업데이트하겠습니다.

감사합니다, @j.jaffeux.

안녕하세요 @j.jaffeux,

이 변경 사항이 언제 병합될지 혹시 아시나요?

안녕하세요, 네 방금 병합했습니다 (그래서 먼저 배포해야 합니다): DEV: adds a topic level bookmark toggle (#14471) · discourse/discourse@20e70d0 · GitHub

또한, 이걸 위해 제가 만든 예시 컴포넌트입니다:

질문이 있으시면 말씀해 주세요.

@j.jaffeux 님,

  1. 이전에 토픽 하단 버튼에서 북마크를 하면 첫 번째 게시물도 북마크로 표시되었는데, 지금은 첫 번째 게시물이 북마크되지 않습니다. 현재 상태가 정상인가요?

  2. 해당 컴포넌트를 모든 케이스로 테스트해 보았으며, 대부분 정상적으로 작동합니다. 다만 북마크 해제(Clear bookmark) 기능이 동기화되지 않는 문제가 있습니다.
    아래 코드를 추가하여 북마크 해제 기능도 정상적으로 작동하도록 수정했습니다.

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

감사합니다.

첫 번째 항목을 확인해 보겠습니다. 두 번째 항목에 대해서는 제가 어떤 경우의 수를 놓쳤을 수도 있습니다. 북마크의 메인 개발자가 현재 자리를 비운 상태인데, 몇 가지 사항을 변경하고 싶지만 그가 돌아올 때까지 기다려야 합니다. 님의 수정은 괜찮을 것 같습니다.

여러 가지 테스트를 해본 결과, 이는 의도된 동작(컴포넌트와 무관)이라고 생각합니다.

피드백 주셔서 감사합니다, @j.jaffeux.

이 핵심 변경 사항을 Staging 및 Production 환경에 반영해 달라는 새로운 티켓을 생성하겠습니다. 그러면 Staging에서 테스트할 수 있습니다.