Exalidraw và Fugu: Cải thiện hành trình cốt lõi của người dùng

Bất kỳ công nghệ đủ tiên tiến nào cũng không thể phân biệt được với ma thuật. Trừ phi bạn hiểu rõ vấn đề. Tôi là Thomas Steiner, bộ phận Quan hệ nhà phát triển tại Google. Trong bản tóm tắt bài nói chuyện tại Google I/O này, tôi sẽ xem xét một số API Fugu mới cũng như cách chúng cải thiện hành trình cốt lõi của người dùng trong PWA Excalidraw. Nhờ đó, bạn có thể lấy cảm hứng từ những ý tưởng này rồi áp dụng vào ứng dụng của mình.

Làm thế nào tôi đến với Excalidraw

Tôi muốn bắt đầu từ một câu chuyện. Vào ngày 1 tháng 1 năm 2020, Christopher Chedeau, một kỹ sư phần mềm tại Facebook, đã đăng bài trên Twitter về một ứng dụng vẽ nhỏ mà anh có bắt đầu làm việc. Với công cụ này, bạn có thể vẽ các hộp và mũi tên mang phong cách hoạt hình vẽ tay. Ngày hôm sau, bạn cũng có thể vẽ dấu ba chấm và văn bản, cũng như chọn đối tượng và di chuyển họ ở xung quanh. Vào ngày 3 tháng 1, ứng dụng đã có tên, Excalidraw, v.v. với mọi khía cạnh tốt đẹp mua tên miền là một trong những hành động đầu tiên của Christopher. Theo bạn hiện có thể sử dụng màu và xuất toàn bộ bản vẽ dưới dạng PNG.

Ảnh chụp màn hình ứng dụng nguyên mẫu Excalidraw cho thấy ứng dụng này hỗ trợ hình chữ nhật, mũi tên, hình elip và văn bản.

Vào ngày 15 tháng 1, Christopher đưa ra một bài đăng trên blog đã thu hút được nhận được rất nhiều sự chú ý trên Twitter, bao gồm cả trang Twitter của tôi. Bài đăng này mở đầu với một vài số liệu thống kê ấn tượng:

  • 12 nghìn người dùng riêng biệt đang hoạt động
  • 1,5 nghìn sao trên GitHub
  • 26 người đóng góp

Đối với một dự án chỉ bắt đầu cách đây 2 tuần thì như vậy không hề tệ. Tuy nhiên, điều thực sự thì sự quan tâm của tôi lại càng giảm đi đối với bài đăng. Christopher viết rằng anh đã thử một sản phẩm mới thời gian: cấp cho tất cả những người đưa ra yêu cầu lấy dữ liệu quyền truy cập cam kết vô điều kiện. Cùng ngày với đọc bài đăng trên blog, tôi đã có một yêu cầu kéo lên đã thêm tính năng hỗ trợ API Truy cập hệ thống tệp vào Excalidraw, khắc phục một lỗi yêu cầu về tính năng mà ai đó đã gửi.

Ảnh chụp màn hình dòng tweet, trong đó tôi công bố bài PR của mình.

Yêu cầu lấy dữ liệu của tôi được hợp nhất một ngày sau đó và từ đó, tôi có toàn quyền truy cập cam kết. Không cần phải nói Tôi không lạm dụng sức mạnh của mình. Và cũng không có bất kỳ ai khác trong số 149 người đóng góp cho đến nay.

Hiện nay, Excalidraw là một ứng dụng web tiến bộ, có thể cài đặt hoàn chỉnh với hỗ trợ ngoại tuyến, chế độ tối tuyệt đẹp và có, khả năng mở và lưu tệp nhờ vào API Truy cập hệ thống tệp.

Ảnh chụp màn hình PWA Excalidraw ở trạng thái hiện tại.

Lipis chia sẻ lý do anh dành nhiều thời gian như vậy cho Excalidraw

Đây là điểm kết thúc "cách tôi đến với Excalidraw" câu chuyện, nhưng trước khi đi sâu vào một số những tính năng tuyệt vời của Excalidraw. Tôi xin hân hạnh giới thiệu Panayiotis. Panayiotis Lipiridis, đang bật Internet, đơn giản được gọi là lipis, là nguồn đóng góp lớn nhất cho Khai thác. Tôi hỏi Lipis động lực nào khiến anh dành nhiều thời gian như vậy cho Excalidraw:

Như mọi người khác, tôi biết đến dự án này qua câu tweet của Christopher. Nội dung đóng góp đầu tiên của tôi là thêm Thư viện màu mở, các màu vẫn một phần của Excalidraw ngày nay. Khi dự án phát triển và chúng tôi nhận được khá nhiều yêu cầu, là xây dựng một chương trình phụ trợ để lưu trữ bản vẽ để người dùng có thể chia sẻ chúng. Nhưng gì thực sự thúc đẩy tôi đóng góp là bất cứ ai thử Excalidraw đều muốn tìm lý do để sử dụng lại từ đầu.

Tôi hoàn toàn đồng ý với lipis. Bất cứ ai đã thử Excalidraw đều muốn tìm lý do để sử dụng lại.

Khai thác trong thực tế

Bây giờ, tôi muốn hướng dẫn bạn cách sử dụng Excalidraw trong thực tế. Tôi không phải là một nghệ sĩ tài năng, nhưng Biểu trưng Google I/O khá đơn giản, vì vậy hãy để tôi dùng thử. Một ô là chữ "i", một đường có thể là dấu gạch chéo và "o" là một vòng tròn. Tôi nhấn giữ phím shift để có được một vòng tròn chính xác. Để tôi di chuyển dấu gạch chéo một chút, nên ảnh trông đẹp hơn. Bây giờ, hãy thêm màu cho chữ "i" và chữ "o". Màu xanh dương là tốt. Có thể một kiểu tô màu nền khác? Tất cả đều ổn định hay cửa sập ngang? Không, Hachure trông đẹp quá. Không hoàn hảo, nhưng đó là ý tưởng về Excalidraw, vậy nên hãy để tôi lưu lại nhé.

Tôi nhấp vào biểu tượng lưu và nhập tên tệp vào hộp thoại lưu tệp. Trong Chrome, trình duyệt hỗ trợ API Truy cập hệ thống tệp, đây không phải là tải xuống mà là thao tác lưu thực sự, trong đó tôi có thể chọn vị trí và tên tệp, và địa điểm, nếu chỉnh sửa, tôi có thể lưu chúng vào cùng một tệp.

Hãy để tôi thay đổi biểu trưng và tạo chữ "i" màu đỏ. Nếu bây giờ tôi nhấp lại vào lưu, nội dung sửa đổi sẽ được lưu vào tệp giống như trước. Để chứng minh, hãy để tôi xoá canvas rồi mở lại tệp. Như bạn có thể thấy, biểu trưng màu đỏ-xanh lam đã sửa đổi vẫn xuất hiện.

Làm việc với tệp

Trên các trình duyệt hiện không hỗ trợ API Truy cập hệ thống tệp, mỗi thao tác lưu đều là tải xuống, vì vậy khi thực hiện thay đổi, tôi sẽ tạo ra nhiều tệp có số tăng dần trong đầy thư mục Tệp đã tải xuống. Nhưng bất chấp nhược điểm này, tôi vẫn có thể lưu tệp.

Mở tệp

Vậy bí mật là gì? Làm cách nào để mở và lưu hoạt động trên các trình duyệt khác nhau có thể hoặc không thể có hỗ trợ API Truy cập hệ thống tệp không? Thao tác mở tệp trong Excalidraw diễn ra trong một hàm có tên là loadFromJSON)(), từ đó sẽ gọi một hàm có tên là 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);
};

Hàm fileOpen() bắt nguồn từ một thư viện nhỏ mà tôi đã viết có tên là browser-fs-access mà chúng tôi sử dụng trong Khai thác. Thư viện này cung cấp quyền truy cập vào hệ thống tệp thông qua API Truy cập hệ thống tệp với một dự phòng cũ để có thể sử dụng trong bất kỳ trình duyệt.

Trước tiên, tôi sẽ cho bạn biết cách triển khai khi API này được hỗ trợ. Sau khi thương lượng các loại MIME và đuôi tệp được chấp nhận, phần trọng tâm là gọi API Truy cập hệ thống tệp hàm showOpenFilePicker(). Hàm này trả về một mảng tệp hoặc một tệp duy nhất, phần phụ thuộc về việc nhiều tệp có được chọn hay không. Việc còn lại là đặt tên người dùng cho tệp đó để có thể truy xuất lại đối tượng đó.

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;
  };
};

Việc triển khai dự phòng dựa vào phần tử input thuộc loại "file". Sau khi thương lượng các loại MIME và tiện ích sẽ được chấp nhận, bước tiếp theo là nhấp vào dữ liệu đầu vào theo phương thức lập trình để hộp thoại mở tệp hiển thị. Khi thay đổi, tức là khi người dùng đã chọn một hoặc nhiều tệp thì lời hứa sẽ được thực hiện.

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();
  });
};

Đang lưu tệp

Bây giờ để lưu. Trong Excalidraw, quá trình lưu sẽ diễn ra trong một hàm có tên là saveAsJSON(). Đầu tiên chuyển đổi tuần tự mảng phần tử Excalidraw thành JSON, chuyển đổi JSON thành một blob, sau đó gọi một có tên là fileSave(). Hàm này tương tự cũng được cung cấp bởi browser-fs-access của chúng tôi.

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 };
};

Một lần nữa, trước tiên, tôi sẽ xem xét việc triển khai cho các trình duyệt có hỗ trợ API Truy cập hệ thống tệp. Chiến lược phát hành đĩa đơn vài dòng đầu tiên có vẻ hơi liên quan, nhưng tất cả những gì chúng làm là thương lượng các loại MIME và tệp tiện ích. Khi tôi đã lưu trước đó và đã có tên người dùng tệp, không cần phải có hộp thoại lưu hiển thị. Tuy nhiên, nếu đây là lần lưu đầu tiên, một hộp thoại tệp sẽ hiển thị và ứng dụng sẽ nhận được tên xử lý tệp để sử dụng trong tương lai. Sau đó, phần còn lại chỉ là ghi vào tệp, điều này xảy ra thông qua luồng có thể ghi.

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;
};

"Lưu dưới dạng" đối tượng

Nếu quyết định bỏ qua tên người dùng hiện có của tệp, tôi có thể triển khai tính năng "lưu dưới dạng" tính năng để tạo một tệp mới dựa trên tệp hiện có. Để hiển thị tệp này, hãy để tôi mở một tệp hiện có, sửa đổi, rồi không ghi đè tệp hiện có, mà tạo một tệp mới bằng cách sử dụng chức năng lưu dưới dạng của chúng tôi. Thao tác này giúp giữ nguyên tệp gốc.

Việc triển khai cho các trình duyệt không hỗ trợ API Truy cập hệ thống tệp rất ngắn vì tất cả đều sẽ tạo một phần tử neo có thuộc tính download có giá trị là tên tệp mong muốn và URL của blob làm giá trị thuộc tính href của nó.

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();
};

Sau đó, phần tử liên kết này được nhấp theo phương thức lập trình. Để tránh rò rỉ bộ nhớ, URL của blob cần bị thu hồi sau khi sử dụng. Vì đây chỉ là một tệp tải xuống nên sẽ không có hộp thoại lưu tệp nào hiển thị và tất cả sẽ nằm trong thư mục Downloads mặc định.

Kéo và thả

Một trong những công cụ tích hợp hệ thống mà tôi yêu thích trên máy tính là kéo và thả. Trong Excalidraw, khi tôi thả một .excalidraw vào ứng dụng, tệp này sẽ mở ngay lập tức và tôi có thể bắt đầu chỉnh sửa. Trên trình duyệt hỗ trợ API Truy cập hệ thống tệp, tôi có thể lưu các thay đổi của mình ngay lập tức. Không cần đi thông qua hộp thoại lưu tệp vì tên người dùng tệp bắt buộc đã được lấy từ thao tác kéo và thả hoạt động.

Bí quyết để thực hiện điều này là bằng cách gọi getAsFileSystemHandle() trên Mục chuyển dữ liệu khi API Truy cập hệ thống tệp được hỗ trợ. Sau đó, tôi bỏ qua tên người dùng sang loadFromBlob() mà bạn có thể nhớ qua vài đoạn văn ở trên. Rất nhiều những việc bạn có thể thực hiện với tệp: mở, lưu, lưu quá mức, kéo, thả. Đồng nghiệp của tôi, Pete Tôi đã ghi lại tất cả các thủ thuật này cũng như nhiều nội dung khác trong bài viết của chúng tôi để bạn có thể bắt kịp trong trường hợp mọi việc diễn ra quá nhanh.

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 });
  });
}

Chia sẻ tệp

Một cách tích hợp hệ thống khác hiện có trên Android, ChromeOS và Windows là thông qua Web Share Target API (API Mục tiêu chia sẻ web). Tôi đang ở trong ứng dụng Files trong thư mục Downloads. N có thể thấy 2 tệp, một trong số đó có tên không phải là chỉ số mô tả untitled và một dấu thời gian. Để kiểm tra trong đó, tôi nhấp vào ba dấu chấm, sau đó chia sẻ và một trong các tuỳ chọn hiện ra là Khai thác. Khi nhấn vào biểu tượng này, tôi có thể thấy rằng tệp vừa chứa lại biểu trưng I/O.

Lipis trên phiên bản Electron không dùng nữa

Một việc bạn có thể làm với các tệp mà tôi chưa nói đến đó là phóng to các tệp đó. Thông thường xảy ra khi bạn mở lại một tệp và ứng dụng đó được liên kết với loại MIME của tệp đó sẽ mở ra. Ví dụ cho .docx, đây sẽ là Microsoft Word.

Khai thác từng sử dụng để tạo một phiên bản Electron của ứng dụng hỗ trợ các liên kết loại tệp như vậy, vì vậy, khi bạn nhấp đúp vào một tệp .excalidraw, Ứng dụng Excalidraw Electron sẽ mở ra. Lipis, người mà bạn từng gặp trước đây, vừa là nhà sáng tạo và là người khấu trừ Excalidraw Electron. Tôi hỏi ông tại sao ông cảm thấy có thể không dùng Phiên bản điện tử:

Mọi người đã yêu cầu dùng ứng dụng Electron ngay từ đầu, chủ yếu vì họ muốn mở tệp bằng cách nhấp đúp. Chúng tôi cũng đã có ý định đưa ứng dụng này vào các cửa hàng ứng dụng. Cùng với đó, ai đó đề xuất tạo một ứng dụng web tiến bộ (PWA) nên chúng ta đã làm cả hai. Thật may mắn, chúng tôi được giới thiệu với Project Fugu Các API như quyền truy cập vào hệ thống tệp, truy cập vào bảng nhớ tạm, xử lý tệp, v.v. Với một cú nhấp chuột duy nhất, bạn có thể cài đặt ứng dụng trên máy tính để bàn hoặc thiết bị di động của bạn mà không làm tăng thêm trọng lượng của Electron. Thật dễ dàng quyết định không dùng phiên bản Electron nữa, chỉ tập trung vào ứng dụng web và biến nó thành PWA tốt nhất có thể. Ngoài ra, chúng tôi hiện có thể phát hành PWA lên Cửa hàng Play và Microsoft Cửa hàng! Hay quá!

Người ta có thể nói rằng Excalidraw cho Electron không được dùng nữa vì Electron rất tệ, nhưng thực ra là nó rất tệ bởi vì web đã trở nên tốt đủ rồi. Tôi thích nội dung này!

Xử lý tệp

Khi tôi nói "web đã trở nên đủ tốt", thì đó là do các tính năng như File sắp ra mắt Xử lý.

Đây là bản cài đặt macOS Big Sur thông thường. Bây giờ, hãy xem điều gì sẽ xảy ra khi tôi nhấp chuột phải vào một Tệp Excalidraw. Tôi có thể chọn mở ứng dụng đó bằng Excalidraw, PWA đã cài đặt. Tất nhiên bạn cũng có thể nhấp đúp. Cách minh hoạ trong bản ghi màn hình sẽ ít ấn tượng hơn.

Tính năng này hoạt động như thế nào? Bước đầu tiên là làm cho các loại tệp mà ứng dụng của tôi có thể xử lý được hệ điều hành. Tôi thực hiện việc này trong một trường mới có tên là file_handlers trong tệp kê khai ứng dụng web. giá trị là một mảng các đối tượng có thao tác và thuộc tính accept. Hành động sẽ xác định URL đường dẫn mà hệ điều hành chạy ứng dụng của bạn tại và đối tượng chấp nhận là các cặp khoá-giá trị của MIME và đuôi tệp được liên kết.

{
  "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"]
      }
    }
  ]
}

Bước tiếp theo là xử lý tệp khi ứng dụng khởi chạy. Quá trình này diễn ra trong launchQueue nơi tôi cần thiết lập người tiêu dùng bằng cách gọi setConsumer(). Tham số cho biến này là một hàm không đồng bộ nhận launchParams. Đối tượng launchParams này có một trường có tên là các tệp giúp tôi xử lý một mảng các tên tệp để xử lý. Tôi chỉ quan tâm đến đầu tiên và từ tên người dùng tệp này, tôi nhận được một blob mà sau đó tôi chuyển cho người bạn cũ của chúng ta 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 });
      });
    });
}

Xin nhắc lại, nếu quá trình này diễn ra quá nhanh, bạn có thể đọc thêm về API Xử lý tệp trong bài viết của tôi. Bạn có thể bật tính năng xử lý tệp bằng cách đặt nền tảng web thử nghiệm cờ tính năng. Dự kiến phiên bản này sẽ có trên Chrome vào cuối năm nay.

Tích hợp bảng nhớ tạm

Một tính năng thú vị khác của Excalidraw là tích hợp bảng nhớ tạm. Tôi có thể sao chép toàn bộ bản vẽ của mình hoặc chỉ một phần của hình mờ đó vào bảng nhớ tạm, có thể thêm hình mờ nếu muốn, sau đó dán vào một ứng dụng khác. Nhân tiện, đây là phiên bản web của ứng dụng Windows 95 Paint.

Cách thức hoạt động của tính năng này đơn giản đến mức đáng ngạc nhiên. Tất cả những gì tôi cần là canvas dưới dạng một blob, sau đó tôi viết vào bảng nhớ tạm bằng cách truyền mảng một phần tử có ClipboardItem cùng với blob vào bảng nhớ tạm navigator.clipboard.write(). Để biết thêm thông tin về những việc bạn có thể làm với bảng nhớ tạm API, Xem bài viết của Jason và bài viết của tôi.

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);
    }
  });
};

Cộng tác với những người khác

Chia sẻ URL phiên

Bạn có biết rằng Excalidraw cũng có chế độ cộng tác không? Những người khác nhau có thể làm việc cùng nhau trên cùng một tài liệu. Để bắt đầu một phiên mới, tôi nhấp vào nút cộng tác trực tiếp rồi bắt đầu phiên hoạt động. Tôi có thể dễ dàng chia sẻ URL của phiên họp với cộng tác viên nhờ API Chia sẻ web mà Excalidraw đã tích hợp.

Cộng tác trực tiếp

Tôi đã mô phỏng một phiên cộng tác trên thiết bị bằng cách chỉnh sửa biểu trưng Google I/O trên Pixelbook của mình, điện thoại Pixel 3a và iPad Pro. Bạn có thể thấy những thay đổi mà tôi thực hiện trên một thiết bị được phản ánh trên tất cả các thiết bị khác.

Thậm chí, tôi còn có thể nhìn thấy tất cả các con trỏ di chuyển xung quanh. Con trỏ của Pixelbook di chuyển ổn định vì nó được điều khiển bằng bàn di chuột, nhưng con trỏ của điện thoại Pixel 3a và con trỏ của máy tính bảng iPad Pro có thể nhảy xung quanh, vì tôi điều khiển các thiết bị này bằng cách nhấn bằng ngón tay của tôi.

Xem trạng thái cộng tác viên

Để cải thiện trải nghiệm cộng tác theo thời gian thực, thậm chí còn có hệ thống phát hiện trạng thái rảnh. Con trỏ của iPad Pro hiển thị một chấm màu xanh lục khi tôi sử dụng. Chấm này chuyển sang màu đen khi tôi chuyển sang thẻ trình duyệt hoặc ứng dụng khác. Khi tôi đang ở trong ứng dụng Excalidraw, nhưng không làm gì cả, con trỏ hiển thị trạng thái rảnh, được biểu tượng bằng ba zZZ.

