From 6363d14e92875e1ba41e9dfe00fe088152b8a053 Mon Sep 17 00:00:00 2001 From: Heri Setiawan Date: Fri, 10 Jan 2025 07:27:55 +0700 Subject: [PATCH 1/3] Fix missing frame when animating thought up/down --- src/components/Editable.tsx | 7 +- src/components/LayoutTree.tsx | 442 +++++++++++---------- src/components/TreeNodeAnimation.tsx | 47 +++ src/components/TreeNodeAnimationContext.ts | 9 + src/hooks/useTreeNodeAnimation.tsx | 13 + 5 files changed, 297 insertions(+), 221 deletions(-) create mode 100644 src/components/TreeNodeAnimation.tsx create mode 100644 src/components/TreeNodeAnimationContext.ts create mode 100644 src/hooks/useTreeNodeAnimation.tsx diff --git a/src/components/Editable.tsx b/src/components/Editable.tsx index d1191d1bd2..e5ef2cc327 100644 --- a/src/components/Editable.tsx +++ b/src/components/Editable.tsx @@ -34,6 +34,7 @@ import { import preventAutoscroll, { preventAutoscrollEnd } from '../device/preventAutoscroll' import * as selection from '../device/selection' import globals from '../globals' +import useTreeNodeAnimation from '../hooks/useTreeNodeAnimation' import findDescendant from '../selectors/findDescendant' import { anyChild, getAllChildrenAsThoughts } from '../selectors/getChildren' import getContexts from '../selectors/getContexts' @@ -135,6 +136,7 @@ const Editable = ({ const oldValueRef = useRef(value) const nullRef = useRef(null) const contentRef = editableRef || nullRef + const { isAnimating, setIsAnimating } = useTreeNodeAnimation() /** Used to prevent edit mode from being incorrectly activated on long tap. The default browser behavior must be prevented if setCursorOnThought was just called. */ // https://github.com/cybersemics/em/issues/1793 @@ -224,6 +226,9 @@ const Editable = ({ path, }), ) + + // Reset isAnimating to false after the cursor is set. + setIsAnimating(false) }, // When isEditing changes, we need to reset the cursor on the thought. // eslint-disable-next-line react-hooks/exhaustive-deps @@ -593,7 +598,7 @@ const Editable = ({ className={cx( multiline ? multilineRecipe() : null, editableRecipe({ - preventAutoscroll: true, + preventAutoscroll: !isAnimating, }), className, )} diff --git a/src/components/LayoutTree.tsx b/src/components/LayoutTree.tsx index 98b71c9f86..e0fa1eb76c 100644 --- a/src/components/LayoutTree.tsx +++ b/src/components/LayoutTree.tsx @@ -1,5 +1,5 @@ import _ from 'lodash' -import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react' +import React, { forwardRef, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react' import { useSelector } from 'react-redux' import { TransitionGroup } from 'react-transition-group' import { CSSTransitionProps } from 'react-transition-group/CSSTransition' @@ -17,6 +17,7 @@ import { isTouch } from '../browser' import { HOME_PATH } from '../constants' import testFlags from '../e2e/testFlags' import useSortedContext from '../hooks/useSortedContext' +import useTreeNodeAnimation from '../hooks/useTreeNodeAnimation' import attributeEquals from '../selectors/attributeEquals' import calculateAutofocus from '../selectors/calculateAutofocus' import findDescendant from '../selectors/findDescendant' @@ -45,6 +46,7 @@ import unroot from '../util/unroot' import DropEnd from './DropEnd' import FadeTransition from './FadeTransition' import HoverArrow from './HoverArrow' +import TreeNodeAnimationProvider from './TreeNodeAnimation' import VirtualThought, { OnResize } from './VirtualThought' /** 1st Pass: A thought with rendering information after the tree has been linearized. */ @@ -379,213 +381,211 @@ const linearizeTree = ( } /** Renders a thought component for mapped treeThoughtsPositioned. */ -const TreeNode = ({ - belowCursor, - cliff, - depth, - env, - height, - indexChild, - indexDescendant, - isCursor, - isEmpty, - isTableCol1, - isTableCol2, - thoughtKey, - leaf, - path, - prevChild, - showContexts, - isLastVisible, - simplePath, - singleLineHeightWithCliff, - style, - thoughtId, - width, - autofocus, - x, - y: _y, - index, - viewportBottom, - treeThoughtsPositioned, - bulletWidth, - cursorUncleId, - setSize, - cliffPaddingStyle, - dragInProgress, - autofocusDepth, - ...transitionGroupsProps -}: TreeThoughtPositioned & { - thoughtKey: string - index: number - viewportBottom: number - treeThoughtsPositioned: TreeThoughtPositioned[] - bulletWidth: number - cursorUncleId: string | null - setSize: OnResize - cliffPaddingStyle: { paddingBottom: number } - dragInProgress: boolean - autofocusDepth: number -} & Pick) => { - const [y, setY] = useState(_y) - const fadeThoughtRef = useRef(null) - const isLastActionNewThought = useSelector(state => { - const lastPatches = state.undoPatches[state.undoPatches.length - 1] - return lastPatches?.some(patch => patch.actions[0] === 'newThought') - }) - - // true if the last action is any of archive/delete/collapse - const isLastActionDelete = useSelector(state => { - const deleteActions: ActionType[] = [ - 'archiveThought', - 'collapseContext', - 'deleteThought', - 'deleteThoughtWithCursor', - ] - const lastPatches = state.undoPatches[state.undoPatches.length - 1] - return lastPatches?.some(patch => deleteActions.includes(patch.actions[0])) - }) +const TreeNode = forwardRef( + ( + { + belowCursor, + cliff, + depth, + env, + height, + indexChild, + indexDescendant, + isCursor, + isEmpty, + isTableCol1, + isTableCol2, + thoughtKey, + leaf, + path, + prevChild, + showContexts, + isLastVisible, + simplePath, + singleLineHeightWithCliff, + style, + thoughtId, + width, + autofocus, + x, + y: _y, + index, + viewportBottom, + treeThoughtsPositioned, + bulletWidth, + cursorUncleId, + setSize, + cliffPaddingStyle, + dragInProgress, + autofocusDepth, + ...transitionGroupsProps + }: TreeThoughtPositioned & { + thoughtKey: string + index: number + viewportBottom: number + treeThoughtsPositioned: TreeThoughtPositioned[] + bulletWidth: number + cursorUncleId: string | null + setSize: OnResize + cliffPaddingStyle: { paddingBottom: number } + dragInProgress: boolean + autofocusDepth: number + } & Pick, + ref: any, + ) => { + const { y } = useTreeNodeAnimation() + const fadeThoughtRef = useRef(null) + const isLastActionNewThought = useSelector(state => { + const lastPatches = state.undoPatches[state.undoPatches.length - 1] + return lastPatches?.some(patch => patch.actions[0] === 'newThought') + }) - useLayoutEffect(() => { - if (y !== _y) { - // When y changes React re-renders the component with the new value of y. It will result in a visual change in the DOM. - // Because this is a state-driven change, React applies the updated value to the DOM, which causes the browser to recognize that - // a CSS property has changed, thereby triggering the CSS transition. - // Without this additional render, updates get batched and subsequent CSS transitions may not work properly. For example, when moving a thought down, it would not animate. - setY(_y) - } - }, [y, _y]) + // true if the last action is any of archive/delete/collapse + const isLastActionDelete = useSelector(state => { + const deleteActions: ActionType[] = [ + 'archiveThought', + 'collapseContext', + 'deleteThought', + 'deleteThoughtWithCursor', + ] + const lastPatches = state.undoPatches[state.undoPatches.length - 1] + return lastPatches?.some(patch => deleteActions.includes(patch.actions[0])) + }) - // List Virtualization - // Do not render thoughts that are below the viewport. - // Exception: The cursor thought and its previous siblings may temporarily be out of the viewport, such as if when New Subthought is activated on a long context. In this case, the new thought will be created below the viewport and needs to be rendered in order for scrollCursorIntoView to be activated. - // Render virtualized thoughts with their estimated height so that document height is relatively stable. - // Perform this check here instead of in virtualThoughtsPositioned since it changes with the scroll position (though currently `sizes` will change as new thoughts are rendered, causing virtualThoughtsPositioned to re-render anyway). - if (belowCursor && !isCursor && y > viewportBottom + height) return null + // List Virtualization + // Do not render thoughts that are below the viewport. + // Exception: The cursor thought and its previous siblings may temporarily be out of the viewport, such as if when New Subthought is activated on a long context. In this case, the new thought will be created below the viewport and needs to be rendered in order for scrollCursorIntoView to be activated. + // Render virtualized thoughts with their estimated height so that document height is relatively stable. + // Perform this check here instead of in virtualThoughtsPositioned since it changes with the scroll position (though currently `sizes` will change as new thoughts are rendered, causing virtualThoughtsPositioned to re-render anyway). + if (belowCursor && !isCursor && y > viewportBottom + height) return null - const nextThought = isTableCol1 ? treeThoughtsPositioned[index + 1] : null - const previousThought = isTableCol1 ? treeThoughtsPositioned[index - 1] : null + const nextThought = isTableCol1 ? treeThoughtsPositioned[index + 1] : null + const previousThought = isTableCol1 ? treeThoughtsPositioned[index - 1] : null - // Adjust col1 width to remove dead zones between col1 and col2, increase the width by the difference between col1 and col2 minus bullet width - const xCol2 = isTableCol1 ? nextThought?.x || previousThought?.x || 0 : 0 - // Increasing margin-right of thought for filling gaps and moving the thought to the left by adding negative margin from right. - const marginRight = isTableCol1 ? xCol2 - (width || 0) - x - (bulletWidth || 0) : 0 + // Adjust col1 width to remove dead zones between col1 and col2, increase the width by the difference between col1 and col2 minus bullet width + const xCol2 = isTableCol1 ? nextThought?.x || previousThought?.x || 0 : 0 + // Increasing margin-right of thought for filling gaps and moving the thought to the left by adding negative margin from right. + const marginRight = isTableCol1 ? xCol2 - (width || 0) - x - (bulletWidth || 0) : 0 - // Speed up the tree-node's transition (normally layoutNodeAnimationDuration) by 50% on New (Sub)Thought only. - const transition = isLastActionNewThought - ? `left {durations.layoutNodeAnimationFast} ease-out,top {durations.layoutNodeAnimationFast} ease-out` - : `left {durations.layoutNodeAnimation} ease-out,top {durations.layoutNodeAnimation} ease-out` + // Speed up the tree-node's transition (normally layoutNodeAnimationDuration) by 50% on New (Sub)Thought only. + const transition = isLastActionNewThought + ? `left {durations.layoutNodeAnimationFast} ease-out,top {durations.layoutNodeAnimationFast} ease-out` + : `left {durations.layoutNodeAnimation} ease-out,top {durations.layoutNodeAnimation} ease-out` - return ( -
- -
- -
-
- - {/* DropEnd (cliff) */} - {dragInProgress && - cliff < 0 && - // do not render hidden cliffs - // rough autofocus estimate - autofocusDepth - depth < 2 && - Array(-cliff) - .fill(0) - .map((x, i) => { - const pathEnd = -(cliff + i) < path.length ? (path.slice(0, cliff + i) as Path) : HOME_PATH - const cliffDepth = unroot(pathEnd).length - - // After table col2, shift the DropEnd left by the width of col1. - // This correctly positions the drop target for dropping after the table view. - // Otherwise it would be too far to the right. - const dropEndMarginLeft = - isTableCol2 && cliffDepth - depth < 0 ? treeThoughtsPositioned[index - 1].width || 0 : 0 - - return ( -
- -
- ) - })} -
- ) -} + +
+ +
+
+ + {/* DropEnd (cliff) */} + {dragInProgress && + cliff < 0 && + // do not render hidden cliffs + // rough autofocus estimate + autofocusDepth - depth < 2 && + Array(-cliff) + .fill(0) + .map((x, i) => { + const pathEnd = -(cliff + i) < path.length ? (path.slice(0, cliff + i) as Path) : HOME_PATH + const cliffDepth = unroot(pathEnd).length + + // After table col2, shift the DropEnd left by the width of col1. + // This correctly positions the drop target for dropping after the table view. + // Otherwise it would be too far to the right. + const dropEndMarginLeft = + isTableCol2 && cliffDepth - depth < 0 ? treeThoughtsPositioned[index - 1].width || 0 : 0 + + return ( +
+ +
+ ) + })} + + ) + }, +) + +TreeNode.displayName = 'TreeNode' /** Lays out thoughts as DOM siblings with manual x,y positioning. */ const LayoutTree = () => { @@ -593,7 +593,7 @@ const LayoutTree = () => { const treeThoughts = useSelector(linearizeTree, _.isEqual) const fontSize = useSelector(state => state.fontSize) const dragInProgress = useSelector(state => state.dragInProgress) - const ref = useRef(null) + const ref = useRef(null) as React.MutableRefObject const indentDepth = useSelector(state => state.cursor && state.cursor.length > 2 ? // when the cursor is on a leaf, the indention level should not change @@ -964,24 +964,26 @@ const LayoutTree = () => { > {treeThoughtsPositioned.map((thought, index) => ( - + + + ))} diff --git a/src/components/TreeNodeAnimation.tsx b/src/components/TreeNodeAnimation.tsx new file mode 100644 index 0000000000..cf36d914f6 --- /dev/null +++ b/src/components/TreeNodeAnimation.tsx @@ -0,0 +1,47 @@ +import { ReactElement, cloneElement, useLayoutEffect, useRef, useState } from 'react' +import { TreeNodeAnimationContext } from './TreeNodeAnimationContext' + +interface TreeNodeAnimationProviderProps { + children: ReactElement + y: number + transitionGroupsProps?: object +} + +/** + * TreeNodeAnimationProvider component to provide animation context to its children. + * + * @param props - The props for the provider. + * @param props.children - The children components. + * @param props.y - The initial y value. + * @param [props.transitionGroupsProps] - Additional props to pass to the children. + * @returns The provider component. + */ +const TreeNodeAnimationProvider = ({ + children, + y: _y, + ...transitionGroupsProps +}: TreeNodeAnimationProviderProps): ReactElement => { + const [isAnimating, setIsAnimating] = useState(false) + const [y, setY] = useState(0) + const nodeRef = useRef(null) + + useLayoutEffect(() => { + if (y !== _y) { + // Mark as animating + setIsAnimating(true) + // When y changes React re-renders the component with the new value of y. It will result in a visual change in the DOM. + // Because this is a state-driven change, React applies the updated value to the DOM, which causes the browser to recognize that + // a CSS property has changed, thereby triggering the CSS transition. + // Without this additional render, updates get batched and subsequent CSS transitions may not work properly. For example, when moving a thought down, it would not animate. + setY(_y) + } + }, [y, _y]) + + return ( + + {cloneElement(children, { ...transitionGroupsProps, ref: nodeRef })} + + ) +} + +export default TreeNodeAnimationProvider diff --git a/src/components/TreeNodeAnimationContext.ts b/src/components/TreeNodeAnimationContext.ts new file mode 100644 index 0000000000..c42f702b05 --- /dev/null +++ b/src/components/TreeNodeAnimationContext.ts @@ -0,0 +1,9 @@ +import { createContext } from 'react' + +export interface TreeNodeAnimationContextProps { + isAnimating: boolean + setIsAnimating: (isAnimating: boolean) => void + y: number +} + +export const TreeNodeAnimationContext = createContext(undefined) diff --git a/src/hooks/useTreeNodeAnimation.tsx b/src/hooks/useTreeNodeAnimation.tsx new file mode 100644 index 0000000000..99d893e395 --- /dev/null +++ b/src/hooks/useTreeNodeAnimation.tsx @@ -0,0 +1,13 @@ +import { useContext } from 'react' +import { TreeNodeAnimationContext, TreeNodeAnimationContextProps } from '../components/TreeNodeAnimationContext' + +/** Custom hook to use the TreeNodeAnimation context. Will throw an error if used outside of a TreeNodeAnimationProvider. */ +const useTreeNodeAnimation = (): TreeNodeAnimationContextProps => { + const context = useContext(TreeNodeAnimationContext) + if (!context) { + throw new Error('useTreeNodeAnimation must be used within a TreeNodeAnimationProvider') + } + return context +} + +export default useTreeNodeAnimation From 69df6850de2ffd69585717a27f8cc5b94c8c9e18 Mon Sep 17 00:00:00 2001 From: Heri Setiawan Date: Mon, 13 Jan 2025 15:39:38 +0700 Subject: [PATCH 2/3] Reset isAnimating flag on transitionend --- src/components/Editable.tsx | 5 +--- src/components/TreeNodeAnimation.tsx | 27 +++++++++++++++++++--- src/components/TreeNodeAnimationContext.ts | 1 - 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/components/Editable.tsx b/src/components/Editable.tsx index e5ef2cc327..f7041feb5f 100644 --- a/src/components/Editable.tsx +++ b/src/components/Editable.tsx @@ -136,7 +136,7 @@ const Editable = ({ const oldValueRef = useRef(value) const nullRef = useRef(null) const contentRef = editableRef || nullRef - const { isAnimating, setIsAnimating } = useTreeNodeAnimation() + const { isAnimating } = useTreeNodeAnimation() /** Used to prevent edit mode from being incorrectly activated on long tap. The default browser behavior must be prevented if setCursorOnThought was just called. */ // https://github.com/cybersemics/em/issues/1793 @@ -226,9 +226,6 @@ const Editable = ({ path, }), ) - - // Reset isAnimating to false after the cursor is set. - setIsAnimating(false) }, // When isEditing changes, we need to reset the cursor on the thought. // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/src/components/TreeNodeAnimation.tsx b/src/components/TreeNodeAnimation.tsx index cf36d914f6..150478ac7d 100644 --- a/src/components/TreeNodeAnimation.tsx +++ b/src/components/TreeNodeAnimation.tsx @@ -21,24 +21,45 @@ const TreeNodeAnimationProvider = ({ y: _y, ...transitionGroupsProps }: TreeNodeAnimationProviderProps): ReactElement => { - const [isAnimating, setIsAnimating] = useState(false) + const isAnimatingRef = useRef(false) const [y, setY] = useState(0) const nodeRef = useRef(null) useLayoutEffect(() => { + const currentNode = nodeRef.current + /** + * Handle the transition end event. + */ + const handleTransitionEnd = () => { + // Mark as animation done after the transition ends + requestAnimationFrame(() => { + isAnimatingRef.current = false + }) + } + + if (currentNode) { + currentNode.addEventListener('transitionend', handleTransitionEnd) + } + if (y !== _y) { // Mark as animating - setIsAnimating(true) + isAnimatingRef.current = true // When y changes React re-renders the component with the new value of y. It will result in a visual change in the DOM. // Because this is a state-driven change, React applies the updated value to the DOM, which causes the browser to recognize that // a CSS property has changed, thereby triggering the CSS transition. // Without this additional render, updates get batched and subsequent CSS transitions may not work properly. For example, when moving a thought down, it would not animate. setY(_y) } + + return () => { + if (currentNode) { + currentNode.removeEventListener('transitionend', handleTransitionEnd) + } + } }, [y, _y]) return ( - + {cloneElement(children, { ...transitionGroupsProps, ref: nodeRef })} ) diff --git a/src/components/TreeNodeAnimationContext.ts b/src/components/TreeNodeAnimationContext.ts index c42f702b05..58b78dde21 100644 --- a/src/components/TreeNodeAnimationContext.ts +++ b/src/components/TreeNodeAnimationContext.ts @@ -2,7 +2,6 @@ import { createContext } from 'react' export interface TreeNodeAnimationContextProps { isAnimating: boolean - setIsAnimating: (isAnimating: boolean) => void y: number } From 54ff6d745aadc331aab46e443d1f22b288def43e Mon Sep 17 00:00:00 2001 From: Heri Setiawan Date: Mon, 13 Jan 2025 15:55:00 +0700 Subject: [PATCH 3/3] Update puppeteer test snapshots --- ...lor-theme-superscript-on-light-theme-1.png | Bin 5625 -> 5628 bytes .../font-size-18-default-superscript-1.png | Bin 5601 -> 5626 bytes .../url/multiline-font-size-13-1.png | Bin 21618 -> 21587 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/e2e/puppeteer/__tests__/__image_snapshots__/render-thoughts/color-theme-superscript-on-light-theme-1.png b/src/e2e/puppeteer/__tests__/__image_snapshots__/render-thoughts/color-theme-superscript-on-light-theme-1.png index 5c80b44de53c583a64f77e240098143e734024a0..4d16a3462283bca1e287c82e1d2d3b7be59c1b3d 100644 GIT binary patch literal 5628 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 literal 5625 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 literal 5601 zcmeHL`B#%y8omJqEW5SZf?=sg?VO6V0;PntV8sqq+(JN>xRk{J1`SDom;|Mju}Y$K zlv5CJsZs(VB1VJ|f+D0Afg&U!!4S$$LRf^bBqYp@oj+iHn>lm%Dd*h#=6>(@ywCeQ z@BJBp2K?p0PAn|?mh&7sS5xmkrrlfrGRuH4gMeqheCrvW&7rF06r-EX7^V| zGH$8mu}N|=QaCg9k|6m-`pCMAxaCT~Cjsg9(&otH8Ll5+S@-)+)K>=|@3P;p;m8IK z$@Ri#{Ig=qpEqgN*_R$*725VUr{(nQit2iG<8<=%o>H%Uh4))8VJwpmODcSHw*u

21U0>BFkI{;kvWW&AB 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 diff --git a/src/e2e/puppeteer/__tests__/__image_snapshots__/url/multiline-font-size-13-1.png b/src/e2e/puppeteer/__tests__/__image_snapshots__/url/multiline-font-size-13-1.png index 90a49c5540d4c052b82a895128b25d42160d383d..11ee0d18bd1012d5b7b376848af971e4484ff322 100644 GIT binary patch literal 21587 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 IuiW{60MNXw*Z=?k