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

Add theme approval step if add-on is available #59

Merged
merged 2 commits into from
Feb 13, 2018

Conversation

lmorchard
Copy link
Contributor

If ?theme param is available on initial page load, assume that this is a
shared theme. Populate the editor UI with that theme and also stash it as a
pendingTheme.

If the add-on is not installed, pendingTheme will do nothing and the
editor will display the incoming shared theme.

If the add-on is installed and responds with a stored current theme,
that theme will replace the one in the editor. Then, a permission
dialog with a preview of the pendingTheme will be presented.

If the user hits "skip" on the dialog, pendingTheme is discarded.

If the user hits "apply", the pending theme is pushed into the add-on
and replaces the theme in the editor.

Fixes #27

@lmorchard
Copy link
Contributor Author

lmorchard commented Feb 9, 2018

Okay, this one could use some help or at least some sanity checking:

First thing is that the theme preview in the dialog is not quite right. Still wrestling with the CSS for the doll a little, but would totally accept some help.

Second thing is that there's a flash of changing content on page load that seems hard to work around:

There's different behavior depending on whether the add-on's installed or not. But, we can't ever really know that the add-on is not installed - we only know that it is installed after a response to a message. So, not getting a response means either it's not installed or it's just taking awhile.

So, what happens is that the uninstalled state appears first, and then everything switches to the installed state once a message makes it through from the add-on. That means the editor switches between themes just as the dialog pops up. Also the CTA to install the add-on goes away. The switch is pretty fast on my machine, but it is noticeable.

We might be able to paper this over with a loading spinner, but the only thing we can really do there is just arbitrarily wait a second or two before giving up on hearing from the add-on. Folks without the add-on would just wait.

src/web/index.js Outdated
log('Received shared theme');
// TODO: figure out if this param theme matches theme from add-on and ignore if so
urlDecodeTheme(params.theme).then(theme => {
// Set the pending theme - only matters if add-on is installed
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is where the complicated part happens...

src/web/index.js Outdated
jsonCodec.decompress(params.theme).then(theme => {
store.dispatch(actions.theme.setTheme({ theme }));
log('Received shared theme');
// TODO: figure out if this param theme matches theme from add-on and ignore if so
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh also TBD: If the ?theme param matches what the current theme already is, we should skip displaying the permission dialog. Haven't implemented that check yet.

@lmorchard
Copy link
Contributor Author

Hmm, and actually it looks like this flashes the shared theme in the browser temporarily too. That seems like a bug in the probably over-zealous Redux middleware. Will poke at that

@lmorchard
Copy link
Contributor Author

Debugged middleware a bit, think I fixed the bug with accidentally applying the shared theme to the browser. Still thinking through the sequence & race conditions on initial load, though

@chuckharmston
Copy link
Contributor

Proposal: we review this PR for its own merits, and defer consideration of the sequencing pending UX on #62.

src/lib/utils.js Outdated
@@ -10,3 +10,8 @@ export const colorToCSS = color => {
? `hsl(${h}, ${s}%, ${l}%)`
: `hsla(${h}, ${s}%, ${l}%, ${color.a * 0.01})`;
};

export const themesEqual = (themeA, themeB) =>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not using this yet, which reminds me of the other thing I'm trying to figure out: When to decide that the shared theme matches the current theme.

I tried doing it as kind of a validation step - the pendingTheme state would not accept a value that matches the current theme. But that ran into race conditions in add-on messaging. Could just check on an arbitrary delay and auto-dismiss the accept dialog, but then there's a flash of content

Copy link
Contributor

Choose a reason for hiding this comment

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

This seems like a good usecase for a selector; just have a boolean prop passed to the <App> that checks the pendingTheme and currentTheme for equality. Then it's just a matter of checking that prop, as passed through the component hierarchy.

Copy link
Contributor Author

@lmorchard lmorchard Feb 13, 2018

Choose a reason for hiding this comment

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

I also tried this as a selector. Problem was, as soon as you change any colors, suddenly the pending theme no longer matches the current theme and the approval dialog appears. Been trying to figure out at what point to just ignore / delete the incoming pendingTheme so that doesn't happen.

Could maybe set another state flag once the user has made any edits and ignore the pendingTheme from there

@lmorchard
Copy link
Contributor Author

Okay, tweaked things to add a userHasEdited flag to use as part of the decision as to whether the shared theme dialog should be displayed. Seems to help solve the issue of skipping the dialog if the shared theme matches current theme

@lmorchard lmorchard force-pushed the 27-incoming-theme-approval branch 3 times, most recently from caa83fc to 0e74196 Compare February 13, 2018 17:35
@lmorchard
Copy link
Contributor Author

One more quick tweak for clarity & to pass linting and I think I'll leave this alone for a bit

@@ -4,9 +4,16 @@ export const makeLog = context => (...args) =>
// eslint-disable-next-line no-console
DEBUG && console.log(`[ThemesRFun ${context}]`, ...args);

export const floorHSLA = color => ({
Copy link
Contributor Author

@lmorchard lmorchard Feb 13, 2018

Choose a reason for hiding this comment

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

Planning to revisit this in #50 - the color picker and theme schema use different magnitudes for HSLA values, but the JS floating point math causes the values to drift. And thus, themes that should be identical look non-identical to the shouldOfferPendingTheme selector because insignificant digits have changed. Will play with normalizing this better in #50

Copy link
Contributor

@chuckharmston chuckharmston left a comment

Choose a reason for hiding this comment

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

Codewise, I don't have any problems here, and it generally works as described. My only concern is that this is a relatively complex workflow that takes some time to grok.

Could you add some documentation about the internal flow, how that flow is related to the state, and why?

Otherwise 👍 from me!

@lmorchard
Copy link
Contributor Author

Could you add some documentation about the internal flow, how that flow is related to the state, and why?

I tried to describe it in the commit message - is that what you're looking for / should that live somewhere else?

src/web/index.js Outdated
@@ -113,9 +125,22 @@ render(

const params = queryString.parse(window.location.search);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Might drop a long comment here about the startup process and shared theme handling

@chuckharmston
Copy link
Contributor

I tried to describe it in the commit message - is that what you're looking for / should that live somewhere else?

Yep! I'd like that type of thing more formally represented in in-repo documentation, with a bit of the "why" attached to the "what".

@@ -111,11 +123,51 @@ render(
document.getElementById('root')
);

/**
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added this comment for now, will file an issue for further doco

If ?theme param is available on initial page load, assume that this is a
shared theme. Populate the editor UI with that theme and also stash it as a
pendingTheme.

If the add-on is not installed, pendingTheme will do nothing and the
editor will display the incoming shared theme.

If the add-on is installed and responds with a stored current theme,
that theme will replace the one in the editor. Then, a permission
dialog with a preview of the pendingTheme will be presented.

If the user hits "skip" on the dialog, pendingTheme is discarded.

If the user hits "apply", the pending theme is pushed into the add-on
and replaces the theme in the editor.

Fixes mozilla#27
@lmorchard
Copy link
Contributor Author

Also added a commit to bump the add-on version and plan to do another development branch deployment after merge

@lmorchard lmorchard merged commit 9d9ba2a into mozilla:master Feb 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants