Skip to content

Commit

Permalink
Partial grid resize mixed with absolute resize (#6546)
Browse files Browse the repository at this point in the history
**Problem:**

When a grid child is stretching on a single direction it should be
possible to cell-resize it along that direction, while element-resize it
in the other direction. The diagonal resize controls should be disabled
in that case.

**Fix:**

Do that.


https://github.com/user-attachments/assets/e53be7c8-08fc-4ffe-8248-d147e01981f9

Fixes #6544
  • Loading branch information
ruggi authored Oct 16, 2024
1 parent 2f54a78 commit 03f7675
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
isInfinityRectangle,
rectangleIntersection,
} from '../../../../core/shared/math-utils'
import { isFillOrStretchModeApplied } from '../../../inspector/inspector-common'
import { isFillOrStretchModeAppliedOnAnySide } from '../../../inspector/inspector-common'
import {
controlsForGridPlaceholders,
gridEdgeToEdgePosition,
Expand Down Expand Up @@ -49,7 +49,7 @@ export const gridResizeElementStrategy: CanvasStrategyFactory = (
return null
}

if (!isFillOrStretchModeApplied(canvasState.startingMetadata, selectedElement)) {
if (!isFillOrStretchModeAppliedOnAnySide(canvasState.startingMetadata, selectedElement)) {
return null
}

Expand Down
41 changes: 37 additions & 4 deletions editor/src/components/canvas/controls/grid-controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ import {
import { useMaybeHighlightElement } from './select-mode/select-mode-hooks'
import { useResizeEdges } from './select-mode/use-resize-edges'
import { getGridHelperStyleMatchingTargetGrid } from './grid-controls-helpers'
import { isFillOrStretchModeAppliedOnSpecificSide } from '../../inspector/inspector-common'

const CELL_ANIMATION_DURATION = 0.15 // seconds

Expand Down Expand Up @@ -1586,6 +1587,28 @@ export const GridResizeControlsComponent = ({ target }: GridResizeControlProps)
},
})

const resizeDirection = useEditorState(
Substores.metadata,
(store) => {
if (element == null) {
return { horizontal: false, vertical: false }
}
return {
horizontal: isFillOrStretchModeAppliedOnSpecificSide(
store.editor.jsxMetadata,
element.elementPath,
'horizontal',
),
vertical: isFillOrStretchModeAppliedOnSpecificSide(
store.editor.jsxMetadata,
element.elementPath,
'vertical',
),
}
},
'GridResizeControlsComponent resizeDirection',
)

if (
element == null ||
element.globalFrame == null ||
Expand Down Expand Up @@ -1618,10 +1641,20 @@ export const GridResizeControlsComponent = ({ target }: GridResizeControlProps)
pointerEvents: 'none',
}}
>
{resizeEdges.top}
{resizeEdges.left}
{resizeEdges.bottom}
{resizeEdges.right}
{when(
resizeDirection.vertical,
<React.Fragment>
{resizeEdges.top}
{resizeEdges.bottom}
</React.Fragment>,
)}
{when(
resizeDirection.horizontal,
<React.Fragment>
{resizeEdges.left}
{resizeEdges.right}
</React.Fragment>,
)}
</div>
</div>
</CanvasOffsetWrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import type { FixedHugFill } from '../../../inspector/inspector-common'
import {
detectFillHugFixedState,
invert,
isFillOrStretchModeAppliedOnAnySide,
isFillOrStretchModeAppliedOnSpecificSide,
resizeToFitCommands,
} from '../../../inspector/inspector-common'
import { setPropHugStrategies } from '../../../inspector/inspector-strategies/inspector-strategies'
Expand Down Expand Up @@ -135,6 +137,38 @@ export const AbsoluteResizeControl = controlForStrategyMemoized(
onEdgeDoubleClick,
})

