Skip to content

Create Modal Layout Picker Container for new Gutenberg pages and feature flag for development#14501

Merged
chipsnyder merged 51 commits intodevelopfrom
gutenberg/issue/2419-MLPContainer-smooth
Jul 30, 2020
Merged

Create Modal Layout Picker Container for new Gutenberg pages and feature flag for development#14501
chipsnyder merged 51 commits intodevelopfrom
gutenberg/issue/2419-MLPContainer-smooth

Conversation

@chipsnyder
Copy link
Copy Markdown
Contributor

@chipsnyder chipsnyder commented Jul 21, 2020

Fixes: wordpress-mobile/gutenberg-mobile#2419

Related PRs:

Description

Adds feature flags and a container view for creating a new modal layout for page creation in Gutenberg.

To test:

To disable or enable the development version of Modal Layout Picker

Classic Editor and Gutenberg Editor with Modal Layout Picker Disabled.

Note: Modal Layout Picker should be disabled and uneditable in any Release build

  • Create a new page from My Site
    • Create a new page by clicking on the Floating Toolbar Button on the My Site Page then select "Site Page"
    • Expect to see the page editor without being prompted with the new modal layout picker
  • Create a new page from Pages
    • Create a new page by clicking on the ➕ on the Pages screen
    • Expect to see the page editor without being prompted with the new modal layout picker

Gutenberg Editor with Modal Layout Picker Enabled

  • Create a new page from My Site
    • Create a new page by clicking on the Floating Toolbar Button on the My Site Page then select "Site Page"
    • Expect to see the modal layout picker container
    • Select "Create Blank Page"
    • Expect to see the page editor
  • Create a new page from Pages.
    • Create a new page by clicking on the ➕ icon on the Pages screen.
    • Expect to see the modal layout picker container
    • Select "Create Blank Page"
    • Expect to see the page editor

On the Modal Layout Picker

  • Selecting the ✖️icon in the top right-hand corner should close the modal without creating a page.
  • Swiping down around the "Grip" in the top middle of the modal should close the modal without creating a page.
    Dismissing the modal
  • Scrolling up in the stubbed rows should collapse the header. Collapsing the header should:
    • Minimize the title
    • Hide the prompt
    • Leave space for adding the category bar in the future.
  • Scrolling down in the stubbed rows should reset the header when reaching the top.
    Continuing to scroll down after reaching the top should dismiss the modal
  • Toggle Dark mode and check the style seems consistent with other views

Screenshots:

Container Collapsed Header Dark Mode

Additional Context

This PR was branched off #14456 using a slightly different approach. For design feedback history please see that PR.

There are some poor layout issues in landscape mode, specifically with larger dynamic fonts. The plan is to revisit landscape at a later point after more of the screen is filled out.

PR submission checklist:

  • I have considered adding unit tests where possible.
  • I have considered adding accessibility improvements for my changes.
  • I have considered if this change warrants user-facing release notes and have added them to RELEASE-NOTES.txt if necessary.

chipsnyder added 23 commits July 1, 2020 12:39
@peril-wordpress-mobile
Copy link
Copy Markdown

peril-wordpress-mobile bot commented Jul 21, 2020

You can test the changes on this Pull Request by downloading it from AppCenter here with build number: 32225. IPA is available here. If you need access to this, you can ask a maintainer to add you.

@peril-wordpress-mobile
Copy link
Copy Markdown

peril-wordpress-mobile bot commented Jul 21, 2020

Warnings
⚠️ PR has more than 500 lines of code changing. Consider splitting into smaller PRs if possible.

Generated by 🚫 dangerJS

@chipsnyder chipsnyder changed the title Gutenberg/issue/2419 mlp container smooth Create Modal Layout Picker Container for new Gutenberg pages and feature flag for development (A different approach) Jul 21, 2020
@peril-wordpress-mobile
Copy link
Copy Markdown

peril-wordpress-mobile bot commented Jul 21, 2020

You can trigger optional UI/connected tests for these changes by visiting CircleCI here.

@chipsnyder
Copy link
Copy Markdown
Contributor Author

@iamthomasbishop

One more thing I'd like is to try applying the regular or chrome system material to the navbar and footer bar (in iOS 12+, iirc), so when scrolling they would become translucent. Is that doable here, @chipsnyder ?

It looks like chrome system material is available on iOS 13+ so I can apply the standard blur on lower versions (this is what the footer had on previous builds).

The way I have the header set up I'll need to make some changes to the layout to get that working but I can get that wrapped up in the morning probably.

As for the animation of the title view, I got that setup. Let me know what you think about it. The only piece I couldn't get working great is when you scroll quickly you'll see both headers as one scrolls into view and the other is animating out.

I just triggered a new build so that should be ready soon if you want to give it a try while I adjust the header.

