Alright, so what we have to do now is fix this little bug that we have. So the bug seems to happen. It looks like any corner I grab, it translates to me grabbing the lower right corner. So no matter where I start I end up there, right? So I compared with my source code and I forgot that end-to-end operator and a bitwise operator are not the same thing.
So what I intended to use here but completely forgot about the importance of is that we're going to use the bitwise operator here. So change all of your double and end quotes here and replace them with a bitwise comparison. And now Let's go ahead and check this out. So if I go ahead and expand, there we go. I can expand in this corner.
If I go ahead top, I can expand top and bottom. Right corner, same thing. Right here, lower right, bottom, lower left, left, and corner left. All working perfectly fine. So that's all that was the mistake.
So inside of my resize bounds right here which is inside of our utils folder. I use the and and operator instead of the bitwise operator. Great! So what we're gonna do next is the ability to translate a layer. So Right now if I try and drag this nothing is happening.
So I can select it, I can resize it and I can kind of move it in that way, right? But I would like to move it by pressing down and dragging it. So let's go ahead inside of our app folder, board, board.id, components, canvas right here. And in here where we have the layer preview we pass in the onLayer pointer down and in here we already set the canvas state to translating which means that we have that logic finished. Remember in our previous module we had to kind of initiate the resizing logic which we did on this on pointer down here so when we click here this switched to resizing mode.
So now when I click here this switches to translating mode. So all we have to do is modify the on pointer move if we are translating. So let's find our onPointerMove method. It should be somewhere up here. There we go.
So we have the case for resizing and now we have the other case for translating. So we are going to prioritize translating over resizing. So let's go ahead and write if canvasState.mode is equal to canvasMode.translating and then we're going to go ahead and open this and we're going to map this with else if like that and then inside of here let's go ahead and have a console.log translating like this just so we confirm that this is actually happening so inside of my terminal here if I move this there we go I am translating but if I move it like this it's not firing that event only if I move it strictly on this layer. Great! Now we have to create a method called translate selected layers So let's go ahead and develop that method.
I'm gonna develop it right here where we have resizeSelectedLayer. So let's do const translateSelectedLayers because this is gonna be able to handle multiple layers later when we add a selection net. It's going to be use mutation as always. And let's go ahead and prepare this like that. And now I want to destructure from the first argument the storage and self.
And from the second argument the point, which is a type of point from my type's canvas import. And now in here I'm gonna check if canvas state that mode is anything other than canvas mode dot translating in that case we can just break this function And now let's create an offset object. So there's not going to be any complicated calculation for this one. So what we have to do is add an x coordinate to be point.x minus canvas state.current.x and then we're going to have Y to be point.Y minus canvas state.current.Y and then let's get all of our live layers with storage.getLayers and now let's go ahead and do for const id of self.presence.selection const individual layer which we are selecting in the presence is going to be LiveLayers.getId and if we can get that layer we are going to update its position using the X coordinate layer.getX plus offset.x and y layer.getY plus offset.y like that and then outside of this for const, we are simply going to do set state, set canvas state, mode canvas mode dot translating and current is going to be the point from our event. And now let's go ahead and add the dependencies here which are going to be the canvas state.
Like that. Perfect. So now we have this. And now we can use this. So let's use the translate selected layers down here in our pointer move.
Where is it? OnPointerMove. So in here we're simply gonna call TranslateSelectedLayers and pass in current as the option and we also need to add this to our dependency array now like this. So let's try it out if this is working and there we go as you can see I can now move my layers around. Perfect.
One thing that seems to be missing besides well the obvious fact that we are not controlling which layer is above another right is that I kind of cannot deselect this so when I click outside this should be deselected but it looks like no matter what I do unless I click on something else this will always stay selected so now I want to make sure that I can create the deselect option. So first let's go back inside of the canvas and let's add onPointerDown method. So I'm gonna go ahead and do this. Right above onPointerUp. So let's do const onPointerDown to be useCallback.
So not useMemo, useCallback. Sorry, not useMutation, useCallback. And it's going to work with the event which is a type of react dot pointer event and in here we're gonna get the point using pointer event to canvas point method which we already have here we're gonna pass the event and the camera and then we're gonna check if canvas state that mode is canvas mode inserting in that case we can break this method because obviously we don't want to prevent them from inserting something. And then we're gonna add a little comment here to do addCaseForDrawing. And for now, what we're gonna do is just to use set canvas state and do origin to be the point and mode to be canvas mode pressing like this and let's go ahead now and add the camera let's add the canvas state.mode set state and start drawing actually start drawing is what we're gonna have later so we don't have that yet and we need set canvas state here like that great so we have on pointer down let's append on pointer down right here in the SVG element on pointer down is going to be on pointer down like this.
And now I want to go ahead back inside of my on pointer up method right here. And currently the only thing we do is we handle the inserting case here. So let's go ahead and modify this a bit by checking if canvasState.mode is in canvasMode.none or if... Whoops where was I? Okay on pointer up so we are adding another if clause so if canvas state mode is canvas mode none or if canvas state mode is canvas mode dot pressing in that case we're gonna go ahead and set state set canvasState to be mode canvasMode.none again so this will kind of unselect our layers and then we're gonna add this to be in the else clause.
So else if and that's important because we want this to overrule anything else and this is not enough by itself so for Now what we can do is we can simply add a console log here, unselect, and we can try it out. So if I go ahead here now and let's say I select something here and then if I click outside, there we go. You can see how unselect is being fired, right? Because we have a case that now handles that. And now using this onSelect event and you can see how it doesn't fire if you select on a specific element.
It only fires if you click outside of anything, on something that's not a layer. So now we're going to leverage that unselect event to deselect all of our layers. So let's create a method called unselectLayers and we can add that somewhere where we work with layers on wheel on resize handle pointer and okay here it is resize selected layer so let's add const unselect layers here to be used mutation. Let me just prepare this method here. And in here, I'm going to extract self and set my presence here.
And that is it. All I'm gonna do inside is going to be if selfPresenceSelectionLength is more than 0. So if we selected something in that case we're going to reset my presence by adding selection to be an empty array and we're also gonna do add to history true like this And then let's go ahead and let's actually use this in the onPointerUp method which we just added this console.log So in here we're now gonna add unselect layers like this and also let's go ahead and let's add that to our dependency array here. So let's try that out now. So if I go here and if I click outside, there we go.
My layers are now successfully getting unselected when I click outside. Perfect. So we can now move, we can resize. This is already starting to look like something, right? What we have to do next is we have to create an additional toolbar here which will open up when I select which will allow me to change the color of the element I'm selecting and also to change the layer depth, right?
So for example if I want to hide that, if I want to hide this white element behind this black element I'm going to do that using that toolbar. But we made so much progress already and the great thing about all of this is that we only have to write all of this logic once and then we just have to simply add new elements inside of our layer preview component. So don't worry it's not like we're gonna have to do some huge amount of work for these elements the only one that's a little bit complex is the pen but again we finished majority of work already and also yeah if you try all of your undo's should be working so both selecting and redoing all of that should be working. Nevertheless, great great job!