Fix undo/redo for Opacity Slider + Style dropdowns. (#2933)

Closes #2664 and #2929 

### Change Type

- [x] `patch` — Bug fix

[^1]: publishes a `patch` release, for devDependencies use `internal`
[^2]: will not publish a new version

### Test Plan

1. Add a step-by-step description of how to test your PR here.
2.

- [ ] Unit Tests
- [ ] End to end tests

### Release Notes

- Fixed issues where undo/redo entries were not being set up correctly
for the opacity slider or the style dropdown menus.
This commit is contained in:
David Sheldrick 2024-02-23 14:25:36 +00:00 committed by GitHub
parent 521d84a611
commit 046ebc4ac0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 18 additions and 14 deletions

View file

@ -1214,7 +1214,7 @@ export class Editor extends EventEmitter<TLEventMap> {
if (partial.isChangingStyle === true) { if (partial.isChangingStyle === true) {
// If we've set to true, set a new reset timeout to change the value back to false after 2 seconds // If we've set to true, set a new reset timeout to change the value back to false after 2 seconds
this._isChangingStyleTimeout = setTimeout(() => { this._isChangingStyleTimeout = setTimeout(() => {
this.updateInstanceState({ isChangingStyle: false }) this.updateInstanceState({ isChangingStyle: false }, { ephemeral: true })
}, 2000) }, 2000)
} }
} }

View file

@ -1927,7 +1927,7 @@ export interface TLUiSliderProps {
// (undocumented) // (undocumented)
label: string; label: string;
// (undocumented) // (undocumented)
onValueChange: (value: number, emphemeral: boolean) => void; onValueChange: (value: number, squashing: boolean) => void;
// (undocumented) // (undocumented)
steps: number; steps: number;
// (undocumented) // (undocumented)

View file

@ -37,7 +37,7 @@ export function MobileStylePanel() {
const handleStylesOpenChange = useCallback( const handleStylesOpenChange = useCallback(
(isOpen: boolean) => { (isOpen: boolean) => {
if (!isOpen) { if (!isOpen) {
editor.updateInstanceState({ isChangingStyle: false }) editor.updateInstanceState({ isChangingStyle: false }, { ephemeral: true })
} }
}, },
[editor] [editor]

View file

@ -21,7 +21,7 @@ export const DefaultStylePanel = memo(function DefaultStylePanel({
const handlePointerOut = useCallback(() => { const handlePointerOut = useCallback(() => {
if (!isMobile) { if (!isMobile) {
editor.updateInstanceState({ isChangingStyle: false }) editor.updateInstanceState({ isChangingStyle: false }, { ephemeral: true })
} }
}, [editor, isMobile]) }, [editor, isMobile])

View file

@ -76,7 +76,7 @@ function useStyleChangeCallback() {
editor.setStyleForSelectedShapes(style, value, { squashing }) editor.setStyleForSelectedShapes(style, value, { squashing })
} }
editor.setStyleForNextShapes(style, value, { squashing }) editor.setStyleForNextShapes(style, value, { squashing })
editor.updateInstanceState({ isChangingStyle: true }) editor.updateInstanceState({ isChangingStyle: true }, { ephemeral: true })
}) })
trackEvent('set-style', { source: 'style-panel', id: style.id, value: value as string }) trackEvent('set-style', { source: 'style-panel', id: style.id, value: value as string })
@ -297,14 +297,14 @@ function OpacitySlider() {
const msg = useTranslation() const msg = useTranslation()
const handleOpacityValueChange = React.useCallback( const handleOpacityValueChange = React.useCallback(
(value: number, ephemeral: boolean) => { (value: number, squashing: boolean) => {
const item = tldrawSupportedOpacities[value] const item = tldrawSupportedOpacities[value]
editor.batch(() => { editor.batch(() => {
if (editor.isIn('select')) { if (editor.isIn('select')) {
editor.setOpacityForSelectedShapes(item, { ephemeral }) editor.setOpacityForSelectedShapes(item, { squashing })
} }
editor.setOpacityForNextShapes(item, { ephemeral }) editor.setOpacityForNextShapes(item, { squashing })
editor.updateInstanceState({ isChangingStyle: true }) editor.updateInstanceState({ isChangingStyle: true }, { ephemeral: true })
}) })
trackEvent('set-style', { source: 'style-panel', id: 'opacity', value }) trackEvent('set-style', { source: 'style-panel', id: 'opacity', value })

View file

@ -1,4 +1,4 @@
import { SharedStyle, StyleProp } from '@tldraw/editor' import { SharedStyle, StyleProp, useEditor } from '@tldraw/editor'
import * as React from 'react' import * as React from 'react'
import { StyleValuesForUi } from '../../../styles' import { StyleValuesForUi } from '../../../styles'
import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey' import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
@ -36,6 +36,7 @@ function _DropdownPicker<T extends string>({
onValueChange, onValueChange,
}: DropdownPickerProps<T>) { }: DropdownPickerProps<T>) {
const msg = useTranslation() const msg = useTranslation()
const editor = useEditor()
const icon = React.useMemo( const icon = React.useMemo(
() => items.find((item) => value.type === 'shared' && item.value === value.value)?.icon, () => items.find((item) => value.type === 'shared' && item.value === value.value)?.icon,
@ -65,7 +66,10 @@ function _DropdownPicker<T extends string>({
type="icon" type="icon"
data-testid={`style.${uiType}.${item.value}`} data-testid={`style.${uiType}.${item.value}`}
title={msg(`${uiType}-style.${item.value}` as TLUiTranslationKey)} title={msg(`${uiType}-style.${item.value}` as TLUiTranslationKey)}
onClick={() => onValueChange(style, item.value, false)} onClick={() => {
editor.mark('select style dropdown item')
onValueChange(style, item.value, false)
}}
> >
<TldrawUiButtonIcon icon={item.icon} /> <TldrawUiButtonIcon icon={item.icon} />
</TldrawUiButton> </TldrawUiButton>

View file

@ -10,7 +10,7 @@ export interface TLUiSliderProps {
value: number | null value: number | null
label: string label: string
title: string title: string
onValueChange: (value: number, emphemeral: boolean) => void onValueChange: (value: number, squashing: boolean) => void
'data-testid'?: string 'data-testid'?: string
} }

View file

@ -24,9 +24,9 @@ export function pasteTldrawContent(editor: Editor, clipboard: TLContent, point?:
seletionBoundsBefore?.collides(selectedBoundsAfter) seletionBoundsBefore?.collides(selectedBoundsAfter)
) { ) {
// Creates a 'puff' to show a paste has happened. // Creates a 'puff' to show a paste has happened.
editor.updateInstanceState({ isChangingStyle: true }) editor.updateInstanceState({ isChangingStyle: true }, { ephemeral: true })
setTimeout(() => { setTimeout(() => {
editor.updateInstanceState({ isChangingStyle: false }) editor.updateInstanceState({ isChangingStyle: false }, { ephemeral: true })
}, 150) }, 150)
} }
} }