Hilfe bei der Suche, warum die Themenliste nach dem Klicken auf den neuen Themen-/Antwortalarm nicht aktualisiert wird

Auf der Theme Creator-Website habe ich versucht, Themen von ignorierten Benutzern aus der Themenliste zu entfernen. Hier ist mein Code:

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

Er funktioniert sowohl auf Mobilgeräten als auch auf Desktops wie erwartet, aber ich habe festgestellt, dass die Themenliste auch nicht aktualisiert wird, nachdem auf die Benachrichtigung für neue Themen/Antworten geklickt wurde.

Ich habe eine Bildschirmaufnahme, die diesen Fehler reproduziert.

In dem Video habe ich die mobile Ansicht auf meinem Desktop betrachtet und eine neue Antwort auf „test new topic alert 3“ von meinem Handy aus erstellt. Dann klicke ich auf dem Desktop auf die Benachrichtigung. Im Normalfall sollte das verschobene Thema ganz oben in den Themen angezeigt werden, aber in diesem Fall nicht.

Ich dachte, die von mir verwendete Methode würde fälschlicherweise ausgelöst, aber sie wird nicht aufgerufen, wenn auf eine Themenbenachrichtigung geklickt wird.

Hat jemand Vorschläge, warum dieser Fehler auftritt? Vielen Dank.

Update: Ich habe festgestellt, dass dadurch auch das automatische Laden weiterer Themen beim Scrollen in der mobilen Ansicht nicht mehr funktioniert.

2 „Gefällt mir“

Wenn Sie den obigen Code entfernen, der keine ignorierten Benutzer anzeigt, ist das Problem dann behoben? Wenn es behoben ist, vermute ich, dass Ihr Code die Themen aller Benutzer (oder mehr Benutzer als er sollte) herausfiltert, was dazu führt, dass sie nicht angezeigt werden.

Ich weiß nicht, woher ignored gefüllt wird, aber es könnte mit dem Benutzernamen des Benutzers gefüllt werden, der das neue Thema erstellt hat, das die Benachrichtigung oben angezeigt hat. Vielleicht wird es mit Benutzern gefüllt, die nicht ignoriert werden sollten? Können Sie die Werte protokollieren, die in ignored vorhanden sind?

2 „Gefällt mir“

Ich glaube nicht, dass das der Fall ist, da dieses Problem nur auf Mobilgeräten/in der mobilen Ansicht aufgetreten ist. (nicht hochgestoßen und kann nicht mehr laden)

Ich habe const ignored = ['david', 'pekka_gaiser', 'sam']; manuell gesetzt, um auf der Theme Creator-Website zu testen, da ich davon ausging, dass ich das Vertrauensniveau, das die Ignore-Funktion nutzen kann, noch nicht erreicht habe oder sie deaktiviert war.

Und das Thema, das ich hochgestoßen habe, ist ein Thema, das ich erstellt habe.

1 „Gefällt mir“

Seltsam, es sei denn, das Problem liegt nicht speziell in diesem Code. Wenn Sie den Code ändern zu:

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

Besteht das Problem weiterhin? Wenn ja, liegt das Problem wahrscheinlich woanders.

2 „Gefällt mir“

Nein, der Fehler ist weg, wenn ich den Block zu dem ändere, was Sie bereitstellen. Ich dachte, vielleicht unterbricht die Filterfunktion den Aktualisierungszyklus der Themen-Daten, aber dieser Fehler tritt nur auf Mobilgeräten auf. Ich kann nicht herausfinden, was den Unterschied zwischen Desktop und Mobilgeräten verursacht…

1 „Gefällt mir“

Dann ist das Einzige, was mir einfällt, dass die Variable ignored falsch befüllt wird, wie ich bereits sagte. Vielleicht ändert sich der Wert irgendwo anders. Versuche, den Code zu ändern zu:

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

Im obigen Code habe ich die Variable ignored in denselben Geltungsbereich gelegt, in dem der Filter angewendet wird, und den Variablennamen geändert, um unbeabsichtigte Änderungen der Array-Werte zu vermeiden (zum Beispiel, wenn irgendwo ignored.push(...) aufgerufen wird, könnten sich seine Werte woanders ändern).

1 „Gefällt mir“

Wenn Sie so etwas tun

this.topics = something_else

Sie definieren diese Eigenschaft neu als etwas anderes. Das ist in Ordnung, wenn nichts anderes diese Eigenschaft beobachtet, aber in diesem Fall beobachten mehrere Dinge das topics-Array.

Zum Beispiel

Wenn Sie dies in einer Entwicklungsumgebung tun, gibt Ember Fehler in der Konsole aus, wie hier.

.

Der wichtigste Punkt hier ist, stattdessen so etwas zu tun:

this.set("topics", something_else)

bis der @tracked-Decorator in Discourse verfügbar ist.

Wenn Sie also so etwas versuchen:

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

sollte es sowohl auf dem Desktop als auch auf dem Handy im Theme Creator funktionieren.

Allerdings…

Wenn Sie dies in einer Entwicklungsumgebung versuchen, sehen Sie einen weiteren Fehler.

Das sollte Ihnen also etwas sagen. Das topics-Array wird an vielen verschiedenen Stellen verwendet. Es ist also keine gute Idee, damit herumzuspielen – insbesondere da Ihr Anwendungsfall hauptsächlich visuell ist und keine Sicherheitsimplikationen damit verbunden sind.

Hier ist mein Vorschlag: Machen Sie einen Schritt zurück und versuchen Sie einen anderen Ansatz. Anstatt zu versuchen, das Array zu ändern, tun Sie etwas viel Einfacheres. Wenn ein ignorierter Benutzer das Thema erstellt hat, fügen Sie eine CSS-Klasse hinzu und blenden Sie es mit CSS aus.
Das machen Sie mit etwas wie diesem – ich habe einige Kommentare hinterlassen, falls Sie sie verfolgen möchten, aber Sie können sie löschen, wenn Sie bereit sind, sie zu verwenden.

Dies kommt in die Initialisierungsdatei:

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

export default apiInitializer("0.11.1", api => {
  // eine ID für Ihre Modifikationen festlegen
  const PLUGIN_ID = "hide-ignored-op-topics";

  // Der Klassenname, den Sie hinzufügen möchten. Das Leerzeichen am Anfang ist erforderlich
  const IGNORED_TOPIC_CLASS_STRING = " ignored-op-topic";

  // aktuellen Benutzer abrufen
  const user = api.getCurrentUser();

  // nicht angemeldet, abbrechen
  if (!user) {
    return;
  }

  // eine Liste der ignorierten Benutzer abrufen
  const ignored = user.ignored_users;

  // Hilfsfunktion zur Vermeidung von Code-Duplizierung
  const addIgnoredTopicClass = context => {
    // Klassen von Core / anderen Plugins und Themes abrufen
    let classList = context._super(...arguments);

    // Ihre Bedingung erstellen
    const shouldAddClass = ignored.includes(
      context.topic.posters[0].user.username
    );

    // ignorierten Klasse hinzufügen, wenn die Bedingung wahr ist
    if (shouldAddClass) {
      classList += IGNORED_TOPIC_CLASS_STRING;
    }

    // die classList plus die Modifikationen zurückgeben, falls vorhanden
    return classList;
  };

  // die Klasse zur Standard-Themenliste hinzufügen, wie auf der "neuesten"-Seite
  api.modifyClass("component:topic-list-item", {
    pluginId: PLUGIN_ID,
    @discourseComputed()
    unboundClassNames() {
      return addIgnoredTopicClass(this);
    }
  });

  // dasselbe für die Themenliste der Kategorienseite tun
  api.modifyClass("component:latest-topic-list-item", {
    pluginId: PLUGIN_ID,
    @discourseComputed()
    unboundClassNames() {
      return addIgnoredTopicClass(this);
    }
  });
});

und dies kommt in /common/common.css

// wir verwenden hier kein display: none;, da wir uns nicht mit load-more beschäftigen wollen
.ignored-op-topic {
  height: 0;
  width: 0;
  position: fixed;
  bottom: 0;
}
2 „Gefällt mir“

Danke, die zweite Methode funktioniert.

Ist es möglich, eine zusätzliche Klasse zum Kindelement der Komponente hinzuzufügen?

Zum Beispiel möchte ich den Avatar des ignorierten Benutzers in der Desktop-Avatarliste auf der rechten Seite des Thementitels ausblenden. Wenn ich eine Klasse zum Themensuchlisten-Element hinzufüge, wird es möglich sein, eine Klasse zu einer Avatar-Komponente hinzuzufügen?

Die unboundClassNames()-Methode, die wir oben verwendet haben, ist für die Klassen verantwortlich, die dem Komponentenelement hinzugefügt werden. Mit anderen Worten, die HTML-Elemente .topic-list-item oder .latest-topic-list-item. Sie können dies hier sehen
discourse/app/assets/javascripts/discourse/app/components/topic-list-item.js at ad4faf637c9caf7e6ac60a614e3838a69c928e27 · discourse/discourse · GitHub
und hier
discourse/app/assets/javascripts/discourse/app/components/latest-topic-list-item.js at 1472e47aae5bfdfb6fd9abfe89beb186c751f514 · discourse/discourse · GitHub
Ember nimmt jeden String, den diese Methode zurückgibt, und fügt ihn als class-Attribut auf dem Element selbst hinzu.
Sie müssen etwas anderes verwenden, wenn Sie Klassen zu Kindern dieses Elements hinzufügen möchten.
Jeder Poster in der posters-Eigenschaft hat eine Eigenschaft namens extras. Diese Eigenschaft wird als Flag für zusätzliche Klassen verwendet, die dem Avatar hinzugefügt werden sollen, wenn er gerendert wird.
Es ist hier gesetzt
discourse/app/assets/javascripts/discourse/app/models/topic-list.js at d3a59e3f695c467c22d02db62532194e17ac827b · discourse/discourse · GitHub
und hier verbraucht
discourse/app/assets/javascripts/discourse/app/templates/list/posters-column.hbr at 1472e47aae5bfdfb6fd9abfe89beb186c751f514 · discourse/discourse · GitHub
Sie können also Klassen zu Avataren in der Topic-Liste basierend auf einer Bedingung hinzufügen, wenn Sie diese Eigenschaft erweitern.
Sie können den @on-Decorator verwenden, wenn die Komponente ihre Attribute erhält, um eine Methode aufzurufen, die dies tut. Da wir diese Komponentenkassen bereits ändern, können wir dieses neue Verhalten in den obigen Code integrieren.
Hier ist, was wir am Ende haben
im Initialisierer

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

Dies sollte Ihnen eine CSS-Klasse ignored-op-topic für Topic-List-Items geben, die von einem ignorierten Benutzer gestartet wurden, und eine CSS-Klasse ignored-user-avatar für jeden Avatar eines ignorierten Benutzers in der Poster-Spalte.
Wir haben bereits die CSS für .ignored-op-topic von oben.

// wir verwenden hier kein display: none;, da wir load-more nicht beeinträchtigen wollen
.ignored-op-topic {
  height: 0;
  width: 0;
  position: fixed;
  bottom: 0;
}

Jetzt möchten Sie ignorierte Benutzer-Avatare in der Poster-Spalte ausblenden.

Tun Sie das nicht. Dies wird zu viel Verwirrung stiften.
Was ist, wenn ein ignorierter Benutzer auf ein Topic antwortet und es hochgestuft wird, aber Sie haben seinen Avatar ausgeblendet? Es würde so aussehen, als hätte jemand anderes das Topic hochgestuft.
Außerdem gibt es auf der Kategorienseite nur einen Avatar neben den Topic-Titeln. Was passiert, wenn die letzte Antwort von einem ignorierten Benutzer stammt? Kein Avatar?
Sie können sehen, wie solche Fälle zu einer unangenehmen Erfahrung für Ihre Benutzer führen würden.
Anstatt ignorierte Benutzer-Avatare auszublenden, können Sie sie durch ein SVG-Icon ersetzen. Alle ignorierten Benutzer haben denselben Avatar. Das können Sie mit CSS tun

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

und es wird so gerendert


und dasselbe auf latest-topic-list-item. Ändern Sie das SVG in jedes gewünschte Icon.
Damit ist das aus dem Weg…
Ich habe Ihre Frage beantwortet, da sie eine gute Gelegenheit bietet, über die Anpassung der Topic-Liste zu sprechen und wie Sie dies tun würden. Ich habe jedoch viele Vorbehalte gegenüber Ihrem Anwendungsfall. Die Notwendigkeit, die Avatare von ignorierten Benutzern auszublenden, deutet auf ein zugrunde liegendes Problem hin. Es ist eine Sache zu sagen

“Diese Person schreibt über Themen, die mich nicht interessieren. Ich werde sie ignorieren, um das Rauschen zu reduzieren.”
aber es ist eine ganz andere Sache zu sagen
“Schon der Anblick des Avatars dieser Person löst eine emotionale Reaktion aus. Ich möchte ihren Avatar nie wieder sehen.”
Sie kennen Ihre Community besser als jeder andere… aber das ist wahrscheinlich etwas, das es wert ist, untersucht zu werden.

4 „Gefällt mir“

Verstanden. Ich habe versucht, die Blockierfunktion wie bei Mastodon oder Twitter so gut wie möglich nachzuahmen, damit man, wenn man einen Benutzer ignoriert, nie wieder Inhalte von ihm sieht. Ich stimme zu, dass die meisten Communities diese Art von Funktion vielleicht nie brauchen werden. Da meine Benutzer danach fragen, möchte ich mein Bestes geben.

1 „Gefällt mir“