إعادة تحميل/تحديث عنصر واجهة مستخدم عند تحديث عنصر واجهة مستخدم آخر

مرحبًا بالجميع،

لقد قمنا بإنشاء أداة “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 بشكل متزامن.

إذًا، كيف يمكنني تحديث أداة “topic-timeline-bookmark” الخاصة بي عند تعيين أو إلغاء تعيين الإشارة المرجعية، أو عند تحديث أداة post-stream؟ إليك الكود الخاص بي:

<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.dispatchWidgetAppEvent('topic-timeline-bookmark', 'force-refresh', 'post-stream:refresh');

في كود الودجت، عرّف الدالة التالية:

api.createWidget("topic-timeline-bookmark", {  
  // تم حذف الكود

  // قد يكون من الممكن تسميتها schedule-rerender
  // مباشرة في استدعاء واجهة برمجة التطبيقات بدلاً من force-refresh
  // وتجنب الحاجة إلى هذه الدالة
  forceRefresh() {
    this.scheduleRerender();
  }
});

أعتقد أن هذا يجب أن يعمل. إذا لم ينجح، فأخبرني وسأحاول بناء مثال عملي محليًا.

شكرًا لك، @joffreyjaffeux، على الرد.

لقد جربنا الكود الذي اقترحته، لكنه لا يعمل.

  1. أضفنا استدعاء الـ API التالي:
    api.dispatchWidgetAppEvent('topic-timeline-bookmark', 'force-refresh', 'post-stream:refresh');
    ثم أضفنا دالة forceRefresh() في ويدجت “topic-timeline-bookmark”.
    لكن هذا لا يعمل.

  2. حاولت أيضًا إعادة تسمية المعامل الثاني لدالة dispatchWidgetAppEvent إلى “schedule-rerender” وحذف دالة forceRefresh من الويدجت. وهذا أيضًا لا يعمل.

لقد بحثت في تنفيذ دالة api.dispatchWidgetAppEvent، فهي تأخذ ثلاث حجج، حيث يكون الثاني هو 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. اختبرنا مكونك وجميع الحالات تعمل بشكل جيد، باستثناء وظيفة مسح الإشارات المرجعية التي لا تعمل بشكل متزامن.
    لجعلها تعمل، أضفنا الأسطر التالية من الكود، والآن تعمل وظيفة مسح الإشارات المرجعية بشكل جيد أيضًا.

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

شكرًا لك.

سأراجع النقطة الأولى. أما بالنسبة للنقطة الثانية، نعم، من الممكن أن تكون قد فاتني حالة ما. المؤلف الرئيسي للعلامات المرجعية غير متاح حاليًا، وأود تغيير بعض الأمور، لكنني أحتاج إلى عودته. إصلاحك يبدو مناسبًا.

بعد إجراء العديد من الاختبارات، أعتقد أن هذا هو المتوقع (وليس مرتبطًا بالمكون).

شكرًا لك، @j.jaffeux، على ملاحظاتك.

سنقوم بإنشاء تذكرة جديدة لطلب تطبيق هذه التغييرات الأساسية على بيئتي الاختبار والإنتاج لدينا، حتى نتمكن من اختبارها على بيئة الاختبار.