fix(avatars): load profile image on settings and sign in pages if available #1733
Conversation
|
Now that |
|
@zaach is this ready for review, or still WIP while we sort out Travis issues? |
|
@pdehaan You can begin review, I should only need to fix the tests. |
b3c8f01
to
cfbed6d
| promise = this.profileClient.getAvatar() | ||
| .then(function (result) { | ||
| if (result.avatar && result.id) { | ||
| Session.set('avatar', result.avatar); |
nchapman
Oct 6, 2014
Contributor
Since we're trying to use Session less, do you think it makes sense to use sessionStorage or localStorage directly here?
Since we're trying to use Session less, do you think it makes sense to use sessionStorage or localStorage directly here?
zaach
Oct 6, 2014
Author
Contributor
Hmm, well we're using it in other views that access the avatar also. I'm inclined to refactor it all at once, e.g. if we merge it into a user model.
Hmm, well we're using it in other views that access the avatar also. I'm inclined to refactor it all at once, e.g. if we merge it into a user model.
nchapman
Oct 6, 2014
Contributor
Yep that makes sense. Carry on!
Yep that makes sense. Carry on!
shane-tomlinson
Oct 7, 2014
Member
I'm introducing a user model in #1646, be prepared. I'm somewhat inclined to think an Avatar could be its own model that is a child of the User model...
I'm introducing a user model in #1646, be prepared. I'm somewhat inclined to think an Avatar could be its own model that is a child of the User model...
| @@ -55,6 +56,13 @@ function (_, p, BaseView, FormView, SignInTemplate, Session, PasswordMixin, Auth | |||
| 'click .use-different': 'useDifferentAccount' | |||
| }, | |||
|
|
|||
| beforeRender: function () { | |||
nchapman
Oct 6, 2014
Contributor
Could this slow down sign in if it takes a while to fetch the image? Would it be better to do this after render?
Could this slow down sign in if it takes a while to fetch the image? Would it be better to do this after render?
zaach
Oct 6, 2014
Author
Contributor
Sure if we're okay with it flashing the default image.
Sure if we're okay with it flashing the default image.
nchapman
Oct 6, 2014
Contributor
Yeah I'm not sure what's preferable. Since images traditionally load async, I don't think it'd feel too unnatural for it to load post render. I think we'd want to leave it blank and just drop in the image, rather than re-rendering the view to minimize any flicker. This isn't a show stopper. Just something to consider.
Yeah I'm not sure what's preferable. Since images traditionally load async, I don't think it'd feel too unnatural for it to load post render. I think we'd want to leave it blank and just drop in the image, rather than re-rendering the view to minimize any flicker. This isn't a show stopper. Just something to consider.
ckarlof
Oct 6, 2014
Contributor
This might be a tricky issue. I'd prefer not to see the flashing if the image load is quick, but if it's slow for some reason (say 5-10s), showing the default image (or spinner) after some reasonable amount time may signal that "nothing's obviously broken".
This might be a tricky issue. I'd prefer not to see the flashing if the image load is quick, but if it's slow for some reason (say 5-10s), showing the default image (or spinner) after some reasonable amount time may signal that "nothing's obviously broken".
nchapman
Oct 6, 2014
Contributor
Agreed. I do think though in many cases that loading the image after render (especially in the cached case) would be imperceptible to the user as long as nothing shifts position. It does feel a bit risky to make the sign in flow dependent on the avatar when it's not absolutely critical.
Agreed. I do think though in many cases that loading the image after render (especially in the cached case) would be imperceptible to the user as long as nothing shifts position. It does feel a bit risky to make the sign in flow dependent on the avatar when it's not absolutely critical.
zaach
Oct 6, 2014
Author
Contributor
Good point... Maybe we should switch to afterRender and if flashing is noticeable during dogfooding, we can do something more involved with spinners.
Good point... Maybe we should switch to afterRender and if flashing is noticeable during dogfooding, we can do something more involved with spinners.
|
So just to be clear: there's still no way to set an avatar, correct? Everyone will be seeing the default for now? |
|
@nchapman Right, only people who know the super secret URL will be able to change their avatar. |
Okay great. |
|
|
||
| return view.render() | ||
| .then(function () { | ||
| assert.equal(view.$('.avatar-wrapper img').length, 0); |
nchapman
Oct 6, 2014
Contributor
So the default image doesn't use an img tag?
So the default image doesn't use an img tag?
nchapman
Oct 6, 2014
Contributor
Ah ok cool.
Ah ok cool.
f604d04
to
ec51fd9
| @@ -43,8 +45,28 @@ function (_, FormView, BaseView, Template, Session, Constants) { | |||
| success: t('Signed out') | |||
| }); | |||
| }); | |||
| }, | |||
|
|
|||
| afterVisible: function () { | |||
shane-tomlinson
Oct 7, 2014
Member
You know, I completely forgot about afterVisible, this would have been useful in the "smooth out the verification flow" PR.
You know, I completely forgot about afterVisible, this would have been useful in the "smooth out the verification flow" PR.
| ], function (p, Session) { | ||
|
|
||
| return { | ||
| // Attempt to load a profile image from the profile server and cache it on Session |
ckarlof
Oct 7, 2014
Contributor
How does this cache get invalidated if the image changes?
How does this cache get invalidated if the image changes?
zaach
Oct 7, 2014
Author
Contributor
It won't be. Alternatively, we can always check the server.
It won't be. Alternatively, we can always check the server.
ckarlof
Oct 7, 2014
Contributor
Let's remove the URL caching for now and push this out to the next train.
Let's remove the URL caching for now and push this out to the next train.
zaach
Oct 7, 2014
Author
Contributor
It's now loaded from the server each time 👍
It's now loaded from the server each time
| } | ||
| }); | ||
| } else { | ||
| // We already have a profile image in Session |
ckarlof
Oct 7, 2014
Contributor
This means we have a profile image URL, correct?
This means we have a profile image URL, correct?
zaach
Oct 7, 2014
Author
Contributor
Right.
Right.
| }, | ||
|
|
||
| afterVisible: function () { | ||
| return this.loadProfileImage(); |
shane-tomlinson
Oct 7, 2014
Member
Does the base class's afterVisible need to be called?
Does the base class's afterVisible need to be called?
| }, function () { | ||
| // Ignore errors and just show the default image | ||
| }); | ||
| }, |
shane-tomlinson
Oct 7, 2014
Member
I think the base class' afterVisible should be called to force an autofocus.
I think the base class' afterVisible should be called to force an autofocus.
zaach
Oct 7, 2014
Author
Contributor
Added 👍
Added
| 'views/decorators/progress_indicator' | ||
| ], | ||
| function (_, p, BaseView, FormView, SignInTemplate, Session, PasswordMixin, AuthErrors, Validate, ServiceMixin, showProgressIndicator) { | ||
| function (_, p, BaseView, FormView, SignInTemplate, Session, PasswordMixin, AuthErrors, Validate, ServiceMixin, AvatarMixin, showProgressIndicator) { |
shane-tomlinson
Oct 7, 2014
Member
Can you break this line, it's running off the end of the screen.
Can you break this line, it's running off the end of the screen.
| 'lib/session', | ||
| 'lib/constants' | ||
| ], | ||
| function (_, FormView, BaseView, Template, Session, Constants) { | ||
| function (_, FormView, BaseView, AvatarMixin, Template, AuthErrors, Session, Constants) { |
shane-tomlinson
Oct 7, 2014
Member
Is AuthErrors used?
Is AuthErrors used?
|
|
||
| view = new View({ | ||
| router: routerMock, | ||
| metrics: metrics, | ||
| window: windowMock, | ||
| fxaClient: fxaClient, | ||
| profileClient: profileClientMock, |
shane-tomlinson
Oct 7, 2014
Member
@ckarlof brought up the idea a few weeks back of adding all these dependencies to a single object, that then gets passed around to the various views. I'm really beginning to see the value of that. We have both had to update tests just to pass in dependencies recently.
@ckarlof brought up the idea a few weeks back of adding all these dependencies to a single object, that then gets passed around to the various views. I'm really beginning to see the value of that. We have both had to update tests just to pass in dependencies recently.
zaach
Oct 7, 2014
Author
Contributor
I like it.
I like it.
| }) | ||
| .then(function (found) { | ||
| if (found) { | ||
| self.logEvent(self.className + '.profile_image_shown'); |
shane-tomlinson
Oct 8, 2014
Member
Should we log a profile_image_now_shown if found === false, or is that taken care of in the error handler?
Should we log a profile_image_now_shown if found === false, or is that taken care of in the error handler?
| return true; | ||
| } | ||
| }) | ||
| .then(function (found) { |
shane-tomlinson
Oct 8, 2014
Member
Can this then be collapsed into the one above?
Can this then be collapsed into the one above?
| return this.profileClient.getAvatar() | ||
| .then(function (result) { | ||
| if (result.avatar && result.id) { | ||
| Session.set('avatar', result.avatar); |
shane-tomlinson
Oct 8, 2014
Member
It looks like we are fetching the avatar in multiple views, but then saving the avatar into the Session. Could we just skip the storage into the Session and return the avatar from profileClient.getAvatar()? Does profileClient.getAvatar cache the images?
It looks like we are fetching the avatar in multiple views, but then saving the avatar into the Session. Could we just skip the storage into the Session and return the avatar from profileClient.getAvatar()? Does profileClient.getAvatar cache the images?
zaach
Oct 8, 2014
Author
Contributor
No, there's no caching in the profileClient. The other avatar pages still use Session.avatar, but we could rip that out and always load it from the server there, too.
No, there's no caching in the profileClient. The other avatar pages still use Session.avatar, but we could rip that out and always load it from the server there, too.
| return this._fetchProfileImage() | ||
| .then(function () { | ||
| if (Session.avatar) { | ||
| self.$('.avatar-wrapper').append(new Image()); |
shane-tomlinson
Oct 8, 2014
Member
This code is also in settings.js, can it ripped out and added to the avatar-mixin?
This code is also in settings.js, can it ripped out and added to the avatar-mixin?
|
@shane-tomlinson Aha– those tests should be removed since |
|
This also reproduces in prod - filed this bug as #1877 |
|
@zaach - another strange Sync case:
Error in the console:
|
6e0fe08
to
5ef6277
This refactor changes a number of things: - introduces User and Account models - imports old Session based sessions into User - handles direct link to settings page from RPs for a specified account (fixes #1686) - redirects unverified accounts that visit /settings (fixes #1716) - introduces a way to pass ephemeral data between views - removes unused avatar-change-via-URL resources/tests (fixes #1544, fixes #1618)
8034039
to
3a6dd96
3a6dd96
to
0492140
|
Congratz @zaach! |
This refactor changes a number of things:
* fix avatar background (fixes #1722)
* loads profile images on settings and sign in account chooser (fixes #1727)
* introduces User and Account models
* imports old Session based sessions into User
* handles direct link to settings page from RPs for a specified account (fixes #1686)
* redirects unverified accounts that visit /settings (fixes #1716)
* introduces a way to pass ephemeral data between views
* removes unused avatar-change-via-URL resources/tests (fixes #1544, fixes #1618)