Những độc giả đam mê ấn phẩm của chúng tôi có thể có xu hướng nghĩ rằng phát hiện nhàn rỗi được thực hiện thông qua API Phát hiện trạng thái không hoạt động, một đề xuất giai đoạn đầu đã được thực hiện trong trong bối cảnh của Project Fugu. Cảnh báo tiết lộ nội dung: không phải. Mặc dù chúng tôi đã triển khai dựa trên API này trong Excalidraw, cuối cùng, chúng tôi đã quyết định chuyển sang một phương pháp truyền thống hơn dựa trên việc đo lường di chuyển con trỏ và chế độ hiển thị trang.

Ảnh chụp màn hình nội dung phản hồi về tính năng Phát hiện trạng thái không hoạt động được gửi trong kho lưu trữ Phát hiện trạng thái rảnh của WICG.

Chúng tôi đã gửi ý kiến phản hồi về lý do API Phát hiện trạng thái không hoạt động không giải quyết được trường hợp sử dụng của chúng ta. Tất cả các API của Project Fugu đều đang được phát triển công khai, vì vậy mọi người đều có thể tham gia và lên tiếng!

Lipis trên thứ đang ngăn cản Excalidraw

Nhân dịp này, tôi hỏi lipi một câu hỏi cuối cùng về những gì anh ấy cho là bị thiếu trên web nền tảng giữ lại Excalidraw:

API Truy cập hệ thống tệp rất hữu ích, nhưng bạn có biết không? Hầu hết các tệp mà tôi quan tâm hiện nay có trong Dropbox hoặc Google Drive của tôi chứ không phải trên đĩa cứng. Tôi muốn API Truy cập hệ thống tệp thêm một tầng trừu tượng để các nhà cung cấp hệ thống tệp từ xa như Dropbox hoặc Google có thể tích hợp và nhà phát triển có thể lập trình. Sau đó, người dùng có thể thư giãn và biết rằng tệp của họ an toàn với nhà cung cấp dịch vụ đám mây mà họ tin tưởng.

Tôi hoàn toàn đồng ý với lipis, tôi cũng sống trên đám mây. Chúng tôi hy vọng rằng điều này sẽ được triển khai sắp tới.

Chế độ ứng dụng dạng thẻ

Rất ấn tượng! Chúng tôi đã thấy rất nhiều tính năng tích hợp API thực sự tuyệt vời trong Excalidraw. Hệ thống tệp, xử lý tệp, clipboard, chia sẻ trên webmục tiêu lượt chia sẻ trên web. Nhưng đây là một điều nữa. Từ trước đến nay, tôi chỉ có thể chỉnh sửa một tài liệu vào một thời điểm nhất định. Không còn nữa. Hãy thưởng thức phiên bản ban đầu của chế độ ứng dụng dạng thẻ trong Excalidraw. Giao diện sẽ như sau.

Tôi có một tệp hiện có đang mở trong PWA Excalidraw đã cài đặt và đang chạy ở chế độ độc lập. Bây giờ Tôi mở một thẻ mới trong cửa sổ độc lập. Đây không phải là thẻ trình duyệt thông thường mà là thẻ PWA. Trong phần này thẻ mới, sau đó tôi có thể mở tệp phụ và thao tác trên các tệp đó một cách độc lập từ cùng một cửa sổ ứng dụng.

Chế độ ứng dụng dạng thẻ đang ở giai đoạn đầu và không phải mọi thứ được thiết lập cố định. Nếu bạn quan tâm, hãy nhớ đọc trạng thái hiện tại của tính năng này trong bài viết của tôi.

Closing (Đang đóng)

Để được cập nhật về tính năng này và các tính năng khác, hãy nhớ xem Trình theo dõi API Fuugu. Chúng tôi rất vui mừng được thúc đẩy web phát triển và giúp bạn làm được nhiều việc hơn trên nền tảng. Hướng đến một Excalidraw không ngừng cải tiến và đây là tất cả mà bạn sẽ tạo ra. Hãy bắt đầu sáng tạo tại excalidraw.com.

Tôi rất mong được thấy một số API mà tôi hiển thị hôm nay xuất hiện trong ứng dụng của bạn. Tôi là Tom, bạn có thể tìm thấy tôi bằng tên @tomayac trên Twitter và trên Internet nói chung. Cảm ơn bạn rất nhiều vì đã xem và tận hưởng phần còn lại của Google I/O.