-
Notifications
You must be signed in to change notification settings - Fork 15
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
) | ||
Array.from(nodesMap.values()) | ||
.sort((a: Node & { level }, b: Node & { level }) => a.level - b.level) | ||
.map((node) => ({ ...node, selected: getPod(node.id)?.selected })) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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"} |
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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)
Also, we need to highlight all selected nodes to give users visual feedback, e.g, in codepod/ui/src/components/Canvas.tsx Lines 405 to 409 in d9c7ccb
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. |
@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
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. |
Separate the pod
selected
states for each user, stop synchronizing all node data by remote YMap. Maintainpod[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:
onNodeDragStop
if I have time, as it looks complicated.