const canResize = useEditorState(
Substores.metadata,
(store) => {
const metadata = store.editor.jsxMetadata

let horizontally = true
let vertically = true
let diagonally = true

for (const element of selectedElementsRef.current) {
if (MetadataUtils.isGridCell(metadata, element)) {
if (isFillOrStretchModeAppliedOnAnySide(metadata, element)) {
diagonally = false
}
if (isFillOrStretchModeAppliedOnSpecificSide(metadata, element, 'horizontal')) {
horizontally = false
}
if (isFillOrStretchModeAppliedOnSpecificSide(metadata, element, 'vertical')) {
vertically = false
}
}
}

return {
horizontally: horizontally,
vertically: vertically,
diagonally: diagonally,
}
},
'AbsoluteResizeControl canResize',
)

return (
<CanvasOffsetWrapper>
<div
Expand All @@ -145,22 +179,45 @@ export const AbsoluteResizeControl = controlForStrategyMemoized(
pointerEvents: 'none',
}}
>
{resizeEdges.top}
{resizeEdges.left}
{resizeEdges.bottom}
{resizeEdges.right}
<ResizePoint ref={topLeftRef} position={{ x: 0, y: 0 }} cursor={CSSCursor.ResizeNWSE} />
<ResizePoint ref={topRightRef} position={{ x: 1, y: 0 }} cursor={CSSCursor.ResizeNESW} />
<ResizePoint
ref={bottomLeftRef}
position={{ x: 0, y: 1 }}
cursor={CSSCursor.ResizeNESW}
/>
<ResizePoint
ref={bottomRightRef}
position={{ x: 1, y: 1 }}
cursor={CSSCursor.ResizeNWSE}
/>
{when(
canResize.vertically,
<React.Fragment>
{resizeEdges.top}
{resizeEdges.bottom}
</React.Fragment>,
)}
{when(
canResize.horizontally,
<React.Fragment>
{resizeEdges.left}
{resizeEdges.right}
</React.Fragment>,
)}
{when(
canResize.diagonally,
<React.Fragment>
<ResizePoint
ref={topLeftRef}
position={{ x: 0, y: 0 }}
cursor={CSSCursor.ResizeNWSE}
/>
<ResizePoint
ref={topRightRef}
position={{ x: 1, y: 0 }}
cursor={CSSCursor.ResizeNESW}
/>
<ResizePoint
ref={bottomLeftRef}
position={{ x: 0, y: 1 }}
cursor={CSSCursor.ResizeNESW}
/>
<ResizePoint
ref={bottomRightRef}
position={{ x: 1, y: 1 }}
cursor={CSSCursor.ResizeNWSE}
/>
</React.Fragment>,
)}
<SizeLabel ref={resizeRef} targets={targets} pathsWereReplaced={pathsWereReplaced} />
</div>
</CanvasOffsetWrapper>
Expand Down
21 changes: 21 additions & 0 deletions editor/src/components/inspector/inspector-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,27 @@ export function isFillOrStretchModeApplied(
)
}

export function isFillOrStretchModeAppliedOnAnySide(
metadata: ElementInstanceMetadataMap,
element: ElementPath,
): boolean {
return (
isFixedHugFillModeAppliedOnAnySide(metadata, element, 'fill') ||
isFixedHugFillModeAppliedOnAnySide(metadata, element, 'stretch')
)
}

export function isFillOrStretchModeAppliedOnSpecificSide(
metadata: ElementInstanceMetadataMap,
element: ElementPath,
side: 'horizontal' | 'vertical',
): boolean {
return (
detectFillHugFixedState(side, metadata, element).fixedHugFill?.type === 'fill' ||
detectFillHugFixedState(side, metadata, element).fixedHugFill?.type === 'stretch'
)
}

export function isFixedHugFillModeAppliedOnAnySide(
metadata: ElementInstanceMetadataMap,
element: ElementPath,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,30 +64,33 @@ Array [
"/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))",
"/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))",
"/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))",
"/Symbol(react.memo)()///UtopiaSpiedExoticType(Symbol(react.fragment))",
"/Symbol(react.memo)()///UtopiaSpiedExoticType(Symbol(react.fragment))",
"/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))",
"/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))",
"/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))",
"/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))",
"/Symbol(react.memo)()///UtopiaSpiedExoticType(Symbol(react.fragment))",
"/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(SizeLabel))",
"/Symbol(react.memo)()///div:data-testid='utopia-storyboard-uid/scene-aaa/app-entity:parent/ccc-absolute-resize-control'",
"/Symbol(react.memo)()///Symbol(react.memo)()",
"////div",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))/Symbol(react.forward_ref)(ResizeEdge)/div:data-testid='resize-control-0.5-0'",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))/Symbol(react.forward_ref)(ResizeEdge)/div:data-testid='resize-control-0-0.5'",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))/Symbol(react.forward_ref)(ResizeEdge)/div:data-testid='resize-control-0.5-1'",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))/Symbol(react.forward_ref)(ResizeEdge)/div:data-testid='resize-control-1-0.5'",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div:data-testid='resize-control-0-0'",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div:data-testid='resize-control-1-0'",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div:data-testid='resize-control-0-1'",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div:data-testid='resize-control-1-1'",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))/Symbol(react.forward_ref)(ResizeEdge)/div:data-testid='resize-control-0.5-0'",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))/Symbol(react.forward_ref)(ResizeEdge)/div:data-testid='resize-control-0.5-1'",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))/Symbol(react.forward_ref)(ResizeEdge)/div:data-testid='resize-control-0-0.5'",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))/Symbol(react.forward_ref)(ResizeEdge)/div:data-testid='resize-control-1-0.5'",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div:data-testid='resize-control-0-0'",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div:data-testid='resize-control-1-0'",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div:data-testid='resize-control-0-1'",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div:data-testid='resize-control-1-1'",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(SizeLabel))/Symbol(react.forward_ref)(SizeLabel)/div:data-testid='SizeLabelTestId'",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(SizeLabel))/Symbol(react.forward_ref)(SizeLabel)/div:data-testid='parent-resize-label'",
"/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div",
Expand Down Expand Up @@ -848,30 +851,33 @@ Array [
"/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))",
"/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))",
"/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))",
"/Symbol(react.memo)()///UtopiaSpiedExoticType(Symbol(react.fragment))",
"/Symbol(react.memo)()///UtopiaSpiedExoticType(Symbol(react.fragment))",
"/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))",
"/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))",
"/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))",
"/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))",
"/Symbol(react.memo)()///UtopiaSpiedExoticType(Symbol(react.fragment))",
"/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(SizeLabel))",
"/Symbol(react.memo)()///div:data-testid='utopia-storyboard-uid/scene-aaa/app-entity:parent/ccc-absolute-resize-control'",
"/Symbol(react.memo)()///Symbol(react.memo)()",
"////div",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))/Symbol(react.forward_ref)(ResizeEdge)/div:data-testid='resize-control-0.5-0'",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))/Symbol(react.forward_ref)(ResizeEdge)/div:data-testid='resize-control-0-0.5'",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))/Symbol(react.forward_ref)(ResizeEdge)/div:data-testid='resize-control-0.5-1'",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))/Symbol(react.forward_ref)(ResizeEdge)/div:data-testid='resize-control-1-0.5'",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div:data-testid='resize-control-0-0'",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div:data-testid='resize-control-1-0'",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div:data-testid='resize-control-0-1'",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div:data-testid='resize-control-1-1'",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))/Symbol(react.forward_ref)(ResizeEdge)/div:data-testid='resize-control-0.5-0'",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))/Symbol(react.forward_ref)(ResizeEdge)/div:data-testid='resize-control-0.5-1'",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))/Symbol(react.forward_ref)(ResizeEdge)/div:data-testid='resize-control-0-0.5'",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))/Symbol(react.forward_ref)(ResizeEdge)/div:data-testid='resize-control-1-0.5'",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div:data-testid='resize-control-0-0'",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div:data-testid='resize-control-1-0'",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div:data-testid='resize-control-0-1'",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div:data-testid='resize-control-1-1'",
"/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(SizeLabel))/Symbol(react.forward_ref)(SizeLabel)/div:data-testid='SizeLabelTestId'",
"/div/Symbol(react.memo)(Symbol(react.forward_ref)(SizeLabel))/Symbol(react.forward_ref)(SizeLabel)/div:data-testid='parent-resize-label'",
"/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div",
Expand Down
Loading

0 comments on commit 03f7675

Please sign in to comment.