From 4ddd1d97b95832051df57af6fa0f9e114f0624ba Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Tue, 20 Apr 2021 13:17:39 +0300 Subject: [PATCH 1/7] Fixes collor-palette scrolling issue --- .../src/color-palette/index.native.js | 62 ++++++------------- .../src/color-palette/style.native.scss | 1 + 2 files changed, 20 insertions(+), 43 deletions(-) diff --git a/packages/components/src/color-palette/index.native.js b/packages/components/src/color-palette/index.native.js index 152845b80d2fc..56772d1674904 100644 --- a/packages/components/src/color-palette/index.native.js +++ b/packages/components/src/color-palette/index.native.js @@ -7,7 +7,6 @@ import { View, Animated, Easing, - Dimensions, Platform, Text, } from 'react-native'; @@ -26,9 +25,8 @@ import ColorIndicator from '../color-indicator'; import { colorsUtils } from '../mobile/color-settings/utils'; const ANIMATION_DURATION = 200; +const SEGMENTED_CONTROL_ANIMATION_DURATION_DELAY = 200; -let contentWidth = 0; -let scrollPosition = 0; let customIndicatorWidth = 0; function ColorPalette( { @@ -81,12 +79,17 @@ function ColorPalette( { useEffect( () => { setShouldShowCustomIndicator( shouldShowCustomIndicatorOption && - ( ! isGradientSegment || isCustomGradientColor ) + ( ! isGradientSegment || + ( isGradientColor && + activeColor && + ! ( colors && colors.includes( activeColor ) ) ) ) ); }, [ shouldShowCustomIndicatorOption, isGradientSegment, - isCustomGradientColor, + activeColor, + colors, + isGradientColor, ] ); const accessibilityHint = isGradientSegment @@ -95,6 +98,15 @@ function ColorPalette( { const customText = __( 'Custom' ); useEffect( () => { + const delayedScroll = setTimeout( () => { + resetScrollPosition(); + }, SEGMENTED_CONTROL_ANIMATION_DURATION_DELAY ); + return () => { + clearTimeout( delayedScroll ); + }; + }, [ currentSegment ] ); + + function resetScrollPosition() { if ( scrollViewRef.current ) { if ( isSelectedCustom() ) { scrollViewRef.current.scrollToEnd(); @@ -102,7 +114,7 @@ function ColorPalette( { scrollViewRef.current.scrollTo( { x: 0, y: 0 } ); } } - }, [ currentSegment ] ); + } function isSelectedCustom() { const isWithinColors = @@ -148,42 +160,11 @@ function ColorPalette( { outputRange: [ 1, 0.7, 1 ], } ); - function deselectCustomGradient() { - const { width } = Dimensions.get( 'window' ); - const isVisible = - contentWidth - scrollPosition - customIndicatorWidth < width; - - if ( isCustomGradientColor ) { - if ( ! isIOS ) { - // Scroll position on Android doesn't adjust automatically when removing the last item from the horizontal list. - // https://github.com/facebook/react-native/issues/27504 - // Workaround: Force the scroll when deselecting custom gradient color and when custom indicator is visible on layout. - if ( - isCustomGradientColor && - isVisible && - scrollViewRef.current - ) { - scrollViewRef.current.scrollTo( { - x: scrollPosition - customIndicatorWidth, - } ); - } - } - } - } - function onColorPress( color ) { - deselectCustomGradient(); performAnimation( color ); setColor( color ); } - function onContentSizeChange( width ) { - contentWidth = width; - if ( isSelectedCustom() && scrollViewRef.current ) { - scrollViewRef.current.scrollToEnd( { animated: ! isIOS } ); - } - } - function onCustomIndicatorLayout( { nativeEvent } ) { const { width } = nativeEvent.layout; if ( width !== customIndicatorWidth ) { @@ -191,10 +172,6 @@ function ColorPalette( { } } - function onScroll( { nativeEvent } ) { - scrollPosition = nativeEvent.contentOffset.x; - } - const verticalSeparatorStyle = usePreferredColorSchemeStyle( styles.verticalSeparator, styles.verticalSeparatorDark @@ -219,8 +196,7 @@ function ColorPalette( { keyboardShouldPersistTaps="always" disableScrollViewPanResponder scrollEventThrottle={ 16 } - onScroll={ onScroll } - onContentSizeChange={ onContentSizeChange } + onContentSizeChange={ resetScrollPosition } onScrollBeginDrag={ () => shouldEnableBottomSheetScroll( false ) } onScrollEndDrag={ () => shouldEnableBottomSheetScroll( true ) } ref={ scrollViewRef } diff --git a/packages/components/src/color-palette/style.native.scss b/packages/components/src/color-palette/style.native.scss index af618dfafded2..b21abc1f4ec65 100644 --- a/packages/components/src/color-palette/style.native.scss +++ b/packages/components/src/color-palette/style.native.scss @@ -1,4 +1,5 @@ .contentContainer { + flex-grow: 1; flex-direction: row; padding: 0 $grid-unit-20; } From 8613bc76cfeebbbb8c6430dea7fee062766b6796 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Mon, 26 Apr 2021 14:19:52 +0300 Subject: [PATCH 2/7] Uses existing ANIMATION_DURATION for clarity --- packages/components/src/color-palette/index.native.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/components/src/color-palette/index.native.js b/packages/components/src/color-palette/index.native.js index 56772d1674904..fef6ae7cedb51 100644 --- a/packages/components/src/color-palette/index.native.js +++ b/packages/components/src/color-palette/index.native.js @@ -25,7 +25,6 @@ import ColorIndicator from '../color-indicator'; import { colorsUtils } from '../mobile/color-settings/utils'; const ANIMATION_DURATION = 200; -const SEGMENTED_CONTROL_ANIMATION_DURATION_DELAY = 200; let customIndicatorWidth = 0; @@ -98,9 +97,10 @@ function ColorPalette( { const customText = __( 'Custom' ); useEffect( () => { - const delayedScroll = setTimeout( () => { - resetScrollPosition(); - }, SEGMENTED_CONTROL_ANIMATION_DURATION_DELAY ); + const delayedScroll = setTimeout( + resetScrollPosition, + ANIMATION_DURATION + ); return () => { clearTimeout( delayedScroll ); }; From 047b2797b0d0b715131ff891315fbb8ef2390602 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Tue, 27 Apr 2021 13:52:09 +0300 Subject: [PATCH 3/7] Adds release note --- packages/react-native-editor/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native-editor/CHANGELOG.md b/packages/react-native-editor/CHANGELOG.md index 6ff33e3fb685a..4f53e4a30c6d7 100644 --- a/packages/react-native-editor/CHANGELOG.md +++ b/packages/react-native-editor/CHANGELOG.md @@ -11,6 +11,7 @@ For each user feature we should also add a importance categorization label to i ## Unreleased - [*] Bottom-sheet: Add custom header [#30291] +- [*] Fixes color picker rendering bug when scrolling [#30994] ## 1.52.0 From 974dd72bb8a93252fb5d9666d50c15ccd0521431 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Thu, 6 May 2021 13:24:53 +0300 Subject: [PATCH 4/7] Revert "Uses existing ANIMATION_DURATION for clarity" This reverts commit 8613bc76cfeebbbb8c6430dea7fee062766b6796. --- packages/components/src/color-palette/index.native.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/components/src/color-palette/index.native.js b/packages/components/src/color-palette/index.native.js index fef6ae7cedb51..56772d1674904 100644 --- a/packages/components/src/color-palette/index.native.js +++ b/packages/components/src/color-palette/index.native.js @@ -25,6 +25,7 @@ import ColorIndicator from '../color-indicator'; import { colorsUtils } from '../mobile/color-settings/utils'; const ANIMATION_DURATION = 200; +const SEGMENTED_CONTROL_ANIMATION_DURATION_DELAY = 200; let customIndicatorWidth = 0; @@ -97,10 +98,9 @@ function ColorPalette( { const customText = __( 'Custom' ); useEffect( () => { - const delayedScroll = setTimeout( - resetScrollPosition, - ANIMATION_DURATION - ); + const delayedScroll = setTimeout( () => { + resetScrollPosition(); + }, SEGMENTED_CONTROL_ANIMATION_DURATION_DELAY ); return () => { clearTimeout( delayedScroll ); }; From 0aad64abb7f698de2393d768f9bcbeab14609093 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Thu, 6 May 2021 13:25:02 +0300 Subject: [PATCH 5/7] Revert "Fixes collor-palette scrolling issue" This reverts commit 4ddd1d97b95832051df57af6fa0f9e114f0624ba. --- .../src/color-palette/index.native.js | 62 +++++++++++++------ .../src/color-palette/style.native.scss | 1 - 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/packages/components/src/color-palette/index.native.js b/packages/components/src/color-palette/index.native.js index 56772d1674904..152845b80d2fc 100644 --- a/packages/components/src/color-palette/index.native.js +++ b/packages/components/src/color-palette/index.native.js @@ -7,6 +7,7 @@ import { View, Animated, Easing, + Dimensions, Platform, Text, } from 'react-native'; @@ -25,8 +26,9 @@ import ColorIndicator from '../color-indicator'; import { colorsUtils } from '../mobile/color-settings/utils'; const ANIMATION_DURATION = 200; -const SEGMENTED_CONTROL_ANIMATION_DURATION_DELAY = 200; +let contentWidth = 0; +let scrollPosition = 0; let customIndicatorWidth = 0; function ColorPalette( { @@ -79,17 +81,12 @@ function ColorPalette( { useEffect( () => { setShouldShowCustomIndicator( shouldShowCustomIndicatorOption && - ( ! isGradientSegment || - ( isGradientColor && - activeColor && - ! ( colors && colors.includes( activeColor ) ) ) ) + ( ! isGradientSegment || isCustomGradientColor ) ); }, [ shouldShowCustomIndicatorOption, isGradientSegment, - activeColor, - colors, - isGradientColor, + isCustomGradientColor, ] ); const accessibilityHint = isGradientSegment @@ -98,15 +95,6 @@ function ColorPalette( { const customText = __( 'Custom' ); useEffect( () => { - const delayedScroll = setTimeout( () => { - resetScrollPosition(); - }, SEGMENTED_CONTROL_ANIMATION_DURATION_DELAY ); - return () => { - clearTimeout( delayedScroll ); - }; - }, [ currentSegment ] ); - - function resetScrollPosition() { if ( scrollViewRef.current ) { if ( isSelectedCustom() ) { scrollViewRef.current.scrollToEnd(); @@ -114,7 +102,7 @@ function ColorPalette( { scrollViewRef.current.scrollTo( { x: 0, y: 0 } ); } } - } + }, [ currentSegment ] ); function isSelectedCustom() { const isWithinColors = @@ -160,11 +148,42 @@ function ColorPalette( { outputRange: [ 1, 0.7, 1 ], } ); + function deselectCustomGradient() { + const { width } = Dimensions.get( 'window' ); + const isVisible = + contentWidth - scrollPosition - customIndicatorWidth < width; + + if ( isCustomGradientColor ) { + if ( ! isIOS ) { + // Scroll position on Android doesn't adjust automatically when removing the last item from the horizontal list. + // https://github.com/facebook/react-native/issues/27504 + // Workaround: Force the scroll when deselecting custom gradient color and when custom indicator is visible on layout. + if ( + isCustomGradientColor && + isVisible && + scrollViewRef.current + ) { + scrollViewRef.current.scrollTo( { + x: scrollPosition - customIndicatorWidth, + } ); + } + } + } + } + function onColorPress( color ) { + deselectCustomGradient(); performAnimation( color ); setColor( color ); } + function onContentSizeChange( width ) { + contentWidth = width; + if ( isSelectedCustom() && scrollViewRef.current ) { + scrollViewRef.current.scrollToEnd( { animated: ! isIOS } ); + } + } + function onCustomIndicatorLayout( { nativeEvent } ) { const { width } = nativeEvent.layout; if ( width !== customIndicatorWidth ) { @@ -172,6 +191,10 @@ function ColorPalette( { } } + function onScroll( { nativeEvent } ) { + scrollPosition = nativeEvent.contentOffset.x; + } + const verticalSeparatorStyle = usePreferredColorSchemeStyle( styles.verticalSeparator, styles.verticalSeparatorDark @@ -196,7 +219,8 @@ function ColorPalette( { keyboardShouldPersistTaps="always" disableScrollViewPanResponder scrollEventThrottle={ 16 } - onContentSizeChange={ resetScrollPosition } + onScroll={ onScroll } + onContentSizeChange={ onContentSizeChange } onScrollBeginDrag={ () => shouldEnableBottomSheetScroll( false ) } onScrollEndDrag={ () => shouldEnableBottomSheetScroll( true ) } ref={ scrollViewRef } diff --git a/packages/components/src/color-palette/style.native.scss b/packages/components/src/color-palette/style.native.scss index b21abc1f4ec65..af618dfafded2 100644 --- a/packages/components/src/color-palette/style.native.scss +++ b/packages/components/src/color-palette/style.native.scss @@ -1,5 +1,4 @@ .contentContainer { - flex-grow: 1; flex-direction: row; padding: 0 $grid-unit-20; } From 27a314b904db9b34c472a57c6c7747e0a64a6ffa Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Thu, 6 May 2021 13:28:18 +0300 Subject: [PATCH 6/7] Revert "[RNMobile] SegmentedControls correction (#28740)" This reverts commit 18cac3af39c71da71a50e3d9d7db05aef3775076. --- .../src/color-palette/index.native.js | 98 ++++++++----------- .../src/color-palette/style.native.scss | 2 +- 2 files changed, 41 insertions(+), 59 deletions(-) diff --git a/packages/components/src/color-palette/index.native.js b/packages/components/src/color-palette/index.native.js index 152845b80d2fc..8776ce2a4cdc6 100644 --- a/packages/components/src/color-palette/index.native.js +++ b/packages/components/src/color-palette/index.native.js @@ -16,7 +16,7 @@ import { map, uniq } from 'lodash'; * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { useRef, useEffect, useState } from '@wordpress/element'; +import { useRef, useEffect } from '@wordpress/element'; import { usePreferredColorSchemeStyle } from '@wordpress/compose'; /** * Internal dependencies @@ -50,15 +50,6 @@ function ColorPalette( { 'linear-gradient(240deg, rgba(0,255,0,.8) 0%, rgba(0,255,0,0) 70.71%)', 'linear-gradient(360deg, rgba(0,0,255,.8) 0%, rgba(0,0,255,0) 70.71%)', ]; - const isCustomGradientColor = isGradientColor && isSelectedCustom(); - - const [ - shouldShowCustomIndicator, - setShouldShowCustomIndicator, - ] = useState( - shouldShowCustomIndicatorOption && - ( ! isGradientSegment || isCustomGradientColor ) - ); const scrollViewRef = useRef(); const isIOS = Platform.OS === 'ios'; @@ -77,17 +68,10 @@ function ColorPalette( { const customIndicatorColor = isGradientSegment ? activeColor : customSwatchGradients; - - useEffect( () => { - setShouldShowCustomIndicator( - shouldShowCustomIndicatorOption && - ( ! isGradientSegment || isCustomGradientColor ) - ); - }, [ - shouldShowCustomIndicatorOption, - isGradientSegment, - isCustomGradientColor, - ] ); + const isCustomGradientColor = isGradientColor && isSelectedCustom(); + const shouldShowCustomIndicator = + shouldShowCustomIndicatorOption && + ( ! isGradientSegment || isCustomGradientColor ); const accessibilityHint = isGradientSegment ? __( 'Navigates to customize the gradient' ) @@ -225,6 +209,41 @@ function ColorPalette( { onScrollEndDrag={ () => shouldEnableBottomSheetScroll( true ) } ref={ scrollViewRef } > + { shouldShowCustomIndicator && ( + + { shouldShowCustomVerticalSeparator && ( + + ) } + + + + { shouldShowCustomLabel && ( + + { isIOS + ? customText + : customText.toUpperCase() } + + ) } + + + + ) } { colors.map( ( color ) => { const scaleValue = isSelected( color ) ? scaleInterpolation : 1; return ( @@ -260,43 +279,6 @@ function ColorPalette( { ); } ) } - { shouldShowCustomIndicator && ( - - { shouldShowCustomVerticalSeparator && ( - - ) } - - - - { shouldShowCustomLabel && ( - - { isIOS - ? customText - : customText.toUpperCase() } - - ) } - - - - ) } ); } diff --git a/packages/components/src/color-palette/style.native.scss b/packages/components/src/color-palette/style.native.scss index af618dfafded2..f23bbae26f65e 100644 --- a/packages/components/src/color-palette/style.native.scss +++ b/packages/components/src/color-palette/style.native.scss @@ -1,5 +1,5 @@ .contentContainer { - flex-direction: row; + flex-direction: row-reverse; padding: 0 $grid-unit-20; } From 9094f38a4767da1fc6735c3c25b75cdce587dcdd Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Thu, 6 May 2021 14:02:04 +0300 Subject: [PATCH 7/7] Adds delay before scrolling to counteract segmented control delay --- .../components/src/color-palette/index.native.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/components/src/color-palette/index.native.js b/packages/components/src/color-palette/index.native.js index 8776ce2a4cdc6..0ae41ca2227b7 100644 --- a/packages/components/src/color-palette/index.native.js +++ b/packages/components/src/color-palette/index.native.js @@ -81,7 +81,7 @@ function ColorPalette( { useEffect( () => { if ( scrollViewRef.current ) { if ( isSelectedCustom() ) { - scrollViewRef.current.scrollToEnd(); + scrollToEndWithDelay(); } else { scrollViewRef.current.scrollTo( { x: 0, y: 0 } ); } @@ -164,10 +164,19 @@ function ColorPalette( { function onContentSizeChange( width ) { contentWidth = width; if ( isSelectedCustom() && scrollViewRef.current ) { - scrollViewRef.current.scrollToEnd( { animated: ! isIOS } ); + scrollToEndWithDelay(); } } + function scrollToEndWithDelay() { + const delayedScroll = setTimeout( () => { + scrollViewRef.current.scrollToEnd(); + }, ANIMATION_DURATION ); + return () => { + clearTimeout( delayedScroll ); + }; + } + function onCustomIndicatorLayout( { nativeEvent } ) { const { width } = nativeEvent.layout; if ( width !== customIndicatorWidth ) {