merge
This commit is contained in:
commit
be41462f3a
35 changed files with 621 additions and 275 deletions
|
@ -105,6 +105,7 @@ var FilePanel = React.createClass({
|
|||
showUrlPreview = { false }
|
||||
tileShape="file_grid"
|
||||
opacity={ this.props.opacity }
|
||||
empty="There are no visible files in this room"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -171,6 +171,7 @@ export default React.createClass({
|
|||
brand={this.props.config.brand}
|
||||
collapsedRhs={this.props.collapse_rhs}
|
||||
enableLabs={this.props.config.enableLabs}
|
||||
referralBaseUrl={this.props.config.referralBaseUrl}
|
||||
/>;
|
||||
if (!this.props.collapse_rhs) right_panel = <RightPanel opacity={this.props.sideOpacity}/>;
|
||||
break;
|
||||
|
|
|
@ -1055,12 +1055,13 @@ module.exports = React.createClass({
|
|||
sessionId={this.state.register_session_id}
|
||||
idSid={this.state.register_id_sid}
|
||||
email={this.props.startingFragmentQueryParams.email}
|
||||
referrer={this.props.startingFragmentQueryParams.referrer}
|
||||
username={this.state.upgradeUsername}
|
||||
guestAccessToken={this.state.guestAccessToken}
|
||||
defaultHsUrl={this.getDefaultHsUrl()}
|
||||
defaultIsUrl={this.getDefaultIsUrl()}
|
||||
brand={this.props.config.brand}
|
||||
teamsConfig={this.props.config.teamsConfig}
|
||||
teamServerConfig={this.props.config.teamServerConfig}
|
||||
customHsUrl={this.getCurrentHsUrl()}
|
||||
customIsUrl={this.getCurrentIsUrl()}
|
||||
registrationUrl={this.props.registrationUrl}
|
||||
|
|
|
@ -48,6 +48,7 @@ var NotificationPanel = React.createClass({
|
|||
showUrlPreview = { false }
|
||||
opacity={ this.props.opacity }
|
||||
tileShape="notif"
|
||||
empty="You have no visible notifications"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -74,6 +74,7 @@ module.exports = React.createClass({
|
|||
// callback for when the status bar can be hidden from view, as it is
|
||||
// not displaying anything
|
||||
onHidden: React.PropTypes.func,
|
||||
|
||||
// callback for when the status bar is displaying something and should
|
||||
// be visible
|
||||
onVisible: React.PropTypes.func,
|
||||
|
@ -113,7 +114,9 @@ module.exports = React.createClass({
|
|||
clearTimeout(this.hideDebouncer);
|
||||
}
|
||||
this.hideDebouncer = setTimeout(() => {
|
||||
this.props.onHidden();
|
||||
// temporarily stop hiding the statusbar as per
|
||||
// https://github.com/vector-im/riot-web/issues/1991#issuecomment-276953915
|
||||
// this.props.onHidden();
|
||||
}, HIDE_DEBOUNCE_MS);
|
||||
}
|
||||
},
|
||||
|
@ -238,7 +241,7 @@ module.exports = React.createClass({
|
|||
|
||||
if (othersCount > 0) {
|
||||
avatars.push(
|
||||
<span className="mx_RoomStatusBar_typingIndicatorRemaining">
|
||||
<span className="mx_RoomStatusBar_typingIndicatorRemaining" key="others">
|
||||
+{othersCount}
|
||||
</span>
|
||||
);
|
||||
|
|
|
@ -1332,12 +1332,14 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
onStatusBarVisible: function() {
|
||||
if (this.unmounted) return;
|
||||
this.setState({
|
||||
statusBarVisible: true,
|
||||
});
|
||||
},
|
||||
|
||||
onStatusBarHidden: function() {
|
||||
if (this.unmounted) return;
|
||||
this.setState({
|
||||
statusBarVisible: false,
|
||||
});
|
||||
|
@ -1507,13 +1509,14 @@ module.exports = React.createClass({
|
|||
});
|
||||
|
||||
var statusBar;
|
||||
let isStatusAreaExpanded = true;
|
||||
|
||||
if (ContentMessages.getCurrentUploads().length > 0) {
|
||||
var UploadBar = sdk.getComponent('structures.UploadBar');
|
||||
statusBar = <UploadBar room={this.state.room} />;
|
||||
} else if (!this.state.searchResults) {
|
||||
var RoomStatusBar = sdk.getComponent('structures.RoomStatusBar');
|
||||
|
||||
isStatusAreaExpanded = this.state.statusBarVisible;
|
||||
statusBar = <RoomStatusBar
|
||||
room={this.state.room}
|
||||
tabComplete={this.tabComplete}
|
||||
|
@ -1683,7 +1686,7 @@ module.exports = React.createClass({
|
|||
);
|
||||
}
|
||||
let statusBarAreaClass = "mx_RoomView_statusArea mx_fadable";
|
||||
if (this.state.statusBarVisible) {
|
||||
if (isStatusAreaExpanded) {
|
||||
statusBarAreaClass += " mx_RoomView_statusArea_expanded";
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ var DEBUG_SCROLL = false;
|
|||
|
||||
// The amount of extra scroll distance to allow prior to unfilling.
|
||||
// See _getExcessHeight.
|
||||
const UNPAGINATION_PADDING = 1500;
|
||||
const UNPAGINATION_PADDING = 3000;
|
||||
// The number of milliseconds to debounce calls to onUnfillRequest, to prevent
|
||||
// many scroll events causing many unfilling requests.
|
||||
const UNFILL_REQUEST_DEBOUNCE_MS = 200;
|
||||
|
@ -570,7 +570,7 @@ module.exports = React.createClass({
|
|||
var boundingRect = node.getBoundingClientRect();
|
||||
var scrollDelta = boundingRect.bottom + pixelOffset - wrapperRect.bottom;
|
||||
|
||||
debuglog("Scrolling to token '" + node.dataset.scrollToken + "'+" +
|
||||
debuglog("ScrollPanel: scrolling to token '" + node.dataset.scrollToken + "'+" +
|
||||
pixelOffset + " (delta: "+scrollDelta+")");
|
||||
|
||||
if(scrollDelta != 0) {
|
||||
|
@ -582,7 +582,7 @@ module.exports = React.createClass({
|
|||
_saveScrollState: function() {
|
||||
if (this.props.stickyBottom && this.isAtBottom()) {
|
||||
this.scrollState = { stuckAtBottom: true };
|
||||
debuglog("Saved scroll state", this.scrollState);
|
||||
debuglog("ScrollPanel: Saved scroll state", this.scrollState);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -601,12 +601,12 @@ module.exports = React.createClass({
|
|||
trackedScrollToken: node.dataset.scrollToken,
|
||||
pixelOffset: wrapperRect.bottom - boundingRect.bottom,
|
||||
};
|
||||
debuglog("Saved scroll state", this.scrollState);
|
||||
debuglog("ScrollPanel: saved scroll state", this.scrollState);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
debuglog("Unable to save scroll state: found no children in the viewport");
|
||||
debuglog("ScrollPanel: unable to save scroll state: found no children in the viewport");
|
||||
},
|
||||
|
||||
_restoreSavedScrollState: function() {
|
||||
|
@ -640,7 +640,7 @@ module.exports = React.createClass({
|
|||
this._lastSetScroll = scrollNode.scrollTop;
|
||||
}
|
||||
|
||||
debuglog("Set scrollTop:", scrollNode.scrollTop,
|
||||
debuglog("ScrollPanel: set scrollTop:", scrollNode.scrollTop,
|
||||
"requested:", scrollTop,
|
||||
"_lastSetScroll:", this._lastSetScroll);
|
||||
},
|
||||
|
|
|
@ -96,6 +96,9 @@ var TimelinePanel = React.createClass({
|
|||
|
||||
// shape property to be passed to EventTiles
|
||||
tileShape: React.PropTypes.string,
|
||||
|
||||
// placeholder text to use if the timeline is empty
|
||||
empty: React.PropTypes.string,
|
||||
},
|
||||
|
||||
statics: {
|
||||
|
@ -990,6 +993,14 @@ var TimelinePanel = React.createClass({
|
|||
);
|
||||
}
|
||||
|
||||
if (this.state.events.length == 0) {
|
||||
return (
|
||||
<div className={ this.props.className + " mx_RoomView_messageListWrapper" }>
|
||||
<div className="mx_RoomView_empty">{ this.props.empty }</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// give the messagepanel a stickybottom if we're at the end of the
|
||||
// live timeline, so that the arrival of new events triggers a
|
||||
// scroll.
|
||||
|
|
|
@ -104,6 +104,9 @@ module.exports = React.createClass({
|
|||
// True to show the 'labs' section of experimental features
|
||||
enableLabs: React.PropTypes.bool,
|
||||
|
||||
// The base URL to use in the referral link. Defaults to window.location.origin.
|
||||
referralBaseUrl: React.PropTypes.string,
|
||||
|
||||
// true if RightPanel is collapsed
|
||||
collapsedRhs: React.PropTypes.bool,
|
||||
},
|
||||
|
@ -458,6 +461,27 @@ module.exports = React.createClass({
|
|||
);
|
||||
},
|
||||
|
||||
_renderReferral: function() {
|
||||
const teamToken = window.localStorage.getItem('mx_team_token');
|
||||
if (!teamToken) {
|
||||
return null;
|
||||
}
|
||||
if (typeof teamToken !== 'string') {
|
||||
console.warn('Team token not a string');
|
||||
return null;
|
||||
}
|
||||
const href = (this.props.referralBaseUrl || window.location.origin) +
|
||||
`/#/register?referrer=${this._me}&team_token=${teamToken}`;
|
||||
return (
|
||||
<div>
|
||||
<h3>Referral</h3>
|
||||
<div className="mx_UserSettings_section">
|
||||
Refer a friend to Riot: <a href={href}>{href}</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
_renderUserInterfaceSettings: function() {
|
||||
var client = MatrixClientPeg.get();
|
||||
|
||||
|
@ -857,6 +881,8 @@ module.exports = React.createClass({
|
|||
{accountJsx}
|
||||
</div>
|
||||
|
||||
{this._renderReferral()}
|
||||
|
||||
{notification_area}
|
||||
|
||||
{this._renderUserInterfaceSettings()}
|
||||
|
|
|
@ -25,6 +25,7 @@ var ServerConfig = require("../../views/login/ServerConfig");
|
|||
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
var RegistrationForm = require("../../views/login/RegistrationForm");
|
||||
var CaptchaForm = require("../../views/login/CaptchaForm");
|
||||
var RtsClient = require("../../../RtsClient");
|
||||
|
||||
var MIN_PASSWORD_LENGTH = 6;
|
||||
|
||||
|
@ -47,23 +48,16 @@ module.exports = React.createClass({
|
|||
defaultIsUrl: React.PropTypes.string,
|
||||
brand: React.PropTypes.string,
|
||||
email: React.PropTypes.string,
|
||||
referrer: React.PropTypes.string,
|
||||
username: React.PropTypes.string,
|
||||
guestAccessToken: React.PropTypes.string,
|
||||
teamsConfig: React.PropTypes.shape({
|
||||
teamServerConfig: React.PropTypes.shape({
|
||||
// Email address to request new teams
|
||||
supportEmail: React.PropTypes.string,
|
||||
teams: React.PropTypes.arrayOf(React.PropTypes.shape({
|
||||
// The displayed name of the team
|
||||
"name": React.PropTypes.string,
|
||||
// The suffix with which every team email address ends
|
||||
"emailSuffix": React.PropTypes.string,
|
||||
// The rooms to use during auto-join
|
||||
"rooms": React.PropTypes.arrayOf(React.PropTypes.shape({
|
||||
"id": React.PropTypes.string,
|
||||
"autoJoin": React.PropTypes.bool,
|
||||
})),
|
||||
})).required,
|
||||
supportEmail: React.PropTypes.string.isRequired,
|
||||
// URL of the riot-team-server to get team configurations and track referrals
|
||||
teamServerURL: React.PropTypes.string.isRequired,
|
||||
}),
|
||||
teamSelected: React.PropTypes.object,
|
||||
|
||||
defaultDeviceDisplayName: React.PropTypes.string,
|
||||
|
||||
|
@ -75,6 +69,7 @@ module.exports = React.createClass({
|
|||
getInitialState: function() {
|
||||
return {
|
||||
busy: false,
|
||||
teamServerBusy: false,
|
||||
errorText: null,
|
||||
// We remember the values entered by the user because
|
||||
// the registration form will be unmounted during the
|
||||
|
@ -90,6 +85,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this._unmounted = false;
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
// attach this to the instance rather than this.state since it isn't UI
|
||||
this.registerLogic = new Signup.Register(
|
||||
|
@ -103,10 +99,40 @@ module.exports = React.createClass({
|
|||
this.registerLogic.setIdSid(this.props.idSid);
|
||||
this.registerLogic.setGuestAccessToken(this.props.guestAccessToken);
|
||||
this.registerLogic.recheckState();
|
||||
|
||||
if (
|
||||
this.props.teamServerConfig &&
|
||||
this.props.teamServerConfig.teamServerURL &&
|
||||
!this._rtsClient
|
||||
) {
|
||||
this._rtsClient = new RtsClient(this.props.teamServerConfig.teamServerURL);
|
||||
|
||||
this.setState({
|
||||
teamServerBusy: true,
|
||||
});
|
||||
// GET team configurations including domains, names and icons
|
||||
this._rtsClient.getTeamsConfig().then((data) => {
|
||||
const teamsConfig = {
|
||||
teams: data,
|
||||
supportEmail: this.props.teamServerConfig.supportEmail,
|
||||
};
|
||||
console.log('Setting teams config to ', teamsConfig);
|
||||
this.setState({
|
||||
teamsConfig: teamsConfig,
|
||||
teamServerBusy: false,
|
||||
});
|
||||
}, (err) => {
|
||||
console.error('Error retrieving config for teams', err);
|
||||
this.setState({
|
||||
teamServerBusy: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
dis.unregister(this.dispatcherRef);
|
||||
this._unmounted = true;
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
|
@ -184,24 +210,41 @@ module.exports = React.createClass({
|
|||
accessToken: response.access_token
|
||||
});
|
||||
|
||||
// Auto-join rooms
|
||||
if (self.props.teamsConfig && self.props.teamsConfig.teams) {
|
||||
for (let i = 0; i < self.props.teamsConfig.teams.length; i++) {
|
||||
let team = self.props.teamsConfig.teams[i];
|
||||
if (self.state.formVals.email.endsWith(team.emailSuffix)) {
|
||||
console.log("User successfully registered with team " + team.name);
|
||||
if (
|
||||
self._rtsClient &&
|
||||
self.props.referrer &&
|
||||
self.state.teamSelected
|
||||
) {
|
||||
// Track referral, get team_token in order to retrieve team config
|
||||
self._rtsClient.trackReferral(
|
||||
self.props.referrer,
|
||||
response.user_id,
|
||||
self.state.formVals.email
|
||||
).then((data) => {
|
||||
const teamToken = data.team_token;
|
||||
// Store for use /w welcome pages
|
||||
window.localStorage.setItem('mx_team_token', teamToken);
|
||||
|
||||
self._rtsClient.getTeam(teamToken).then((team) => {
|
||||
console.log(
|
||||
`User successfully registered with team ${team.name}`
|
||||
);
|
||||
if (!team.rooms) {
|
||||
break;
|
||||
return;
|
||||
}
|
||||
// Auto-join rooms
|
||||
team.rooms.forEach((room) => {
|
||||
if (room.autoJoin) {
|
||||
console.log("Auto-joining " + room.id);
|
||||
MatrixClientPeg.get().joinRoom(room.id);
|
||||
if (room.auto_join && room.room_id) {
|
||||
console.log(`Auto-joining ${room.room_id}`);
|
||||
MatrixClientPeg.get().joinRoom(room.room_id);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, (err) => {
|
||||
console.error('Error getting team config', err);
|
||||
});
|
||||
}, (err) => {
|
||||
console.error('Error tracking referral', err);
|
||||
});
|
||||
}
|
||||
|
||||
if (self.props.brand) {
|
||||
|
@ -273,7 +316,15 @@ module.exports = React.createClass({
|
|||
});
|
||||
},
|
||||
|
||||
onTeamSelected: function(teamSelected) {
|
||||
if (!this._unmounted) {
|
||||
this.setState({ teamSelected });
|
||||
}
|
||||
},
|
||||
|
||||
_getRegisterContentJsx: function() {
|
||||
const Spinner = sdk.getComponent("elements.Spinner");
|
||||
|
||||
var currStep = this.registerLogic.getStep();
|
||||
var registerStep;
|
||||
switch (currStep) {
|
||||
|
@ -283,17 +334,23 @@ module.exports = React.createClass({
|
|||
case "Register.STEP_m.login.dummy":
|
||||
// NB. Our 'username' prop is specifically for upgrading
|
||||
// a guest account
|
||||
if (this.state.teamServerBusy) {
|
||||
registerStep = <Spinner />;
|
||||
break;
|
||||
}
|
||||
registerStep = (
|
||||
<RegistrationForm
|
||||
showEmail={true}
|
||||
defaultUsername={this.state.formVals.username}
|
||||
defaultEmail={this.state.formVals.email}
|
||||
defaultPassword={this.state.formVals.password}
|
||||
teamsConfig={this.props.teamsConfig}
|
||||
teamsConfig={this.state.teamsConfig}
|
||||
guestUsername={this.props.username}
|
||||
minPasswordLength={MIN_PASSWORD_LENGTH}
|
||||
onError={this.onFormValidationFailed}
|
||||
onRegisterClick={this.onFormSubmit} />
|
||||
onRegisterClick={this.onFormSubmit}
|
||||
onTeamSelected={this.onTeamSelected}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case "Register.STEP_m.login.email.identity":
|
||||
|
@ -322,7 +379,6 @@ module.exports = React.createClass({
|
|||
}
|
||||
var busySpinner;
|
||||
if (this.state.busy) {
|
||||
var Spinner = sdk.getComponent("elements.Spinner");
|
||||
busySpinner = (
|
||||
<Spinner />
|
||||
);
|
||||
|
@ -367,7 +423,7 @@ module.exports = React.createClass({
|
|||
return (
|
||||
<div className="mx_Login">
|
||||
<div className="mx_Login_box">
|
||||
<LoginHeader />
|
||||
<LoginHeader icon={this.state.teamSelected ? this.state.teamSelected.icon : null}/>
|
||||
{this._getRegisterContentJsx()}
|
||||
<LoginFooter />
|
||||
</div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue