Get started
تصميم استيراد سمة مخصصة من tweakcn
تصميم استيراد سمة مخصصة من tweakcn
الحالة: تمت الموافقة في الطرفية بتاريخ 2026-04-22
الملخص
أضف فتحة واحدة فقط لسمة مخصصة محلية في المتصفح لواجهة التحكم يمكن استيرادها من رابط مشاركة tweakcn. تظل عائلات السمات المضمنة الحالية claw وknot وdash كما هي. تعمل عائلة custom الجديدة مثل عائلة سمات OpenClaw عادية، وتدعم أوضاع light وdark وsystem عندما تتضمن حمولة tweakcn المستوردة مجموعتي رموز فاتحة وداكنة.
تُخزن السمة المستوردة فقط في ملف تعريف المتصفح الحالي مع بقية إعدادات واجهة التحكم. ولا تُكتب إلى إعدادات Gateway ولا تتزامن عبر الأجهزة أو المتصفحات.
المشكلة
نظام سمات واجهة التحكم مغلق حاليًا على ثلاث عائلات سمات مضمنة ثابتة في الشفرة:
ui/src/ui/theme.tsui/src/ui/views/config.tsui/src/styles/base.css
يمكن للمستخدمين التبديل بين العائلات المضمنة ومتغيرات الوضع، لكن لا يمكنهم إدخال سمة من tweakcn من دون تعديل CSS في المستودع. النتيجة المطلوبة أصغر من نظام سمات عام: إبقاء السمات المضمنة الثلاث وإضافة فتحة مستوردة واحدة يتحكم بها المستخدم ويمكن استبدالها من رابط tweakcn.
الأهداف
- إبقاء عائلات السمات المضمنة الحالية من دون تغيير.
- إضافة فتحة مخصصة مستوردة واحدة فقط، وليس مكتبة سمات.
- قبول رابط مشاركة tweakcn أو عنوان URL مباشر بالشكل
https://tweakcn.com/r/themes/{id}. - حفظ السمة المستوردة في التخزين المحلي للمتصفح فقط.
- جعل الفتحة المستوردة تعمل مع عناصر التحكم الحالية لأوضاع
lightوdarkوsystem. - إبقاء سلوك الفشل آمنًا: أي استيراد سيئ لا يكسر أبدًا سمة واجهة المستخدم النشطة.
غير الأهداف
- لا مكتبة متعددة السمات ولا قائمة استيرادات محلية في المتصفح.
- لا حفظ من جهة Gateway ولا مزامنة عبر الأجهزة.
- لا محرر CSS عشوائي ولا محرر JSON خام للسمات.
- لا تحميل تلقائي لأصول الخطوط البعيدة من tweakcn.
- لا محاولة لدعم حمولات tweakcn التي تعرض وضعًا واحدًا فقط.
- لا إعادة هيكلة عامة لنظام السمات في المستودع تتجاوز الوصلات المطلوبة لواجهة التحكم.
قرارات المستخدم المتخذة مسبقًا
- إبقاء السمات المضمنة الثلاث.
- إضافة فتحة استيراد واحدة مدعومة من tweakcn.
- تخزين السمة المستوردة في المتصفح، وليس في إعدادات Gateway.
- دعم
lightوdarkوsystemللفتحة المستوردة. - استبدال الفتحة المخصصة بالاستيراد التالي هو السلوك المقصود.
النهج الموصى به
أضف معرف عائلة سمات رابعًا، custom، إلى نموذج سمات واجهة التحكم. تصبح عائلة custom قابلة للاختيار فقط عند وجود استيراد tweakcn صالح. تُطبّع الحمولة المستوردة إلى سجل سمة مخصصة خاص بـ OpenClaw وتُخزن في التخزين المحلي للمتصفح مع بقية إعدادات واجهة المستخدم.
في وقت التشغيل، يعرض OpenClaw وسم <style> مدارًا يعرّف كتل متغيرات CSS المخصصة المحلولة:
:root[data-theme="custom"] { ... }
:root[data-theme="custom-light"] { ... }
هذا يبقي متغيرات السمة المخصصة محصورة في عائلة custom ويتجنب تسريب متغيرات CSS المضمنة إلى العائلات المضمنة.
البنية
نموذج السمة
حدّث ui/src/ui/theme.ts:
- وسّع
ThemeNameليشملcustom. - وسّع
ResolvedThemeليشملcustomوcustom-light. - وسّع
VALID_THEME_NAMES. - حدّث
resolveTheme()بحيث تعكسcustomسلوك العائلة الحالي:custom + dark->customcustom + light->custom-lightcustom + system->customأوcustom-lightبناءً على تفضيل نظام التشغيل
لا تُضاف أسماء بديلة قديمة لـ custom.
نموذج الحفظ
وسّع حفظ UiSettings في ui/src/ui/storage.ts بحمولة اختيارية واحدة للسمة المخصصة:
customTheme?: ImportedCustomTheme
الشكل المخزن الموصى به:
type ImportedCustomTheme = {
sourceUrl: string;
themeId: string;
label: string;
importedAt: string;
light: Record<string, string>;
dark: Record<string, string>;
};
ملاحظات:
- يخزن
sourceUrlإدخال المستخدم الأصلي بعد التطبيع. themeIdهو معرف سمة tweakcn المستخرج من عنوان URL.labelهو حقلnameفي tweakcn عند وجوده، وإلاCustom.lightوdarkهما خرائط رموز OpenClaw مطبعة مسبقًا، وليستا حمولات tweakcn خام.- تعيش الحمولة المستوردة بجانب الإعدادات المحلية الأخرى في المتصفح وتُسلسل في مستند التخزين المحلي نفسه.
- إذا كانت بيانات السمة المخصصة المخزنة مفقودة أو غير صالحة عند التحميل، فتجاهل الحمولة وارجع إلى
theme: "claw"عندما تكون العائلة المحفوظة هيcustom.
التطبيق وقت التشغيل
أضف مدير أوراق أنماط ضيقًا للسمة المخصصة في وقت تشغيل واجهة التحكم، مملوكًا قرب ui/src/ui/app-settings.ts وui/src/ui/theme.ts.
المسؤوليات:
- إنشاء أو تحديث وسم
<style id="openclaw-custom-theme">ثابت واحد فيdocument.head. - إصدار CSS فقط عند وجود حمولة سمة مخصصة صالحة.
- إزالة محتوى وسم النمط عند مسح الحمولة.
- إبقاء CSS العائلات المضمنة في
ui/src/styles/base.css؛ لا تُدرج الرموز المستوردة في ورقة الأنماط المحفوظة في المستودع.
يعمل هذا المدير كلما حُمّلت الإعدادات أو حُفظت أو استُوردت أو مُسحت.
محددات وضع الضوء
ينبغي أن يفضّل التنفيذ data-theme-mode="light" لتنسيق الضوء عبر العائلات بدلًا من معاملة custom-light كحالة خاصة. إذا كان محدد موجود مثبتًا على data-theme="light" ويحتاج إلى التطبيق على كل عائلة فاتحة، فوسّعه ضمن هذا العمل.
تجربة الاستيراد
حدّث ui/src/ui/views/config.ts في قسم Appearance:
- أضف بطاقة سمة
CustomبجانبClawوKnotوDash. - اعرض البطاقة كمعطلة عندما لا توجد سمة مخصصة مستوردة.
- أضف لوحة استيراد تحت شبكة السمات تحتوي على:
- حقل إدخال نصي واحد لرابط مشاركة tweakcn أو عنوان URL بالشكل
/r/themes/{id} - زر
Importواحد - مسار
Replaceواحد عندما تكون حمولة مخصصة موجودة بالفعل - إجراء
Clearواحد عندما تكون حمولة مخصصة موجودة بالفعل
- حقل إدخال نصي واحد لرابط مشاركة tweakcn أو عنوان URL بالشكل
- اعرض تسمية السمة المستوردة ومضيف المصدر عند وجود حمولة.
- إذا كانت السمة النشطة هي
custom، فإن استيراد بديل يُطبق فورًا. - إذا لم تكن السمة النشطة هي
custom، فإن الاستيراد يخزن الحمولة الجديدة فقط إلى أن يختار المستخدم بطاقةCustom.
ينبغي أيضًا أن يعرض منتقي السمة في الإعدادات السريعة في ui/src/ui/views/config-quick.ts خيار Custom فقط عند وجود حمولة.
تحليل عنوان URL والجلب البعيد
يقبل مسار الاستيراد في المتصفح:
https://tweakcn.com/themes/{id}https://tweakcn.com/r/themes/{id}
ينبغي أن يطبع التنفيذ كلا الشكلين إلى:
https://tweakcn.com/r/themes/{id}
ثم يجلب المتصفح نقطة نهاية /r/themes/{id} المطبعة مباشرة.
استخدم مدقق مخطط ضيقًا للحمولة الخارجية. يُفضّل مخطط zod لأن هذه حدود خارجية غير موثوقة.
الحقول البعيدة المطلوبة:
nameفي المستوى الأعلى كسلسلة اختياريةcssVars.themeككائن اختياريcssVars.lightككائنcssVars.darkككائن
إذا كان cssVars.light أو cssVars.dark مفقودًا، فارفض الاستيراد. هذا مقصود: سلوك المنتج المعتمد هو دعم كامل للأوضاع، وليس تركيبًا تقديريًا للجانب المفقود.
ربط الرموز
لا تعكس متغيرات tweakcn بشكل أعمى. طبّع مجموعة محدودة إلى رموز OpenClaw واشتق الباقي في مساعد.
الرموز المستوردة مباشرة
من كل كتلة وضع في tweakcn:
backgroundforegroundcardcard-foregroundpopoverpopover-foregroundprimaryprimary-foregroundsecondarysecondary-foregroundmutedmuted-foregroundaccentaccent-foregrounddestructivedestructive-foregroundborderinputringradius
من cssVars.theme المشتركة عند وجودها:
font-sansfont-mono
إذا تجاوزت كتلة وضع font-sans أو font-mono أو radius، فالقيمة المحلية للوضع هي التي تفوز.
الرموز المشتقة لـ OpenClaw
يشتق المستورد متغيرات خاصة بـ OpenClaw من ألوان الأساس المستوردة:
--bg-accent--bg-elevated--bg-hover--panel--panel-strong--panel-hover--chrome--chrome-strong--text--text-strong--chat-text--muted--muted-strong--accent-hover--accent-muted--accent-subtle--accent-glow--focus--focus-ring--focus-glow--secondary--secondary-foreground--danger--danger-muted--danger-subtle
تعيش قواعد الاشتقاق في مساعد نقي لكي يمكن اختبارها بشكل مستقل. صيغ مزج الألوان الدقيقة تفصيل تنفيذي، لكن يجب أن يحقق المساعد قيدين:
- الحفاظ على تباين مقروء قريب من نية السمة المستوردة
- إنتاج خرج ثابت للحمولة المستوردة نفسها
الرموز المتجاهلة في v1
تُتجاهل رموز tweakcn هذه عمدًا في الإصدار الأول:
chart-*sidebar-*font-serifshadow-*tracking-*letter-spacingspacing
هذا يبقي النطاق على الرموز التي تحتاجها واجهة التحكم الحالية فعليًا.
الخطوط
تُستورد سلاسل مكدس الخطوط إذا كانت موجودة، لكن OpenClaw لا يحمّل أصول الخطوط البعيدة في v1. إذا أشار المكدس المستورد إلى خطوط غير متاحة في المتصفح، فسيُطبق سلوك الرجوع العادي.
سلوك الفشل
يجب أن تفشل الاستيرادات السيئة بشكل مغلق.
- تنسيق عنوان URL غير صالح: اعرض خطأ تحقق مضمنًا، ولا تجلب.
- مضيف أو شكل مسار غير مدعوم: اعرض خطأ تحقق مضمنًا، ولا تجلب.
- فشل الشبكة، أو استجابة غير OK، أو JSON مشوه: اعرض خطأ مضمنًا، وأبقِ الحمولة المخزنة الحالية من دون تغيير.
- فشل المخطط أو غياب كتل light/dark: اعرض خطأ مضمنًا، وأبقِ الحمولة المخزنة الحالية من دون تغيير.
- إجراء المسح:
- يزيل الحمولة المخصصة المخزنة
- يزيل محتوى وسم النمط المخصص المدار
- إذا كانت
customنشطة، يبدّل عائلة السمة عائدًا إلىclaw
- حمولة مخصصة مخزنة غير صالحة عند التحميل الأول:
- تجاهل الحمولة المخزنة
- لا تصدر CSS مخصصة
- إذا كانت عائلة السمة المحفوظة هي
custom، فارجع إلىclaw
ينبغي ألا يترك أي استيراد فاشل في أي لحظة المستند النشط مع متغيرات CSS مخصصة جزئية مطبقة.
الملفات المتوقع تغييرها في التنفيذ
الملفات الأساسية:
ui/src/ui/theme.tsui/src/ui/storage.tsui/src/ui/app-settings.tsui/src/ui/views/config.tsui/src/ui/views/config-quick.tsui/src/styles/base.css
مساعدون جدد محتملون:
ui/src/ui/custom-theme.ts
الاختبارات:
ui/src/ui/app-settings.test.tsui/src/ui/storage.node.test.tsui/src/ui/views/config.browser.test.ts- اختبارات مركزة جديدة لتحليل عنوان URL وتطبيع الحمولة
الاختبار
الحد الأدنى من تغطية التنفيذ:
- تحليل عنوان URL لرابط مشاركة إلى معرف سمة tweakcn
- تطبيع
/themes/{id}و/r/themes/{id}إلى عنوان URL الجلب - رفض المضيفين غير المدعومين والمعرفات المشوهة
- التحقق من شكل حمولة tweakcn
- ربط حمولة tweakcn صالحة إلى خرائط رموز OpenClaw مطبعة للوضعين الفاتح والداكن
- تحميل الحمولة المخصصة وحفظها في الإعدادات المحلية للمتصفح
- حل
customلـlightوdarkوsystem - تعطيل اختيار
Customعندما لا توجد حمولة - تطبيق السمة المستوردة فورًا عندما تكون
customنشطة بالفعل - الرجوع إلى
clawعندما تُمسح السمة المخصصة النشطة
هدف التحقق اليدوي:
- استيراد سمة tweakcn معروفة من الإعدادات
- التبديل بين
lightوdarkوsystem - التبديل بين
customوالعائلات المضمنة - إعادة تحميل الصفحة وتأكيد استمرار السمة المخصصة المستوردة محليًا
ملاحظات الطرح
هذه الميزة صغيرة عمدًا. إذا طلب المستخدمون لاحقًا سمات مستوردة متعددة، أو إعادة تسمية، أو تصديرًا، أو مزامنة عبر الأجهزة، فتعامل مع ذلك كتصميم لاحق. لا تبنِ مسبقًا تجريد مكتبة سمات في هذا التنفيذ.