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

Gravatar: Show current user's local image #9369

Merged
merged 2 commits into from
Nov 17, 2016
Merged

Conversation

v18
Copy link
Contributor

@v18 v18 commented Nov 15, 2016

The changes in this PR:

  • <Gravatar /> becomes a connected component that uses getUserTempGravatar
  • <Gravatar /> exports default and Gravatar. The 3 components that use require to use <Gravatar /> now use the default export
  • update <Gravatar /> to an ES6 class

What we're testing

In each case, test to make sure that the <Gravatar/> on the page shows up, and that there are no errors in the console.

Manual Testing

The three components that use require to use <Gravatar /> are:

  1. components/user (UserItem)
    This can be tested at http://calypso.localhost:3000/settings/import/$wpcom_site by going through an import
  2. my-sites/people/delete-user (DeleteUser)
    This cannot be tested right now since the component seems to not be working atm (not allowing to reassign posts to a user). The link to test is here: http://calypso.localhost:3000/people/edit/editor/$jetpack_site - try deleting a user
  3. post-editor/editor-author (EditorAuthor)
    This can be tested at the editor: http://calypso.localhost:3000/post/$site

The following components use import to use <Gravatar />, and did not need to be changed, sorted by URL:

A: http://calypso.localhost:3000/read/feeds/45401477/posts/1216523546#comments

  1. reader/comments/form.jsx - try to leave a comment
  2. reader/comments/post-comment.jsx - read the comments already there
  3. blocks/reader-avatar (ReaderAvatar)
  4. blocks/reader-related-card-v2 (RelatedPostCard)

B: http://calypso.localhost:3000/posts/my/$site

  1. blocks/comments/form.jsx (PostCommentForm) - leave a comment
  2. blocks/comments/post-comment - view comments
  3. my-sites/posts/posts-navigation - the navigation bar at the top of the page: published/me/everyone

C: http://calypso.localhost:3000/me

  1. layout/masterbar/logged-in - the masterbar
  2. me/sidebar-navigation/sidebar-navigation.jsx
  3. me/profile-gravatar
  4. EditGravatar

D: http://calypso.localhost:3000/
reader/post-byline

E: http://calypso.localhost:3000/people/team/$site
my-sites/people/people-profile

F: http://calypso.localhost:3000/posts/$site
my-sites/draft/index.jsx click on 'everyone' to see the drafts list with Gravatars

G: http://calypso.localhost:3000/read/a8c
reader/site-and-author-icon/ - find an x-post

H: http://calypso.localhost:3000/devdocs/blocks/search-card
blocks/reader-author-and-site (AuthorAndSite) (not in prod)

I: http://calypso.localhost:3000/recommendations/start
reader/start/post-preview.jsx

J: http://calypso.localhost:3000/jetpack/connect
signup/jetpack-connect/authorize-form.jsx enter a .org URL to connect to JP

K: user invitation link

  1. my-sites/invites/invite-header
  2. my-sites/invites/invite-accept-logged-in

L: https://wpcalypso.wordpress.com/devdocs/blocks/happiness-support
components/happiness-support (HappinessSupport)

M: http://calypso.localhost:3000/help
me/help/help-happiness-engineers

N: Component: signup/jetpack-connect/sso.jsx. Steps:

  1. Start with a connected Jetpack site
  2. Enable the SSO module in Jetpack
  3. Sign out of both .com and the Jetpack site
  4. Sign in to WP.com with a different account (that isn't connected to the Jetpack site)
  5. Visit selfhostedsite/wp-admin
  6. "Connect to WP.com:
  7. See a "Connect with WordPress.com" screen, switch to calypso.localhost:3000 in the URL
  8. Make sure you see the <Gravatar /> and no errors

e2e tests

For the original PR (#8456) that attempted to make similar changes there were some failing e2e tests. All of the e2e tests pass, except these 3:

  • wp-post-nux-spec: customizer timeout
  • wp-theme-multisite-spec: timeout on element (cannot repro, and element we're waiting for does indeed not exist)
  • wp-theme-switch-spec: timeout on element (cannot repro, and element we're waiting for does indeed not exist)

@v18 v18 added [Feature] User & Account Settings (/me) Settings and tools for managing your WordPress.com user account. [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. labels Nov 15, 2016
@matticbot
Copy link
Contributor

@@ -6,7 +6,7 @@ var React = require( 'react' );
/**
* Internal dependencies
*/
var Gravatar = require( 'components/gravatar' );
var Gravatar = require( 'components/gravatar' ).default;
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's change this to an import usage. This protects us against breakages if components/gravatar goes back to exporting 1 thing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed, that's a better plan :) Updated all the components to use import instead.

}

export default connect( ( state, ownProps ) => {
const userId = ownProps.user && ownProps.user.ID;
Copy link
Contributor

Choose a reason for hiding this comment

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

Optional:

get( ownProps, 'user.id', false );

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's neat, I'm using it now. Didn't use false as the fallback since we're expecting undefined anyway.

this.setState( { failedToLoad: true } );
},
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Needs a semicolon

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Missed this one earlier, fixed now.

@@ -18,7 +18,7 @@ const Card = require( 'components/card' ),
FormButtonsBar = require( 'components/forms/form-buttons-bar' ),
AuthorSelector = require( 'blocks/author-selector' ),
UsersActions = require( 'lib/users/actions' ),
Gravatar = require( 'components/gravatar' ),
Gravatar = require( 'components/gravatar' ).default,
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's add an Gravatar import after the requires. We can go back to clean up the rest of the requires in a follow up janitorial PR

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

@@ -6,7 +6,7 @@ const React = require( 'react' );
/**
* Internal dependencies
*/
const Gravatar = require( 'components/gravatar' ),
const Gravatar = require( 'components/gravatar' ).default,
Copy link
Contributor

Choose a reason for hiding this comment

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

imports seems small enough in this file to convert all of them

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

@v18 v18 force-pushed the add/gravatar-image-editor branch from 224b054 to de6c9e0 Compare November 15, 2016 22:04
@v18 v18 force-pushed the add/gravatar-local-image branch from 6c06b1c to d9c0e7e Compare November 15, 2016 22:45
@v18
Copy link
Contributor Author

v18 commented Nov 15, 2016

Updated & rebased branch.

@v18 v18 force-pushed the add/gravatar-local-image branch 2 times, most recently from adcbea7 to 022b060 Compare November 16, 2016 15:06
@v18 v18 changed the base branch from add/gravatar-image-editor to master November 16, 2016 15:06
@gwwar
Copy link
Contributor

gwwar commented Nov 16, 2016

👍 Verified that only usage of require( 'components/gravatar' ) is in a test. With the feature turned off, I can post/navigate normally

@gwwar
Copy link
Contributor

gwwar commented Nov 16, 2016

👍 With the feature on, my gravatar is updated instantly, and within 5 min, if I refresh it will correctly show the gravatar src vs the local cache.

Copy link
Contributor

@lamosty lamosty left a comment

Choose a reason for hiding this comment

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

Nice work!

The code is working fine (I didn't find any regressions). However, I added a few smaller things/ideas. Could you please look at them?

export class Gravatar extends Component {
constructor() {
super( ...arguments );
this.state = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of having to write constructor just to set the initial state, I discovered that we can use ES7 static properties to define the initial state as well. This is how:

export class Gravatar extends Component {
   state = {
      failedToLoad: false
   };

 // ... other code follows

Note: I'm not 100% sure it'll work, actually. Haven't tried myself. :)

Copy link
Contributor

Choose a reason for hiding this comment

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

You mean property initializers right, since we don't want this to be static. 😄 I'm fine with the above usage

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Leaving as-is for now.


propTypes: {
static displayName = 'Gravatar';
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need this for the case when require is used instead of import?

Copy link
Contributor

@gwwar gwwar Nov 16, 2016

Choose a reason for hiding this comment

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

Oh missed this, but displayName is added in a babel transform, so this isn't necessary here unless we want one that has a different value from the class name

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 good catch, I removed it.

propTypes: {
static displayName = 'Gravatar';

static propTypes = {
user: React.PropTypes.object,
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we import PropTypes directly so we don't have to write React. before it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good! Imported PropTypes.

},
imgSize: React.PropTypes.number,
// connected props:
tempImage: React.PropTypes.oneOfType( [
Copy link
Contributor

Choose a reason for hiding this comment

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

Why can be the tempImage both a string and a bool? We could maybe add some inline comment to clarify further. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure thing, added comments to clarify.

failedToLoad: false
};
},
imgSize: 96,
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this in px? If yes, could we add it as an inline comment, please?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm! Not really sure about adding a comment here since it's not obvious at first glance what imgSize and size are there for, and if they both have a px comment it may get more confusing. Both of these are described in the README - is that enough to go on, what do you think @lamosty?

Copy link
Contributor

Choose a reason for hiding this comment

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

If it's in README (sorry for not noticing), it's good enough. :)

const avatarURL = this.getResizedImageURL( safeImageURL( this.props.user.avatar_URL ) );

const avatarURL = this.props.tempImage ||
this.getResizedImageURL( safeImageURL( this.props.user.avatar_URL ) );
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we extract these props out of props at the top of the function? Like:

const {
   alt,
   user,
   tempImage,
   size
   // etc...
} = this.props;

Also, shouldn't we write a new selector for getting the user's avatar_URL instead of accessing it directly like user.avatar_URL? :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could we extract these props out of props

Yes :) I extracted the props in render and also in getResizedImageURL.

shouldn't we write a new selector for getting the user's avatar_URL

Do you mean a new redux selector? If so, some components use their own user objects, not relying on the users in state.users, so they won't be able to pass in an ID and let <Gravatar /> get the selected user's info. For example, ReaderAvatar.


export default connect( ( state, ownProps ) => {
return {
tempImage: getUserTempGravatar( state, get( ownProps, 'user.ID' ) ),
Copy link
Contributor

Choose a reason for hiding this comment

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

We could maybe default to the ID of the current user in get( ownProps, 'user.ID' ) if user object is not provided in ownProps.

Copy link
Contributor Author

@v18 v18 Nov 16, 2016

Choose a reason for hiding this comment

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

Do you mean the user passed in to the <Gravatar /> component? If that's the case, we don't always have an ID or a user object to rely on. I'd rather not complicate the logic, since getUserTempGravatar expects a missing ID if we don't have it, so I think it's ok not to provide anything in that case.

Copy link
Contributor

@lamosty lamosty Nov 16, 2016

Choose a reason for hiding this comment

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

Okay, I see.

The idea I have is to return some default value from the get helper fn if user.ID is not found in ownProps. It would be a bit easier to reason about if I saw the default value there.

In case getUserTempGravatar accepts false as the userId, we can just add it like:

tempImage: getUserTempGravatar( state, get( ownProps, 'user.ID', false ) )

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I can dig adding a default value instead of relying on undefined for readability. Updated it here, and added a test.

@@ -18,9 +18,9 @@ const Card = require( 'components/card' ),
FormButtonsBar = require( 'components/forms/form-buttons-bar' ),
AuthorSelector = require( 'blocks/author-selector' ),
UsersActions = require( 'lib/users/actions' ),
Gravatar = require( 'components/gravatar' ),
accept = require( 'lib/accept' ),
analytics = require( 'lib/analytics' );
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe add a blank line below so old requires and new imports are separated. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried it out with a new line, and the extra space makes it seem like <Gravatar /> is not an internal dependency, so I guess it's a bit strange either way. It looks ok to me without the extra line since the import keyword is in a new block-ish, so thinking of leaving as is.

Copy link
Contributor

Choose a reason for hiding this comment

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

We should just follow up by porting the rest of the requires to imports in a janitorial PR. Spacing isn't a huge deal for now.

@lamosty lamosty added [Status] Needs Author Reply and removed [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. labels Nov 16, 2016
@v18 v18 force-pushed the add/gravatar-local-image branch from 022b060 to 8a9ca8c Compare November 16, 2016 23:21
@v18
Copy link
Contributor Author

v18 commented Nov 16, 2016

Updated, added README section, and rebased.

@gwwar gwwar dismissed lamosty’s stale review November 16, 2016 23:49

Feedback looks good. Let's put larger changes such as new selectors into a follow up PRs

@gwwar gwwar added [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. and removed [Status] Ready to Merge labels Nov 16, 2016
import PostActions from 'lib/posts/actions';
import touchDetect from 'lib/touch-detect';
import sitesFactory from 'lib/sites-list';
import stats from 'lib/posts/stats';
Copy link
Contributor

Choose a reason for hiding this comment

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

Whoops, this one is easy to miss. So either

import { recordStat, recordEvent } from 'lib/posts/stats';
//plus update usages below

or

import * as stats from 'lib/posts/stats';

Copy link
Contributor

Choose a reason for hiding this comment

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

As you mentioned, we can repro the issue by navigating to a multi-author site, start a draft, then attempt to change author:
screen shot 2016-11-16 at 4 29 34 pm

Copy link
Contributor

Choose a reason for hiding this comment

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

I did a quick audit of the other imports, and they look ok.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to import * as stats from 'lib/posts/stats';. All other imports looks ok to me, too.

@v18 v18 force-pushed the add/gravatar-local-image branch 2 times, most recently from 8ab9560 to 31036a1 Compare November 17, 2016 14:51
expectedResultString = '<img alt="Bob The Tester" class="gravatar" ' +
'src="https://0.gravatar.com/' +
'avatar/cf55adb1a5146c0a11a808bce7842f7b?s=96&amp;d=mm" ' +
'width="32" height="32"/>';
Copy link
Member

Choose a reason for hiding this comment

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

let's also use one const or let per variable please 😄

expectedResultString = '<img alt="Bob The Tester" class="gravatar" ' +
'src="https://0.gravatar.com/' +
'avatar/cf55adb1a5146c0a11a808bce7842f7b?s=96&amp;d=mm" ' +
'width="32" height="32"/>';

assert.equal( expectedResultString, stripReactAttributes( ReactDomServer.renderToStaticMarkup( gravatar ) ) );
Copy link
Member

Choose a reason for hiding this comment

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

@v18 I highly recommend you check out enzyme() for testing. it can make testing React components significantly easier.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@dmsnell - these tests were written before my time. I'm not sure that updating the tests for this PR falls under the scope here :) The tests I wrote for a different PR use enzyme <3

Copy link
Member

Choose a reason for hiding this comment

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

@v18 as you will. I would hate to add more cruft if it's not too much more work to update there. wouldn't have to change the whole file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@dmsnell I know what you mean :) On the other hand, to change the tests, I'd need to rework the entire file, no? They all rely on checking the final HTML output vs checking properties.

@dmsnell
Copy link
Member

dmsnell commented Nov 17, 2016

@v18 why are we assigning a temporary src and providing selectors for it?

@gwwar
Copy link
Contributor

gwwar commented Nov 17, 2016

why are we assigning a temporary src and providing selectors for it?

This is so when you update a gravatar on /me, you see the change immediately. Otherwise it will take another 5 minutes before the gravatar img cache expires.

@dmsnell
Copy link
Member

dmsnell commented Nov 17, 2016

This is so when you update a gravatar on /me, you see the change immediately. Otherwise it will take another 5 minutes before the gravatar img cache expires.

how does this matter to Calypso though? if we change the avatar in our state, why does the gravatar cache matter?

@v18
Copy link
Contributor Author

v18 commented Nov 17, 2016

@dmsnell - so when we request an image, Gravatar sends back the response with a cache directive of 5 minutes. This means that even when the image is updated on Gravatar.com, the browser won't refetch it. It's a bit more complicated since Chrome will actually not refetch it even after 5 minutes.

For the user this means that the image won't show up immediately, which is :sadxmas:, so we display the local image we already have once it's uploaded for a smooth experience.

I went over some more details in #9212.

@v18 v18 force-pushed the add/gravatar-local-image branch from 31036a1 to da655a5 Compare November 17, 2016 16:21
@v18
Copy link
Contributor Author

v18 commented Nov 17, 2016

Updated with above comments, & rebased.

@dmsnell
Copy link
Member

dmsnell commented Nov 17, 2016

For the user this means that the image won't show up immediately, which is :sadxmas:, so we display the local image we already have once it's uploaded for a smooth experience.

this is indeed sad, but do we need the temp image? if we're going to be using it, why not simply store the uploaded "temporary" image as the de-facto real gravatar image and forget about the "temp" stuff. it will only persist through the current browsing session anyway (unless the user uploads another one).

on the other hand, the "temporary" image won't persist either, will it? won't we need to grab the Gravatar URL on each actual Calypso load?

@v18
Copy link
Contributor Author

v18 commented Nov 17, 2016

this is indeed sad, but do we need the temp image? if we're going to be using it, why not simply store the uploaded "temporary" image as the de-facto real gravatar image and forget about the "temp" stuff.

I'm not sure I understand what you mean here. Store the uploaded "temporary" image where?

on the other hand, the "temporary" image won't persist either, will it? won't we need to grab the Gravatar URL on each actual Calypso load?

Yes, that's correct. In fact we fetch Gravatars many times through the lifecycle of one browsing session. This is probably true even if is less than 5 minutes, since we use many Gravatar sizes.

@dmsnell
Copy link
Member

dmsnell commented Nov 17, 2016

I'm not sure I understand what you mean here. Store the uploaded "temporary" image where?

instead of doing

gravatarUrl = buildGravatarUrl( email )
tempAvatarUrl = uploadedImageUrl

do

gravatarUrl = uploadedImageUrl

we fetch Gravatars many times through the lifecycle of one browsing session

are we doing multiple fetches for any given email? why would we do that? if we are, it seems like it would be worthwhile to store the returned Gravatar URL in state and not fetch it again if we already have it. we could surely get out of sync with Gravatar, but within a single session is probably more than sufficient.

@dmsnell
Copy link
Member

dmsnell commented Nov 17, 2016

This is probably true even if is less than 5 minutes, since we use many Gravatar sizes.

does the temporary URL work as-is even when requesting multiple sizes?

@gwwar
Copy link
Contributor

gwwar commented Nov 17, 2016

this is indeed sad, but do we need the temp image?

It's nice user feedback that something happened. I suggest you walk through steps in #9317

The difference being that at the end of the flow you see the new image rather than the old gravatar
45a390ac-a867-11e6-8906-81708764a695-1

won't we need to grab the Gravatar URL on each actual Calypso load?

Which is fine since Gravatar should be the source of truth

@v18
Copy link
Contributor Author

v18 commented Nov 17, 2016

are we doing multiple fetches for any given email? why would we do that? if we are, it seems like it would be worthwhile to store the returned Gravatar URL in state and not fetch it again if we already have it. we could surely get out of sync with Gravatar, but within a single session is probably more than sufficient.

@dmsnell Yes, exactly, we are doing multiple fetches. The reason is because we sometimes request Gravatars of different sizes. Also, after the 5 minute cache is up, the browser should be re-fetching the cached result of the previous fetch, given browser specs.

I agree with you, there are definitely a bunch of unneeded network requests going on. I'm not 100% sure yet whether tackling Gravatar network requests is of one of the highest priorities in Calypso, even in terms of performance work. I think that after the new uploading Gravatar feature is done, it would be worthwhile to examine if it's a good road to go under given other priorities.

does the temporary URL work as-is even when requesting multiple sizes?

Yes. The temporary image is locally stored as a base64 string, so we're not doing network requests to get different sizes.

@gwwar
Copy link
Contributor

gwwar commented Nov 17, 2016

it seems like it would be worthwhile to store the returned Gravatar URL in state and not fetch it again if we already have it

There's already a browser cache of 5 minutes. I don't think it's worthwhile to have application state deal with caching and invalidating this for other users whose gravatars won't change

For the uploaded image we went for the simple approach:
#8456 (comment)

@dmsnell
Copy link
Member

dmsnell commented Nov 17, 2016

okay @gwwar and @v18 this is all fine. based on what I'm reading, I think we could have gotten away without creating a bunch of temp variables and complexity, but since this is now so far along in the process I'm going to back away from it.

if we're storing the temp image and know when to stop using it, we could just as easily store the temp image as truth and know when to stop using it as well. just a little nudge that things aren't always as inherently complex as they may seem.

@dmsnell
Copy link
Member

dmsnell commented Nov 17, 2016

Which is fine since Gravatar should be the source of truth

well, we are explicitly stating here that it shouldn't be (by means of the temp image). this is why I advocate so strongly for designing Calypso such that our app state is the source of truth and any changes from the outside should come in through a middleware layer - trust the framework to manage the data.

@gwwar
Copy link
Contributor

gwwar commented Nov 17, 2016

we could just as easily store the temp image as truth and know when to stop using it as well. just a little nudge that things aren't always as inherently complex as they may seem.

Polling the user object would overwrite any temp images. Knowing what values to keep is difficult without adding complexity

@v18 v18 force-pushed the add/gravatar-local-image branch from da655a5 to 383fa5e Compare November 17, 2016 17:59
@v18
Copy link
Contributor Author

v18 commented Nov 17, 2016

Updated the branch. All e2e pass, and all the manual tests are working.

@gwwar gwwar added [Status] Ready to Merge and removed [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. labels Nov 17, 2016
@gwwar
Copy link
Contributor

gwwar commented Nov 17, 2016

Let's :shipit: and keep a close eye on the deploy. Great work @v18 !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] User & Account Settings (/me) Settings and tools for managing your WordPress.com user account.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants