لا يمكن تمييز أي تقنية متقدمة بما يكفي عن السحر. ما لم تفهم ذلك. اسمي "توماس شتاينر"، وأعمل في قسم "علاقات المطوّرين" في 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.
"لابيس" عن سبب تخصيص الكثير من وقته لتطبيق Excali draw
نختم قصة "كيفية استخدامي 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 للكائنات الثنائية الكبيرة (blob) كقيمة السمة 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 متوافقة. ثم أقوم بتمرير مؤشر الملف هذا
إلى 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
، يتم فتح تطبيق Excali draw Electron. "ليبيس"، الذي سبق أن قابلته، هو صانع
ومسؤول إيقاف Excalidraw Electron نهائيًا. سألته عن سبب اعتقاده أنّه من الممكن إيقاف استخدام
إصدار Electron نهائيًا:
يطلب الأشخاص تطبيق Electron منذ البداية، ويرجع ذلك أساسًا إلى رغبتهم في فتح الملفات عن طريق النقر المزدوج. كنا ننوي أيضًا طرح التطبيق في متاجر التطبيقات. بالتوازي مع ذلك، اقترح شخص ما إنشاء تطبيق ويب تقدّمي بدلاً من ذلك، لذلك فعلنا الاثنين معًا. ولحسن الحظ، تم تعريفنا بواجهات برمجة تطبيقات Project Fugu مثل الوصول إلى نظام الملفات والوصول إلى الحافظة ومعالجة الملفات والمزيد. يمكنك بمجرد نقرة واحدة تثبيت التطبيق على جهاز الكمبيوتر المكتبي أو الجهاز الجوّال، بدون التحميل الزائد لبرنامج Electron. كان من السهل اتخاذ قرار بالتوقّف نهائيًا عن استخدام إصدار Electron والتركيز على تطبيق الويب فقط وجعله أفضل تطبيق ويب تقدّمي ممكن. أصبح بإمكاننا الآن نشر تطبيقات الويب التقدّمية (PWA) على "متجر Play" وMicrosoft Store. هذا إنجاز عظيم.
يمكن للمرء أن يقول "إكساليبيدري" لشركة 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 });
});
});
}
مرة أخرى، إذا سارت الأمور بسرعة كبيرة، يمكنك الاطّلاع على المزيد من المعلومات حول واجهة برمجة تطبيقات معالجة الملفات في مقالتي. يمكنك تفعيل معالجة الملفات من خلال ضبط علامة ميزات منصّة الويب التجريبية . ومن المقرّر أن تظهر في 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. تنبيه بكشف تفاصيل عن الحبكة: لا، ليس صحيحًا. وعلى الرغم من اعتمادنا على واجهة برمجة التطبيقات هذه في Excali draw، قرّرنا في النهاية اعتماد منهج تقليدي يستند إلى قياس حركة المؤشر ومستوى رؤية الصفحة.
قدّمنا ملاحظات حول سبب عدم قدرة واجهة برمجة تطبيقات 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 الذي يعمل في وضع التشغيل المستقل. الآن أفتح علامة تبويب جديدة في النافذة المستقلة. هذه ليست علامة تبويب متصفّح عادية، ولكنها علامة تبويب تطبيق ويب تقدّمي (PWA). في علامة التبويب الجديدة هذه، يمكنني بعد ذلك فتح ملف ثانوي والعمل عليه بشكل مستقل من نفس نافذة التطبيق.
ما زال وضع التطبيق المبوب في مراحله الأولى ولم يتم ضبط كل شيء على ما يرام. إذا كنت مهتمًا بذلك، يُرجى قراءة الحالة الحالية لهذه الميزة في مقالتي.
الخاتمة
للاطّلاع على آخر الأخبار حول هذه الميزة وغيرها من الميزات، يمكنك مشاهدة أداة تتبُّع واجهة برمجة التطبيقات Fuugu. نحن متحمسون للغاية للمضي قدمًا في الويب والسماح لك بفعل المزيد على المنصة. نشكرك على استخدام Excalidraw الذي نسعى باستمرار إلى تحسينه، ونشكرك أيضًا على كل التطبيقات الرائعة التي ستنشئها. ما عليك سوى البدء في صناعة المحتوى من خلال الرابط excalidraw.com.
نحن في انتظار رؤية بعض واجهات برمجة التطبيقات التي عرضناها اليوم تظهر في تطبيقاتك. اسمي تامر، ويمكنك العثور عليّ باعتباري @tomayac على Twitter وعلى الإنترنت بشكل عام. شكرًا جزيلاً على المشاهدة، ونتمنى لك الاستمتاع بباقي فعاليات Google I/O.