Besoin d'aide pour trouver pourquoi la liste des sujets ne se met pas à jour après avoir cliqué sur l'alerte nouveau sujet/réponse

Sur le site du créateur de thèmes, j’essayais de supprimer les sujets des utilisateurs ignorés de la liste des sujets, voici mon code

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

Cela fonctionne aussi bien sur mobile que sur ordinateur, comme prévu, mais je constate que cela empêche également la liste des sujets de se mettre à jour après avoir cliqué sur l’alerte nouveau sujet/réponse.

J’ai un enregistrement d’écran qui reproduit ce bug.

Dans la vidéo, je regardais la vue mobile sur mon ordinateur et je créais une nouvelle réponse à ‘test new topic alert 3’ depuis mon téléphone portable, puis je cliquais sur l’alerte sur l’ordinateur. Dans le cas normal, le sujet mis à jour devrait apparaître en haut des sujets, mais ce n’est pas le cas ici.

Je pensais que la méthode que j’ai utilisée ci-dessus était déclenchée par erreur, mais elle n’est pas appelée lorsque l’on clique sur une alerte de sujet.

Quelqu’un a-t-il des suggestions sur la raison de ce bug ? Merci beaucoup.

Mise à jour : j’ai constaté que cela empêchait également le chargement automatique de plus de sujets lors du défilement de ne plus fonctionner en vue mobile.

2 « J'aime »

Si vous supprimez le code ci-dessus qui n’affiche pas les utilisateurs ignorés, le problème est-il résolu ? Si c’est le cas, je suppose que votre code filtre les sujets de tous les utilisateurs (ou de plus d’utilisateurs qu’il ne le devrait), ce qui les empêche de s’afficher.

Je ne sais pas d’où ignored est rempli, mais il pourrait être rempli avec le nom d’utilisateur de l’utilisateur qui a créé le nouveau sujet qui a affiché l’alerte en haut. Peut-être qu’il est rempli avec des utilisateurs qui ne devraient pas être ignorés ? Pouvez-vous enregistrer les valeurs présentes dans ignored ?

2 « J'aime »

Je pense que ce n’est pas le cas puisque ce problème ne s’est produit que sur mobile/vue mobile. (pas de “bump” et impossible de charger plus)

J’ai défini manuellement const ignored = ['david', 'pekka_gaiser', 'sam']; afin de tester sur le site du créateur de thèmes, car j’ai supposé que je n’avais pas atteint le niveau de confiance requis pour utiliser la fonction d’ignoré ou qu’elle était désactivée.

Et le sujet que j’ai “bumpé” est un sujet que j’ai créé.

1 « J'aime »

Bizarre, à moins que le problème ne vienne pas spécifiquement de ce code. Si vous modifiez le code pour :

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

le problème persiste-t-il ? S’il persiste, le problème se situe probablement ailleurs.

2 « J'aime »

Non, le bug disparaît si je modifie le bloc pour ce que vous fournissez. Je pensais que la fonction de filtrage pourrait interrompre le cycle de mise à jour des données du sujet, mais ce bug ne se produit que sur mobile. Je n’arrive pas à comprendre ce qui cause la différence entre le bureau et le mobile…

1 « J'aime »

Alors la seule chose à laquelle je peux penser est que la variable ignored est mal remplie comme je l’ai dit précédemment. Peut-être qu’ailleurs la valeur est modifiée. Essayez de changer le code en :

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)
        );
      }
});

Dans le code ci-dessus, j’ai placé la variable ignored dans la même portée où le filtre est appliqué, et j’ai changé le nom de la variable pour éviter des modifications involontaires des valeurs du tableau (par exemple, si quelque part on appelle ignored.push(...), cela pourrait changer ses valeurs ailleurs).

1 « J'aime »

Lorsque vous faites quelque chose comme ceci

this.topics = something_else

Vous redéfinissez cette propriété en quelque chose d’autre. C’est bien si rien d’autre ne surveille cette propriété, mais dans ce cas, plusieurs éléments surveillent le tableau topics.

Par exemple

Si vous faites cela sur une installation de développement, Ember générera des erreurs dans la console comme suit.

.

Donc, la principale leçon à retenir ici est de faire quelque chose comme ceci à la place.

this.set("topics", something_else)

jusqu’à ce que le décorateur @tracked arrive dans Discourse.

Donc, si vous essayez quelque chose comme ceci

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);
  }
});

Cela devrait fonctionner sur ordinateur et mobile sur le créateur de thèmes.

Cependant…

Si vous essayez cela sur une installation de développement, vous verrez une autre erreur.

Cela devrait donc vous indiquer quelque chose. Le tableau topics est utilisé dans de nombreux endroits différents. Il n’est donc pas judicieux de le modifier, surtout que votre cas d’utilisation est principalement visuel et qu’il n’y a pas d’implications de sécurité.

Voici ce que je suggère : prenez du recul et essayez une approche différente. Au lieu d’essayer de modifier le tableau, faites quelque chose de beaucoup plus simple. Si un utilisateur ignoré a créé le sujet, ajoutez une classe CSS et masquez-le avec CSS.

Vous le faites avec quelque chose comme ceci - j’ai laissé quelques commentaires si vous souhaitez suivre, mais vous pouvez les supprimer lorsque vous êtes prêt à l’utiliser.

Ceci va dans le fichier d’initialisation :

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

export default apiInitializer("0.11.1", api => {
  // définir un id pour vos modifications
  const PLUGIN_ID = "hide-ignored-op-topics";

  // Le nom de classe que vous souhaitez ajouter. L'espace au début est requis
  const IGNORED_TOPIC_CLASS_STRING = " ignored-op-topic";

  // obtenir l'utilisateur actuel
  const user = api.getCurrentUser();

  // non connecté, quitter
  if (!user) {
    return;
  }

  // obtenir une liste d'utilisateurs ignorés
  const ignored = user.ignored_users;

  // fonction d'aide pour éviter de dupliquer le code
  const addIgnoredTopicClass = context => {
    // obtenir les classes du cœur / d'autres plugins et thèmes
    let classList = context._super(...arguments);

    // créer votre condition
    const shouldAddClass = ignored.includes(
      context.topic.posters[0].user.username
    );

    // ajouter la classe ignorée si la condition est vraie
    if (shouldAddClass) {
      classList += IGNORED_TOPIC_CLASS_STRING;
    }

    // retourner la liste des classes plus les modifications, le cas échéant
    return classList;
  };

  // ajouter la classe à la liste de sujets par défaut comme sur la page "latest"
  api.modifyClass("component:topic-list-item", {
    pluginId: PLUGIN_ID,
    @discourseComputed()
    unboundClassNames() {
      return addIgnoredTopicClass(this);
    }
  });

  // faire de même pour la liste de sujets de la page des catégories
  api.modifyClass("component:latest-topic-list-item", {
    pluginId: PLUGIN_ID,
    @discourseComputed()
    unboundClassNames() {
      return addIgnoredTopicClass(this);
    }
  });
});

et ceci va dans /common/common.css

// nous n'utilisons pas display: none; ici car nous ne voulons pas interférer avec le chargement plus
.ignored-op-topic {
  height: 0;
  width: 0;
  position: fixed;
  bottom: 0;
}
2 « J'aime »

Merci, la 2e méthode fonctionne.

Est-il possible d’ajouter une classe supplémentaire à l’élément enfant du composant ?

Par exemple, j’aimerais masquer l’avatar de l’utilisateur ignoré dans la liste d’avatars du bureau sur le côté droit du titre du sujet, en ajoutant une classe à l’élément de la liste des sujets, sera-t-il possible d’ajouter une classe à un composant d’avatar ?

La méthode unboundClassNames() que nous avons utilisée ci-dessus est responsable des classes ajoutées à l’élément du composant. En d’autres termes, les éléments HTML .topic-list-item ou .latest-topic-list-item. Vous pouvez le voir ici

et ici

Ember prend la chaîne de caractères renvoyée par cette méthode et l’ajoute comme attribut class sur l’élément lui-même.
Vous devrez utiliser autre chose si vous souhaitez ajouter des classes aux enfants de cet élément.
Chaque afficheur dans la propriété posters a une propriété appelée extras. Cette propriété est utilisée comme indicateur pour les classes supplémentaires à ajouter à l’avatar lors de son rendu.
Elle est définie ici

et consommée ici

Ainsi, vous pouvez ajouter des classes aux avatars dans la liste des sujets en fonction d’une condition si vous étendez cette propriété.
Vous pouvez utiliser le décorateur @on lorsque le composant reçoit ses attributs pour appeler une méthode afin de le faire. Puisque nous modifions déjà ces classes de composants, nous pouvons intégrer ce nouveau comportement dans le code ci-dessus.
Voici ce que nous obtenons
dans l’initialiseur

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);
    },
  });
});

Cela devrait vous donner une classe CSS ignored-op-topic sur les éléments de liste de sujets initiés par un utilisateur ignoré et une classe CSS ignored-user-avatar sur chaque avatar d’utilisateur ignoré dans la colonne des afficheurs.
Nous avons déjà le CSS pour .ignored-op-topic ci-dessus.

// nous n'utilisons pas display: none; ici car nous ne voulons pas interférer avec le chargement
.ignored-op-topic {
  height: 0;
  width: 0;
  position: fixed;
  bottom: 0;
}

Maintenant, vous voulez masquer les avatars des utilisateurs ignorés dans la colonne des afficheurs.

Ne faites pas cela. Cela créera beaucoup de confusion.
Et si un utilisateur ignoré répondait à un sujet, et qu’il était remonté, mais que vous aviez masqué son avatar ? Cela donnerait l’impression que quelqu’un d’autre a remonté le sujet.
De plus, il n’y a qu’un seul avatar sur la page des catégories à côté des titres de sujets. Que se passe-t-il si la dernière réponse est d’un utilisateur ignoré ? Pas d’avatar ?
Vous pouvez voir comment de tels cas créeraient une expérience désagréable pour vos utilisateurs.
Au lieu de masquer les avatars des utilisateurs ignorés, vous pouvez les remplacer par une icône SVG. Tous les utilisateurs ignorés auront le même avatar. Vous pouvez le faire avec du 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  );
}

et il sera rendu comme ceci


et de même sur latest-topic-list-item. Changez le SVG pour l’icône que vous souhaitez utiliser.
Cela étant dit…
J’ai répondu à votre question car c’est une bonne occasion de parler de la personnalisation de la liste des sujets et de la manière dont vous pourriez le faire. Cependant, j’ai beaucoup de réserves quant à votre cas d’utilisation. Le besoin de masquer les avatars des utilisateurs ignorés indique un problème sous-jacent. C’est une chose de dire

“cette personne écrit sur des sujets qui ne m’intéressent pas. Je vais l’ignorer pour réduire le bruit.”
mais c’est une tout autre chose de dire
“même voir l’avatar de cette personne déclenche une réponse émotionnelle. Je ne veux plus jamais voir son avatar.”
Vous connaissez votre communauté mieux que quiconque… mais c’est probablement quelque chose qui mérite d’être examiné.

4 « J'aime »

Compris. J’essayais d’imiter la fonction de blocage comme Mastodon ou Twitter autant que possible, c’est-à-dire que lorsque vous ignorez un utilisateur, vous ne verrez plus jamais de contenu de sa part. Je suis d’accord que la plupart des communautés n’auront peut-être jamais besoin de ce type de fonction. Puisque mes utilisateurs le demandent, je voudrais faire de mon mieux.

1 « J'aime »