Als Teil unserer kontinuierlichen Bemühungen zur Verbesserung der Discourse-Codebasis entfernen wir die Verwendung des veralteten „Widget“-Rendersystems und ersetzen es durch Glimmer-Komponenten.
Kürzlich haben wir das Beitragsmenü modernisiert, das jetzt in Discourse über die Einstellung glimmer_post_menu_mode verfügbar ist.
Diese Einstellung akzeptiert drei mögliche Werte:
disabled: Verwendet das veraltete „Widget“-System.auto: Erkennt die Kompatibilität Ihrer aktuellen Plugins und Themes. Wenn welche inkompatibel sind, wird das veraltete System verwendet; andernfalls wird das neue Menü verwendet.enabled: Verwendet das neue Menü. Wenn Sie ein inkompatibles Plugin oder Theme haben, kann Ihre Seite beschädigt werden.
Wir haben unsere offiziellen Plugins bereits aktualisiert, um mit dem neuen Menü kompatibel zu sein. Wenn Sie jedoch noch ein Drittanbieter-Plugin, -Theme oder eine -Theme-Komponente haben, die mit dem neuen Menü inkompatibel ist, ist ein Upgrade erforderlich.
Warnungen werden in der Browserkonsole ausgegeben, die die Quelle der Inkompatibilität identifizieren.
Zeitplan für die Einführung
Dies sind grobe Schätzungen, die Änderungen unterliegen
Q4 2024:
Kernimplementierung abgeschlossen
Offizielle Plugins aktualisiert
Auf Meta aktiviert
glimmer_post_menu_modestandardmäßig aufauto; Deprecation-Meldungen in der Konsole aktiviert
Upgrade-Empfehlungen veröffentlicht
Q1 2025:
Drittanbieter-Plugins und Themes sollten aktualisiert sein
Deprecation-Meldungen beginnen und lösen eine Warnbanner für Administratoren für verbleibende Probleme aus
Das neue Beitragsmenü standardmäßig aktiviert
Q2 2025
1. April - Entfernung der Feature-Flag-Einstellung und des veralteten Codes
Was bedeutet das für mich?
Wenn Ihr Plugin oder Theme „Widget“-APIs verwendet, um das Beitragsmenü anzupassen, müssen diese aktualisiert werden, um mit der neuen Version kompatibel zu sein.
Wie kann ich das neue Beitragsmenü testen?
In der neuesten Version von Discourse wird das neue Beitragsmenü aktiviert, wenn Sie keine inkompatiblen Plugins oder Themes haben.
Wenn Sie inkompatible Erweiterungen installiert haben, können Sie als Administrator die Einstellung trotzdem auf enabled ändern, um das neue Menü zu erzwingen. Verwenden Sie dies mit Vorsicht, da Ihre Seite je nach installierten Anpassungen beschädigt sein könnte.
In dem unwahrscheinlichen Fall, dass dieses automatische System nicht wie erwartet funktioniert, können Sie diesen „automatischen Feature-Flag“ vorübergehend mit der oben genannten Einstellung überschreiben. Falls Sie dies tun müssen, teilen Sie uns dies bitte in diesem Thema mit.
Muss ich mein Plugin oder Theme aktualisieren?
Sie müssen Ihre Plugins oder Themes aktualisieren, wenn sie eine der folgenden Anpassungen durchführen:
-
Verwendung von
decorateWidget,changeWidgetSetting,reopenWidgetoderattachWidgetActionan diesen Widgets:post-menupost-user-tip-shimsmall-user-list
-
Verwendung einer der folgenden API-Methoden:
addPostMenuButtonremovePostMenuButtonreplacePostMenuButton
Falls Sie Erweiterungen haben, die eine der oben genannten Anpassungen durchführen, wird eine Warnung in der Konsole ausgegeben, die das Plugin oder die Komponente identifiziert, die aktualisiert werden muss, wenn Sie eine Topic-Seite aufrufen.
Die Deprecation-ID lautet:
discourse.post-menu-widget-overrides
Wenn Sie mehr als ein Theme in Ihrer Instanz verwenden, überprüfen Sie bitte alle, da Warnungen nur für aktive Plugins und derzeit verwendete Themes sowie Theme-Komponenten ausgegeben werden.
Was sind die Ersatzlösungen?
Wir haben den Value Transformer post-menu-buttons als neue API zur Anpassung des Beitragsmenüs eingeführt.
Der Value Transformer bietet ein DAG-Objekt, das das Hinzufügen, Ersetzen, Entfernen oder Neuordnen von Schaltflächen ermöglicht. Es stellt zudem Kontextinformationen bereit, wie den Beitrag, der mit dem Menü verknüpft ist, den Status des angezeigten Beitrags und Schaltflächenschlüssel, um eine einfachere Platzierung der Elemente zu ermöglichen.
Die DAG-API erwartet Ember-Komponenten, wenn die API eine neue Schaltflächendefinition wie .add oder .replace benötigt.
Jede Anpassung ist anders, aber hier sind einige Richtlinien für die häufigsten Anwendungsfälle:
addPostMenuButton
Vorher:
withPluginApi("1.34.0", (api) => {
api.addPostMenuButton("solved", (attrs) => {
if (attrs.can_accept_answer) {
const isOp = currentUser?.id === attrs.topicCreatedById;
return {
action: "acceptAnswer",
icon: "far-check-square",
className: "unaccepted",
title: "solved.accept_answer",
label: isOp ? "solved.solution" : null,
position: attrs.topic_accepted_answer ? "second-last-hidden" : "first",
};
}
});
});
Nachher:
Die folgenden Beispiele verwenden das Template Tag Format (gjs) von Ember.
// components/solved-accept-answer-button.gjs
import Component from "@glimmer/component";
import { action } from "@ember/object";
import { inject as service } from "@ember/service";
import DButton from "discourse/components/d_button";
import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
export default class SolvedAcceptAnswerButton extends Component {
// Gibt an, ob die Schaltfläche sofort angezeigt oder hinter der „Mehr anzeigen“-Schaltfläche versteckt wird
static hidden(args) {
return args.post.topic_accepted_answer;
}
...
<template>
<DButton
class="post-action-menu__solved-unaccepted unaccepted"
...attributes
@action={{this.acceptAnswer}}
@icon="far-check-square"
@label={{if this.showLabel "solved.solution"}}
@title="solved.accept_answer"
/>
</template>
}
// initializer.js
import SolvedAcceptAnswerButton from "../components/solved-accept-answer-button";
...
withPluginApi("1.34.0", (api) => {
api.registerValueTransformer(
"post-menu-buttons",
({
value: dag,
context: {
post,
firstButtonKey, // Schlüssel der ersten Schaltfläche
secondLastHiddenButtonKey, // Schlüssel der zweiten vorletzten versteckten Schaltfläche
lastHiddenButtonKey, // Schlüssel der letzten versteckten Schaltfläche
},
}) => {
dag.add(
"solved",
SolvedAcceptAnswerButton,
post.topic_accepted_answer
? {
before: lastHiddenButtonKey,
after: secondLastHiddenButtonKey,
}
: {
before: [
"assign", // vom assign-Plugin hinzugefügte Schaltfläche
firstButtonKey,
],
}
);
}
);
});
Styling Ihrer Schaltflächen
Es wird empfohlen,
...attributeswie im obigen Beispiel in Ihrer Komponente einzufügen.In Kombination mit der Verwendung der Komponenten
DButtonoderDMenuübernimmt dies die Boilerplate-Klassen und stellt sicher, dass Ihre Schaltfläche dem Format der anderen Schaltflächen im Beitragsmenü folgt.Zusätzliche Formatierungen können mit Ihren benutzerdefinierten Klassen angegeben werden.
replacePostMenuButton
- Vorher:
withPluginApi("1.34.0", (api) => {
api.replacePostMenuButton("like", {
name: "discourse-reactions-actions",
buildAttrs: (widget) => {
return { post: widget.findAncestorModel() };
},
shouldRender: (widget) => {
const post = widget.findAncestorModel();
return post && !post.deleted_at;
},
});
});
- Nachher:
import ReactionsActionButton from "../components/discourse-reactions-actions-button";
...
withPluginApi("1.34.0", (api) => {
api.registerValueTransformer(
"post-menu-buttons",
({ value: dag, context: { buttonKeys } }) => {
// ReactionsActionButton ist die neue Schaltflächenkomponente
dag.replace(buttonKeys.LIKE, ReactionsActionButton);
}
);
});
removePostMenuButton
- Vorher:
withPluginApi("1.34.0", (api) => {
api.removePostMenuButton('like', (attrs, state, siteSettings, settings, currentUser) => {
if (attrs.post_number === 1) {
return true;
}
});
});
- Nachher:
withPluginApi("1.34.0", (api) => {
api.registerValueTransformer(
"post-menu-buttons",
({ value: dag, context: { post, buttonKeys } }) => {
if (post.post_number === 1) {
dag.delete(buttonKeys.LIKE);
}
}
);
});
Was ist mit anderen Anpassungen?
Wenn Ihre Anpassung nicht mit der neuen API erreicht werden kann, die wir eingeführt haben, teilen Sie uns dies bitte mit, indem Sie ein neues Entwickler-Thema erstellen, um dies zu diskutieren.
Ich bin Autor eines Plugins/Themes. Wie aktualisiere ich ein Theme/Plugin, um während der Übergangszeit sowohl das alte als auch das neue Beitragsmenü zu unterstützen?
Wir haben das folgende Muster verwendet, um sowohl die alte als auch die neue Version des Beitragsmenüs in unseren Plugins zu unterstützen:
function customizePostMenu(api) {
const transformerRegistered = api.registerValueTransformer(
"post-menu-buttons",
({ value: dag, context }) => {
// neue Beitragsmenü-Anpassungen
...
}
);
const silencedKey =
transformerRegistered && "discourse.post-menu-widget-overrides";
withSilencedDeprecations(silencedKey, () => customizeWidgetPostMenu(api));
}
function customizeWidgetPostMenu(api) {
// alte „Widget“-Code-Anpassung hier
...
}
export default {
name: "my-plugin",
initialize(container) {
withPluginApi("1.34.0", customizePostMenu);
}
};
Weitere Beispiele
Sie können unsere offiziellen Plugins auf Beispiele für die Verwendung der neuen API überprüfen: