بحاجة إلى مساعدة في معرفة سبب عدم تحديث قائمة المواضيع بعد النقر على تنبيه موضوع جديد/رد

في موقع منشئ السمات، كنت أحاول إزالة المواضيع من المستخدمين المتجاهلين من قائمة المواضيع، وهذا هو الكود الخاص بي

api.modifyClass("component:topic-list", {
      @on("didReceiveAttrs")
      removeIgnoredUsers() {
        this.topics = this.topics.filter(
          topic => !ignored.includes(topic.posters[0].user.username)
        );
      }
});

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

لدي تسجيل شاشة لإعادة إنتاج هذه المشكلة.

في الفيديو، كنت أنظر إلى عرض الجوال على سطح المكتب الخاص بي وأنشئ ردًا جديدًا على ‘test new topic alert 3’ من هاتفي المحمول، ثم أنقر على التنبيه على سطح المكتب، في الحالة العادية، يجب أن يظهر الموضوع الذي تم دفعه في أعلى المواضيع، ولكنه لا يظهر في هذه الحالة.

اعتقدت أن الطريقة التي استخدمتها أعلاه تم تشغيلها عن طريق الخطأ ولكنها لا تُستدعى عند النقر على تنبيه موضوع.

هل لدى أي شخص أي اقتراحات حول سبب حدوث هذه المشكلة؟ شكرًا جزيلاً.

تحديث: وجدت أنه يتسبب أيضًا في عدم عمل تحميل المزيد من المواضيع تلقائيًا أثناء التمرير في عرض الجوال.

إعجابَين (2)

إذا قمت بإزالة الكود أعلاه الذي لا يعرض المستخدمين المتجاهلين، فهل تم حل المشكلة؟ إذا تم حلها، فأتوقع أن الكود الخاص بك يقوم بتصفية مواضيع جميع المستخدمين (أو عدد أكبر من المستخدمين مما ينبغي)، مما يتسبب في عدم ظهورها.

لا أعرف من أين يتم ملء ignored، ولكن ربما يتم ملؤها باسم المستخدم الذي أنشأ الموضوع الجديد الذي عرض التنبيه في الأعلى. ربما يتم ملؤها بمستخدمين لا ينبغي تجاهلهم؟ هل يمكنك تسجيل القيم الموجودة في ignored؟

إعجابَين (2)

أعتقد أن هذا ليس هو الحال لأن هذه المشكلة حدثت فقط على الهاتف المحمول / عرض الهاتف المحمول. (لم يتم دفعه ولا يمكن تحميل المزيد)

لقد قمت بتعيين const ignored = ['david', 'pekka_gaiser', 'sam']; يدويًا لاختبار موقع منشئ السمة حيث افترضت أنني لم أصل إلى مستوى الثقة الذي يمكنه استخدام ميزة التجاهل أو تم تعطيلها.

والموضوع الذي دفعته هو موضوع قمت بإنشائه.

إعجاب واحد (1)

غريب، إلا إذا كانت المشكلة ليست في هذا الكود تحديدًا. إذا قمت بتغيير الكود إلى:

api.modifyClass("component:topic-list", {
      @on("didReceiveAttrs")
      removeIgnoredUsers() {
        this.topics = this.topics.filter(() => true);
      }
});

هل تستمر المشكلة؟ إذا استمرت، فالمشكلة على الأرجح في مكان آخر.

إعجابَين (2)

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

إعجاب واحد (1)

إذًا الشيء الوحيد الذي يمكنني التفكير فيه هو أن المتغير ignored يتم ملؤه بشكل خاطئ كما قلت سابقًا. ربما يقوم مكان آخر بتغيير القيمة. حاول تغيير الكود إلى:

api.modifyClass("component:topic-list", {
      @on("didReceiveAttrs")
      removeIgnoredUsers() {
        const ignored2 = ['david', 'pekka_gaiser', 'sam'];
        this.topics = this.topics.filter(
          topic => !ignored2.includes(topic.posters[0].user.username)
        );
      }
});

في الكود أعلاه، وضعت المتغير ignored في نفس النطاق الذي يتم فيه تطبيق المرشح، وغيرت اسم المتغير لتجنب التغييرات غير المقصودة في قيم المصفوفة (على سبيل المثال، إذا استدعى مكان ما ignored.push(...)، فقد يغير قيمه في مكان آخر).

إعجاب واحد (1)

عندما تفعل شيئًا كهذا

this.topics = something_else

فأنت تعيد تعريف هذا الخاصية لشيء آخر. هذا جيد إذا لم يكن هناك شيء آخر يراقب هذه الخاصية، ولكن في هذه الحالة، هناك العديد من الأشياء التي تراقب مصفوفة topics.

على سبيل المثال

إذا قمت بذلك في تثبيت تطوير، فسوف يرمي Ember أخطاء في وحدة التحكم مثل هذه.

.

لذا، فإن النتيجة الرئيسية هنا هي القيام بشيء كهذا بدلاً من ذلك.

this.set("topics", something_else)

حتى يصل مُزخرف @tracked إلى Discourse.

لذا، إذا حاولت شيئًا كهذا

api.modifyClass("component:topic-list", {
  @on("didReceiveAttrs")
  removeIgnoredUsers() {
    const filtered = this.topics.filter(
      topic => !ignored.includes(topic.posters[0].user.username)
    );
    this.set("topics", filtered);
  }
});

يجب أن يعمل على كل من سطح المكتب والجوال في منشئ الثيمات.

ومع ذلك…

إذا حاولت ذلك في تثبيت تطوير، سترى خطأ آخر.

لذا يجب أن يخبرك هذا بشيء ما. تُستخدم مصفوفة topics في العديد من الأماكن المختلفة. لذلك ليس من الجيد العبث بها - خاصة وأن حالة الاستخدام الخاصة بك بصرية في المقام الأول ولا توجد آثار أمنية متضمنة.

إليك ما أقترحه: خذ خطوة إلى الوراء وحاول نهجًا مختلفًا. بدلاً من محاولة تعديل المصفوفة، قم بشيء أبسط بكثير. إذا قام مستخدم تم تجاهله بإنشاء الموضوع، فأضف فئة CSS واخفها باستخدام CSS.

تقوم بذلك بشيء كهذا - تركت بعض التعليقات إذا كنت تريد المتابعة ولكن يمكنك حذفها عندما تكون جاهزًا لاستخدامها.

هذا يذهب في ملف المُهيئ:

import { apiInitializer } from "discourse/lib/api";
import discourseComputed from "discourse-common/utils/decorators";

export default apiInitializer("0.11.1", api => {
  // set an id for your modifications
  const PLUGIN_ID = "hide-ignored-op-topics";

  // The class name you want to add. The space at the start is required
  const IGNORED_TOPIC_CLASS_STRING = " ignored-op-topic";

  // get current user
  const user = api.getCurrentUser();

  // not logged in, bail
  if (!user) {
    return;
  }

  // get a list of ignored users
  const ignored = user.ignored_users;

  // helper function to avoid duplicating code
  const addIgnoredTopicClass = context => {
    // get classes from core / other plugins and themes
    let classList = context._super(...arguments);

    // create your condition
    const shouldAddClass = ignored.includes(
      context.topic.posters[0].user.username
    );

    // add ignored class if condition is true
    if (shouldAddClass) {
      classList += IGNORED_TOPIC_CLASS_STRING;
    }

    // return the classList plus the modifications if any
    return classList;
  };

  // add the class to the default topic list like on the "latest" page
  api.modifyClass("component:topic-list-item", {
    pluginId: PLUGIN_ID,
    @discourseComputed()
    unboundClassNames() {
      return addIgnoredTopicClass(this);
    }
  });

  // do the same for the categories page topic list
  api.modifyClass("component:latest-topic-list-item", {
    pluginId: PLUGIN_ID,
    @discourseComputed()
    unboundClassNames() {
      return addIgnoredTopicClass(this);
    }
  });
});

وهذا يذهب في /common/common.css

// we don't use display: none; here because we don't want to mess with load-more
.ignored-op-topic {
  height: 0;
  width: 0;
  position: fixed;
  bottom: 0;
}
إعجابَين (2)

شكرًا لك، الطريقة الثانية تعمل.

هل من الممكن إضافة فئة إضافية للعنصر الفرعي للمكون؟

على سبيل المثال، أود إخفاء صورة المستخدم الذي تم تجاهله في قائمة الصور الرمزية لسطح المكتب على الجانب الأيمن من عنوان الموضوع، عند إضافة فئة إلى عنصر قائمة الموضوع، هل سيكون من الممكن إضافة فئة إلى مكون الصورة الرمزية؟

إن طريقة unboundClassNames() التي استخدمناها أعلاه مسؤولة عن الفئات المضافة إلى عنصر المكون. بعبارة أخرى، عناصر HTML .topic-list-item أو .latest-topic-list-item. يمكنك رؤية ذلك هنا

discourse/app/assets/javascripts/discourse/app/components/topic-list-item.js at ad4faf637c9caf7e6ac60a614e3838a69c928e27 · discourse/discourse · GitHub

وهنا

discourse/app/assets/javascripts/discourse/app/components/latest-topic-list-item.js at 1472e47aae5bfdfb6fd9abfe89beb186c751f514 · discourse/discourse · GitHub

يأخذ Ember أي سلسلة نصية تعيدها هذه الطريقة ويضيفها كسمة class على العنصر نفسه.

ستحتاج إلى استخدام شيء آخر إذا كنت ترغب في إضافة فئات إلى العناصر الفرعية لهذا العنصر.

كل ناشر في خاصية posters لديه خاصية تسمى extras. تُستخدم هذه الخاصية كعلامة للفئات الإضافية التي سيتم إضافتها إلى الصورة الرمزية عند عرضها.

تم تعيينها هنا

discourse/app/assets/javascripts/discourse/app/models/topic-list.js at d3a59e3f695c467c22d02db62532194e17ac827b · discourse/discourse · GitHub

ويتم استهلاكها هنا

discourse/app/assets/javascripts/discourse/app/templates/list/posters-column.hbr at 1472e47aae5bfdfb6fd9abfe89beb186c751f514 · discourse/discourse · GitHub

لذلك، يمكنك إضافة فئات إلى الصور الرمزية في قائمة المواضيع بناءً على شرط إذا قمت بتوسيع هذه الخاصية.

يمكنك استخدام المُزين @on عندما يستقبل المكون سماته لاستدعاء طريقة للقيام بذلك. نظرًا لأننا نقوم بالفعل بتعديل فئات المكون هذه، يمكننا دمج هذا السلوك الجديد في الكود أعلاه.

هذا ما توصلنا إليه

في المُهيئ

import { apiInitializer } from "discourse/lib/api";
import discourseComputed, { on } from "discourse-common/utils/decorators";

export default apiInitializer("0.11.1", (api) => {
  const PLUGIN_ID = "hide-ignored-op-topics";
  const IGNORED_TOPIC_CLASS_STRING = " ignored-op-topic";
  const IGNORED_AVATAR_CLASS_STRING = " ignored-user-avatar";

  const user = api.getCurrentUser();

  if (!user) {
    return;
  }

  const ignoredUsers = user.ignored_users;

  function isIgnoredUser(poster) {
    return ignoredUsers.includes(poster.user.username);
  }

  function addIgnoredTopicClass() {
    let classList = this._super(...arguments);
    
    const topicCreator = this.topic.posters[0];

    if (isIgnoredUser(topicCreator)) {
      classList += IGNORED_TOPIC_CLASS_STRING;
    }

    return classList;
  }

  function addIgnoredAvatarClass() {
    this.topic.posters.forEach((poster) => {
      if (isIgnoredUser(poster)) {
        // default raw topic-lists
        poster.extras += IGNORED_AVATAR_CLASS_STRING;

        // categories page topic lists
        poster.user.set("extras", IGNORED_AVATAR_CLASS_STRING);
      }
    });
  }

  api.modifyClass("component:topic-list-item", {
    pluginId: PLUGIN_ID,

    @discourseComputed()
    unboundClassNames() {
      return addIgnoredTopicClass.call(this);
    },

    @on("didReceiveAttrs")
    ignoredAvatarClass() {
      addIgnoredAvatarClass.call(this);
    },
  });

  api.modifyClass("component:latest-topic-list-item", {
    pluginId: PLUGIN_ID,

    @discourseComputed()
    unboundClassNames() {
      return addIgnoredTopicClass.call(this);
    },

    @on("didReceiveAttrs")
    ignoredAvatarClass() {
      addIgnoredAvatarClass.call(this);
    },
  });
});

يجب أن يمنحك هذا فئة CSS ignored-op-topic على عناصر قائمة المواضيع التي بدأها مستخدم تم تجاهله وفئة CSS ignored-user-avatar على كل صورة رمزية لمستخدم تم تجاهله في عمود الناشرين.

لدينا بالفعل CSS لـ .ignored-op-topic من الأعلى.

// we don't use display: none; here because we don't want to mess with load-more
.ignored-op-topic {
  height: 0;
  width: 0;
  position: fixed;
  bottom: 0;
}

الآن، تريد إخفاء الصور الرمزية للمستخدمين الذين تم تجاهلهم في عمود قائمة المواضيع.

لا تفعل ذلك. سيؤدي هذا إلى الكثير من الارتباك.

ماذا لو رد مستخدم تم تجاهله على موضوع، وتم دفعه، ولكن لديك صورته الرمزية مخفية؟ سيبدو الأمر وكأن شخصًا آخر قام بدفع الموضوع.

أيضًا، هناك صورة رمزية واحدة فقط في صفحة الفئات بجوار عناوين المواضيع. ماذا يحدث إذا كان آخر رد من مستخدم تم تجاهله؟ لا توجد صورة رمزية؟

يمكنك أن ترى كيف أن مثل هذه الحالات ستخلق تجربة غير سارة لمستخدميك.

بدلاً من إخفاء الصور الرمزية للمستخدمين الذين تم تجاهلهم، يمكنك استبدالها بأيقونة SVG. سيكون لجميع المستخدمين الذين تم تجاهلهم نفس الصورة الرمزية. يمكنك القيام بذلك باستخدام CSS

.ignored-user-avatar {
  background: white;
  border: 1px solid transparent;
  box-sizing: border-box;
  opacity: 0.5;
  content: svg-uri(
    '\u003csvg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"\u003e\u003cpath d="m256 0c141.385 0 256 114.615 256 256s-114.615 256-256 256-256-114.615-256-256 114.615-256 256-256zm0 105c-83.262 0-151 67.74-151 151s67.737 151 151 151 151-67.736 151-151-67.74-151-151-151zm-52.816 130.621a22.119 22.119 0 1 0 0-44.237 22.119 22.119 0 0 0 0 44.237zm127.749-22.121a22.116 22.116 0 0 0 -22.12-22.12 22.119 22.119 0 1 0 22.12 22.12zm-40.233 70.79a9.439 9.439 0 0 0 -13.35-13.347l-21.35 21.357-21.352-21.357a9.438 9.438 0 1 0 -13.348 13.347l21.352 21.352-21.352 21.358a9.438 9.438 0 1 0 13.347 13.347l21.353-21.355 21.351 21.351a9.439 9.439 0 0 0 13.349-13.343l-21.352-21.354z"/\u003e\u003c/svg\u003e'\n  );
}

وسيتم عرضه على النحو التالي

ونفس الشيء على latest-topic-list-item. قم بتغيير SVG إلى أي أيقونة تريد استخدامها.

مع إزالة ذلك من الطريق…

أجبت على سؤالك لأنه فرصة جيدة للحديث عن تخصيص قائمة المواضيع وكيف يمكنك القيام بذلك. ومع ذلك، لدي الكثير من التحفظات بشأن حالة الاستخدام الخاصة بك. الحاجة إلى إخفاء الصور الرمزية للمستخدمين الذين تم تجاهلهم تشير إلى مشكلة أساسية. من السهل أن تقول

“هذا الشخص يكتب عن مواضيع لست مهتمًا بها. سأتجاهله لتقليل الضوضاء.”

ولكن من شيء مختلف تمامًا أن تقول

“حتى رؤية صورة هذا الشخص الرمزية تثير استجابة عاطفية. لا أريد أبدًا رؤية صورته الرمزية مرة أخرى.”

أنت تعرف مجتمعك أكثر من أي شخص آخر… ولكن ربما يستحق الأمر البحث في ذلك.

4 إعجابات

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

إعجاب واحد (1)