#339: fix username was not updated in AccounSwither, when using ChangeUsername form

This commit is contained in:
SleepWalker 2017-07-12 21:30:05 +03:00
parent b18844906f
commit c8517db19f
3 changed files with 44 additions and 26 deletions

View File

@ -28,7 +28,7 @@ export class AccountSwitcher extends Component {
id: PropTypes.number id: PropTypes.number
})) }))
}), }),
user: userShape, // TODO: remove me, when we will be sure, that accounts.active is always set for user user: userShape, // TODO: remove me, when we will be sure, that accounts.active is always set for user (event after register)
skin: PropTypes.oneOf(skins), skin: PropTypes.oneOf(skins),
highlightActiveAccount: PropTypes.bool, // whether active account should be expanded and shown on the top highlightActiveAccount: PropTypes.bool, // whether active account should be expanded and shown on the top
allowLogout: PropTypes.bool, // whether to show logout icon near each account allowLogout: PropTypes.bool, // whether to show logout icon near each account
@ -46,7 +46,8 @@ export class AccountSwitcher extends Component {
render() { render() {
const { accounts, skin, allowAdd, allowLogout, highlightActiveAccount } = this.props; const { accounts, skin, allowAdd, allowLogout, highlightActiveAccount } = this.props;
const activeAccount = accounts.active || this.props.user; // const activeAccount = accounts.active || this.props.user;
const activeAccount = this.props.user;
let {available} = accounts; let {available} = accounts;
@ -163,8 +164,7 @@ import { authenticate, revoke } from 'components/accounts/actions';
export default connect(({accounts, user}) => ({ export default connect(({accounts, user}) => ({
accounts, accounts,
user, user
userLang: user.lang // this is to force re-render on lang change
}), { }), {
switchAccount: authenticate, switchAccount: authenticate,
removeAccount: revoke removeAccount: revoke

View File

@ -1,23 +1,25 @@
// @flow
import { UPDATE, SET, CHANGE_LANG } from './actions'; import { UPDATE, SET, CHANGE_LANG } from './actions';
export type User = { export type User = {
id: number, id: ?number,
uuid: string, uuid: ?string,
token: string, token: string,
username: string, username: string,
email: string, email: string,
avatar: string, avatar: string,
isGuest: boolean, isGuest: boolean,
isActive: boolean, isActive: boolean,
passwordChangedAt: number, passwordChangedAt: ?number,
hasMojangUsernameCollision: bool, hasMojangUsernameCollision: bool,
}; };
const defaults = { const defaults: User = {
id: null, id: null,
uuid: null, uuid: null,
username: '', username: '',
token: '',
email: '', email: '',
// will contain user's email or masked email // will contain user's email or masked email
// (e.g. ex**ple@em*il.c**) depending on what information user have already provided // (e.g. ex**ple@em*il.c**) depending on what information user have already provided
@ -35,8 +37,8 @@ const defaults = {
}; };
export default function user( export default function user(
state = null, state: User = defaults,
{type, payload = null} {type, payload}: {type: string, payload: ?Object}
) { ) {
switch (type) { switch (type) {
case CHANGE_LANG: case CHANGE_LANG:

View File

@ -1,5 +1,5 @@
// @flow
import React, { Component } from 'react'; import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import classNames from 'classnames'; import classNames from 'classnames';
@ -7,25 +7,33 @@ import { AccountSwitcher } from 'components/accounts';
import styles from './loggedInPanel.scss'; import styles from './loggedInPanel.scss';
import { userShape } from 'components/user/User'; import type { User } from 'components/user';
export default class LoggedInPanel extends Component { export default class LoggedInPanel extends Component {
static displayName = 'LoggedInPanel'; props: {
static propTypes = { user: User
user: userShape
}; };
state = { state = {
isAccountSwitcherActive: false isAccountSwitcherActive: false
}; };
_isMounted: boolean = false;
el: ?HTMLElement;
componentDidMount() { componentDidMount() {
document.addEventListener('click', this.onBodyClick); if (window.document) {
window.document.addEventListener('click', this.onBodyClick);
}
this._isMounted = true; this._isMounted = true;
} }
componentWillUnmount() { componentWillUnmount() {
document.removeEventListener('click', this.onBodyClick); if (window.document) {
window.document.removeEventListener('click', this.onBodyClick);
}
this._isMounted = false; this._isMounted = false;
} }
@ -34,7 +42,7 @@ export default class LoggedInPanel extends Component {
const { isAccountSwitcherActive } = this.state; const { isAccountSwitcherActive } = this.state;
return ( return (
<div className={classNames(styles.loggedInPanel)}> <div ref={(el) => this.el = el} className={classNames(styles.loggedInPanel)}>
<div className={classNames(styles.activeAccount, { <div className={classNames(styles.activeAccount, {
[styles.activeAccountExpanded]: isAccountSwitcherActive [styles.activeAccountExpanded]: isAccountSwitcherActive
})}> })}>
@ -45,7 +53,7 @@ export default class LoggedInPanel extends Component {
</button> </button>
<div className={classNames(styles.accountSwitcherContainer)}> <div className={classNames(styles.accountSwitcherContainer)}>
<AccountSwitcher skin="light" onAfterAction={this.toggleAccountSwitcher} /> <AccountSwitcher skin="light" onAfterAction={this.onToggleAccountSwitcher} />
</div> </div>
</div> </div>
</div> </div>
@ -56,14 +64,18 @@ export default class LoggedInPanel extends Component {
isAccountSwitcherActive: !this.state.isAccountSwitcherActive isAccountSwitcherActive: !this.state.isAccountSwitcherActive
}); });
onExpandAccountSwitcher = (event) => { onToggleAccountSwitcher = () => {
this.toggleAccountSwitcher();
};
onExpandAccountSwitcher = (event: Event) => {
event.preventDefault(); event.preventDefault();
this.toggleAccountSwitcher(); this.toggleAccountSwitcher();
}; };
onBodyClick = createOnOutsideComponentClickHandler( onBodyClick = createOnOutsideComponentClickHandler(
() => ReactDOM.findDOMNode(this), () => this.el,
() => this.state.isAccountSwitcherActive && this._isMounted, () => this.state.isAccountSwitcherActive && this._isMounted,
() => this.toggleAccountSwitcher() () => this.toggleAccountSwitcher()
); );
@ -81,15 +93,19 @@ export default class LoggedInPanel extends Component {
* *
* @return {function} * @return {function}
*/ */
function createOnOutsideComponentClickHandler(getEl, isActive, callback) { function createOnOutsideComponentClickHandler(
getEl: () => ?HTMLElement,
isActive: () => boolean,
callback: Function
) {
// TODO: we have the same logic in LangMenu // TODO: we have the same logic in LangMenu
// Probably we should decouple this into some helper function // Probably we should decouple this into some helper function
// TODO: the name of function may be better... // TODO: the name of function may be better...
return (event) => { return (event: MouseEvent & {target: HTMLElement}) => {
if (isActive()) {
const el = getEl(); const el = getEl();
if (!el.contains(event.target) && el !== event.taget) { if (isActive() && el) {
if (!el.contains(event.target) && el !== event.target) {
event.preventDefault(); event.preventDefault();
// add a small delay for the case someone have alredy called toggle // add a small delay for the case someone have alredy called toggle