أي تكنولوجيا متقدمة بما يكفي لا يمكن تمييزها عن السحر. ما لم تكن تفهمها. اسمي "توماس شتاينر"، وأعمل في قسم "علاقات المطوّرين" في Google. في هذه المقالة التي تتناول محادثتي في مؤتمر Google I/O، سأتناول بعض واجهات برمجة التطبيقات الجديدة في Fugu وكيفية تحسينها لتجارب المستخدمين الأساسية في تطبيق Excalidraw المتوافق مع الويب. ويمكنك الاستفادة من هذه الأفكار وتطبيقها على تطبيقاتك.
كيف بدأت باستخدام Excalidraw
أريد البدء بقصة. في 1 كانون الثاني (يناير) 2020، قال كريستوفر تشيداو، مهندس برامج في Facebook، في تغريدة على تويتر إنّه بدأ العمل على تطبيق رسم صغير. باستخدام هذه الأداة، يمكنك رسم مربّعات وسهام تبدو وكأنها من رسوم متحركة و مرسومة يدويًا. في اليوم التالي، يمكنك أيضًا رسم أشكال بيضاوية ونصوص، بالإضافة إلى اختيار العناصر ونقلها. في 3 كانون الثاني (يناير)، حصل التطبيق على اسمه، Excalidraw، وكما هو الحال مع كل مشروع جيد بجانب عمله الرئيسي، كان شراء اسم النطاق من أوّل الإجراءات التي اتّخذها "كريستوفر". أصبح بإمكانك الآن استخدام الألوان وتصدير الرسم بالكامل بتنسيق PNG.
في 15 كانون الثاني (يناير)، نشر "كريستوفر" مشاركة مدوّنة جذبت الكثير من الاهتمام على Twitter، بما في ذلك اهتمامي. بدأت المشاركة ببعض الإحصاءات المميّزة:
- 12 ألف مستخدم نشط فريد
- 1.5 ألف نجم على GitHub
- 26 مساهمًا
بالنسبة إلى مشروع بدأ منذ أسبوعَين فقط، هذا ليس سيئًا على الإطلاق. ولكن ما لفت انتباهي حقًا هو ما ورد في الأسفل من المشاركة. كتب "كريستوفر" أنّه جرّب شيئًا جديدًا هذه المرة: منح كل من أرسل طلبًا ناجحةً إذن الوصول إلى الإصدارات غير المشروطة. في اليوم نفسه الذي قرأت فيه مشاركة المدونة، أرسلت طلب سحب أدى إلى إضافة واجهة برمجة التطبيقات File System Access API إلى Excalidraw، ما أدى إلى حلّ طلب ميزة قدّمه أحد المستخدمين.
تم دمج طلب سحب التغييرات بعد يوم واحد، ومنذ ذلك الحين، أصبح لديّ إذن وصول كامل للالتزام. لا داعي للقول إنّه لم أُسيء استخدام سلطتي. ولم يفعل أيّ من المساهمين الـ 149 ذلك حتى الآن.
أصبح Excalidraw اليوم تطبيق ويب تقدّميًا قابلاً للتثبيت بالكامل ومزوّدًا بإمكانية الاستخدام بلا إنترنت ووضع داكن رائع، بالإضافة إلى إمكانية فتح الملفات وحفظها بفضل File System Access API.
يشرح "ليبيس" سبب تخصيصه الكثير من وقته لاستخدام Excalidraw
نختم قصة "كيفية استخدامي Excalidraw"، ولكن قبل الاطّلاع على بعض ميزات Excalidraw الرائعة، يسرّنا أن نقدّم لك Panayiotis. "بانايوتيس ليبيريديس"، المعروف على الإنترنت باسم lipis، هو أكبر مساهم في Excalidraw. سألتُ "ليبيس" عن الدافع الذي يدفعه إلى تخصيص الكثير من وقته لخدمة Excalidraw:
مثل الجميع، تعرّفت على هذا المشروع من خلال تغريدة "كريستوفر". كانت مساهمتي الأولى هي إضافة مكتبة الألوان المفتوحة، وهي الألوان التي لا تزال جزءًا من Excalidraw حتى اليوم. مع تطوّر المشروع وتلقّي العديد من الطلبات، كانت مساهمتي التالية مهمة جدًا، وهي إنشاء نظام أساسي لتخزين الرسومات حتى يتمكّن المستخدمون من مشاركتها. ما يدفعني حقًا إلى المساهمة هو أنّ أي مستخدم جرّب Excalidraw سيبحث عن أعذار لاستخدامه مجددًا.
أوافق تمامًا على ما قاله "ليبيس". إنّ أي مستخدم جرّب Excalidraw سيبحث عن أعذار لاستخدامه مرة أخرى.
استخدام Excalidraw
أريد أن أعرض لك الآن كيفية استخدام Excalidraw في الممارسة العملية. لست فنّانًا بارعًا، ولكن ملف تعريف علامة Google I/O التجارية بسيط بما يكفي، لذا سأحاول إنشاء صورة له. المربّع هو الحرف "i"، ويمكن أن يكون الخط هو العلامة المائلة، والحرف "o" هو دائرة. أضغط مع الاستمرار على مفتاح Shift للحصول على دائرة مثالية. سأحرّك العلامة المائلّة قليلاً لكي تبدو أفضل. الآن سنضيف بعض الألوان إلى الحرفَين "i" و "o". الأزرق مناسب. هل يمكن أن يكون هناك نمط تعبئة مختلف؟ هل هي كلها صلبة أم مموّهة؟ لا، يبدو أنّ خطوط الحَشْوة رائعة. ليست مثالية، ولكن هذه هي فكرة Excalidraw، لذا اسمح لي بحفظها.
انقر على رمز الحفظ وأدخِل اسم ملف في مربّع الحوار الخاص بحفظ الملف. في Chrome، وهو متصفّح يتكامل مع واجهة برمجة التطبيقات File System Access API، لا يتم تنزيل الملفات، بل يتم حفظها، ويمكنني تحديد مكان الملف واسمه، وفي حال إجراء تعديلات، يمكنني حفظها في الملف نفسه.
سأغيّر الشعار وأجعل الحرف "i" باللون الأحمر. إذا نقرت الآن على "حفظ" مرة أخرى، سيتم حفظ التعديل في الملف نفسه كما في السابق. كدليل على ذلك، يُرجى محو اللوحة وإعادة فتح الملف. كما ترى، ظهر الشعار المُعدَّل باللونَين الأحمر والأزرق مرة أخرى.
العمل مع الملفات
في المتصفحات التي لا تتوافق حاليًا مع واجهة برمجة التطبيقات File System Access API، تكون كل عملية حفظ عملية تنزيل، لذلك عندما أجري تغييرات، أحصل على ملفات متعددة برقم متزايد في اسم الملف تملأ مجلد "عمليات التنزيل". ولكن على الرغم من هذا الجانب السلبي، لا يزال بإمكاني حفظ الملف.
فتح الملفات
ما هو السر؟ كيف يمكن أن يعمل كلّ من الفتح والحفظ على متصفّحات مختلفة قد توفّر أو لا توفّر
واجهة برمجة التطبيقات File System Access API؟ يتم فتح ملف في Excalidraw من خلال دالة تُسمى
loadFromJSON)(
)، والتي تستدعي بدورها دالة تُسمى fileOpen()
.
export const loadFromJSON = async (localAppState: AppState) => {
const blob = await fileOpen({
description: 'Excalidraw files',
extensions: ['.json', '.excalidraw', '.png', '.svg'],
mimeTypes: ['application/json', 'image/png', 'image/svg+xml'],
});
return loadFromBlob(blob, localAppState);
};
دالة fileOpen()
التي تأتي من مكتبة صغيرة كتبتها باسم
browser-fs-access التي نستخدمها في
Excalidraw. توفّر هذه المكتبة إمكانية الوصول إلى نظام الملفات من خلال واجهة برمجة التطبيقات
File System Access API مع بديل قديم، لذا يمكن استخدامها في أي
متصفّح.
سأعرض لك أولاً عملية التنفيذ عندما تكون واجهة برمجة التطبيقات متاحة. بعد التفاوض على
أنواع MIME وامتدادات الملفات المقبولة، يتم استدعاء showOpenFilePicker()
، وهي دالّة واجهة برمجة التطبيقات File System Access API. تعرض هذه الدالة صفيفًا من الملفات أو ملفًا واحدًا، استنادًا
إلى ما إذا تم اختيار ملفات متعددة. كل ما عليك فعله بعد ذلك هو وضع معرّف الملف على ملف
العنصر، حتى يمكن استرجاعه مرة أخرى.
export default async (options = {}) => {
const accept = {};
// Not shown: deal with extensions and MIME types.
const handleOrHandles = await window.showOpenFilePicker({
types: [
{
description: options.description || '',
accept: accept,
},
],
multiple: options.multiple || false,
});
const files = await Promise.all(handleOrHandles.map(getFileWithHandle));
if (options.multiple) return files;
return files[0];
const getFileWithHandle = async (handle) => {
const file = await handle.getFile();
file.handle = handle;
return file;
};
};
تعتمد عملية تنفيذ العنصر الاحتياطي على عنصر input
من النوع "file"
. بعد التفاوض بشأن
أنواع MIME والإضافات التي سيتم قبولها، تكون الخطوة التالية هي النقر آليًا على عنصر
الإدخال لعرض مربّع الحوار لفتح الملف. عند التغيير، أي عندما يختار المستخدم ملفًا واحدًا أو
ملفًا متعدّدًا، يتم حلّ الوعد.
export default async (options = {}) => {
return new Promise((resolve) => {
const input = document.createElement('input');
input.type = 'file';
const accept = [
...(options.mimeTypes ? options.mimeTypes : []),
options.extensions ? options.extensions : [],
].join();
input.multiple = options.multiple || false;
input.accept = accept || '*/*';
input.addEventListener('change', () => {
resolve(input.multiple ? Array.from(input.files) : input.files[0]);
});
input.click();
});
};
حفظ الملفات
ننتقل الآن إلى الحفظ. في Excalidraw، يتم الحفظ في دالة تُسمى saveAsJSON()
. أولاً، تتم سلسليَة مصفوفة عناصر Excalidraw إلى تنسيق JSON، ثم يتم تحويل تنسيق JSON إلى ملف نصي، ثم يتم استدعاء دالة تدعى fileSave()
. توفّر مكتبة
browser-fs-access هذه الدالة أيضًا.
export const saveAsJSON = async (
elements: readonly ExcalidrawElement[],
appState: AppState,
) => {
const serialized = serializeAsJSON(elements, appState);
const blob = new Blob([serialized], {
type: 'application/vnd.excalidraw+json',
});
const fileHandle = await fileSave(
blob,
{
fileName: appState.name,
description: 'Excalidraw file',
extensions: ['.excalidraw'],
},
appState.fileHandle,
);
return { fileHandle };
};
مرة أخرى، دعنا ننظر أولاً إلى عملية التنفيذ للمتصفّحات المتوافقة مع واجهة برمجة التطبيقات File System Access API. يبدو أنّه هناك بعض التعقيد في السطرَين الأولَين، ولكنّهما لا يفعلان سوى التفاوض على أنواع MIME وملف الإضافات. عندما أكون قد حفظت الملف من قبل وكان لديّ معرّف ملف، ليس من الضروري عرض مربّع حوار حفظ. ولكن إذا كان هذا هو الحفظ الأول، يتم عرض مربّع حوار الملفات ويحصل التطبيق على معرّف ملف مجددًا لاستخدامه في المستقبل. بعد ذلك، تتم كتابة الباقي في الملف، وذلك من خلال بث قابل للكتابة.
export default async (blob, options = {}, handle = null) => {
options.fileName = options.fileName || 'Untitled';
const accept = {};
// Not shown: deal with extensions and MIME types.
handle =
handle ||
(await window.showSaveFilePicker({
suggestedName: options.fileName,
types: [
{
description: options.description || '',
accept: accept,
},
],
}));
const writable = await handle.createWritable();
await writable.write(blob);
await writable.close();
return handle;
};
ميزة "الحفظ باسم"
إذا قررت تجاهل اسم معرِّف ملف حالي، يمكنني تنفيذ ميزة "حفظ باسم" لإنشاء ملف جديد استنادًا إلى ملف حالي. لتوضيح ذلك، سأفتح ملفًا حاليًا وأُجري بعض تعديلات عليه، ثم لن أُلغي الملف الحالي، بل سأنشئ ملفًا جديدًا باستخدام ميزة "الحفظ باسم". ويبقى الملف الأصلي بدون أي تغيير.
إنّ عملية التنفيذ للمتصفّحات التي لا تتوافق مع واجهة برمجة التطبيقات File System Access API قصيرة، لأنّ كل ما يتمه
هو إنشاء عنصر رابط يتضمّن سمة download
تكون قيمتها اسم الملف المطلوب
وعنوان URL للملف المصغّر كقيمة لسمة href
.
export default async (blob, options = {}) => {
const a = document.createElement('a');
a.download = options.fileName || 'Untitled';
a.href = URL.createObjectURL(blob);
a.addEventListener('click', () => {
setTimeout(() => URL.revokeObjectURL(a.href), 30 * 1000);
});
a.click();
};
بعد ذلك، يتم النقر على عنصر الربط آليًا. لمنع تسرب الذاكرة، يجب
إبطال عنوان URL للملفّ المصغّر بعد استخدامه. بما أنّ هذا الإجراء هو مجرد عملية تنزيل، لن يتم عرض مربّع حوار لحفظ الملفات مطلقًا، وسيتم حفظ كل
الملفات في المجلد التلقائي Downloads
.
السحب والإفلات
من عمليات دمج النظام المفضّلة لدي على الكمبيوتر المكتبي هي السحب والإفلات. في Excalidraw، عند إسقاط ملف
.excalidraw
على التطبيق، يتم فتحه على الفور ويمكنني بدء التعديل. في المتصفّحات
التي تتيح استخدام واجهة برمجة التطبيقات File System Access API، يمكنني أيضًا حفظ التغييرات على الفور. لا حاجة إلى الانتقال إلى مربع حوار حفظ الملف لأنّه تم الحصول على معرّف الملف المطلوب من عملية السحب والإفلات.
يكمن سرّ تحقيق ذلك في استدعاء getAsFileSystemHandle()
في عنصر
نقل البيانات عندما تكون واجهة برمجة التطبيقات File System Access API متوافقة. بعد ذلك، أُرسل اسم FILE المشار إليه إلى loadFromBlob()
، وهو الاسم الذي قد تتذكره من فقرتَين أعلاه. يمكنك تنفيذ العديد من
الإجراءات مع الملفات، مثل فتحها وحفظها وحفظها مرارًا وتكرارًا وسحبها وإفلاتها. لقد سجّلتُ أنا وزميلي "بيت"
كل هذه الحيل وغيرها في مقالتنا حتى تتمكّن من
الاطّلاع عليها في حال لم تتمكن من فهم كل هذه المعلومات بسرعة.
const file = event.dataTransfer?.files[0];
if (file?.type === 'application/json' || file?.name.endsWith('.excalidraw')) {
this.setState({ isLoading: true });
// Provided by browser-fs-access.
if (supported) {
try {
const item = event.dataTransfer.items[0];
file as any.handle = await item as any
.getAsFileSystemHandle();
} catch (error) {
console.warn(error.name, error.message);
}
}
loadFromBlob(file, this.state).then(({ elements, appState }) =>
// Load from blob
).catch((error) => {
this.setState({ isLoading: false, errorMessage: error.message });
});
}
مشاركة الملفات
يمكن أيضًا دمج النظام حاليًا على Android وChromeOS وWindows من خلال
Web Share Target API. أنا الآن في تطبيق "الملفات" في مجلّد Downloads
.
أرى ملفين، أحدهما يحمل الاسم غير الوصفي untitled
وطابوقًا زمنيًا. للتحقّق مما يحتوي عليه
، انقر على النقاط الثلاث، ثم على مشاركة، وأحد الخيارات التي تظهر هو
Excalidraw. عند النقر على الرمز، أرى أنّ الملف يحتوي على شعار I/O مرة أخرى.
Lipis على إصدار Electron المتوقّف
هناك إجراء يمكنك تنفيذه مع الملفات لم أتحدث عنه بعد، وهو النقر عليها مرّتين. في العادة، يؤدي النقر مرّتين على ملف إلى فتح التطبيق المرتبط بنوع MIME للملف. على سبيل المثال، بالنسبة إلى .docx
، سيكون Microsoft Word.
كان Excalidraw متوفّرًا في السابق بإصدار Electron من التطبيق الذي كان يسمح بربط أنواع الملفات هذه، لذلك عند النقر مرّتين على ملف .excalidraw
، كان يتم فتح
تطبيق Excalidraw Electron. "ليبيس"، الذي سبق أن قابلته، هو صانع
ومسؤول إيقاف Excalidraw Electron نهائيًا. سألته عن سبب اعتقاده أنّه من الممكن إيقاف استخدام
إصدار Electron نهائيًا:
كان المستخدمون يطلبون تطبيقًا مكتوبًا بلغة Electron منذ البداية، ويرجع ذلك بشكل أساسي إلى أنّهم أرادوا فتح الملفات بالنقر مرّتين. كنا ننوي أيضًا طرح التطبيق في متاجر التطبيقات. في الوقت نفسه، اقترح أحدهم إنشاء تطبيق متوافق مع الأجهزة الجوّالة (PWA) بدلاً من ذلك، لذلك فعلنا كليهما. لحسن الحظ، تم تقديمنا إلى Project Fugu واجهات برمجة التطبيقات، مثل الوصول إلى نظام الملفات والوصول إلى الحافظة ومعالجة الملفات وغير ذلك. بنقرة واحدة، يمكنك تثبيت التطبيق على جهاز الكمبيوتر المكتبي أو الجهاز الجوّال بدون استخدام Electron. كان من السهل اتخاذ قرار بالتوقّف نهائيًا عن استخدام إصدار Electron والتركيز على تطبيق الويب فقط وجعله أفضل تطبيق ويب تقدّمي ممكن. بالإضافة إلى ذلك، أصبح بإمكاننا الآن نشر التطبيقات المتوافقة مع الأجهزة الجوّالة على "متجر Play" وMicrosoft Store. هذا إنجاز عظيم.
يمكن القول أنّه لم يتم إيقاف Excalidraw لنظام التشغيل Electron نهائيًا لأنّ Electron سيئ، بل لأنّ الويب أصبح جيدًا بما يكفي. أعجبني هذا الإجراء.
معالجة الملفات
عندما أقول "أصبح الويب جيدًا بما يكفي"، أقصد الميزات مثل ميزة "معالجة الملفات" القادمة.
هذه عملية تثبيت عادية لنظام التشغيل macOS Big Sur. ونريد الآن معرفة ما يحدث عند النقر بزر الماوس الأيمن على ملف Excalidraw. يمكنني اختيار فتحه باستخدام Excalidraw، وهو تطبيق الويب التقدّمي المثبَّت. بالطبع، يمكن أيضًا النقر مرّتين، ولكنّه ليس مؤثرًا جدًا في تسجيل الشاشة.
كيف يتم ذلك؟ الخطوة الأولى هي إعلام
نظام التشغيل بأنواع الملفات التي يمكن لتطبيقي معالجتها. أُجري ذلك في حقل جديد يُسمى file_handlers
في بيان تطبيق الويب. تمثل
قيمته مصفوفة من العناصر التي تحتوي على إجراء وسمة accept
. يحدِّد الإجراء مسار عنوان URL الذي يشغِّل نظام التشغيل تطبيقك من خلاله، ويكون عنصر القبول عبارة عن أزواج مفاتيح وقيم لأنواع MIME
وإضافات الملفات المرتبطة.
{
"name": "Excalidraw",
"description": "Excalidraw is a whiteboard tool...",
"start_url": "/",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff",
"file_handlers": [
{
"action": "/",
"accept": {
"application/vnd.excalidraw+json": [".excalidraw"]
}
}
]
}
الخطوة التالية هي معالجة الملف عند تشغيل التطبيق. يحدث ذلك في واجهة launchQueue
حيث أحتاج إلى ضبط مستهلك من خلال الاتصال، حسنًا، setConsumer()
. المعلّمة لهذه الدالة
هي دالة غير متزامنة تتلقّى launchParams
. يحتوي عنصر launchParams
هذا على حقل يُسمى files يحصل من خلاله على صفيف من معالِم الملفات للعمل بها. لا يهمّني سوى
الملف الأول، ومن معرّف الملف هذا أحصل على ملف نصي أُرسله بعد ذلك إلى صديقنا القديم
loadFromBlob()
.
if ('launchQueue' in window && 'LaunchParams' in window) {
window as any.launchQueue
.setConsumer(async (launchParams: { files: any[] }) => {
if (!launchParams.files.length) return;
const fileHandle = launchParams.files[0];
const blob: Blob = await fileHandle.getFile();
blob.handle = fileHandle;
loadFromBlob(blob, this.state).then(({ elements, appState }) =>
// Initialize app state.
).catch((error) => {
this.setState({ isLoading: false, errorMessage: error.message });
});
});
}
مرة أخرى، إذا كان هذا الشرح سريعًا جدًا، يمكنك قراءة المزيد من المعلومات عن واجهة برمجة التطبيقات File Handling API في مقالتي. يمكنك تفعيل معالجة الملفات من خلال ضبط علامة ميزات منصّة الويب التجريبية. من المقرّر طرحها في Chrome في وقت لاحق من هذا العام.
دمج الحافظة
من الميزات الرائعة الأخرى في Excalidraw هي دمج الحافظة. يمكنني نسخ الرسم بالكامل أو أجزاء منه فقط إلى الحافظة، وربما إضافة علامة مائية إذا أردت، ثم لصقه في تطبيق آخر. هذا هو إصدار الويب من تطبيق Paint في نظام التشغيل Windows 95.
إنّ طريقة عمل هذه الميزة بسيطة بشكلٍ مدهش. كل ما أحتاج إليه هو اللوحة ككتلة، والتي أكتبها بعد ذلك
في الحافظة من خلال تمرير صفيف يتألف من عنصر واحد مع ClipboardItem
مع الكتلة إلى الدالة
navigator.clipboard.write()
. لمزيد من المعلومات حول الإجراءات التي يمكنك اتّخاذها باستخدام واجهة برمجة التطبيقات الخاصة بالحافظة، يمكنك الاطّلاع على مقالة "جيسون" ومقالتي.
export const copyCanvasToClipboardAsPng = async (canvas: HTMLCanvasElement) => {
const blob = await canvasToBlob(canvas);
await navigator.clipboard.write([
new window.ClipboardItem({
'image/png': blob,
}),
]);
};
export const canvasToBlob = async (canvas: HTMLCanvasElement): Promise<Blob> => {
return new Promise((resolve, reject) => {
try {
canvas.toBlob((blob) => {
if (!blob) {
return reject(new CanvasError(t('canvasError.canvasTooBig'), 'CANVAS_POSSIBLY_TOO_BIG'));
}
resolve(blob);
});
} catch (error) {
reject(error);
}
});
};
التعاون مع الآخرين
مشاركة عنوان URL لجلسة
هل تعلم أنّ Excalidraw يتضمّن أيضًا وضعًا تعاونيًا؟ يمكن لمستخدمين مختلفين العمل معًا على المستند نفسه. لبدء جلسة جديدة، انقر على زر التعاون المباشر ثم ابدأ جلسة. يمكنني مشاركة عنوان URL للجلسة مع المتعاونين بسهولة بفضل واجهة برمجة التطبيقات Web Share API التي دمجها Excalidraw.
التعاون المباشر
لقد محاكاة جلسة تعاون على الجهاز من خلال العمل على شعار Google I/O على جهاز Pixelbook وهاتف Pixel 3a وجهاز iPad Pro. يمكنك ملاحظة أنّ التغييرات التي أجريها على أحد الأجهزة تظهر على جميع الأجهزة الأخرى.
يمكنني أيضًا رؤية جميع المؤشرات وهي تتحرك. يتحرك مؤشر Pixelbook بثبات، لأنّه يتم التحكّم فيه باستخدام لوحة لمس، ولكن مؤشر هاتف Pixel 3a ومؤشر جهاز iPad Pro اللوحي يتحركان بشكل عشوائي، لأنّي أتحكّم في هذين الجهازَين من خلال النقر بإصبعي.
الاطّلاع على حالات المتعاونين
لتحسين تجربة التعاون في الوقت الفعلي، يتم تشغيل نظام رصد الخمول. يعرض مؤشر iPad Pro نقطة خضراء عند استخدامه. تتحول النقطة إلى اللون الأسود عند التبديل إلى علامة تبويب أو تطبيق مختلف في المتصفّح. وعندما أكون في تطبيق Excalidraw، ولكن لا أفعل أيّ شيء، يشير المؤشر إلى أنّني غير نشِط، ويظهر ذلك من خلال الرمز zZZ الثلاثي.
قد يظنّ القرّاء المهتمون بنشراتنا أنّ ميزة "رصد التوقف عن التصفّح" يتم تنفيذها من خلال Idle Detection API، وهو اقتراح في مرحلة مبكرة تم العمل عليه في سياق Project Fugu. تنبيه بكشف تفاصيل عن الحبكة: لا، ليس صحيحًا. على الرغم من أنّنا نفّذنا واجهة برمجة التطبيقات هذه في Excalidraw، قرّرنا في النهاية اتّباع نهج أكثر تقليدية يستند إلى قياس حركة المؤشر ومستوى ظهور الصفحة.
أرسلنا ملاحظات حول سبب عدم حلّ واجهة برمجة التطبيقات Idle Detection API لحالة الاستخدام التي واجهناها. يتم تطوير جميع واجهات برمجة التطبيقات في Project Fugu بشكل علني، ما يتيح للجميع التفاعل والتعبير عن آرائهم.
Lipis on what is holding back Excalidraw
في هذا السياق، طرحنا على "ليبيس" سؤالاً أخيرًا بشأن ما يعتقد أنّه غير متوفّر في منصة الويب التي تمنع Excalidraw من التقدّم:
واجهة برمجة التطبيقات File System Access API رائعة، ولكن هل لديك فكرة؟ معظم الملفات التي تهمّني هذه الأيام تقع في Dropbox أو Google Drive، وليس على القرص الصلب. أتمنى أن تتضمّن File System Access API طبقة تجريدية لمقدّمي أنظمة الملفات البعيدة، مثل Dropbox أو Google، لدمج الواجهة معهم وأن يتمكّن المطوّرون من استخدامها في الرموز البرمجية. يمكن للمستخدمين بعد ذلك أن يشعروا بالراحة ويعرفوا أنّ ملفاتهم آمنة مع مقدّم خدمة السحابة الإلكترونية الذي يثقون به.
أوافق تمامًا على ما قاله "ليبيس"، فأنا أستخدم السحابة الإلكترونية أيضًا. نأمل أن يتم تنفيذ ذلك قريبًا.
وضع التطبيق المُقسَّم إلى علامات تبويب
ممتاز. لقد شهدنا الكثير من عمليات الدمج الرائعة لواجهات برمجة التطبيقات في Excalidraw. نظام الملفات ومعالجة الملفات الحافظة ومشاركة الويب هدف مشاركة الويب إليك معلومة أخرى. حتى الآن، كان بإمكاني تعديل مستند واحد فقط في كل مرة. لم يعُد ذلك صحيحًا. يُرجى الاستفادة لأول مرة من إصدار مبكر من وضع التطبيقات المُفصَّلة في Excalidraw. إليك كيف يبدو.
لدي ملف حالي مفتوح في تطبيق الويب التقدّمي المثبَّت Excalidraw الذي يعمل في وضع التشغيل المستقل. الآن، أفتح علامة تبويب جديدة في النافذة المستقلة. هذه ليست علامة تبويب عادية في المتصفّح، بل علامة تبويب لتطبيق متوافق مع الأجهزة الجوّالة. في هذه علامة التبويب الجديدة، يمكنني بعد ذلك فتح ملف ثانوي والعمل عليه بشكل مستقل عن نافذة التطبيق نفسها.
لا يزال وضع التطبيقات المُقسّمة إلى علامات تبويب في مراحله الأولى، ولم يتم تحديد كل التفاصيل بعد. إذا كان الموضوع يهمّك، يمكنك الاطّلاع على الحالة الحالية لهذه الميزة في مقالتي.
الخاتمة
للاطّلاع على آخر المعلومات حول هذه الميزة وغيرها، احرص على مشاهدة تتبُّع Fugu API. نحن متحمّسون جدًا لتعزيز الويب و السماح لك بتنفيذ المزيد من الإجراءات على المنصة. نشكرك على استخدام Excalidraw الذي نسعى باستمرار إلى تحسينه، ونشكرك أيضًا على كل التطبيقات الرائعة التي ستنشئها. يمكنك البدء في إنشاء الرسومات على excalidraw.com.
نحن في انتظار رؤية بعض واجهات برمجة التطبيقات التي عرضناها اليوم تظهر في تطبيقاتك. اسمي "توم"، يمكنك العثور عليّ على Twitter وعبر الإنترنت بشكل عام باسم @tomayac. شكرًا جزيلاً على المشاهدة، ونتمنى لك الاستمتاع ببقية فعاليات Google I/O.