V-Py / svelte-kanban

A simple kanban made with Svelte
MIT License
45 stars 9 forks source link

Refactor for CRDT-based multiuser support #60

Open dev-guy opened 10 months ago

dev-guy commented 10 months ago

Goal

Share the same Kanban board across different browsers or browser tabs, potentially to multiple users over the Internet.

Scope

This effort will clear a path for CRDT support with svelte-kanban. CRDT features will not be added to svelte-kanban because they will require additional libraries and changes to the API. It will be fairly easy to add CRDT-based multiuser support to svelte-kanban without negatively impacting the user experience, performance, API, or code quality.

CRDT support will be implemented in a fork using SyncedStore which integrates YJs and Svelte stores.

Changes Needed

  1. SyncedStore only manages non-array objects ({}). Therefore, $columns which is currently a writable( [ ] ) must be refactored as: writable( { columns: [ ] } ).
  2. Do not overwrite the $columns store with a shallow copy. CRDT supports manipulating arrays, e.g., push, pop, and assigning a value to an array index, but SyncedStore doesn't allow $columns = [...newColumns] since other users might also add a column at roughly the same time. Instead, do this: $columns = $columns at the end of addCard() etc.. This will cause Svelte reactivity to kick in without assigning a new array. This idiom also uses less CPU and memory.
  3. Calculate rectangle boundaries for cards on the fly. This information doesn't belong in a database that is shared across browsers with different geometries.
  4. Remove 'empty' cards from the $column store. An empty card looks like a dragged card's shadow where it will be placed when the mouse button is released. There should only be one empty card per Kanban board user. The current implementation allows for many empty cards, causing tricky bugs that are difficult to reproduce.

Additional Improvements

This would be a good opportunity to:

  1. Remove exports from store.js that aren't used
  2. Fix some linter warnings, such as unused imports
  3. Implement #67
  4. Fix #51
  5. Fix #74
  6. Fix #75
  7. Implement the first half of #66

Deferred

The following issues apply to multiuser scenarios. Since multiuser mode will not be enabled for this particular issue, they can be addressed later.

  1. Tracking which card is being dragged using the X,Y coordinates on the board will not work when other users can change the board at the same time. Instead, the id of the card will need to be tracked and the card will need to be located by its id. This will be addressed when #61 is implemented.
  2. The drop target column can be deleted before the user releases the mouse button. This bug will be addressed after #61.
  3. The dragged card can be deleted before the user releases the mouse button. This bug will be addressed after #61.
  4. The column from which a card is dragged can be deleted before the user releases the mouse button. This bug will be addressed after #61.
  5. Moving a column by one user immediately after another user deletes a column may result in errors
  6. Moving or dragging a card within a column immediately after another users deletes the same or different card in the target column may result in errors
  7. Updating a card (eg its title or category) immediately after another user deletes it
dev-guy commented 10 months ago

The following branch works but you need to run the following first: PORT=4444 npx y-webrtc server.js

https://github.com/good-ware/svelte-kanban/tree/synced-store

Demo

One window is Chrome and the other is Safari.

https://github.com/V-Py/svelte-kanban/assets/12297328/e4c8b0ee-6128-4c9c-b3f6-6f439610da1a

It's a little quirky.

dev-guy commented 10 months ago

Close up of a move column bug. It only happens when moving a column to the left. Notice when you move a column to the left, an extra card shows up in the new right-most column at the bottom in the other browser/tab.

https://github.com/V-Py/svelte-kanban/assets/12297328/8b39766a-7348-41f7-9c35-a8ea0ffc25e0

dev-guy commented 10 months ago

The move column bug is fixed. The fix involved using different orders depending on which direction the column is moved.

I tried the following method when moving right, which is how it works without CRDT. However, it doesn't work with CRDT: