ज़रूरत के मुताबिक विकसित की गई कोई भी टेक्नोलॉजी, जादू से अलग नहीं होती. जब तक आपको यह समझ न आ जाए. मेरा नाम थॉमस स्टाइनर है. मैं Google में डेवलपर रिलेशंस टीम में काम करता हूं. Google I/O में मैंने जो बातचीत की थी उसके बारे में इस लेख में बताया गया है. इसमें, मैं कुछ नए Fugu API के बारे में बताऊंगा. साथ ही, यह भी बताऊंगा कि ये Excalidraw PWA में उपयोगकर्ता के मुख्य टास्क को कैसे बेहतर बनाते हैं. इससे आपको इन आइडिया से प्रेरणा मिल सकती है और इन्हें अपने ऐप्लिकेशन में लागू किया जा सकता है.
मैंने Excalidraw का इस्तेमाल कैसे शुरू किया
मुझे एक कहानी से शुरुआत करनी है. 1 जनवरी, 2020 को Facebook के सॉफ़्टवेयर इंजीनियर, क्रिस्टोफ़र शेडो ने एक छोटे से ड्रॉइंग ऐप्लिकेशन के बारे में ट्वीट किया. इस ऐप्लिकेशन पर उन्होंने काम करना शुरू किया था. इस टूल की मदद से, कार्टून जैसे बॉक्स और हाथ से बनाए गए ऐरो बनाए जा सकते हैं. अगले दिन, आपके पास टेक्स्ट और एलिप्स बनाने के साथ-साथ ऑब्जेक्ट चुनने और उन्हें इधर-उधर ले जाने का विकल्प भी होता है. तीन जनवरी को, इस ऐप्लिकेशन का नाम Excalidraw रखा गया. साथ ही, हर अच्छे साइड प्रोजेक्ट की तरह, क्रिस्टोफ़र ने सबसे पहले डोमेन का नाम खरीदा. अब आपके पास रंगों का इस्तेमाल करने और पूरी ड्राइंग को PNG फ़ाइल के तौर पर एक्सपोर्ट करने का विकल्प है.
क्रिस्टोफ़र ने 15 जनवरी को एक ब्लॉग पोस्ट की थी. इस पोस्ट ने Twitter पर काफ़ी लोगों का ध्यान खींचा. मेरा भी ध्यान इस पोस्ट ने खींचा. पोस्ट में कुछ बेहतरीन आंकड़े दिए गए थे:
- 12 हज़ार यूनीक ऐक्टिव उपयोगकर्ता
- GitHub पर 1.5 हज़ार स्टार
- 26 योगदान देने वाले
यह प्रोजेक्ट सिर्फ़ दो हफ़्ते पहले शुरू हुआ था. इसलिए, यह परफ़ॉर्मेंस काफ़ी अच्छी है. हालांकि, पोस्ट में नीचे की ओर दी गई जानकारी ने मेरी दिलचस्पी बढ़ा दी. क्रिस्टोफ़र ने लिखा कि उन्होंने इस बार कुछ नया आज़माया है: पुल अनुरोध करने वाले हर व्यक्ति को बिना किसी शर्त के कमिट करने का ऐक्सेस देना. मैंने जिस दिन ब्लॉग पोस्ट पढ़ी थी उसी दिन, मैंने एक पुल अनुरोध किया था. इससे Excalidraw में फ़ाइल सिस्टम ऐक्सेस एपीआई की सुविधा जोड़ी गई थी. साथ ही, किसी व्यक्ति ने सुविधा के लिए अनुरोध किया था, उसे ठीक किया गया था.
मेरा पुल अनुरोध एक दिन बाद मर्ज कर दिया गया. इसके बाद, मेरे पास कमिट करने का पूरा ऐक्सेस था. कहने की ज़रूरत नहीं कि मैंने अपनी ताक़त का गलत इस्तेमाल नहीं किया. इसके अलावा, अब तक योगदान देने वाले 149 लोगों में से किसी ने भी ऐसा नहीं किया है.
आज, Excalidraw एक ऐसा प्रोग्रेसिव वेब ऐप्लिकेशन है जिसे इंस्टॉल किया जा सकता है. इसमें ऑफ़लाइन मोड की सुविधा है. साथ ही, इसमें गहरे रंग वाला मोड भी है. इसके अलावा, इसमें File System Access API की मदद से फ़ाइलें खोलने और सेव करने की सुविधा भी है.
लिपीस ने बताया कि वे अपना ज़्यादातर समय Excalidraw को क्यों देते हैं
तो यह थी "मैंने Excalidraw का इस्तेमाल कैसे शुरू किया" कहानी. अब मैं Excalidraw की कुछ बेहतरीन सुविधाओं के बारे में बताऊंगी. इससे पहले, मैं Panayiotis का परिचय कराना चाहूंगी. Panayiotis Lipiridis, जिन्हें इंटरनेट पर lipis के नाम से जाना जाता है, Excalidraw में सबसे ज़्यादा योगदान देने वाले व्यक्ति हैं. मैंने लिपिस से पूछा कि उन्हें Excalidraw पर इतना समय बिताने के लिए क्या प्रेरणा मिलती है:
मुझे भी इस प्रोजेक्ट के बारे में क्रिस्टोफ़र के ट्वीट से पता चला. मेरा पहला योगदान Open Color library को जोड़ना था. ये रंग आज भी 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 टाइप और फ़ाइल एक्सटेंशन पर बातचीत करने के बाद, मुख्य हिस्सा File System Access API के फ़ंक्शन showOpenFilePicker()
को कॉल कर रहा है. यह फ़ंक्शन, फ़ाइलों का अरे या एक फ़ाइल दिखाता है. यह इस बात पर निर्भर करता है कि एक से ज़्यादा फ़ाइलें चुनी गई हैं या नहीं. इसके बाद, फ़ाइल हैंडल को फ़ाइल ऑब्जेक्ट पर रखा जाता है, ताकि इसे फिर से ऐक्सेस किया जा सके.
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;
};
};
फ़ॉलबैक लागू करने के लिए, "file"
टाइप के input
एलिमेंट का इस्तेमाल किया जाता है. स्वीकार किए जाने वाले 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;
};
"इस रूप में सेव करें" सुविधा
अगर मुझे किसी मौजूदा फ़ाइल हैंडल को अनदेखा करना है, तो "इस नाम से सेव करें" सुविधा का इस्तेमाल करके, मौजूदा फ़ाइल के आधार पर एक नई फ़ाइल बनाई जा सकती है. इसे दिखाने के लिए, मुझे एक मौजूदा फ़ाइल खोलनी है. इसमें कुछ बदलाव करने हैं. इसके बाद, मौजूदा फ़ाइल को सेव नहीं करना है, बल्कि 'इस नाम से सेव करें' सुविधा का इस्तेमाल करके एक नई फ़ाइल बनानी है. इससे ओरिजनल फ़ाइल में कोई बदलाव नहीं होता.
जिन ब्राउज़र पर फ़ाइल सिस्टम ऐक्सेस एपीआई काम नहीं करता उनके लिए, इस सुविधा को लागू करने का तरीका छोटा है. ऐसा इसलिए, क्योंकि यह सिर्फ़ एक ऐंकर एलिमेंट बनाता है. इसमें download
एट्रिब्यूट की वैल्यू, फ़ाइल का नाम होता है. साथ ही, 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();
};
इसके बाद, ऐंकर एलिमेंट पर प्रोग्राम के हिसाब से क्लिक किया जाता है. मेमोरी लीक को रोकने के लिए, इस्तेमाल के बाद blob यूआरएल को रद्द करना ज़रूरी है. यह सिर्फ़ डाउनलोड है. इसलिए, फ़ाइल सेव करने का कोई डायलॉग बॉक्स कभी नहीं दिखता. साथ ही, सभी फ़ाइलें डिफ़ॉल्ट Downloads
फ़ोल्डर में सेव हो जाती हैं.
खींचें और छोड़ें
डेस्कटॉप पर, सिस्टम इंटिग्रेशन की मेरी पसंदीदा सुविधाओं में से एक है खींचकर छोड़ना. Excalidraw में, किसी .excalidraw
फ़ाइल को ऐप्लिकेशन पर ड्रॉप करने पर, वह तुरंत खुल जाती है और उसमें बदलाव किया जा सकता है. जिन ब्राउज़र पर File System Access API काम करता है उन पर, मैं अपने बदलावों को तुरंत सेव कर सकता हूं. फ़ाइल सेव करने के लिए डायलॉग बॉक्स खोलने की ज़रूरत नहीं है, क्योंकि फ़ाइल हैंडल को खींचें और छोड़ें की सुविधा से हासिल किया गया है.
फ़ाइल सिस्टम ऐक्सेस एपीआई के साथ काम करने वाले डेटा ट्रांसफ़र आइटम पर getAsFileSystemHandle()
को कॉल करके, इस सुविधा को चालू किया जा सकता है. इसके बाद, मैं इस फ़ाइल हैंडल को 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 के ज़रिए होता है. यहाँ मैं Files ऐप्लिकेशन में अपने 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 Store और Microsoft Store पर PWA पब्लिश कर सकते हैं! यह शानदार है!
यह कहा जा सकता है कि Excalidraw for Electron को इसलिए बंद नहीं किया गया, क्योंकि Electron खराब है. ऐसा बिलकुल नहीं है. बल्कि, इसलिए बंद किया गया, क्योंकि वेब अब बेहतर हो गया है. मुझे यह पसंद है!
फ़ाइल मैनेज करना
जब मैं कहता हूं कि "वेब अब काफ़ी बेहतर हो गया है", तो इसकी वजह फ़ाइल हैंडलिंग जैसी सुविधाएं हैं.
यह macOS Big Sur का सामान्य इंस्टॉलेशन है. अब देखें कि Excalidraw फ़ाइल पर राइट क्लिक करने पर क्या होता है. मेरे पास इसे इंस्टॉल किए गए PWA, Excalidraw से खोलने का विकल्प है. ज़रूर, डबल-क्लिक करने से भी काम हो जाएगा. हालांकि, स्क्रीनकास्ट में इसे दिखाना थोड़ा मुश्किल है.
यह कैसे काम करता है? पहला चरण यह है कि ऑपरेटिंग सिस्टम को यह बताया जाए कि मेरा ऐप्लिकेशन किस तरह की फ़ाइलों को हैंडल कर सकता है. मैंने इसे वेब ऐप्लिकेशन मेनिफ़ेस्ट में file_handlers
नाम के नए फ़ील्ड में किया है. इसकी वैल्यू, ऑब्जेक्ट का एक कलेक्शन होती है. इसमें एक ऐक्शन और एक accept
प्रॉपर्टी होती है. कार्रवाई से उस यूआरएल पाथ का पता चलता है जिस पर ऑपरेटिंग सिस्टम आपके ऐप्लिकेशन को लॉन्च करता है. साथ ही, accept ऑब्जेक्ट, 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
ऑब्जेक्ट में फ़ाइलें नाम का एक फ़ील्ड है. इससे मुझे काम करने के लिए फ़ाइल हैंडल का एक कलेक्शन मिलता है. मुझे सिर्फ़ पहले वाले की ज़रूरत है. इस फ़ाइल हैंडल से मुझे एक ब्लॉब मिलता है, जिसे मैं अपने पुराने दोस्त 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 की एक और बेहतरीन सुविधा, क्लिपबोर्ड इंटिग्रेशन है. मैं अपनी पूरी ड्रॉइंग या उसके कुछ हिस्सों को क्लिपबोर्ड में कॉपी कर सकता/सकती हूं. अगर मुझे लगता है, तो वॉटरमार्क जोड़ सकता/सकती हूं. इसके बाद, इसे किसी दूसरे ऐप्लिकेशन में चिपकाया जा सकता है. वैसे, यह Windows 95 के Paint ऐप्लिकेशन का वेब वर्शन है.
इसके काम करने का तरीका काफ़ी आसान है. मुझे सिर्फ़ कैनवस को एक ब्लब के तौर पर चाहिए. इसके बाद, मैं इसे क्लिपबोर्ड पर लिखता हूं. इसके लिए, मुझे navigator.clipboard.write()
फ़ंक्शन में ब्लब के साथ एक एलिमेंट वाला ऐरे पास करना होता है.ClipboardItem
क्लिपबोर्ड एपीआई की मदद से क्या-क्या किया जा सकता है, इस बारे में ज़्यादा जानने के लिए, Jason और मेरा लेख पढ़ें.
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);
}
});
};
दूसरे लोगों के साथ मिलकर काम करना
सेशन का यूआरएल शेयर करना
क्या आपको पता है कि Excalidraw में साथ मिलकर काम करने का मोड भी होता है? अलग-अलग लोग एक ही दस्तावेज़ पर एक साथ काम कर सकते हैं. नया सेशन शुरू करने के लिए, मैं लाइव कोलैबरेशन बटन पर क्लिक करता/करती हूँ. इसके बाद, सेशन शुरू करता/करती हूँ. Excalidraw में Web Share API इंटिग्रेट किया गया है. इसकी मदद से, मैं अपने साथ काम करने वाले लोगों के साथ सेशन का यूआरएल आसानी से शेयर कर सकता हूं.
लाइव स्ट्रीम के दौरान मिलकर काम करना
मैंने अपने Pixelbook, Pixel 3a फ़ोन, और iPad Pro पर Google I/O के लोगो पर काम करके, स्थानीय तौर पर साथ मिलकर काम करने का एक सेशन सिम्युलेट किया है. आपको दिख रहा होगा कि मैंने एक डिवाइस पर जो बदलाव किए हैं वे सभी डिवाइसों पर दिख रहे हैं.
मुझे सभी कर्सर घूमते हुए भी दिख रहे हैं. Pixelbook का कर्सर लगातार घूम रहा है, क्योंकि इसे ट्रैकपैड से कंट्रोल किया जाता है. हालांकि, Pixel 3a फ़ोन और iPad Pro टैबलेट का कर्सर इधर-उधर घूम रहा है, क्योंकि इन डिवाइसों को उंगली से टैप करके कंट्रोल किया जाता है.
सहयोगियों के स्टेटस देखना
रीयलटाइम में साथ मिलकर काम करने के अनुभव को बेहतर बनाने के लिए, एक सिस्टम यह पता लगाता है कि उपयोगकर्ता कुछ समय से कोई गतिविधि नहीं कर रहा है. iPad Pro के कर्सर पर हरे रंग का बिंदु दिखता है. किसी दूसरे ब्राउज़र टैब या ऐप्लिकेशन पर स्विच करने पर, यह बिंदु काला हो जाता है. साथ ही, Excalidraw ऐप्लिकेशन में कुछ भी न करने पर, कर्सर के ऊपर तीन zZZs दिखते हैं. इससे पता चलता है कि उपयोगकर्ता कुछ नहीं कर रहा है.
हमारी पब्लिकेशन पढ़ने वाले लोगों को लग सकता है कि उपयोगकर्ता की गतिविधि का पता लगाने की सुविधा, Idle Detection API के ज़रिए लागू की जाती है. यह एक शुरुआती प्रस्ताव है, जिस पर Project Fugu के संदर्भ में काम किया गया है. स्पॉइलर अलर्ट: ऐसा नहीं है. Excalidraw में इस एपीआई के आधार पर सुविधा लागू की गई थी. हालांकि, आखिर में हमने पॉइंटर के मूवमेंट और पेज के दिखने के आधार पर, ज़्यादा पारंपरिक तरीके का इस्तेमाल करने का फ़ैसला किया.
हमने सुझाव दिया है कि Idle Detection API, हमारे इस्तेमाल के उदाहरण को क्यों हल नहीं कर रहा है. Project Fugu के सभी एपीआई, ओपन सोर्स के तौर पर डेवलप किए जा रहे हैं. इसलिए, हर कोई इसमें अपनी राय दे सकता है और अपनी बात रख सकता है!
Excalidraw को बेहतर बनाने के लिए सुझाव
इस बारे में बात करते हुए, मैंने लिपिस से एक आखिरी सवाल पूछा कि उनके हिसाब से वेब प्लैटफ़ॉर्म में क्या कमी है जिसकी वजह से Excalidraw को आगे बढ़ने में मुश्किल हो रही है:
File System Access API बहुत अच्छा है, लेकिन क्या आपको पता है कि? आजकल, मेरी ज़्यादातर ज़रूरी फ़ाइलें मेरे Dropbox या Google Drive में सेव हैं, न कि मेरी हार्ड डिस्क में. मेरी इच्छा है कि फ़ाइल सिस्टम ऐक्सेस एपीआई में, Dropbox या Google जैसे रिमोट फ़ाइल सिस्टम उपलब्ध कराने वालों के लिए एक ऐब्स्ट्रैक्शन लेयर शामिल हो, ताकि वे इसके साथ इंटिग्रेट कर सकें. साथ ही, डेवलपर इसके लिए कोड लिख सकें. इसके बाद, उपयोगकर्ता को यह भरोसा हो सकता है कि उनकी फ़ाइलें, क्लाउड सेवा देने वाली उस कंपनी के साथ सुरक्षित हैं जिस पर वे भरोसा करते हैं.
मैं लिपिस से पूरी तरह सहमत हूं. मैं भी क्लाउड में रहता हूं. हमें उम्मीद है कि इसे जल्द ही लागू कर दिया जाएगा.
टैब किए गए ऐप्लिकेशन मोड
वाह! हमने Excalidraw में कई बेहतरीन एपीआई इंटिग्रेशन देखे हैं. फ़ाइल सिस्टम, फ़ाइल हैंडलिंग, क्लिपबोर्ड, वेब शेयर, और वेब शेयर टारगेट. हालांकि, एक और बात है. अब तक, मैं एक बार में सिर्फ़ एक दस्तावेज़ में बदलाव कर सकता था. अब नहीं. Excalidraw में टैब किए गए ऐप्लिकेशन मोड के शुरुआती वर्शन का पहली बार इस्तेमाल करें. यह इस तरह दिखता है.
मैंने इंस्टॉल किए गए Excalidraw PWA में कोई मौजूदा फ़ाइल खोली है. यह स्टैंडअलोन मोड में चल रहा है. अब मैं स्टैंडअलोन विंडो में एक नया टैब खोलता/खोलती हूं. यह सामान्य ब्राउज़र टैब नहीं है, बल्कि PWA टैब है. इस नए टैब में, दूसरी फ़ाइल खोली जा सकती है. साथ ही, एक ही ऐप्लिकेशन विंडो में इन दोनों फ़ाइलों पर अलग-अलग काम किया जा सकता है.
टैब किए गए ऐप्लिकेशन मोड पर अभी काम चल रहा है और यह शुरुआती चरण में ही है. इसलिए, हो सकता है कि फ़िलहाल सभी प्रॉडक्ट को टैग न किया जा सके. अगर आपको इस सुविधा के बारे में जानना है, तो मेरे लेख में जाकर, इस सुविधा की मौजूदा स्थिति के बारे में ज़रूर पढ़ें.
आखिरी हिस्सा
इस और अन्य सुविधाओं के बारे में अपडेट पाने के लिए, हमारे Fugu API ट्रैकर को ज़रूर देखें. हमें वेब को आगे बढ़ाने और आपको इस प्लैटफ़ॉर्म पर ज़्यादा सुविधाएं देने में बेहद खुशी हो रही है. हम Excalidraw को लगातार बेहतर बनाने के लिए काम करते रहेंगे. साथ ही, हम आपके बनाए गए सभी बेहतरीन ऐप्लिकेशन के लिए शुभकामनाएं देते हैं. excalidraw.com पर जाकर, डायग्राम बनाना शुरू करें.
हमें उम्मीद है कि आज हमने जो एपीआई दिखाए हैं वे जल्द ही आपके ऐप्लिकेशन में दिखेंगे. मेरा नाम टॉम है. मुझे Twitter पर @tomayac के तौर पर और इंटरनेट पर खोजा जा सकता है. वीडियो देखने के लिए बहुत-बहुत धन्यवाद. Google I/O के बाकी सेशन का आनंद लें.