كجزء من جهودنا المستمرة لتحسين قاعدة كود Discourse، نقوم بإزالة استخدامات نظام عرض “widget” القديم واستبدالها بمكونات Glimmer.
مؤخرًا، قمنا بتحديث قائمة المنشور، وهي الآن متاحة في Discourse خلف إعداد glimmer_post_menu_mode.
يقبل هذا الإعداد ثلاثة قيم محتملة:
disabled: استخدام نظام “widget” القديمauto: سيكتشف توافق الإضافات والمظاهر الحالية لديك. إذا كانت أي منها غير متوافقة، فسيتم استخدام النظام القديم؛ وإلا سيتم استخدام القائمة الجديدة.enabled: سيتم استخدام القائمة الجديدة. إذا كان لديك أي إضافة أو مظهر غير متوافق، فقد يتعطل موقعك.
لقد قمنا بالفعل بتحديث إضافاتنا الرسمية لتكون متوافقة مع القائمة الجديدة، ولكن إذا كنت لا تزال تستخدم أي إضافة أو مظهر أو مكون مظهر تابع لجهة خارجية غير متوافق مع القائمة الجديدة، فسيكون تحديثها مطلوبًا.
سيتم طباعة تحذيرات في وحدة تحكم المتصفح لتحديد مصدر عدم التوافق.
جدول زمني للتطبيق
هذه تقديرات تقريبية قابلة للتغيير
الربع الرابع 2024:
اكتمل التنفيذ الأساسي
تم تحديث الإضافات الرسمية
تم التمكين في Meta
تم تعيين glimmer_post_menu_modeافتراضيًا إلىauto؛ وتم تفعيل رسائل إبطال في وحدة التحكم
تم نشر نصائح الترقية
الربع الأول 2025:
يجب تحديث الإضافات والمظاهر التابعة لجهات خارجية
تبدأ رسائل الإبطال، مما يؤدي إلى ظهور شريط تحذير للمسؤول لأي مشكلات متبقية
تم تمكين قائمة المنشور الجديدة افتراضيًا
الربع الثاني 2025
1 أبريل - إزالة إعداد ميزة العلم والكود القديم
ماذا يعني هذا بالنسبة لي؟
إذا كانت إضافة أو مظهر الخاص بك يستخدم أي واجهات برمجة تطبيقات (APIs) لـ ‘widget’ لتخصيص قائمة المنشور، فسيحتاج ذلك إلى التحديث ليكون متوافقًا مع الإصدار الجديد.
كيف يمكنني تجربة قائمة المنشور الجديدة؟
في أحدث إصدار من Discourse، سيتم تمكين قائمة المنشور الجديدة إذا لم يكن لديك أي إضافة أو مظهر غير متوافق.
إذا كان لديك امتدادات غير متوافقة مثبتة، فبصفتك مسؤولًا، يمكنك تغيير الإعداد إلى enabled لإجبار استخدام القائمة الجديدة. استخدم هذا بحذر حيث قد يتعطل موقعك اعتمادًا على التخصيصات المثبتة لديك.
في الحالة غير المحتملة التي لا يعمل فيها هذا النظام التلقائي كما هو متوقع، يمكنك تجاوز هذا “معلمة الميزة التلقائية” مؤقتًا باستخدام الإعداد المذكور أعلاه. إذا كنت بحاجة إلى ذلك، يرجى إبلاغنا في هذا الموضوع.
هل أحتاج إلى تحديث إضافتي ومظهري؟
ستحتاج إلى تحديث الإضافات أو المظاهر الخاصة بك إذا قامت بأي من التخصيصات التالية:
-
استخدام
decorateWidget،changeWidgetSetting،reopenWidgetأوattachWidgetActionعلى هذه الـ widgets:post-menupost-user-tip-shimsmall-user-list
-
استخدام أي من طرق واجهة برمجة التطبيقات (API) التالية:
addPostMenuButtonremovePostMenuButtonreplacePostMenuButton
في حال كان لديك امتدادات تقوم بأحد التخصيصات المذكورة أعلاه، سيتم طباعة تحذير في وحدة التحكم لتحديد الإضافة أو المكون الذي يحتاج إلى ترقية عند الوصول إلى صفحة موضوع.
معرف الإبطال هو:
discourse.post-menu-widget-overrides
إذا كنت تستخدم أكثر من مظهر في مثيلتك، فتأكد من التحقق من جميعها حيث سيتم طباعة التحذيرات فقط للإضافات النشطة والمظاهر والمكونات المظهرية المستخدمة حاليًا.
ما هي البدائل؟
لقد قدمنا محول القيمة post-menu-buttons كواجهة برمجة تطبيقات (API) جديدة لتخصيص قائمة المنشور.
يوفر محول القيمة كائن DAG يسمح بإضافة أو استبدال أو حذف أو إعادة ترتيب الأزرار. كما يوفر معلومات سياقية مثل المنشور المرتبط بالقائمة، وحالة المنشور المعروض، ومفاتيح الأزرار لتمكين وضع العناصر بسهولة.
تتوقع واجهات برمجة تطبيقات DAG استقبال مكونات Ember إذا كانت واجهة برمجة التطبيقات تحتاج إلى تعريف زر جديد مثل .add و .replace.
كل تخصيص مختلف، ولكن إليك بعض التوجيهات لأكثر حالات الاستخدام شيوعًا:
addPostMenuButton
قبل:
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",
};
}
});
});
بعد:
تستخدم الأمثلة أدناه تنسيق قالب Ember Template Tag Format (gjs)
// 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 {
// يشير إلى ما إذا كان الزر سيظهر فورًا أو يكون مخفيًا خلف زر إظهار المزيد
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, // مفتاح الزر الأول
secondLastHiddenButtonKey, // مفتاح الزر المخفي الثاني من النهاية
lastHiddenButtonKey, // مفتاح الزر المخفي الأخير
},
}) => {
dag.add(
"solved",
SolvedAcceptAnswerButton,
post.topic_accepted_answer
? {
before: lastHiddenButtonKey,
after: secondLastHiddenButtonKey,
}
: {
before: [
"assign", // زر تمت إضافته بواسطة إضافة assign
firstButtonKey,
],
}
);
}
);
});
تنسيق أزرارك
يُوصى بتضمين
...attributesكما هو موضح في المثال أعلاه في مكونك.عند دمجه مع استخدام مكونات
DButtonأوDMenu، سيعني ذلك الاهتمام بالفئات الأساسية (boilerplate classes) ويضمن أن يتبع الزر تنسيق الأزرار الأخرى في قائمة المنشور.يمكن تحديد تنسيق إضافي باستخدام فئاتك المخصصة.
replacePostMenuButton
- قبل:
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;
},
});
});
- بعد:
import ReactionsActionButton from "../components/discourse-reactions-actions-button";
...
withPluginApi("1.34.0", (api) => {
api.registerValueTransformer(
"post-menu-buttons",
({ value: dag, context: { buttonKeys } }) => {
// ReactionsActionButton هو مكون الزر الجديد
dag.replace(buttonKeys.LIKE, ReactionsActionButton);
}
);
});
removePostMenuButton
- قبل:
withPluginApi("1.34.0", (api) => {
api.removePostMenuButton('like', (attrs, state, siteSettings, settings, currentUser) => {
if (attrs.post_number === 1) {
return true;
}
});
});
- بعد:
withPluginApi("1.34.0", (api) => {
api.registerValueTransformer(
"post-menu-buttons",
({ value: dag, context: { post, buttonKeys } }) => {
if (post.post_number === 1) {
dag.delete(buttonKeys.LIKE);
}
}
);
});
ماذا عن التخصيصات الأخرى؟
إذا لم يكن بإمكانك تحقيق تخصيصك باستخدام واجهة برمجة التطبيقات (API) الجديدة التي قدمناها، فيرجى إبلاغنا بإنشاء موضوع تطوير جديد لمناقشته.
أنا مؤلف إضافة/مظهر. كيف يمكنني تحديث مظهر/إضافة لدعم كل من القائمة القديمة والجديدة للمنشورات أثناء فترة الانتقال؟
لقد استخدمنا النمط أدناه لدعم كل من الإصدار القديم والجديد من قائمة المنشور في إضافاتنا:
function customizePostMenu(api) {
const transformerRegistered = api.registerValueTransformer(
"post-menu-buttons",
({ value: dag, context }) => {
// تخصيصات قائمة المنشور الجديدة
...
}
);
const silencedKey =
transformerRegistered && "discourse.post-menu-widget-overrides";
withSilencedDeprecations(silencedKey, () => customizeWidgetPostMenu(api));
}
function customizeWidgetPostMenu(api) {
// تخصيصات كود "widget" القديم هنا
...
}
export default {
name: "my-plugin",
initialize(container) {
withPluginApi("1.34.0", customizePostMenu);
}
};
المزيد من الأمثلة
يمكنك التحقق من إضافاتنا الرسمية للحصول على أمثلة حول كيفية استخدام واجهة برمجة التطبيقات (API) الجديدة: