Skip to content

Commit

Permalink
c'est horrible
Browse files Browse the repository at this point in the history
  • Loading branch information
bkrmendy committed Oct 18, 2024
1 parent 16660b5 commit d68fbc0
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 38 deletions.
111 changes: 105 additions & 6 deletions editor/src/components/editor/actions/action-utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ElementPath, PropertyPath } from 'utopia-shared/src/types'
import { mapDropNulls, safeIndex } from '../../../core/shared/array-utils'
import { mapDropNulls, safeIndex, uniq } from '../../../core/shared/array-utils'
import type { CanvasCommand } from '../../canvas/commands/commands'
import type { EditorAction } from '../action-types'
import { isFromVSCodeAction } from './actions-from-vscode'
Expand Down Expand Up @@ -507,10 +507,7 @@ interface ElementPathAndProp {
prop: string
}

export function getPropertiesToRemoveFromCommands(
commands: CanvasCommand[],
): PropertiesWithElementPath[] {
const deltas = propertyUpdateDeltaFromCanvasCommand(commands)
function getPropertiesToRemoveFromDeltas(deltas: PropertyUpdateDelta[]): Record<string, string[]> {
const simpleStyle = interpretPropertyUpdates(deltas)

const allRemoves: ElementPathAndProp[] = mapDropNulls(
Expand All @@ -527,8 +524,110 @@ export function getPropertiesToRemoveFromCommands(
ensureEntryExists(result, remove.elementPath, [])
result[EP.toString(remove.elementPath)].push(remove.prop)
}
return result
}

const PaddingLonghands = ['paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft']

interface PropertyPatchValues {
gap?: '0px'
paddingTop?: '0px'
paddingRight?: '0px'
paddingBottom?: '0px'
paddingLeft?: '0px'
}

function setPropertyValue(
propertyPatchValues: PropertyPatchValues,
prop: string,
): PropertyPatchValues {
switch (prop) {
case 'gap':
propertyPatchValues.gap = '0px'
break
case 'paddingTop':
propertyPatchValues.paddingTop = '0px'
break
case 'paddingRight':
propertyPatchValues.paddingRight = '0px'
break
case 'paddingBottom':
propertyPatchValues.paddingBottom = '0px'
break
case 'paddingLeft':
propertyPatchValues.paddingLeft = '0px'
break
default:
break
}

return propertyPatchValues
}

export interface PropertiesToPatchWithDefaults {
[elementPathString: string]: PropertyPatchValues
}

function substituteShorthandProperties(
propsToSetByElement: Record<string, string[]>,
elementPathString: string,
prop: string,
): string[] {
const paddingShorthandSet = propsToSetByElement[elementPathString]?.includes('padding')

if (prop === 'padding') {
return PaddingLonghands.filter((p) => !propsToSetByElement[elementPathString]?.includes(p))
}

if (PaddingLonghands.includes(prop)) {
if (paddingShorthandSet) {
return []
}
}
return [prop]
}

export function getPropertiesToPatchFromCommands(
commands: CanvasCommand[],
): PropertiesToPatchWithDefaults {
const deltas = propertyUpdateDeltaFromCanvasCommand(commands)
const propsToRemove = getPropertiesToRemoveFromDeltas(deltas)

const propsToSetByElement: Record<string, string[]> = {}
for (const delta of deltas) {
if (delta.type === 'set') {
ensureEntryExists(propsToSetByElement, delta.element, [])
propsToSetByElement[EP.toString(delta.element)].push(delta.prop)
}
}

const withPropsSubstituted = Object.entries(propsToRemove).map(
([elementPathString, props]): [string, string[]] => [
elementPathString,
uniq(
props.flatMap((prop) =>
substituteShorthandProperties(propsToSetByElement, elementPathString, prop),
),
),
],
)

const result: PropertiesToPatchWithDefaults = {}
for (const [elementPathString, props] of withPropsSubstituted) {
ensureEntryExists(result, EP.fromString(elementPathString), {})
result[elementPathString] = props.reduce(setPropertyValue, {})
}

return result
}

export function getPropertiesToRemoveFromCommands(
commands: CanvasCommand[],
): PropertiesWithElementPath[] {
const deltas = propertyUpdateDeltaFromCanvasCommand(commands)
const propsToRemove = getPropertiesToRemoveFromDeltas(deltas)

return Object.entries(result).map(([elementPathString, props]) => ({
return Object.entries(propsToRemove).map(([elementPathString, props]) => ({
elementPath: EP.fromString(elementPathString),
properties: props.map((p) => PP.create('style', p)),
}))
Expand Down
12 changes: 8 additions & 4 deletions editor/src/components/editor/store/dispatch-strategies.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,12 @@ import type {
StartPostActionSession,
} from '../action-types'
import { SelectComponents } from '../action-types'
import type { PropertiesWithElementPath } from '../actions/action-utils'
import type {
PropertiesToPatchWithDefaults,
PropertiesWithElementPath,
} from '../actions/action-utils'
import {
getPropertiesToPatchFromCommands,
getPropertiesToRemoveFromCommands,
isClearInteractionSession,
isCreateOrUpdateInteractionSession,
Expand Down Expand Up @@ -63,10 +67,10 @@ import type { ElementPath } from 'utopia-shared/src/types'

export interface PropertiesToPatch {
type: 'properties-to-patch'
propertiesToPatch: PropertiesWithElementPath[]
propertiesToPatch: PropertiesToPatchWithDefaults
}

export const propertiesToPatch = (props: PropertiesWithElementPath[]): PropertiesToPatch => ({
export const propertiesToPatch = (props: PropertiesToPatchWithDefaults): PropertiesToPatch => ({
type: 'properties-to-patch',
propertiesToPatch: props,
})
Expand Down Expand Up @@ -704,7 +708,7 @@ function handleUpdate(
),
newStrategyState: newStrategyState,
postProcessingData: propertiesToPatch(
getPropertiesToRemoveFromCommands(strategyResult.commands),
getPropertiesToPatchFromCommands(strategyResult.commands),
),
}
} else {
Expand Down
41 changes: 13 additions & 28 deletions editor/src/components/editor/store/dispatch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { CanvasAction } from '../../canvas/canvas-types'
import type { LocalNavigatorAction } from '../../navigator/actions'
import type { EditorAction, EditorDispatch, UpdateMetadataInEditorState } from '../action-types'
import { isLoggedIn } from '../action-types'
import type { PropertiesWithElementPath } from '../actions/action-utils'
import type { PropertiesToPatchWithDefaults } from '../actions/action-utils'
import {
isTransientAction,
isUndoOrRedo,
Expand Down Expand Up @@ -68,6 +68,7 @@ import { handleStrategies, normalizationData, updatePostActionState } from './di
import type { MetaCanvasStrategy } from '../../canvas/canvas-strategies/canvas-strategies'
import { RegisteredCanvasStrategies } from '../../canvas/canvas-strategies/canvas-strategies'
import { arrayOfPathsEqual, removePathsWithDeadUIDs } from '../../../core/shared/element-path'
import * as EP from '../../../core/shared/element-path'
import { notice } from '../../../components/common/notice'
import { getUidMappings, getAllUniqueUidsFromMapping } from '../../../core/model/get-uid-mappings'
import { updateSimpleLocks } from '../../../core/shared/element-locking'
Expand Down Expand Up @@ -96,6 +97,7 @@ import { getActivePlugin } from '../../canvas/plugins/style-plugins'
import { mapDropNulls } from '../../../core/shared/array-utils'
import { propertyToSet, updateBulkProperties } from '../../canvas/commands/set-property-command'
import { foldAndApplyCommandsSimple } from '../../canvas/commands/commands'
import * as PP from '../../../core/shared/property-path'

type DispatchResultFields = {
nothingChanged: boolean
Expand Down Expand Up @@ -1124,40 +1126,23 @@ function addNormalizationDataFromActions(
)
}

const PropertyDefaultValues: Record<string, string> = {
gap: '0px',
padding: '0px',
paddingTop: '0px',
paddingRight: '0px',
paddingBottom: '0px',
paddingLeft: '0px',
}

function patchRemovedProperties(
editor: EditorState,
propertiesToPatch: PropertiesWithElementPath[],
propertiesToPatch: PropertiesToPatchWithDefaults,
): EditorState {
const propertiesToSetCommands = mapDropNulls(
({ elementPath, properties }) =>
getJSXElementFromProjectContents(elementPath, editor.projectContents) == null
([elementPathString, properties]) =>
getJSXElementFromProjectContents(EP.fromString(elementPathString), editor.projectContents) ==
null
? null
: updateBulkProperties(
'always',
elementPath,
mapDropNulls((property) => {
const [maybeStyle, maybeCSSProp] = property.propertyElements
if (maybeStyle !== 'style' || maybeCSSProp == null) {
return null
}

const defaultValue = PropertyDefaultValues[maybeCSSProp]
if (defaultValue == null) {
return null
}
return propertyToSet(property, defaultValue)
}, properties),
EP.fromString(elementPathString),
Object.entries(properties).map(([property, value]) => {
return propertyToSet(PP.create('style', property), value)
}),
),
propertiesToPatch,
Object.entries(propertiesToPatch),
)
return foldAndApplyCommandsSimple(editor, propertiesToSetCommands)
}
Expand All @@ -1167,7 +1152,7 @@ function runRemovedPropertyPatchingAndNormalization(
postProcessingData: PostProcessingData,
): EditorState {
if (postProcessingData.type === 'properties-to-patch') {
return postProcessingData.propertiesToPatch.length === 0
return Object.keys(postProcessingData.propertiesToPatch).length === 0
? editorState
: patchRemovedProperties(editorState, postProcessingData.propertiesToPatch)
}
Expand Down

0 comments on commit d68fbc0

Please sign in to comment.