Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RNMobile] Cover block: Support isDark attribute #40691

Merged
merged 8 commits into from
May 3, 2022
Merged
60 changes: 2 additions & 58 deletions packages/block-library/src/cover/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
* External dependencies
*/
import classnames from 'classnames';
import FastAverageColor from 'fast-average-color';
import { colord, extend } from 'colord';
import { extend } from 'colord';
import namesPlugin from 'colord/plugins/names';

/**
Expand Down Expand Up @@ -73,6 +72,7 @@ import {
isContentPositionCenter,
getPositionClassName,
} from './shared';
import useCoverIsDark from './use-cover-is-dark';

extend( [ namesPlugin ] );

Expand All @@ -89,13 +89,6 @@ function getInnerBlocksTemplate( attributes ) {
];
}

function retrieveFastAverageColor() {
if ( ! retrieveFastAverageColor.fastAverageColor ) {
retrieveFastAverageColor.fastAverageColor = new FastAverageColor();
}
return retrieveFastAverageColor.fastAverageColor;
}

function CoverHeightInput( {
onChange,
onUnitChange,
Expand Down Expand Up @@ -197,55 +190,6 @@ function ResizableCover( {
);
}

/**
* useCoverIsDark is a hook that returns a boolean variable specifying if the cover
* background is dark or not.
*
* @param {?string} url Url of the media background.
* @param {?number} dimRatio Transparency of the overlay color. If an image and
* color are set, dimRatio is used to decide what is used
* for background darkness checking purposes.
* @param {?string} overlayColor String containing the overlay color value if one exists.
* @param {?Object} elementRef If a media background is set, elementRef should contain a reference to a
* dom element that renders that media.
*
* @return {boolean} True if the cover background is considered "dark" and false otherwise.
*/
function useCoverIsDark( url, dimRatio = 50, overlayColor, elementRef ) {
const [ isDark, setIsDark ] = useState( false );
useEffect( () => {
// If opacity is lower than 50 the dominant color is the image or video color,
// so use that color for the dark mode computation.
if ( url && dimRatio <= 50 && elementRef.current ) {
retrieveFastAverageColor().getColorAsync(
elementRef.current,
( color ) => {
setIsDark( color.isDark );
}
);
}
}, [ url, url && dimRatio <= 50 && elementRef.current, setIsDark ] );
useEffect( () => {
// If opacity is greater than 50 the dominant color is the overlay color,
// so use that color for the dark mode computation.
if ( dimRatio > 50 || ! url ) {
if ( ! overlayColor ) {
// If no overlay color exists the overlay color is black (isDark )
setIsDark( true );
return;
}
setIsDark( colord( overlayColor ).isDark() );
}
}, [ overlayColor, dimRatio > 50 || ! url, setIsDark ] );
useEffect( () => {
if ( ! url && ! overlayColor ) {
// Reset isDark.
setIsDark( false );
}
}, [ ! url && ! overlayColor, setIsDark ] );
return isDark;
}

function mediaPosition( { x, y } ) {
return `${ Math.round( x * 100 ) }% ${ Math.round( y * 100 ) }%`;
}
Expand Down
53 changes: 40 additions & 13 deletions packages/block-library/src/cover/edit.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
Platform,
} from 'react-native';
import Video from 'react-native-video';
import classnames from 'classnames/dedupe';

/**
* WordPress dependencies
Expand Down Expand Up @@ -47,7 +48,7 @@ import {
store as blockEditorStore,
} from '@wordpress/block-editor';
import { compose, withPreferredColorScheme } from '@wordpress/compose';
import { withSelect, withDispatch } from '@wordpress/data';
import { useDispatch, withSelect, withDispatch } from '@wordpress/data';
import {
useEffect,
useState,
Expand All @@ -71,6 +72,7 @@ import {
COVER_DEFAULT_HEIGHT,
} from './shared';
import Controls from './controls';
import useCoverIsDark from './use-cover-is-dark';

/**
* Constants
Expand Down Expand Up @@ -113,6 +115,7 @@ const Cover = ( {
customGradient,
gradient,
overlayColor,
isDark,
} = attributes;
const [ isScreenReaderEnabled, setIsScreenReaderEnabled ] = useState(
false
Expand Down Expand Up @@ -180,18 +183,6 @@ const Cover = ( {

const openMediaOptionsRef = useRef();

// Used to set a default color for its InnerBlocks
// since there's no system to inherit styles yet
// the RichText component will check if there are
// parent styles for the current block. If there are,
// it will use that color instead.
useEffect( () => {
// While we don't support theme colors.
if ( ! attributes.overlayColor || ( ! attributes.overlay && url ) ) {
setAttributes( { childrenStyles: styles.defaultColor } );
}
}, [ setAttributes ] );

// Initialize uploading flag to false, awaiting sync.
const [ isUploadInProgress, setIsUploadInProgress ] = useState( false );

Expand Down Expand Up @@ -257,6 +248,42 @@ const Cover = ( {
openGeneralSidebar();
}

const { __unstableMarkNextChangeAsNotPersistent } = useDispatch(
blockEditorStore
);
const isCoverDark = useCoverIsDark(
isDark,
url,
dimRatio,
overlayColorValue?.color
);

useEffect( () => {
// This side-effect should not create an undo level.
__unstableMarkNextChangeAsNotPersistent();
// Used to set a default color for its InnerBlocks
// since there's no system to inherit styles yet
// the RichText component will check if there are
// parent styles for the current block. If there are,
// it will use that color instead.
setAttributes( {
isDark: isCoverDark,
childrenStyles: isCoverDark
? styles.defaultColor
: styles.defaultColorLightMode,
} );

// Ensure that "is-light" is removed from "className" attribute if cover background is dark.
if ( isCoverDark && attributes.className?.includes( 'is-light' ) ) {
const className = classnames( attributes.className, {
'is-light': false,
} );
setAttributes( {
className: className !== '' ? className : undefined,
} );
}
}, [ isCoverDark ] );

const backgroundColor = getStylesFromColorScheme(
styles.backgroundSolid,
styles.backgroundSolidDark
Expand Down
4 changes: 4 additions & 0 deletions packages/block-library/src/cover/style.native.scss
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@
color: $white;
}

.defaultColorLightMode {
color: $black;
}

.background {
width: 100%;
height: 100%;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`color settings clears the selected overlay color and mantains the inner blocks 1`] = `
"<!-- wp:cover -->
<div class=\\"wp-block-cover\\"><span aria-hidden=\\"true\\" class=\\"wp-block-cover__background has-background-dim-100 has-background-dim\\"></span><div class=\\"wp-block-cover__inner-container\\"><!-- wp:paragraph {\\"align\\":\\"center\\",\\"placeholder\\":\\"Write title…\\"} -->
"<!-- wp:cover {\\"isDark\\":false} -->
<div class=\\"wp-block-cover is-light\\"><span aria-hidden=\\"true\\" class=\\"wp-block-cover__background has-background-dim-100 has-background-dim\\"></span><div class=\\"wp-block-cover__inner-container\\"><!-- wp:paragraph {\\"align\\":\\"center\\",\\"placeholder\\":\\"Write title…\\"} -->
<p class=\\"has-text-align-center\\"></p>
<!-- /wp:paragraph --></div></div>
<!-- /wp:cover -->"
Expand All @@ -17,16 +17,16 @@ exports[`color settings sets a color for the overlay background when the placeho
`;

exports[`color settings sets a gradient overlay background when a solid background was already selected 1`] = `
"<!-- wp:cover {\\"gradient\\":\\"light-green-cyan-to-vivid-green-cyan\\"} -->
<div class=\\"wp-block-cover\\"><span aria-hidden=\\"true\\" class=\\"wp-block-cover__background has-background-dim-100 has-background-dim has-background-gradient has-light-green-cyan-to-vivid-green-cyan-gradient-background\\"></span><div class=\\"wp-block-cover__inner-container\\"><!-- wp:paragraph {\\"align\\":\\"center\\",\\"placeholder\\":\\"Write title…\\"} -->
"<!-- wp:cover {\\"gradient\\":\\"light-green-cyan-to-vivid-green-cyan\\",\\"isDark\\":false} -->
<div class=\\"wp-block-cover is-light\\"><span aria-hidden=\\"true\\" class=\\"wp-block-cover__background has-background-dim-100 has-background-dim has-background-gradient has-light-green-cyan-to-vivid-green-cyan-gradient-background\\"></span><div class=\\"wp-block-cover__inner-container\\"><!-- wp:paragraph {\\"align\\":\\"center\\",\\"placeholder\\":\\"Write title…\\"} -->
<p class=\\"has-text-align-center\\"></p>
<!-- /wp:paragraph --></div></div>
<!-- /wp:cover -->"
`;

exports[`color settings toggles between solid colors and gradients 1`] = `
"<!-- wp:cover {\\"gradient\\":\\"light-green-cyan-to-vivid-green-cyan\\"} -->
<div class=\\"wp-block-cover\\"><span aria-hidden=\\"true\\" class=\\"wp-block-cover__background has-background-dim-100 has-background-dim has-background-gradient has-light-green-cyan-to-vivid-green-cyan-gradient-background\\"></span><div class=\\"wp-block-cover__inner-container\\"><!-- wp:paragraph {\\"align\\":\\"center\\",\\"placeholder\\":\\"Write title…\\"} -->
"<!-- wp:cover {\\"gradient\\":\\"light-green-cyan-to-vivid-green-cyan\\",\\"isDark\\":false} -->
<div class=\\"wp-block-cover is-light\\"><span aria-hidden=\\"true\\" class=\\"wp-block-cover__background has-background-dim-100 has-background-dim has-background-gradient has-light-green-cyan-to-vivid-green-cyan-gradient-background\\"></span><div class=\\"wp-block-cover__inner-container\\"><!-- wp:paragraph {\\"align\\":\\"center\\",\\"placeholder\\":\\"Write title…\\"} -->
<p class=\\"has-text-align-center\\"></p>
<!-- /wp:paragraph --></div></div>
<!-- /wp:cover -->"
Expand Down
71 changes: 71 additions & 0 deletions packages/block-library/src/cover/use-cover-is-dark.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* External dependencies
*/
import FastAverageColor from 'fast-average-color';
import { colord } from 'colord';

/**
* WordPress dependencies
*/
import { useEffect, useState } from '@wordpress/element';

function retrieveFastAverageColor() {
if ( ! retrieveFastAverageColor.fastAverageColor ) {
retrieveFastAverageColor.fastAverageColor = new FastAverageColor();
}
return retrieveFastAverageColor.fastAverageColor;
}

/**
* useCoverIsDark is a hook that returns a boolean variable specifying if the cover
* background is dark or not.
*
* @param {?string} url Url of the media background.
* @param {?number} dimRatio Transparency of the overlay color. If an image and
* color are set, dimRatio is used to decide what is used
* for background darkness checking purposes.
* @param {?string} overlayColor String containing the overlay color value if one exists.
* @param {?Object} elementRef If a media background is set, elementRef should contain a reference to a
* dom element that renders that media.
*
* @return {boolean} True if the cover background is considered "dark" and false otherwise.
*/
export default function useCoverIsDark(
url,
dimRatio = 50,
overlayColor,
elementRef
) {
const [ isDark, setIsDark ] = useState( false );
useEffect( () => {
// If opacity is lower than 50 the dominant color is the image or video color,
// so use that color for the dark mode computation.
if ( url && dimRatio <= 50 && elementRef.current ) {
retrieveFastAverageColor().getColorAsync(
elementRef.current,
( color ) => {
setIsDark( color.isDark );
}
);
}
}, [ url, url && dimRatio <= 50 && elementRef.current, setIsDark ] );
useEffect( () => {
// If opacity is greater than 50 the dominant color is the overlay color,
// so use that color for the dark mode computation.
if ( dimRatio > 50 || ! url ) {
if ( ! overlayColor ) {
// If no overlay color exists the overlay color is black (isDark )
setIsDark( true );
return;
}
setIsDark( colord( overlayColor ).isDark() );
}
}, [ overlayColor, dimRatio > 50 || ! url, setIsDark ] );
useEffect( () => {
if ( ! url && ! overlayColor ) {
// Reset isDark.
setIsDark( false );
}
}, [ ! url && ! overlayColor, setIsDark ] );
return isDark;
}
51 changes: 51 additions & 0 deletions packages/block-library/src/cover/use-cover-is-dark.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* External dependencies
*/

import { colord } from 'colord';

/**
* WordPress dependencies
*/
import { useEffect, useState } from '@wordpress/element';

/**
* useCoverIsDark is a hook that returns a boolean variable specifying if the cover
* background is dark or not.
*
* @param {?boolean} initialValue Initial value.
* @param {?string} url Url of the media background.
* @param {?number} dimRatio Transparency of the overlay color. If an image and
* color are set, dimRatio is used to decide what is used
* for background darkness checking purposes.
* @param {?string} overlayColor String containing the overlay color value if one exists.
*
* @return {boolean} True if the cover background is considered "dark" and false otherwise.
*/
export default function useCoverIsDark(
initialValue = false,
url,
dimRatio = 50,
overlayColor
) {
const [ isDark, setIsDark ] = useState( initialValue );
useEffect( () => {
// If opacity is greater than 50 the dominant color is the overlay color,
// so use that color for the dark mode computation.
if ( dimRatio > 50 || ! url ) {
if ( ! overlayColor ) {
// If no overlay color exists the overlay color is black (isDark )
setIsDark( true );
return;
}
setIsDark( colord( overlayColor ).isDark() );
}
}, [ overlayColor, dimRatio > 50 || ! url, setIsDark ] );
useEffect( () => {
if ( ! url && ! overlayColor ) {
// Reset isDark.
setIsDark( false );
}
}, [ ! url && ! overlayColor, setIsDark ] );
return isDark;
}
1 change: 1 addition & 0 deletions packages/react-native-editor/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ For each user feature we should also add a importance categorization label to i
## Unreleased

- [**] [Buttons block] Fix Android-only issue related to displaying formatting buttons after closing the block settings [#40725]
- [**] [Cover block] Improve color contrast between background and text [#40691]

## 1.75.0

Expand Down