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] Update image size UI control #19232

Merged
merged 12 commits into from
Feb 12, 2020

Conversation

cameronvoell
Copy link
Member

@cameronvoell cameronvoell commented Dec 19, 2019

Description

Updates the mobile SelectControl (currently only used on mobile in the Image Block) to use a Cycle Button style UI (CyclePickerCell) instead of nested BottomSheets (PickerCell).

How has this been tested?

See Gutenberg-Mobile PR: wordpress-mobile/gutenberg-mobile#1574
In order to test with image urls updating correctly via api requests, this was tested in WordPress iOS and WordPress Android

  1. Open an article in the editor with an image.
  2. Click the gear button to open image settings
  3. Click the menu row labeled "Size" multiple times.
  4. Note the menu size value and Image within the block are updated simultaneously.

Screenshots

size-changes

Types of changes

  • Introduces cycle button UI for updating the size of an image from the BottomSheet menu in an Image Block.
  • Removes duplicated default image size declarations and instead utilizes image sizes from the editor settings data store.

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • My code has proper inline documentation.
  • I've included developer documentation if appropriate.
  • I've updated all React Native files affected by any refactorings/renamings in this PR. .

Copy link

@test-case-reminder test-case-reminder bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are some suggested test cases for this PR.

WordPress iOS:

  • Simultaneous uploads - steps
  • Image block - Insert image from device (failing) - steps
  • Image block - Insert image from device (cancel) - steps
  • Image block - Add Caption - steps
  • Image block - Close/Re-open post with an ongoing image upload - steps
  • Image block - Close post with an ongoing image upload - steps
  • Image block - Switch to classic editor with an image block in page - steps

WordPress Android:

  • Simultaneous uploads - steps
  • Image block - Insert image from device (failing) - steps
  • Image block - Insert image from device (cancel) - steps
  • Image block - Add Caption - steps
  • Image block - Close/Re-open post with an ongoing image upload - steps
  • Image block - Close post with an ongoing image upload - steps
  • Image block - Switch to classic editor with an image block in page - steps

If you think that suggestions should be improved please edit the configuration file here. You can also modify/add test-suites to be used in the configuration.

If you are a beginner in mobile platforms follow build instructions.

