utopia
utopia copied to clipboard
Click to insert as a strategy
Problem: Click to insert was broken after draw to insert was introduced as a strategy. Furthermore, click to insert always inserted with absolute positioning, even into a flex container.
Fix: Extend the draw-to-insert strategy so it can insert with clicking too.
We can detect that a "drag" is a "click" when the drag is null in the interaction, and the interaction is just finished (so a mouse up has happened without move)
To make this possible, we need to know in the apply
function if it is running when interaction is finished or earlier. To achieve this I added a lifecycle
parameter to the apply
function, and I fill that in in dispatch-strategies
.
This is very similar to the command lifecycle, but not the same. This lifecycle can make it possible to emit different commands from the strategy in the different lifecycle phases.
Theoretically we could remove lifecycle management from commands, and always only emit the commands which are relevant in that lifecycle.
E.g. instead of
return strategyApplicationResult([
...commandsForSelectedElements.commands,
pushIntendedBounds(commandsForSelectedElements.intendedBounds),
updateHighlightedViews('mid-interaction', []),
setElementsToRerenderCommand(selectedElements),
setCursorCommand('mid-interaction', CSSCursor.Select),
])
we could write:
const alwaysCommands = [
...commandsForSelectedElements.commands,
pushIntendedBounds(commandsForSelectedElements.intendedBounds),
setElementsToRerenderCommand(selectedElements),
setCursorCommand('mid-interaction', CSSCursor.Select),
])
return lifecycle === 'mid-interaction' ? strategyApplicationResult([
...alwaysCommands,
updateHighlightedViews([]),
]) : strategyApplicationResult(alwaysCommands)
But I believe this is just way more complicated to use, so I decided to keep lifecycle management inside commands too.
Job #2391: Bundle Size — 48.58MB (~+0.01%).
60f879b0aad51a191ea438de58fa1e810e0416f6 vs 07beb3d27037fa38270495d6ca6a23bee98d0535
Link to test editor
Performance test results:
Highlight Regular (5%)
Before: 17.1ms (16.1-63.8ms)
After: 18ms (17.3-55.4ms)
Highlight All Elements (-3%)
Selection (12%)
Before: 134.5ms (121.2-202.2ms)
After: 150.1ms (126.8-221.2ms)
De-Selection (12%)
Before: 37.3ms (34.1-59.3ms)
After: 41.8ms (35.1-61.9ms)
Selection Change (-1%)
Scroll Canvas (-5%)
Before: 3.8ms (3.5-15.9ms)
After: 3.6ms (3.5-20.1ms)
Resize (-13%)
Before: 60.5ms (55.8-129.8ms)
After: 52.9ms (50.1-129.1ms)
Absolute Move (Just Move, Large) (9%)
Before: 63.1ms (57.7-155.5ms)
After: 68.7ms (60.2-152.1ms)
Absolute Move (Just Move, Small) (9%)
Before: 14.4ms (12-49.1ms)
After: 15.7ms (13.5-23.2ms)
Absolute Move (Interaction, Large) (9%)
Before: 284.8ms (265.3-401.9ms)
After: 310.6ms (281-410.3ms)
Absolute Move (Interaction, Small) (10%)
Before: 82.9ms (74.2-147.8ms)
After: 91.2ms (81.9-142.1ms)
But I believe this is just way more complicated to use, so I decided to keep lifecycle management inside commands too.
so when I added lifecycle to commands, I started from adding lifecycle to the apply function. but then I realized the code can be much more succinct if the lifecycle is in the commands. but yeah, it is best if we expose this information to the apply function and the commands as well