@iamthomasbishop
Copy link
Copy Markdown

The way I have the header set up I'll need to make some changes to the layout to get that working but I can get that wrapped up in the morning probably.

Sounds good 👍

As for the animation of the title view, I got that setup. Let me know what you think about it. The only piece I couldn't get working great is when you scroll quickly you'll see both headers as one scrolls into view and the other is animating out.

This feels really solid. The momentary double-title thing doesn't bother me a whole lot, but if you are able to solve it then even better. 😀

Copy link
Copy Markdown
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.

Thank you for the update @chipsnyder - It's looking a lot better now! 🙏

Landscape mode on iPhone 7 is now much better! 🎉

I added a few of code comments, only the one related to accessibility label might be a blocker for now.

The momentary double-title thing doesn't bother me a whole lot, but if you are able to solve it then even better. 😀

About the animation, it also looks good to me :)

I did a fast test anchoring the title's alpha value to the largeTitleView.frame.maxY value and got an interesting result:

title_animation

In this way the alpha animation speed is controlled by the scroll itself. Seems simple enough to be implemented in this round but I won't block on this one 👍

}

private static func showLayoutPicker(from controller: UIViewController, _ completion: @escaping TemplateSelectionCompletion) {
let storyboard = UIStoryboard(name: "LayoutPickerStoryboard", bundle: Bundle.main)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we have a convenience initializer here? It could return an optional instance of GutenbergLayoutPickerViewController, and its navigation controller can be accessed via UIViewController property.

Also, we have a StoryboardLoadable protocol that might be helpful

Alternatively, we could also instantiate the NavigationController in code and set its root controller to what we want. In this way the Storyboard only holds the Controller we are interested in (GutenbergLayoutPickerViewController in this case). And both the custom Navigation Controller and the Layout picker can also be used separately if needed in the future. But this also works well so ✅

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

both the custom Navigation Controller and the Layout picker can also be used separately if needed in the future.

This would still be possible in one storyboard. The Navigation Controller can still be created programmatically with the standard UINavigationController init methods. I can add a storyboardID to the Gutenberg Layout Picker View Controller Scene to allow the instantiation of that separately if needed.

Alternatively, we could also instantiate the NavigationController in code and set its root controller

I'm happy to switch this over if that's our standard practice. My goal here was to follow Apple's recommendation that the storyboard contains all of the design-time elements that are related to the flow of a set of screens. GutenbergLayoutPickerViewController assumes that the navigation controller is an instance of GutenbergLightNavigationController to hide the bar's shadow properly. Although with the changes I'll be making to add the visual effects @iamthomasbishop requested, I'll hide the navigation bar for this view instead. However, GutenbergLightNavigationController does still have other considerations in it to enforce the flow displays correctly, and using the view without a navigation controller won't work as we build out the preview button which will push a new view controller.

Since this felt more connected in the flow of the UI I felt the storyboard should include it to provide the full picture. If that time came when we did want to reuse the root view controller, that would still be doable with minimal code changes. Being forced to make those changes would also prompt the future developer to consider the best way to handle the design settings of the navigation controller to accommodate all of the uses.

Ultimately I think either approach will work, I just wanted to share my thoughts on it, and I'm happy to proceed in whichever way you feel is best and most consistent.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the detail explanation!

Originally the main idea behind my suggestion was to hide the required init steps and configuration inside the GutenbergLayoutPickerViewController, in a way that PageCoordinator.swift doesn't need to know about storyboard details that seems internal to the controller (specially with it being tightly bounded with the navigation controller).

The Storyboard config as you explained it makes perfect sense to me! Let's keep it this way.

<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="systemFillColor" red="0.47058823529999999" green="0.47058823529999999" blue="0.50196078430000002" alpha="0.20000000000000001" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" label="Close"/>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It's more recomendable to set accessibility labels via code so they are translated.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Is this more related to how we handle localization for our app? ie should I be setting all text programmatically?

If I localize the storyboard I get:

/* Class = "UIButton"; accessibilityLabel = "Close"; ObjectID = "Fgx-ig-LXQ"; */
"Fgx-ig-LXQ.accessibilityLabel" = "Close";

But if we don't localize the storyboards then I can move the other text values over.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this more related to how we handle localization for our app? ie should I be setting all text programmatically?

Yes I believe so. Our Localization scripts make use of NSLocalizedString to gather and send the strings to GlotPress, so using localized storyboard I believe it won't work.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the info! I'll move those strings over.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thank you!

Here's some info about localization best practices (from our team):
https://github.com/wordpress-mobile/WordPress-iOS/blob/develop/docs/localization.md

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

🙇‍♂️

@chipsnyder
Copy link
Copy Markdown
Contributor Author

chipsnyder commented Jul 28, 2020

I did a fast test anchoring the title's alpha value to the largeTitleView.frame.maxY value and got an interesting result:

I'm going to revisit this path to solve the double case. It looks like you're using a different anchor point than I was. The way I tried it originally was phasing in the other small title by the % that the big title was off the screen and it didn't look great, because you would see both.

I'm not sure I fully understand what you mean by anchoring the title's alpha value to the largeTitleView.frame.maxY The way I have this set up is it animation will begin animating once the view disappears.

Can you share the snippit you used for your quick test?

@chipsnyder
Copy link
Copy Markdown
Contributor Author

@iamthomasbishop and @etoledom This is updated now with a new build (32185) generated for the header chrome style. However, It's hard to see the difference without setting the background color for cells. So we might want to focus on that in the next PR when I add some content to the rows.

I also didn't make any changes to the header animation. I started building in a cancel for that, but it started causing crashes. So I figured that might be better to adjust toward the end if we still want to.

@etoledom
Copy link
Copy Markdown
Contributor

etoledom commented Jul 29, 2020

By Anchoring I just meant making it (inverse) relative to largeTitleView.frame.maxY.

Can you share the snippit you used for your quick test?

This is a quite rough example (edited a bit more concise):

func scrollViewDidScroll(_ scrollView: UIScrollView) {
       // ....

        let alpha = (-largeTitleView.frame.maxY / 10.0).clamp(min: 0, max: 1)
        titleView.isHidden = alpha == 0
        titleView.alpha = alpha
}

Then you removed everything related to titleIsHidden.

There might be other considerations too with the code to handle small screen sizes.

@etoledom
Copy link
Copy Markdown
Contributor

It's hard to see the difference without setting the background color for cells. So we might want to focus on that in the next PR when I add some content to the rows.

I agree with this too! 👍

@chipsnyder
Copy link
Copy Markdown
Contributor Author

@etoledom Those static strings have been moved to be programmatic now. I left the original values for the labels in place just to help the system guess an appropriate intrinsic size after loading.

@chipsnyder
Copy link
Copy Markdown
Contributor Author

chipsnyder commented Jul 29, 2020

By Anchoring I just meant making it (inverse) relative to largeTitleView.frame.maxY.

Ah ok, I see what you're doing here. When I did it, I originally had

let alpha = (largeTitleView.frame.height-largeTitleView.frame.maxY / largeTitleView.frame.height)

So as the large title was getting close to disappearing, the small title would appear, and then you ended up with a case where both were showing which I didn't like.

I put this in place, and it seems to be working well. I just needed to make some adjustments to when it "snaps" into place and when entering compact views. There is an additional point in the scrolling where you don't see either header in this approach compared to the other however the "snap" fixes that so it wouldn't really be noticeable.

Just as a quick aside where did you come up with the 10? Or is this just a magic number that felt right?

Edit:

After doing some more testing on this approach I'm noticing the view flashes a bit. Since we're happy with the animation the way it is I think I would prefer to explore this approach at a later time. WDYT?

RPReplay_Final1596045746 2020-07-29 14_07_49

@etoledom etoledom self-requested a review July 30, 2020 11:16
Copy link
Copy Markdown
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.

Thank you for the update!

With the changes on the header, is it still necessary to have a custom Navigation Controller?

After doing some more testing on this approach I'm noticing the view flashes a bit. Since we're happy with the animation the way it is I think I would prefer to explore this approach at a later time. WDYT?

Absolutely, let's not block this PR on the animation 👍

Just as a quick aside where did you come up with the 10? Or is this just a magic number that felt right?

Yeah, it's a magic number.
I noticed that maxY changed around 1 to 10 in the range we were interested in, so dividing that by 10 looked like a good option. But doesn't have to be strictly 10.

(Looks like kind of a t = d/v equation 🤔, so 10 would be the velocity of the transition).

About the glitch (for a future PR):
We could try fix that glitch if we start the alpha changes a bit earlier. Let's say half height of the largeTitleView earlier. Something like:

let alpha = -(maxY - (height / 2)) / 10
Very similar to what you had previously :)
In this way on the snap position, the calculation already gives alpha = 1 and it won't jump to other values.


Let's move ahead, this looks good and feels great! Nice job @chipsnyder 🎉

@chipsnyder
Copy link
Copy Markdown
Contributor Author

Thanks @etoledom, I appreciate your great review :)

With the changes on the header, is it still necessary to have a custom Navigation Controller?

The style for the navigation bar when we push the Preview screen is a bit different than the existing Light Navigation Controller so we'll still want the customized one for that.

@chipsnyder chipsnyder merged commit 2f045a6 into develop Jul 30, 2020
@chipsnyder chipsnyder deleted the gutenberg/issue/2419-MLPContainer-smooth branch July 30, 2020 14:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Modal Layout Picker] Create Modal window for Modal Layout Picker

3 participants