@cameronvoell cameronvoell added the Mobile App - i.e. Android or iOS Native mobile impl of the block editor. (Note: used in scripts, ping mobile folks to change) label Dec 19, 2019
@cameronvoell cameronvoell self-assigned this Dec 19, 2019
@cameronvoell cameronvoell marked this pull request as ready for review December 19, 2019 06:41
@@ -17,7 +17,7 @@ function SelectControl( {
const id = `inspector-select-control-${ instanceId }`;

return (
<PickerCell
<CyclePickerCell
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though I did not include it in this PR yet. I am proposing that we remove PickerCell.(though Picker is still super useful!). Though PickerCell gets the BottomSheet nested menu about 80% there, it feels like a fundamental restriction of a react-native-modal Modal nested inside of another, that we will not be able to close the containing Modal before showing the child Modal without editing the underlying library. @Tug @etoledom thoughts?

One reason this might be worth doing now is in order to decouple PickerCell from Cross Platform component refactoring efforts, like seen here in SelectControl.

Copy link
Contributor

@etoledom etoledom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great to me and works perfect 🎉

There's one thing I'm not sure about, maybe @pinarol and @iamthomasbishop, could give more lights:

With this PR we are changing the UX of SelectControl. Probably not a big deal since this is the only place we are using it so far, but for future features this could be not the best approach, if there are a lot more options to choose from.

@iamthomasbishop already gave his 👍 for this UX on this particular use case.

It's also true that the current SelectControl needs a lot of work, so this might be a good enough mid step toward a better component, but I'm unsure of the future plans. Main question is: Is it OK to replace the SelectControl UX like this or would it be better to have a different component with this UX while maintaining the current SelectControl to use in case we need it? (Still considering that PickerCell is not being removed as mentioned here.

I personally think it's fine to merge this PR, but asking here to also give awareness of the change.

Comment on lines 58 to 84
const IMAGE_SIZE_THUMBNAIL = 'thumbnail';
const IMAGE_SIZE_MEDIUM = 'medium';
const IMAGE_SIZE_LARGE = 'large';
const IMAGE_SIZE_FULL_SIZE = 'full';
const DEFAULT_SIZE_SLUG = IMAGE_SIZE_LARGE;
const sizeOptionLabels = {
[ IMAGE_SIZE_THUMBNAIL ]: __( 'Thumbnail' ),
[ IMAGE_SIZE_MEDIUM ]: __( 'Medium' ),
[ IMAGE_SIZE_LARGE ]: __( 'Large' ),
[ IMAGE_SIZE_FULL_SIZE ]: __( 'Full Size' ),
};
const sizeOptions = map( sizeOptionLabels, ( label, option ) => ( { value: option, label } ) );

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@iamthomasbishop
Copy link

With this PR we are changing the UX of SelectControl. Probably not a big deal since this is the only place we are using it so far, but for future features this could be not the best approach, if there are a lot more options to choose from.

@etoledom Agreed, and while this is fine for the short-term, I don't even think this is the best solution for this interaction in the long-term. I don't have visibility into whether this will also change/affect other controls, but if so can we document the effects? // cc @cameronvoell

@etoledom
Copy link
Contributor

I don't have visibility into whether this will also change/affect other controls, but if so can we document the effects?

This changes SelectControl, instead of presenting a new bottom-sheet with the options to select, it now behaves as shown in the gif. What I mean is that the whole control component behaves this way, not just this instance of it. But again, we don't have other instances in use anywhere else yet.

No other controls are modified at all.

@cameronvoell
Copy link
Member Author

cameronvoell commented Jan 15, 2020

This changes SelectControl, instead of presenting a new bottom-sheet with the options to select, it now behaves as shown in the gif. What I mean is that the whole control component behaves this way, not just this instance of it. But again, we don't have other instances in use anywhere else yet.

@etoledom I didn't think we were using SelectControl either, but it turns out it is in the Gallery settings menu and it was added to Video Settings two months ago here:

<SelectControl
label={ __( 'Preload' ) }
value={ preload }
onChange={ ( value ) => setAttributes( { preload: value } ) }
options={ [
{ value: 'auto', label: __( 'Auto' ) },
{ value: 'metadata', label: __( 'Metadata' ) },
{ value: 'none', label: __( 'None' ) },
] }

I added a new CycleSelectControl (31caac7) to use in Image Settings until we solve the nested bottom sheet menu problem.

@etoledom
Copy link
Contributor

etoledom commented Jan 23, 2020

I added a new CycleSelectControl (31caac7) to use in Image Settings until we solve the nested bottom sheet menu problem.

Nice addition! Thanks @cameronvoell 🙏

but it turns out it is in the Gallery settings menu and it was added to Video Settings two months ago

For Galleries, I've noticed here that the SelectControl is used also for Image Sizes.

Probably we should sync here and have the same UX in both image sizes and gallery image sizes.

cc @iamthomasbishop @mkevins @pinarol

@etoledom etoledom self-requested a review January 23, 2020 14:10
@iamthomasbishop
Copy link

Probably we should sync here and have the same UX in both image sizes and gallery image sizes

Agreed, we probably should.

const { align, url, height, width, alt, href, id, linkTarget, sizeSlug } = attributes;

const actions = [ { label: __( 'Clear All Settings' ), onPress: this.onClearSettings } ];

const getImageSizeOptions = () => map( imageSizes, ( { label, slug } ) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's necessary to make that a function here, just computing size options should be fine:

const sizeOptions = imageSizes.map( ( { label, slug } ) => ( { value: slug, label } ) );

Copy link
Member Author

@cameronvoell cameronvoell Feb 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, fixed here: 9e71910

const id = `inspector-select-control-${ instanceId }`;

return (
<CyclePickerCell
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I see the benefit in having both a CycleSelectControl and a CyclePickerCell, they seem mostly identical.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd prefer to keep it this way for now. It matches other Control / BottomSheet Cell pairs like ToggleControl / SwitchCell and I think there may be implications later on related to cross platform controls, where the control might become independent of where it lives in the UI. This issue has some interesting conversation on that topic #18018

...cellProps
} = props;

const cycleOptionValue = () => {
Copy link
Contributor

@Tug Tug Jan 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A better name for this function imo would be nextOptionValue. Cycle does indicate that the possible options form a cycle but it's hard to understand that this is returning the next one from the currently selected one.
I think readability could be improved here as well, something as simple as this would really help I think

const nextOptionValue = () => {
	const selectedOptionIndex = findIndex( options, { value } );
	return options[ ( selectedOptionIndex + 1 ) % options.length ].value;
};

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to handle the case where options is en empty array as well ;)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated constant name 9aa8aa7 . Added checks here 12ebc85 so the image block will hide image size options if sizes / default are ever empty or not matching, and a check so that the CycleSelectControl value will just be blank if it is ever passed empty options.

<Cell
onPress={ () => onChangeValue( cycleOptionValue() ) }
editable={ false }
value={ options[ findIndex( options, [ 'value', value ] ) ].label }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, let's create variables with explicit names that should help improve readability.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment above, this was improved in 9aa8aa7 and 12ebc85

Copy link
Contributor

@Tug Tug left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change looks good, I had a few minor comments about the code but otherwise I think it's ready. I like the fact that we create a new SelectControl component for that!

@pinarol
Copy link
Contributor

pinarol commented Jan 27, 2020

@mkevins this is not urgent but could you open an issue to start a discussion about whether we want to use the same circle button for Gallery or not? I believe we should be consistent among blocks but Gallery settings are x-platform already, so let's see what we can do there. We can dive into this after finishing the upload option.

@etoledom
Copy link
Contributor

Thanks @pinarol !
@cameronvoell - Let's land this PR after addressing @Tug's comments 🎉

@mkevins
Copy link
Contributor

mkevins commented Feb 3, 2020

One consideration I have for this kind of UX is for users low bandwidth / connectivity. In earlier tests with Gallery image size options, I noticed that when I change size options, I must wait for a new file to download (each size option must be cached individually). This mean that to change sizes with a cycle picker, the user may be required to download all sizes to their device, as they cycle through them. I'm not sure how much of an issue this is, or how many users will utilize this feature with low bandwidth. Perhaps not a major issue, just wanted to note that. cc: @iamthomasbishop

@cameronvoell cameronvoell force-pushed the rnmobile/fix-image-size-ui-control branch from 8bd9ec1 to 9e71910 Compare February 3, 2020 06:32
@cameronvoell
Copy link
Member Author

@cameronvoell - Let's land this PR after addressing @Tug's comments 🎉

Thanks for the review @Tug! Let me know if it looks like I addressed your comments.

@cameronvoell cameronvoell requested a review from Tug February 3, 2020 09:10
Copy link
Contributor

@Tug Tug left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@iamthomasbishop
Copy link

Sorry @mkevins, I totally missed this last week!

One consideration I have for this kind of UX is for users low bandwidth / connectivity. In earlier tests with Gallery image size options, I noticed that when I change size options, I must wait for a new file to download (each size option must be cached individually). This mean that to change sizes with a cycle picker, the user may be required to download all sizes to their device, as they cycle through them. I'm not sure how much of an issue this is, or how many users will utilize this feature with low bandwidth. Perhaps not a major issue, just wanted to note that. cc: @iamthomasbishop

That's a great point, regarding offline or low-bandwidth situations. I wonder if there is any way to load only one size (large or full?) image behind the scenes and have the control only simulate the change? This would bring better performance for any bandwidth scenario.

@etoledom
Copy link
Contributor

I wonder if there is any way to load only one size (large or full?) image behind the scenes and have the control only simulate the change?

Sounds like a good option! And I believe it's possible 👍
But I'd add it as an optimisation on a separate ticket.

@iamthomasbishop
Copy link

Sounds like a good option! And I believe it's possible 👍
But I'd add it as an optimisation on a separate ticket.

Sounds good! 👍

@@ -357,9 +357,9 @@ export class ImageEdit extends React.Component {
},
];

const sizeOptions = map( imageSizes, ( { label, slug } ) => ( {
const sizeOptions = map( imageSizes, ( { name, slug } ) => ( {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to accommodate this change - #19800

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Mobile App - i.e. Android or iOS Native mobile impl of the block editor. (Note: used in scripts, ping mobile folks to change)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants