Merge pull request #200 from matrix-org/matthew/loginfixes
Bring back lost functionality on login/register/password-reset screens
This commit is contained in:
commit
672a5cb89c
8 changed files with 206 additions and 86 deletions
|
@ -25,6 +25,7 @@ var matrixClient = null;
|
||||||
var localStorage = window.localStorage;
|
var localStorage = window.localStorage;
|
||||||
|
|
||||||
function deviceId() {
|
function deviceId() {
|
||||||
|
// XXX: is Math.random()'s deterministicity a problem here?
|
||||||
var id = Math.floor(Math.random()*16777215).toString(16);
|
var id = Math.floor(Math.random()*16777215).toString(16);
|
||||||
id = "W" + "000000".substring(id.length) + id;
|
id = "W" + "000000".substring(id.length) + id;
|
||||||
if (localStorage) {
|
if (localStorage) {
|
||||||
|
@ -34,7 +35,7 @@ function deviceId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createClient(hs_url, is_url, user_id, access_token, guestAccess) {
|
function createClientForPeg(hs_url, is_url, user_id, access_token, guestAccess) {
|
||||||
var opts = {
|
var opts = {
|
||||||
baseUrl: hs_url,
|
baseUrl: hs_url,
|
||||||
idBaseUrl: is_url,
|
idBaseUrl: is_url,
|
||||||
|
@ -68,7 +69,7 @@ if (localStorage) {
|
||||||
var guestAccess = new GuestAccess(localStorage);
|
var guestAccess = new GuestAccess(localStorage);
|
||||||
if (access_token && user_id && hs_url) {
|
if (access_token && user_id && hs_url) {
|
||||||
console.log("Restoring session for %s", user_id);
|
console.log("Restoring session for %s", user_id);
|
||||||
createClient(hs_url, is_url, user_id, access_token, guestAccess);
|
createClientForPeg(hs_url, is_url, user_id, access_token, guestAccess);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log("Session not found.");
|
console.log("Session not found.");
|
||||||
|
@ -91,7 +92,7 @@ class MatrixClient {
|
||||||
|
|
||||||
// FIXME, XXX: this all seems very convoluted :(
|
// FIXME, XXX: this all seems very convoluted :(
|
||||||
//
|
//
|
||||||
// if we replace the singleton using URLs we bypass our createClient()
|
// if we replace the singleton using URLs we bypass our createClientForPeg()
|
||||||
// global helper function... but if we replace it using
|
// global helper function... but if we replace it using
|
||||||
// an access_token we don't?
|
// an access_token we don't?
|
||||||
//
|
//
|
||||||
|
@ -105,6 +106,7 @@ class MatrixClient {
|
||||||
baseUrl: hs_url,
|
baseUrl: hs_url,
|
||||||
idBaseUrl: is_url
|
idBaseUrl: is_url
|
||||||
});
|
});
|
||||||
|
|
||||||
// XXX: factor this out with the localStorage setting in replaceUsingAccessToken
|
// XXX: factor this out with the localStorage setting in replaceUsingAccessToken
|
||||||
if (localStorage) {
|
if (localStorage) {
|
||||||
try {
|
try {
|
||||||
|
@ -123,11 +125,11 @@ class MatrixClient {
|
||||||
try {
|
try {
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("Error using local storage");
|
console.warn("Error clearing local storage", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.guestAccess.markAsGuest(Boolean(isGuest));
|
this.guestAccess.markAsGuest(Boolean(isGuest));
|
||||||
createClient(hs_url, is_url, user_id, access_token, this.guestAccess);
|
createClientForPeg(hs_url, is_url, user_id, access_token, this.guestAccess);
|
||||||
if (localStorage) {
|
if (localStorage) {
|
||||||
try {
|
try {
|
||||||
localStorage.setItem("mx_hs_url", hs_url);
|
localStorage.setItem("mx_hs_url", hs_url);
|
||||||
|
@ -136,7 +138,7 @@ class MatrixClient {
|
||||||
localStorage.setItem("mx_access_token", access_token);
|
localStorage.setItem("mx_access_token", access_token);
|
||||||
console.log("Session persisted for %s", user_id);
|
console.log("Session persisted for %s", user_id);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("Error using local storage: can't persist session!");
|
console.warn("Error using local storage: can't persist session!", e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.warn("No local storage available: can't persist session!");
|
console.warn("No local storage available: can't persist session!");
|
||||||
|
|
|
@ -85,6 +85,32 @@ module.exports = React.createClass({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getCurrentHsUrl: function() {
|
||||||
|
if (MatrixClientPeg.get()) {
|
||||||
|
return MatrixClientPeg.get().getHomeserverUrl();
|
||||||
|
}
|
||||||
|
else if (window.localStorage && window.localStorage.getItem("mx_hs_url")) {
|
||||||
|
return window.localStorage.getItem("mx_hs_url");
|
||||||
|
}
|
||||||
|
else if (this.props.config) {
|
||||||
|
return this.props.config.default_hs_url
|
||||||
|
}
|
||||||
|
return "https://matrix.org";
|
||||||
|
},
|
||||||
|
|
||||||
|
getCurrentIsUrl: function() {
|
||||||
|
if (MatrixClientPeg.get()) {
|
||||||
|
return MatrixClientPeg.get().getIdentityServerUrl();
|
||||||
|
}
|
||||||
|
else if (window.localStorage && window.localStorage.getItem("mx_is_url")) {
|
||||||
|
return window.localStorage.getItem("mx_is_url");
|
||||||
|
}
|
||||||
|
else if (this.props.config) {
|
||||||
|
return this.props.config.default_is_url
|
||||||
|
}
|
||||||
|
return "https://matrix.org";
|
||||||
|
},
|
||||||
|
|
||||||
componentWillMount: function() {
|
componentWillMount: function() {
|
||||||
this.favicon = new Favico({animation: 'none'});
|
this.favicon = new Favico({animation: 'none'});
|
||||||
},
|
},
|
||||||
|
@ -92,8 +118,8 @@ module.exports = React.createClass({
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
this._autoRegisterAsGuest = false;
|
this._autoRegisterAsGuest = false;
|
||||||
if (this.props.enableGuest) {
|
if (this.props.enableGuest) {
|
||||||
if (!this.props.config || !this.props.config.default_hs_url) {
|
if (!this.getCurrentHsUrl()) {
|
||||||
console.error("Cannot enable guest access: No supplied config prop for HS/IS URLs");
|
console.error("Cannot enable guest access: can't determine HS URL to use");
|
||||||
}
|
}
|
||||||
else if (this.props.startingQueryParams.client_secret && this.props.startingQueryParams.sid) {
|
else if (this.props.startingQueryParams.client_secret && this.props.startingQueryParams.sid) {
|
||||||
console.log("Not registering as guest; registration.");
|
console.log("Not registering as guest; registration.");
|
||||||
|
@ -167,19 +193,19 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
_registerAsGuest: function() {
|
_registerAsGuest: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
var config = this.props.config;
|
console.log("Doing guest login on %s", this.getCurrentHsUrl());
|
||||||
console.log("Doing guest login on %s", config.default_hs_url);
|
var hsUrl = this.getCurrentHsUrl();
|
||||||
MatrixClientPeg.replaceUsingUrls(
|
var isUrl = this.getCurrentIsUrl();
|
||||||
config.default_hs_url, config.default_is_url
|
|
||||||
);
|
MatrixClientPeg.replaceUsingUrls(hsUrl, isUrl);
|
||||||
MatrixClientPeg.get().registerGuest().done(function(creds) {
|
MatrixClientPeg.get().registerGuest().done(function(creds) {
|
||||||
console.log("Registered as guest: %s", creds.user_id);
|
console.log("Registered as guest: %s", creds.user_id);
|
||||||
self._setAutoRegisterAsGuest(false);
|
self._setAutoRegisterAsGuest(false);
|
||||||
self.onLoggedIn({
|
self.onLoggedIn({
|
||||||
userId: creds.user_id,
|
userId: creds.user_id,
|
||||||
accessToken: creds.access_token,
|
accessToken: creds.access_token,
|
||||||
homeserverUrl: config.default_hs_url,
|
homeserverUrl: hsUrl,
|
||||||
identityServerUrl: config.default_is_url,
|
identityServerUrl: isUrl,
|
||||||
guest: true
|
guest: true
|
||||||
});
|
});
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
|
@ -201,6 +227,9 @@ module.exports = React.createClass({
|
||||||
case 'logout':
|
case 'logout':
|
||||||
if (window.localStorage) {
|
if (window.localStorage) {
|
||||||
window.localStorage.clear();
|
window.localStorage.clear();
|
||||||
|
// preserve our HS & IS URLs for convenience
|
||||||
|
window.localStorage.setItem("mx_hs_url", this.getCurrentHsUrl());
|
||||||
|
window.localStorage.setItem("mx_is_url", this.getCurrentIsUrl());
|
||||||
}
|
}
|
||||||
Notifier.stop();
|
Notifier.stop();
|
||||||
UserActivity.stop();
|
UserActivity.stop();
|
||||||
|
@ -744,7 +773,7 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.error("Unknown screen : %s", screen);
|
console.info("Ignoring showScreen for '%s'", screen);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -908,6 +937,8 @@ module.exports = React.createClass({
|
||||||
var NewVersionBar = sdk.getComponent('globals.NewVersionBar');
|
var NewVersionBar = sdk.getComponent('globals.NewVersionBar');
|
||||||
var ForgotPassword = sdk.getComponent('structures.login.ForgotPassword');
|
var ForgotPassword = sdk.getComponent('structures.login.ForgotPassword');
|
||||||
|
|
||||||
|
// work out the HS URL prompts we should show for
|
||||||
|
|
||||||
// needs to be before normal PageTypes as you are logged in technically
|
// needs to be before normal PageTypes as you are logged in technically
|
||||||
if (this.state.screen == 'post_registration') {
|
if (this.state.screen == 'post_registration') {
|
||||||
return (
|
return (
|
||||||
|
@ -1004,26 +1035,34 @@ module.exports = React.createClass({
|
||||||
username={this.state.upgradeUsername}
|
username={this.state.upgradeUsername}
|
||||||
disableUsernameChanges={Boolean(this.state.upgradeUsername)}
|
disableUsernameChanges={Boolean(this.state.upgradeUsername)}
|
||||||
guestAccessToken={this.state.guestAccessToken}
|
guestAccessToken={this.state.guestAccessToken}
|
||||||
hsUrl={this.props.config.default_hs_url}
|
defaultHsUrl={this.props.config.default_hs_url}
|
||||||
isUrl={this.props.config.default_is_url}
|
defaultIsUrl={this.props.config.default_is_url}
|
||||||
|
customHsUrl={this.getCurrentHsUrl()}
|
||||||
|
customIsUrl={this.getCurrentIsUrl()}
|
||||||
registrationUrl={this.props.registrationUrl}
|
registrationUrl={this.props.registrationUrl}
|
||||||
onLoggedIn={this.onRegistered}
|
onLoggedIn={this.onRegistered}
|
||||||
onLoginClick={this.onLoginClick} />
|
onLoginClick={this.onLoginClick}
|
||||||
|
onRegisterClick={this.onRegisterClick} />
|
||||||
);
|
);
|
||||||
} else if (this.state.screen == 'forgot_password') {
|
} else if (this.state.screen == 'forgot_password') {
|
||||||
return (
|
return (
|
||||||
<ForgotPassword
|
<ForgotPassword
|
||||||
homeserverUrl={this.props.config.default_hs_url}
|
defaultHsUrl={this.props.config.default_hs_url}
|
||||||
identityServerUrl={this.props.config.default_is_url}
|
defaultIsUrl={this.props.config.default_is_url}
|
||||||
onComplete={this.onLoginClick} />
|
customHsUrl={this.getCurrentHsUrl()}
|
||||||
|
customIsUrl={this.getCurrentIsUrl()}
|
||||||
|
onComplete={this.onLoginClick}
|
||||||
|
onLoginClick={this.onLoginClick} />
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<Login
|
<Login
|
||||||
onLoggedIn={this.onLoggedIn}
|
onLoggedIn={this.onLoggedIn}
|
||||||
onRegisterClick={this.onRegisterClick}
|
onRegisterClick={this.onRegisterClick}
|
||||||
homeserverUrl={this.props.config.default_hs_url}
|
defaultHsUrl={this.props.config.default_hs_url}
|
||||||
identityServerUrl={this.props.config.default_is_url}
|
defaultIsUrl={this.props.config.default_is_url}
|
||||||
|
customHsUrl={this.getCurrentHsUrl()}
|
||||||
|
customIsUrl={this.getCurrentIsUrl()}
|
||||||
onForgotPasswordClick={this.onForgotPasswordClick}
|
onForgotPasswordClick={this.onForgotPasswordClick}
|
||||||
onLoginAsGuestClick={this.props.enableGuest && this.props.config && this.props.config.default_hs_url ? this._registerAsGuest: undefined}
|
onLoginAsGuestClick={this.props.enableGuest && this.props.config && this.props.config.default_hs_url ? this._registerAsGuest: undefined}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -27,8 +27,12 @@ module.exports = React.createClass({
|
||||||
displayName: 'ForgotPassword',
|
displayName: 'ForgotPassword',
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
homeserverUrl: React.PropTypes.string,
|
defaultHsUrl: React.PropTypes.string,
|
||||||
identityServerUrl: React.PropTypes.string,
|
defaultIsUrl: React.PropTypes.string,
|
||||||
|
customHsUrl: React.PropTypes.string,
|
||||||
|
customIsUrl: React.PropTypes.string,
|
||||||
|
onLoginClick: React.PropTypes.func,
|
||||||
|
onRegisterClick: React.PropTypes.func,
|
||||||
onComplete: React.PropTypes.func.isRequired
|
onComplete: React.PropTypes.func.isRequired
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -152,8 +156,9 @@ module.exports = React.createClass({
|
||||||
else {
|
else {
|
||||||
resetPasswordJsx = (
|
resetPasswordJsx = (
|
||||||
<div>
|
<div>
|
||||||
To reset your password, enter the email address linked to your account:
|
<div className="mx_Login_prompt">
|
||||||
<br />
|
To reset your password, enter the email address linked to your account:
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<form onSubmit={this.onSubmitForm}>
|
<form onSubmit={this.onSubmitForm}>
|
||||||
<input className="mx_Login_field" ref="user" type="text"
|
<input className="mx_Login_field" ref="user" type="text"
|
||||||
|
@ -175,11 +180,21 @@ module.exports = React.createClass({
|
||||||
</form>
|
</form>
|
||||||
<ServerConfig ref="serverConfig"
|
<ServerConfig ref="serverConfig"
|
||||||
withToggleButton={true}
|
withToggleButton={true}
|
||||||
defaultHsUrl={this.props.homeserverUrl}
|
defaultHsUrl={this.props.defaultHsUrl}
|
||||||
defaultIsUrl={this.props.identityServerUrl}
|
defaultIsUrl={this.props.defaultIsUrl}
|
||||||
|
customHsUrl={this.props.customHsUrl}
|
||||||
|
customIsUrl={this.props.customIsUrl}
|
||||||
onHsUrlChanged={this.onHsUrlChanged}
|
onHsUrlChanged={this.onHsUrlChanged}
|
||||||
onIsUrlChanged={this.onIsUrlChanged}
|
onIsUrlChanged={this.onIsUrlChanged}
|
||||||
delayTimeMs={0}/>
|
delayTimeMs={0}/>
|
||||||
|
<div className="mx_Login_error">
|
||||||
|
</div>
|
||||||
|
<a className="mx_Login_create" onClick={this.props.onLoginClick} href="#">
|
||||||
|
Return to login
|
||||||
|
</a>
|
||||||
|
<a className="mx_Login_create" onClick={this.props.onRegisterClick} href="#">
|
||||||
|
Create a new account
|
||||||
|
</a>
|
||||||
<LoginFooter />
|
<LoginFooter />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -30,28 +30,29 @@ var ServerConfig = require("../../views/login/ServerConfig");
|
||||||
module.exports = React.createClass({displayName: 'Login',
|
module.exports = React.createClass({displayName: 'Login',
|
||||||
propTypes: {
|
propTypes: {
|
||||||
onLoggedIn: React.PropTypes.func.isRequired,
|
onLoggedIn: React.PropTypes.func.isRequired,
|
||||||
homeserverUrl: React.PropTypes.string,
|
|
||||||
identityServerUrl: React.PropTypes.string,
|
customHsUrl: React.PropTypes.string,
|
||||||
|
customIsUrl: React.PropTypes.string,
|
||||||
|
defaultHsUrl: React.PropTypes.string,
|
||||||
|
defaultIsUrl: React.PropTypes.string,
|
||||||
|
|
||||||
// login shouldn't know or care how registration is done.
|
// login shouldn't know or care how registration is done.
|
||||||
onRegisterClick: React.PropTypes.func.isRequired,
|
onRegisterClick: React.PropTypes.func.isRequired,
|
||||||
|
|
||||||
// login shouldn't care how password recovery is done.
|
// login shouldn't care how password recovery is done.
|
||||||
onForgotPasswordClick: React.PropTypes.func,
|
onForgotPasswordClick: React.PropTypes.func,
|
||||||
onLoginAsGuestClick: React.PropTypes.func,
|
onLoginAsGuestClick: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps: function() {
|
|
||||||
return {
|
|
||||||
homeserverUrl: 'https://matrix.org/',
|
|
||||||
identityServerUrl: 'https://matrix.org'
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
busy: false,
|
busy: false,
|
||||||
errorText: null,
|
errorText: null,
|
||||||
enteredHomeserverUrl: this.props.homeserverUrl,
|
enteredHomeserverUrl: this.props.customHsUrl || this.props.defaultHsUrl,
|
||||||
enteredIdentityServerUrl: this.props.identityServerUrl
|
enteredIdentityServerUrl: this.props.customIsUrl || this.props.defaultIsUrl,
|
||||||
|
|
||||||
|
// used for preserving username when changing homeserver
|
||||||
|
username: "",
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -76,12 +77,26 @@ module.exports = React.createClass({displayName: 'Login',
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onUsernameChanged: function(username) {
|
||||||
|
this.setState({ username: username });
|
||||||
|
},
|
||||||
|
|
||||||
onHsUrlChanged: function(newHsUrl) {
|
onHsUrlChanged: function(newHsUrl) {
|
||||||
this._initLoginLogic(newHsUrl);
|
var self = this;
|
||||||
|
this.setState({
|
||||||
|
enteredHomeserverUrl: newHsUrl
|
||||||
|
}, function() {
|
||||||
|
self._initLoginLogic(newHsUrl);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onIsUrlChanged: function(newIsUrl) {
|
onIsUrlChanged: function(newIsUrl) {
|
||||||
this._initLoginLogic(null, newIsUrl);
|
var self = this;
|
||||||
|
this.setState({
|
||||||
|
enteredIdentityServerUrl: newIsUrl
|
||||||
|
}, function() {
|
||||||
|
self._initLoginLogic(null, newIsUrl);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_initLoginLogic: function(hsUrl, isUrl) {
|
_initLoginLogic: function(hsUrl, isUrl) {
|
||||||
|
@ -162,6 +177,8 @@ module.exports = React.createClass({displayName: 'Login',
|
||||||
return (
|
return (
|
||||||
<PasswordLogin
|
<PasswordLogin
|
||||||
onSubmit={this.onPasswordLogin}
|
onSubmit={this.onPasswordLogin}
|
||||||
|
initialUsername={this.state.username}
|
||||||
|
onUsernameChanged={this.onUsernameChanged}
|
||||||
onForgotPasswordClick={this.props.onForgotPasswordClick} />
|
onForgotPasswordClick={this.props.onForgotPasswordClick} />
|
||||||
);
|
);
|
||||||
case 'm.login.cas':
|
case 'm.login.cas':
|
||||||
|
@ -203,8 +220,10 @@ module.exports = React.createClass({displayName: 'Login',
|
||||||
{ this.componentForStep(this._getCurrentFlowStep()) }
|
{ this.componentForStep(this._getCurrentFlowStep()) }
|
||||||
<ServerConfig ref="serverConfig"
|
<ServerConfig ref="serverConfig"
|
||||||
withToggleButton={true}
|
withToggleButton={true}
|
||||||
defaultHsUrl={this.props.homeserverUrl}
|
customHsUrl={this.props.customHsUrl}
|
||||||
defaultIsUrl={this.props.identityServerUrl}
|
customIsUrl={this.props.customIsUrl}
|
||||||
|
defaultHsUrl={this.props.defaultHsUrl}
|
||||||
|
defaultIsUrl={this.props.defaultIsUrl}
|
||||||
onHsUrlChanged={this.onHsUrlChanged}
|
onHsUrlChanged={this.onHsUrlChanged}
|
||||||
onIsUrlChanged={this.onIsUrlChanged}
|
onIsUrlChanged={this.onIsUrlChanged}
|
||||||
delayTimeMs={1000}/>
|
delayTimeMs={1000}/>
|
||||||
|
@ -216,7 +235,6 @@ module.exports = React.createClass({displayName: 'Login',
|
||||||
Create a new account
|
Create a new account
|
||||||
</a>
|
</a>
|
||||||
{ loginAsGuestJsx }
|
{ loginAsGuestJsx }
|
||||||
<br/>
|
|
||||||
<LoginFooter />
|
<LoginFooter />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -36,8 +36,10 @@ module.exports = React.createClass({
|
||||||
sessionId: React.PropTypes.string,
|
sessionId: React.PropTypes.string,
|
||||||
registrationUrl: React.PropTypes.string,
|
registrationUrl: React.PropTypes.string,
|
||||||
idSid: React.PropTypes.string,
|
idSid: React.PropTypes.string,
|
||||||
hsUrl: React.PropTypes.string,
|
customHsUrl: React.PropTypes.string,
|
||||||
isUrl: React.PropTypes.string,
|
customIsUrl: React.PropTypes.string,
|
||||||
|
defaultHsUrl: React.PropTypes.string,
|
||||||
|
defaultIsUrl: React.PropTypes.string,
|
||||||
email: React.PropTypes.string,
|
email: React.PropTypes.string,
|
||||||
username: React.PropTypes.string,
|
username: React.PropTypes.string,
|
||||||
guestAccessToken: React.PropTypes.string,
|
guestAccessToken: React.PropTypes.string,
|
||||||
|
@ -50,8 +52,6 @@ module.exports = React.createClass({
|
||||||
return {
|
return {
|
||||||
busy: false,
|
busy: false,
|
||||||
errorText: null,
|
errorText: null,
|
||||||
enteredHomeserverUrl: this.props.hsUrl,
|
|
||||||
enteredIdentityServerUrl: this.props.isUrl
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ module.exports = React.createClass({
|
||||||
this.dispatcherRef = dis.register(this.onAction);
|
this.dispatcherRef = dis.register(this.onAction);
|
||||||
// attach this to the instance rather than this.state since it isn't UI
|
// attach this to the instance rather than this.state since it isn't UI
|
||||||
this.registerLogic = new Signup.Register(
|
this.registerLogic = new Signup.Register(
|
||||||
this.props.hsUrl, this.props.isUrl
|
this.props.customHsUrl, this.props.customIsUrl
|
||||||
);
|
);
|
||||||
this.registerLogic.setClientSecret(this.props.clientSecret);
|
this.registerLogic.setClientSecret(this.props.clientSecret);
|
||||||
this.registerLogic.setSessionId(this.props.sessionId);
|
this.registerLogic.setSessionId(this.props.sessionId);
|
||||||
|
@ -242,11 +242,15 @@ module.exports = React.createClass({
|
||||||
{busySpinner}
|
{busySpinner}
|
||||||
<ServerConfig ref="serverConfig"
|
<ServerConfig ref="serverConfig"
|
||||||
withToggleButton={true}
|
withToggleButton={true}
|
||||||
defaultHsUrl={this.state.enteredHomeserverUrl}
|
customHsUrl={this.props.customHsUrl}
|
||||||
defaultIsUrl={this.state.enteredIdentityServerUrl}
|
customIsUrl={this.props.customIsUrl}
|
||||||
|
defaultHsUrl={this.props.defaultHsUrl}
|
||||||
|
defaultIsUrl={this.props.defaultIsUrl}
|
||||||
onHsUrlChanged={this.onHsUrlChanged}
|
onHsUrlChanged={this.onHsUrlChanged}
|
||||||
onIsUrlChanged={this.onIsUrlChanged}
|
onIsUrlChanged={this.onIsUrlChanged}
|
||||||
delayTimeMs={1000} />
|
delayTimeMs={1000} />
|
||||||
|
<div className="mx_Login_error">
|
||||||
|
</div>
|
||||||
<a className="mx_Login_create" onClick={this.props.onLoginClick} href="#">
|
<a className="mx_Login_create" onClick={this.props.onLoginClick} href="#">
|
||||||
I already have an account
|
I already have an account
|
||||||
</a>
|
</a>
|
||||||
|
@ -256,11 +260,13 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var LoginHeader = sdk.getComponent('login.LoginHeader');
|
var LoginHeader = sdk.getComponent('login.LoginHeader');
|
||||||
|
var LoginFooter = sdk.getComponent('login.LoginFooter');
|
||||||
return (
|
return (
|
||||||
<div className="mx_Login">
|
<div className="mx_Login">
|
||||||
<div className="mx_Login_box">
|
<div className="mx_Login_box">
|
||||||
<LoginHeader />
|
<LoginHeader />
|
||||||
{this._getRegisterContentJsx()}
|
{this._getRegisterContentJsx()}
|
||||||
|
<LoginFooter />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -31,12 +31,11 @@ module.exports = React.createClass({
|
||||||
servers by specifying a different Home server URL.
|
servers by specifying a different Home server URL.
|
||||||
<br/>
|
<br/>
|
||||||
This allows you to use this app with an existing Matrix account on
|
This allows you to use this app with an existing Matrix account on
|
||||||
a different Home server.
|
a different home server.
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
You can also set a custom Identity server but this will affect
|
You can also set a custom identity server but this will typically prevent
|
||||||
people's ability to find you if you use a server in a group other
|
interaction with users based on email address.
|
||||||
than the main Matrix.org group.
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_Dialog_buttons">
|
<div className="mx_Dialog_buttons">
|
||||||
|
|
|
@ -23,13 +23,26 @@ var ReactDOM = require('react-dom');
|
||||||
module.exports = React.createClass({displayName: 'PasswordLogin',
|
module.exports = React.createClass({displayName: 'PasswordLogin',
|
||||||
propTypes: {
|
propTypes: {
|
||||||
onSubmit: React.PropTypes.func.isRequired, // fn(username, password)
|
onSubmit: React.PropTypes.func.isRequired, // fn(username, password)
|
||||||
onForgotPasswordClick: React.PropTypes.func // fn()
|
onForgotPasswordClick: React.PropTypes.func, // fn()
|
||||||
|
initialUsername: React.PropTypes.string,
|
||||||
|
initialPassword: React.PropTypes.string,
|
||||||
|
onUsernameChanged: React.PropTypes.func,
|
||||||
|
onPasswordChanged: React.PropTypes.func,
|
||||||
|
},
|
||||||
|
|
||||||
|
getDefaultProps: function() {
|
||||||
|
return {
|
||||||
|
onUsernameChanged: function() {},
|
||||||
|
onPasswordChanged: function() {},
|
||||||
|
initialUsername: "",
|
||||||
|
initialPassword: "",
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
username: "",
|
username: this.props.initialUsername,
|
||||||
password: ""
|
password: this.props.initialPassword,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -40,10 +53,12 @@ module.exports = React.createClass({displayName: 'PasswordLogin',
|
||||||
|
|
||||||
onUsernameChanged: function(ev) {
|
onUsernameChanged: function(ev) {
|
||||||
this.setState({username: ev.target.value});
|
this.setState({username: ev.target.value});
|
||||||
|
this.props.onUsernameChanged(ev.target.value);
|
||||||
},
|
},
|
||||||
|
|
||||||
onPasswordChanged: function(ev) {
|
onPasswordChanged: function(ev) {
|
||||||
this.setState({password: ev.target.value});
|
this.setState({password: ev.target.value});
|
||||||
|
this.props.onPasswordChanged(ev.target.value);
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
|
|
|
@ -29,8 +29,21 @@ module.exports = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
onHsUrlChanged: React.PropTypes.func,
|
onHsUrlChanged: React.PropTypes.func,
|
||||||
onIsUrlChanged: React.PropTypes.func,
|
onIsUrlChanged: React.PropTypes.func,
|
||||||
defaultHsUrl: React.PropTypes.string,
|
|
||||||
defaultIsUrl: React.PropTypes.string,
|
// default URLs are defined in config.json (or the hardcoded defaults)
|
||||||
|
// they are used if the user has not overridden them with a custom URL.
|
||||||
|
// In other words, if the custom URL is blank, the default is used.
|
||||||
|
defaultHsUrl: React.PropTypes.string, // e.g. https://matrix.org
|
||||||
|
defaultIsUrl: React.PropTypes.string, // e.g. https://vector.im
|
||||||
|
|
||||||
|
// custom URLs are explicitly provided by the user and override the
|
||||||
|
// default URLs. The user enters them via the component's input fields,
|
||||||
|
// which is reflected on these properties whenever on..UrlChanged fires.
|
||||||
|
// They are persisted in localStorage by MatrixClientPeg, and so can
|
||||||
|
// override the default URLs when the component initially loads.
|
||||||
|
customHsUrl: React.PropTypes.string,
|
||||||
|
customIsUrl: React.PropTypes.string,
|
||||||
|
|
||||||
withToggleButton: React.PropTypes.bool,
|
withToggleButton: React.PropTypes.bool,
|
||||||
delayTimeMs: React.PropTypes.number // time to wait before invoking onChanged
|
delayTimeMs: React.PropTypes.number // time to wait before invoking onChanged
|
||||||
},
|
},
|
||||||
|
@ -39,6 +52,8 @@ module.exports = React.createClass({
|
||||||
return {
|
return {
|
||||||
onHsUrlChanged: function() {},
|
onHsUrlChanged: function() {},
|
||||||
onIsUrlChanged: function() {},
|
onIsUrlChanged: function() {},
|
||||||
|
customHsUrl: "",
|
||||||
|
customIsUrl: "",
|
||||||
withToggleButton: false,
|
withToggleButton: false,
|
||||||
delayTimeMs: 0
|
delayTimeMs: 0
|
||||||
};
|
};
|
||||||
|
@ -46,19 +61,21 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
hs_url: this.props.defaultHsUrl,
|
hs_url: this.props.customHsUrl,
|
||||||
is_url: this.props.defaultIsUrl,
|
is_url: this.props.customIsUrl,
|
||||||
original_hs_url: this.props.defaultHsUrl,
|
// if withToggleButton is false, then show the config all the time given we have no way otherwise of making it visible
|
||||||
original_is_url: this.props.defaultIsUrl,
|
configVisible: !this.props.withToggleButton ||
|
||||||
// no toggle button = show, toggle button = hide
|
(this.props.customHsUrl !== this.props.defaultHsUrl) ||
|
||||||
configVisible: !this.props.withToggleButton
|
(this.props.customIsUrl !== this.props.defaultIsUrl)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onHomeserverChanged: function(ev) {
|
onHomeserverChanged: function(ev) {
|
||||||
this.setState({hs_url: ev.target.value}, function() {
|
this.setState({hs_url: ev.target.value}, function() {
|
||||||
this._hsTimeoutId = this._waitThenInvoke(this._hsTimeoutId, function() {
|
this._hsTimeoutId = this._waitThenInvoke(this._hsTimeoutId, function() {
|
||||||
this.props.onHsUrlChanged(this.state.hs_url.replace(/\/$/, ""));
|
var hsUrl = this.state.hs_url.trim().replace(/\/$/, "");
|
||||||
|
if (hsUrl === "") hsUrl = this.props.defaultHsUrl;
|
||||||
|
this.props.onHsUrlChanged(hsUrl);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -66,7 +83,9 @@ module.exports = React.createClass({
|
||||||
onIdentityServerChanged: function(ev) {
|
onIdentityServerChanged: function(ev) {
|
||||||
this.setState({is_url: ev.target.value}, function() {
|
this.setState({is_url: ev.target.value}, function() {
|
||||||
this._isTimeoutId = this._waitThenInvoke(this._isTimeoutId, function() {
|
this._isTimeoutId = this._waitThenInvoke(this._isTimeoutId, function() {
|
||||||
this.props.onIsUrlChanged(this.state.is_url.replace(/\/$/, ""));
|
var isUrl = this.state.is_url.trim().replace(/\/$/, "");
|
||||||
|
if (isUrl === "") isUrl = this.props.defaultIsUrl;
|
||||||
|
this.props.onIsUrlChanged(isUrl);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -78,18 +97,18 @@ module.exports = React.createClass({
|
||||||
return setTimeout(fn.bind(this), this.props.delayTimeMs);
|
return setTimeout(fn.bind(this), this.props.delayTimeMs);
|
||||||
},
|
},
|
||||||
|
|
||||||
getHsUrl: function() {
|
onServerConfigVisibleChange: function(visible, ev) {
|
||||||
return this.state.hs_url;
|
|
||||||
},
|
|
||||||
|
|
||||||
getIsUrl: function() {
|
|
||||||
return this.state.is_url;
|
|
||||||
},
|
|
||||||
|
|
||||||
onServerConfigVisibleChange: function(ev) {
|
|
||||||
this.setState({
|
this.setState({
|
||||||
configVisible: ev.target.checked
|
configVisible: visible
|
||||||
});
|
});
|
||||||
|
if (!visible) {
|
||||||
|
this.props.onHsUrlChanged(this.props.defaultHsUrl);
|
||||||
|
this.props.onIsUrlChanged(this.props.defaultIsUrl);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.props.onHsUrlChanged(this.state.hs_url);
|
||||||
|
this.props.onIsUrlChanged(this.state.is_url);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
showHelpPopup: function() {
|
showHelpPopup: function() {
|
||||||
|
@ -104,12 +123,19 @@ module.exports = React.createClass({
|
||||||
var toggleButton;
|
var toggleButton;
|
||||||
if (this.props.withToggleButton) {
|
if (this.props.withToggleButton) {
|
||||||
toggleButton = (
|
toggleButton = (
|
||||||
<div>
|
<div style={{ textAlign: 'center' }}>
|
||||||
<input className="mx_Login_checkbox" id="advanced" type="checkbox"
|
<input className="mx_Login_radio" id="basic" name="configVisible" type="radio"
|
||||||
|
checked={!this.state.configVisible}
|
||||||
|
onChange={this.onServerConfigVisibleChange.bind(this, false)} />
|
||||||
|
<label className="mx_Login_label" htmlFor="basic">
|
||||||
|
Default server
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<input className="mx_Login_radio" id="advanced" name="configVisible" type="radio"
|
||||||
checked={this.state.configVisible}
|
checked={this.state.configVisible}
|
||||||
onChange={this.onServerConfigVisibleChange} />
|
onChange={this.onServerConfigVisibleChange.bind(this, true)} />
|
||||||
<label className="mx_Login_label" htmlFor="advanced">
|
<label className="mx_Login_label" htmlFor="advanced">
|
||||||
Use custom server options (advanced)
|
Custom server
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -124,14 +150,14 @@ module.exports = React.createClass({
|
||||||
Home server URL
|
Home server URL
|
||||||
</label>
|
</label>
|
||||||
<input className="mx_Login_field" id="hsurl" type="text"
|
<input className="mx_Login_field" id="hsurl" type="text"
|
||||||
placeholder={this.state.original_hs_url}
|
placeholder={this.props.defaultHsUrl}
|
||||||
value={this.state.hs_url}
|
value={this.state.hs_url}
|
||||||
onChange={this.onHomeserverChanged} />
|
onChange={this.onHomeserverChanged} />
|
||||||
<label className="mx_Login_label mx_ServerConfig_islabel" htmlFor="isurl">
|
<label className="mx_Login_label mx_ServerConfig_islabel" htmlFor="isurl">
|
||||||
Identity server URL
|
Identity server URL
|
||||||
</label>
|
</label>
|
||||||
<input className="mx_Login_field" id="isurl" type="text"
|
<input className="mx_Login_field" id="isurl" type="text"
|
||||||
placeholder={this.state.original_is_url}
|
placeholder={this.props.defaultIsUrl}
|
||||||
value={this.state.is_url}
|
value={this.state.is_url}
|
||||||
onChange={this.onIdentityServerChanged} />
|
onChange={this.onIdentityServerChanged} />
|
||||||
<a className="mx_ServerConfig_help" href="#" onClick={this.showHelpPopup}>
|
<a className="mx_ServerConfig_help" href="#" onClick={this.showHelpPopup}>
|
||||||
|
|
Loading…
Reference in a new issue