تخيل أنك تعمل على تطبيق داخلي لفريقك: لوحة تحكم، أداة إدارة ملفات، أو عميل بسيط يتصل بـ REST API (واجهة برمجة تطبيقات تعتمد على طلبات HTTP). التطبيق مطلوب على ويندوز، وبعض الفريق يستخدم macOS، وفريق البنية التحتية يعمل على لينكس. هنا يظهر السؤال المزعج: هل تبني ثلاث نسخ Native (أصلية لكل نظام)، أم تراهن على إطار واحد؟ مع Flutter Desktop 2026 أصبح هذا السؤال أكثر جدية بعد إعلان جوجل أن Canonical ستقود صيانة وخارطة طريق Flutter Desktop لمنصات Windows وmacOS وLinux.1
الخبر ليس مجرد تغيير إداري داخل مشروع مفتوح المصدر. بالنسبة لك كمطور، هذا يعني أن الجزء المكتبي من Flutter لم يعد إضافة جانبية تُستخدم عند الحاجة، بل أصبح له راعٍ تقني يستخدمه في منتجات حقيقية، ويملك مصلحة مباشرة في تحسينه. Canonical استخدمت Flutter منذ 2021 كخيار افتراضي لتطوير تطبيقات Ubuntu Desktop، ومن أمثلتها App Center وFirmware Updater وSecurity Center.1
ما هو Flutter Desktop؟
Flutter Desktop هو قدرة Flutter على بناء تطبيقات سطح مكتب Native-compiled (مترجمة إلى تطبيق أصلي) تعمل على Windows وmacOS وLinux من قاعدة كود واحدة. بدلاً من تشغيل تطبيقك داخل Browser Engine (محرك متصفح) كامل، كما يحدث في كثير من تطبيقات Electron، يترجم Flutter التطبيق ليعمل كتطبيق سطح مكتب فعلي مع وصول إلى إمكانات النظام الأساسية.2
تصف وثائق Flutter الرسمية دعم سطح المكتب بأنه دعم لتجميع تطبيقات Windows وmacOS وLinux أصلية، كما يمتد الدعم إلى Plugins (حزم تربط كود Dart بقدرات النظام).3
Flutter provides support for compiling a native Windows, macOS, or Linux desktop app. Flutter’s desktop support also extends to plugins. — Flutter Docs3
الفكرة العملية هنا أنك تستطيع مشاركة جزء كبير من UI (واجهة المستخدم)، Business Logic (منطق العمل)، وNetworking (الاتصال بالشبكة) بين الموبايل والويب وسطح المكتب. لكن هذا لا يعني أن تجربة سطح المكتب ستصبح ممتازة تلقائياً. ما زلت تحتاج إلى التفكير في حجم الشاشة، اختصارات لوحة المفاتيح، القوائم، النوافذ، الملفات، وتجربة المستخدم التي يتوقعها مستخدم سطح المكتب.
| العنصر | ماذا يعني لك كمطور؟ |
|---|---|
| قاعدة كود مشتركة | تكتب معظم المنطق مرة واحدة وتستهدف أكثر من منصة. |
| أداء Native-compiled | تحصل على أداء أقرب لتطبيقات سطح المكتب التقليدية دون تضمين محرك متصفح ضخم.2 |
| Plugins | يمكنك الوصول إلى ملفات النظام، التخزين المحلي، روابط النظام، وبعض APIs الأصلية عبر حزم جاهزة.3 |
| قابلية التوزيع | تستطيع بناء نسخ Release لكل منصة، ثم نشرها بالأسلوب المناسب لكل نظام.3 |
لماذا تهتم بـ Flutter Desktop 2026؟
أهمية Flutter Desktop 2026 تأتي من ثلاثة تغييرات متداخلة. الأول أن Canonical أصبحت مسؤولة عن الصيانة وخارطة الطريق لسطح المكتب بصفتها Strategic Steward (وصياً استراتيجياً) لهذا الجزء من Flutter.1 الثاني أن Flutter نفسه يتحرك نحو Core (نواة) أخف، مع نقل Material وCupertino إلى حزم مستقلة، ما يساعد على فصل تحديثات واجهة المستخدم عن تحديثات الإطار الأساسية.1 الثالث أن دعم النوافذ المتعددة بدأ ينتقل من مطلب مزعج إلى مسار فعلي في تطوير Flutter Desktop.1
بالنسبة لك، هذا يعني أن تطبيقات سطح المكتب بفلاتر قد تصبح أكثر قابلية للاعتماد في مشاريع الأدوات الداخلية، لوحات التحكم، تطبيقات الإنتاجية، وبرامج الشركات الصغيرة التي تحتاج إلى دعم أكثر من نظام تشغيل دون تضخيم الفريق أو الميزانية.
| التغيير في Flutter Desktop 2026 | الأثر العملي على مشروعك |
|---|---|
| Canonical تقود صيانة سطح المكتب | احتمالية أعلى لتحسينات واقعية مبنية على استخدام يومي في تطبيقات سطح مكتب فعلية. |
| دعم Multi-window (النوافذ المتعددة) | بناء تطبيقات أقرب لتوقعات مستخدمي سطح المكتب، مثل Dialogs وTooltips ونوافذ ثانوية.1 |
| فصل Material وCupertino | تحكم أفضل في توقيت تبني تغييرات التصميم، وتقليل المفاجآت أثناء تحديث Flutter.1 |
| نقل بعض الكلاسات إلى Dart Packages | إعادة استخدام مكونات أساسية في مشاريع Dart دون سحب Flutter Framework كاملاً.1 |
لكن يجب أن تكون واقعياً. Flutter Desktop ليس حلاً سحرياً لكل شيء. إذا كنت تبني أداة تتطلب تكاملاً عميقاً جداً مع النظام، أو تعتمد على Drivers، أو تحتاج إلى واجهة مطابقة 100% لتفاصيل كل نظام تشغيل، فقد تحتاج إلى Native Development (تطوير أصلي) أو إلى طبقة Native إضافية بجانب Flutter.
كيف تبدأ مع Flutter Desktop 2026؟
ابدأ بالطريقة العملية: تأكد أن جهازك يرى منصة سطح المكتب التي تريدها، ثم أنشئ مشروعاً بسيطاً، ثم أضف دعماً للمنصات المكتبية إذا كان لديك مشروع Flutter قائم. وثائق Flutter توضح أن إنشاء مشروع يدعم سطح المكتب لا يختلف كثيراً عن إنشاء أي مشروع Flutter آخر بعد تجهيز بيئة التطوير المناسبة.3
flutter doctor
flutter create desktop_notes
cd desktop_notes
flutter run -d linux
# أو على ويندوز:
flutter run -d windows
# أو على macOS:
flutter run -d macos
هذا الكود يبدأ بفحص البيئة عبر flutter doctor للتأكد من أن أدوات البناء المطلوبة موجودة. بعد ذلك تنشئ مشروعاً جديداً باسم desktop_notes وتدخل إلى مجلده. أمر flutter run -d يحدد الجهاز أو المنصة المستهدفة، وهذا مفيد عندما يكون لديك أكثر من هدف مثل Chrome أو Android أو Linux. إذا لم تضع -d سيعرض Flutter غالباً قائمة بالأهداف المتاحة لتختار منها.3
إذا كان لديك تطبيق Flutter قائم وتريد إضافة دعم سطح المكتب له، يمكنك تنفيذ الأمر التالي من جذر المشروع:
flutter create --platforms=windows,macos,linux .
هذا الأمر لا ينشئ مشروعاً جديداً من الصفر، بل يضيف ملفات Runner (مشغل التطبيق الأصلي) ومجلدات المنصات المكتبية إلى مشروعك الحالي. استخدمه عندما يكون لديك تطبيق موبايل أو ويب وتريد اختباره كسطح مكتب. يمكنك أيضاً تقليل القائمة إلى منصة واحدة مثل windows فقط إذا كان مشروعك لا يحتاج إلى دعم باقي الأنظمة منذ البداية.3
ولبناء نسخة Release قابلة للاختبار أو التوزيع الداخلي، استخدم الأمر المناسب لمنصتك:
flutter build linux
flutter build windows
flutter build macos
هذه الأوامر تنتج نسخة Release بدلاً من نسخة Debug. لا تتعامل مع هذه النسخة كمنتج نهائي مباشرة؛ اختبرها على جهاز حقيقي، راقب حجم الملفات، وتأكد من عمل packages والملفات المحلية والاتصال بالشبكة. إذا كنت تستهدف ويندوز، فوثائق Flutter تذكر أن النشر عبر Microsoft Store ممكن، لكنه ليس إجبارياً، ويمكنك اختيار طرق توزيع أخرى إذا أردت تحكماً أكبر.5
مثال تطبيقي كامل
لنجعل الخبر عملياً. سنبني مثالاً صغيراً لتطبيق ملاحظات مكتبي يستفيد من المساحة الأوسع على سطح المكتب. الفكرة بسيطة: إذا كان التطبيق يعمل على شاشة عريضة، نعرض قائمة جانبية باستخدام NavigationRail، وإذا ضاقت الشاشة نستخدم واجهة أبسط. هذا ليس مجرد شكل جمالي؛ تطبيقات سطح المكتب تحتاج غالباً إلى Layout (تخطيط واجهة) يستغل العرض الأفقي ولا يتصرف مثل شاشة هاتف مكبرة.
ضع الكود التالي داخل ملف lib/main.dart في مشروع Flutter جديد:
import 'package:flutter/material.dart';
void main() {
runApp(const DesktopNotesApp());
}
class DesktopNotesApp extends StatelessWidget {
const DesktopNotesApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Desktop Notes',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
useMaterial3: true,
),
home: const NotesHomePage(),
);
}
}
class NotesHomePage extends StatefulWidget {
const NotesHomePage({super.key});
@override
State<NotesHomePage> createState() => _NotesHomePageState();
}
class _NotesHomePageState extends State<NotesHomePage> {
int selectedIndex = 0;
final notes = const [
'راجع خطة نشر نسخة سطح المكتب',
'اختبر التطبيق على Windows وLinux',
'أضف اختصارات لوحة المفاتيح لاحقاً',
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: LayoutBuilder(
builder: (context, constraints) {
final isWide = constraints.maxWidth >= 800;
if (isWide) {
return Row(
children: [
NavigationRail(
selectedIndex: selectedIndex,
onDestinationSelected: (index) {
setState(() => selectedIndex = index);
},
labelType: NavigationRailLabelType.all,
destinations: const [
NavigationRailDestination(
icon: Icon(Icons.note_outlined),
selectedIcon: Icon(Icons.note),
label: Text('الملاحظات'),
),
NavigationRailDestination(
icon: Icon(Icons.settings_outlined),
selectedIcon: Icon(Icons.settings),
label: Text('الإعدادات'),
),
],
),
const VerticalDivider(width: 1),
Expanded(child: _ContentArea(index: selectedIndex, notes: notes)),
],
);
}
return _ContentArea(index: selectedIndex, notes: notes);
},
),
);
}
}
class _ContentArea extends StatelessWidget {
const _ContentArea({required this.index, required this.notes});
final int index;
final List<String> notes;
@override
Widget build(BuildContext context) {
if (index == 1) {
return const Center(
child: Text('إعدادات التطبيق ستظهر هنا'),
);
}
return ListView.separated(
padding: const EdgeInsets.all(24),
itemCount: notes.length,
separatorBuilder: (_, __) => const SizedBox(height: 12),
itemBuilder: (context, noteIndex) {
return Card(
child: ListTile(
leading: const Icon(Icons.desktop_windows),
title: Text(notes[noteIndex]),
subtitle: const Text('مثال عملي لتخطيط مناسب لتطبيق سطح مكتب'),
),
);
},
);
}
}
هذا المثال يستخدم LayoutBuilder لمعرفة عرض النافذة أثناء التشغيل، ثم يقرر هل يعرض NavigationRail أم يكتفي بالمحتوى. هذه نقطة مهمة في تطبيقات Flutter Desktop 2026، لأن المستخدم قد يغير حجم النافذة باستمرار. الكود أيضاً يوضح كيف تفكر في سطح المكتب كتجربة مختلفة عن الهاتف: مساحة أوسع، تنقل جانبي، ومحتوى قابل للقراءة دون ازدحام. يمكنك تشغيله مباشرة بالأوامر السابقة ثم تغيير حجم النافذة لترى الفرق.
إذا أردت خطوة أكثر قرباً من تطبيقات الشركات، أضف اتصالاً بسيطاً بـ API. في المثال التالي نستخدم FutureBuilder لعرض بيانات تأتي من خدمة خارجية، ويمكنك لاحقاً استبدال الرابط بـ API الخاص بمشروعك:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class RemoteStatusCard extends StatelessWidget {
const RemoteStatusCard({super.key});
Future<String> fetchStatus() async {
final response = await http.get(
Uri.parse('https://jsonplaceholder.typicode.com/todos/1'),
);
if (response.statusCode != 200) {
throw Exception('فشل الاتصال بالخادم');
}
final data = jsonDecode(response.body) as Map<String, dynamic>;
return data['title'] as String;
}
@override
Widget build(BuildContext context) {
return FutureBuilder<String>(
future: fetchStatus(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
}
if (snapshot.hasError) {
return Text('حدث خطأ: ${snapshot.error}');
}
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Text('حالة المهمة: ${snapshot.data}'),
),
);
},
);
}
}
قبل استخدام هذا الكود أضف حزمة http إلى مشروعك عبر flutter pub add http. الكلاس RemoteStatusCard يجلب بيانات JSON من API تجريبي ثم يعرضها داخل بطاقة. هذا النمط مناسب جداً لتطبيقات سطح المكتب الداخلية التي تتصل بلوحات تحكم أو أنظمة إدارة أو Backend قائم. المهم ألا تضع مفاتيح API الحساسة داخل تطبيق سطح المكتب مباشرة، لأن المستخدم يستطيع غالباً استخراجها من ملفات التطبيق.
ما الذي تغير فعلاً في Flutter Desktop 2026؟
أهم تغيير ليس أن Flutter أصبح يدعم سطح المكتب فجأة؛ الدعم موجود منذ سنوات. الجديد هو أن المسؤولية أصبحت أوضح. عندما تقود Canonical صيانة Flutter Desktop، فأنت أمام طرف يبني تطبيقات سطح مكتب فعلية ويحتاج إلى تحسين التجربة يومياً، لا مجرد دعم نظري لمنصة إضافية.1
ومن الجانب الفني، دعم النوافذ المتعددة يغيّر طبيعة التطبيقات الممكنة. تطبيق سطح المكتب ليس شاشة واحدة فقط. لديك Tooltips (تلميحات)، Dialogs (نوافذ حوار)، Menus (قوائم)، وربما نوافذ عمل مستقلة. Canonical أوضحت في مقال سابق أن حصر تطبيقات Flutter Desktop في نافذة واحدة كان قيداً واضحاً، وأن النوافذ المتعددة تجعل القوائم والتلميحات أكثر اندماجاً مع توقعات سطح المكتب.4
| قبل التحسينات | بعد نضج مسار Flutter Desktop |
|---|---|
| تطبيق يبدو أحياناً كهاتف مكبر على شاشة كبيرة | تطبيق يستغل المساحة الأفقية والقوائم والنوافذ بشكل أفضل. |
| خوف أكبر من تغييرات UI الكاسرة داخل SDK | فصل مكتبات التصميم يمنحك تحكماً أفضل في التحديثات.1 |
| اعتماد قوي على جوجل وحدها في الأولويات | حوكمة أوسع وشريك متخصص يقود سطح المكتب.1 |
| صعوبة في بناء تجارب Multi-window طبيعية | مسار أوضح لدعم Tooltips وDialogs ونوافذ إضافية.1 |
هذا لا يلغي مسؤوليتك في اختبار التطبيق على كل نظام. تطبيق يعمل جيداً على لينكس قد يحتاج تعديلات للويندوز، خصوصاً في التوزيع، الأيقونات، حجم النافذة، الملفات، والتكامل مع النظام. وثائق Flutter الخاصة بويندوز تذكر مثلاً إمكان استخدام dart:ffi للتعامل مع Win32 APIs، كما تشير إلى حزم مثل win32 وfluent_ui وbitsdojo_window لتجارب أكثر قرباً من بيئة ويندوز.6
نصائح ومزالق يجب تجنبها
لا تبدأ مشروع Flutter Desktop باعتبار سطح المكتب مجرد Target (هدف بناء) إضافي. إذا نقلت واجهة موبايل كما هي إلى شاشة 27 بوصة، سيشعر المستخدم أن التطبيق غريب حتى لو كان سريعاً. ابدأ من Layout متجاوب، واستخدم عناصر مثل NavigationRail أو Sidebars (أشرطة جانبية)، وفكر في كثافة المعلومات التي يراها المستخدم على الشاشة.
لا تؤجل اختبار المنصات إلى نهاية المشروع. من الأفضل أن تشغّل التطبيق أسبوعياً على Windows وLinux وmacOS إن كانت ضمن خطتك. بعض Plugins لا تدعم كل المنصات بالتساوي، وبعض التفاصيل الصغيرة مثل مسارات الملفات أو أذونات النظام قد تظهر متأخرة وتكلفك وقتاً كبيراً.
لا تبالغ في الاعتماد على Packages غير ناضجة. قبل اختيار أي Plugin لتطبيق سطح مكتب، افتح صفحة الحزمة وتأكد من دعم Windows وmacOS وLinux، وعدد الإصدارات، وآخر تحديث، والمشكلات المفتوحة. سطح المكتب أكثر حساسية في هذه النقطة لأنك قد تحتاج إلى سلوك أصلي عميق.
لا تضع Secrets (مفاتيح سرية) داخل تطبيقك. في تطبيقات سطح المكتب، اعتبر كل شيء داخل التطبيق قابلاً للفحص. إذا كان تطبيقك يحتاج إلى مفتاح حساس، ضعه في Backend آمن واجعل التطبيق يتواصل مع الخادم وفق صلاحيات محددة.
ولا تنس تجربة التوزيع منذ البداية. بناء التطبيق محلياً شيء، وتحويله إلى حزمة قابلة للتثبيت شيء آخر. على ويندوز لديك خيارات مثل Microsoft Store أو MSIX أو مثبت مخصص، وعلى لينكس قد تفكر في Snap أو AppImage أو حزم النظام، وعلى macOS ستتعامل مع التوقيع وNotarization (توثيق التطبيق لدى آبل). هذه التفاصيل ليست ممتعة دائماً، لكنها جزء من نجاح تطبيق سطح المكتب.
الخلاصة والرأي
Flutter Desktop أصبح خياراً يستحق التجربة الجادة إذا كنت تبني تطبيقاً متعدد المنصات بواجهة غنية، خصوصاً إذا كان فريقك يعرف Flutter أو Dart بالفعل. شراكة جوجل وكانونيكال تعطي ثقة أكبر في مستقبل سطح المكتب، لأن الصيانة لم تعد هامشية، بل أصبحت بيد جهة تستخدم Flutter في تطبيقات إنتاجية حقيقية.1
استخدم Flutter Desktop عندما تريد بناء لوحة تحكم داخلية، أداة إنتاجية، تطبيق إدارة بيانات، أو نسخة سطح مكتب من منتج موجود على الموبايل. تجنبه أو اختبره بحذر إذا كان مشروعك يحتاج تكاملاً عميقاً جداً مع النظام، أو واجهة Native مطابقة لكل منصة، أو Plugins غير متوفرة بعد.
ابدأ الآن بمشروع صغير: شغّل الكود أعلاه على جهازك، جرّب تغيير حجم النافذة، ثم أضف شاشة تتصل بـ REST API في مشروعك.




