From 0c140fb00e73c745a68e32f1c68423589fc3d75d Mon Sep 17 00:00:00 2001
From: Sean Parsons <217400+seanparsons@users.noreply.github.com>
Date: Wed, 4 Oct 2023 14:43:10 +0100
Subject: [PATCH] feature(groups) Convert group child percentage pins to pixel
based pins. (#4314)
- Added `whenReplacingPercentageValues` property to `SetCssLengthProperty`.
- `runSetCssLengthProperty` now adds an appropriate toast when
replacing a percentage based property and when it is instructed to
warn in this particular case.
- `setElementPins` now replaces the children's pin values with pixel based ones
in all cases regardless of what was there before.
- `runPushIntendedBoundsAndUpdateGroups` ensures that any toasts are carried
forward in the editor state patch.
- The patching part of `runShowToastCommand` has been extracted into a utility
function `addToastPatch`.
---
.../strategies/groups.spec.browser2.tsx | 14 +++-
...ard-absolute-move-resize.spec.browser2.tsx | 4 +-
...tended-bounds-and-update-groups-command.ts | 31 +++++---
.../canvas/commands/set-css-length-command.ts | 35 ++++++++-
.../canvas/commands/show-toast-command.ts | 13 +++-
.../editor/shortcuts.spec.browser2.tsx | 76 +++++++++++++++++++
6 files changed, 153 insertions(+), 20 deletions(-)
diff --git a/editor/src/components/canvas/canvas-strategies/strategies/groups.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/groups.spec.browser2.tsx
index eb60781446c7..27200ab719ea 100644
--- a/editor/src/components/canvas/canvas-strategies/strategies/groups.spec.browser2.tsx
+++ b/editor/src/components/canvas/canvas-strategies/strategies/groups.spec.browser2.tsx
@@ -32,6 +32,7 @@ import { resizeElement } from './absolute-resize.test-utils'
import { changeInspectorNumberControl } from '../../../inspector/common/inspector.test-utils'
import { ParentOutlinesTestIdSuffix } from '../../controls/parent-outlines'
import { ParentBoundsTestIdSuffix } from '../../controls/parent-bounds'
+import { safeIndex } from '../../../../core/shared/array-utils'
const GroupPath = `${BakedInStoryboardUID}/${TestSceneUID}/${TestAppUID}:root-div/group`
@@ -2156,6 +2157,11 @@ describe('Groups behaviors', () => {
await selectComponentsForTest(editor, [fromString(GroupPath)])
await resizeElement(editor, { x: 100, y: 50 }, EdgePositionBottomRight, emptyModifiers)
+ const toasts = editor.getEditorState().editor.toasts
+ expect(toasts).toHaveLength(1)
+ const firstToast = safeIndex(toasts, 0)
+ expect(firstToast?.id).toEqual('percentage-pin-replaced')
+
expect(groupDiv.style.width).toBe('300px')
expect(groupDiv.style.height).toBe('300px')
@@ -2178,8 +2184,8 @@ describe('Groups behaviors', () => {
assertStylePropsSet(editor, `${GroupPath}/child-2`, {
left: 150,
top: 120,
- width: '50%',
- height: '60%',
+ width: 150,
+ height: 180,
right: undefined,
bottom: undefined,
})
@@ -2212,8 +2218,8 @@ describe('Groups behaviors', () => {
assertStylePropsSet(editor, `${GroupPath}/child-2`, {
left: 175,
top: 140,
- width: '50%',
- height: '60%',
+ width: 175,
+ height: 210,
right: undefined,
bottom: undefined,
})
diff --git a/editor/src/components/canvas/canvas-strategies/strategies/keyboard-absolute-move-resize.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/keyboard-absolute-move-resize.spec.browser2.tsx
index f47972be72f9..383d8d60170e 100644
--- a/editor/src/components/canvas/canvas-strategies/strategies/keyboard-absolute-move-resize.spec.browser2.tsx
+++ b/editor/src/components/canvas/canvas-strategies/strategies/keyboard-absolute-move-resize.spec.browser2.tsx
@@ -265,7 +265,7 @@ describe('Keyboard Absolute Resize E2E', () => {
})
})
- it('keeps trueuing up groups as directions change', async () => {
+ it('keeps trueing up groups as directions change', async () => {
const renderResult = await renderTestEditorWithCode(
formatTestProjectCode(
makeTestProjectCodeWithSnippet(`
@@ -349,7 +349,7 @@ describe('Keyboard Absolute Resize E2E', () => {
>
= (
let propsToUpdate: Array
= []
+ let percentageValueWasReplaced: boolean = false
+
const parsePercentResult = parseCSSPercent(simpleValueResult.value)
if (
isRight(parsePercentResult) &&
@@ -146,6 +153,13 @@ export const runSetCssLengthProperty: CommandFunction = (
? command.value.value
: cssPixelLength(command.value.valuePx)
+ if (
+ command.whenReplacingPercentageValues === 'warn-about-replacement' &&
+ isRight(parsePercentResult)
+ ) {
+ percentageValueWasReplaced = true
+ }
+
const printedValue = printCSSNumberOrKeyword(newCssValue, 'px')
propsToUpdate.push({
@@ -161,8 +175,25 @@ export const runSetCssLengthProperty: CommandFunction = (
propsToUpdate,
)
+ // Always include the property update patch, but potentially also include a warning
+ // that a percentage based property was replaced with a pixel based one.
+ let editorStatePatches: Array = [propertyUpdatePatch]
+ if (percentageValueWasReplaced) {
+ editorStatePatches.push(
+ addToastPatch(
+ editorStateWithPropsDeleted.toasts,
+ notice(
+ 'One or more percentage based style properties were replaced with a pixel based one.',
+ 'INFO',
+ false,
+ 'percentage-pin-replaced',
+ ),
+ ),
+ )
+ }
+
return {
- editorStatePatches: [propertyUpdatePatch],
+ editorStatePatches: editorStatePatches,
commandDescription: `Set Css Length Prop: ${EP.toUid(command.target)}/${PP.toString(
command.property,
)} by ${
diff --git a/editor/src/components/canvas/commands/show-toast-command.ts b/editor/src/components/canvas/commands/show-toast-command.ts
index 21e1e81c897e..004b79a6b8bb 100644
--- a/editor/src/components/canvas/commands/show-toast-command.ts
+++ b/editor/src/components/canvas/commands/show-toast-command.ts
@@ -1,6 +1,6 @@
import type { Notice, NoticeLevel } from '../../common/notice'
import { notice } from '../../common/notice'
-import type { EditorState } from '../../editor/store/editor-state'
+import type { EditorState, EditorStatePatch } from '../../editor/store/editor-state'
import type { InteractionLifecycle } from '../canvas-strategies/canvas-strategy-types'
import type { CommandFunctionResult, WhenToRun } from './commands'
@@ -22,6 +22,14 @@ export function showToastCommand(
}
}
+export function addToastPatch(
+ currentToasts: ReadonlyArray,
+ noticeToAdd: Notice,
+): EditorStatePatch {
+ const updatedToasts = [...currentToasts.filter((t) => t.id !== noticeToAdd.id), noticeToAdd]
+ return { toasts: { $set: updatedToasts } }
+}
+
export function runShowToastCommand(
editorState: EditorState,
command: ShowToastCommand,
@@ -34,9 +42,8 @@ export function runShowToastCommand(
}
}
- const toasts = [...editorState.toasts.filter((t) => t.id !== command.notice.id), command.notice]
return {
commandDescription: 'Show a toast',
- editorStatePatches: [{ toasts: { $set: toasts } }],
+ editorStatePatches: [addToastPatch(editorState.toasts, command.notice)],
}
}
diff --git a/editor/src/components/editor/shortcuts.spec.browser2.tsx b/editor/src/components/editor/shortcuts.spec.browser2.tsx
index 683ccc50dc1d..dc9190d9954f 100644
--- a/editor/src/components/editor/shortcuts.spec.browser2.tsx
+++ b/editor/src/components/editor/shortcuts.spec.browser2.tsx
@@ -1,3 +1,4 @@
+import { safeIndex } from '../../core/shared/array-utils'
import { BakedInStoryboardUID, BakedInStoryboardVariableName } from '../../core/model/scene-utils'
import * as EP from '../../core/shared/element-path'
import type { CanvasRectangle } from '../../core/shared/math-utils'
@@ -1263,6 +1264,81 @@ describe('group selection', () => {
)
})
+ it('wraps selected elements with percentage dimensions in a Group', async () => {
+ const renderResult = await renderTestEditorWithCode(
+ makeTestProjectCodeWithSnippet(
+ ``,
+ ),
+ 'await-first-dom-report',
+ )
+
+ await selectComponentsForTest(renderResult, [
+ EP.fromString(`${BakedInStoryboardUID}/${TestSceneUID}/${TestAppUID}:container/aaa`),
+ EP.fromString(`${BakedInStoryboardUID}/${TestSceneUID}/${TestAppUID}:container/bbb`),
+ ])
+
+ await expectSingleUndo2Saves(renderResult, async () =>
+ pressKey('g', { modifiers: cmdModifier }),
+ )
+
+ const toasts = renderResult.getEditorState().editor.toasts
+ expect(toasts).toHaveLength(1)
+ const firstToast = safeIndex(toasts, 0)
+ expect(firstToast?.id).toEqual('percentage-pin-replaced')
+
+ expect(getPrintedUiJsCodeWithoutUIDs(renderResult.getEditorState())).toEqual(
+ makeTestProjectCodeWithSnippetWithoutUIDs(
+ ``,
+ ),
+ )
+ })
+
it('if Group is not imported, it is added to the imports after the Group has been inserted', async () => {
const editor = await renderTestEditorWithCode(
`import { Scene, Storyboard } from 'utopia-api'