Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Support Multi-selection in ctrl way #125

Merged
merged 1 commit into from
Dec 7, 2022

Conversation

li-xin-yi
Copy link
Collaborator

@li-xin-yi li-xin-yi commented Dec 7, 2022

Separate the pod selected states for each user, stop synchronizing all node data by remote YMap. Maintain pod[id].selected in local and apply their states every time after pulling updates from the remote yjs server.

Change the implementation to support multi-selection in a Ctrl way: keep pressing Ctrl and click on the drag handle of several pods, then you can drag or delete all of them at once, like what we do on a Windows desktop when selecting multiple files.

close #112

Known issues:

  1. A guest user cannot select any pod now. It is fine so far. I will fix it when implementing the clipboard to enable copy a bunch of pods from a read-only repo and then paste them into another repo where they are allowed to write.
  2. If you select two codeNodes and drag them into one scopeNode, only the one you drag on can be bound into the scope. I can fix it by overwriting onNodeDragStop if I have time, as it looks complicated.
  3. If you choose nodes with different levels (e.g., a codeNode and its parent Scope Node), drag or delete them, anything cloud happen, including they are moving in a mess, or crash. If you have time, please discuss the rule to group nodes and I can prohibit some unexpected selection behaviors to mitigate it.

Copy link
Collaborator

@lihebi lihebi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@lihebi lihebi merged commit d9c7ccb into codepod-io:main Dec 7, 2022
)
Array.from(nodesMap.values())
.sort((a: Node & { level }, b: Node & { level }) => a.level - b.level)
.map((node) => ({ ...node, selected: getPod(node.id)?.selected }))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the only way to un-sync the nodesMap[id].selected field from yjs? For example, is it possible to still use nodesMap[id].selected, but stop applying the sync (in either observer or useNodesStateSynced::onNodesChanges)?

Managing the field in Zustand state sounds a bit over-complicated to me. And it looks like we have to implement the de-select logic when we do this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only ground truth source is nodesMap, which is shared by all users. We have to maintain an individual selected state for each user. Actually, we have already implemented de-selection.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I got what you meant. I realized its cons just now: new selection change will not be applied if no update in the remote nodesMap, un-selecting a node by clicking on the pane is a very typical case in which no update is written into nodesMap, so it will not sync the selection change in time.

I have an idea about the possible solution: stop writing selected fields of nodes into nodesMap, keep a selectedNode set in store, observe any update both on nodesMap and selectedNode to compose the complete data of nodes. But notice nodes in reactflow is just a list not map, which may cause some performance issue.

@@ -970,6 +947,7 @@ export function Canvas() {
nodesDraggable={role !== RoleType.GUEST}
// disable node delete on backspace when the user is a guest.
deleteKeyCode={role === RoleType.GUEST ? null : "Backspace"}
multiSelectionKeyCode={"Control"}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not work on Mac, because control triggers right-click context menu. The default "Meta" works better (which is the command key).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I propose to disable option 1 and use "shift" for option 2, i.e.,

+          selectionKeyCode={null}
+          multiSelectionKeyCode={"Shift"}

Ref: #112 (comment)

@lihebi
Copy link
Collaborator

lihebi commented Dec 7, 2022

Also, we need to highlight all selected nodes to give users visual feedback, e.g, in

borderColor: pod.ispublic
? "green"
: !isPodFocused
? "#d6dee6"
: "#3182ce",

we could change to something like this:

borderColor: pod.ispublic
          ? "green"
+          : isPodFocused || pod.selected
+         ? "#3182ce"
+          : "#d6dee6",

But still, we need to implement the de-select logic.

@li-xin-yi
Copy link
Collaborator Author

@lihebi I tried some idea in this branch (main...li-xin-yi:codepod-1:fix/multi-selection-misc) to fix the de-selecting issue and enable meta hotkey for macOS users, now it shows a brozen border when selected and the same-parent rule activates, however there are still some tiny intrinsic issues:

  1. useReactflow.setNodes() doesn't work on node propriety changes, so de-selection upon focus in the editor fails.
  2. if you don't release the ctrl / meta before dragging, the same-parent rule doesn't work, I guess it is because the selection change sync after the ctrl released.

I shall take a look at those issues this afternoon and try to use some props (https://reactflow.dev/docs/api/react-flow-props/#onselectionchange-nodes-edges--onselectionchangeparams-5) to rewrite the implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Supporting selecting multiple cells and move them all at once
2 participants