Merge remote-tracking branch 'origin/develop' into matthew/e2e_backups
This commit is contained in:
commit
f62e92a07b
65 changed files with 2335 additions and 540 deletions
|
@ -480,7 +480,7 @@ export default React.createClass({
|
|||
group_id: groupId,
|
||||
},
|
||||
});
|
||||
dis.dispatch({action: 'view_set_mxid'});
|
||||
dis.dispatch({action: 'require_registration'});
|
||||
willDoOnboarding = true;
|
||||
}
|
||||
this.setState({
|
||||
|
@ -723,6 +723,11 @@ export default React.createClass({
|
|||
},
|
||||
|
||||
_onJoinClick: async function() {
|
||||
if (this._matrixClient.isGuest()) {
|
||||
dis.dispatch({action: 'require_registration'});
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({membershipBusy: true});
|
||||
|
||||
// Wait 500ms to prevent flashing. Do this before sending a request otherwise we risk the
|
||||
|
|
|
@ -45,6 +45,8 @@ import createRoom from "../../createRoom";
|
|||
import KeyRequestHandler from '../../KeyRequestHandler';
|
||||
import { _t, getCurrentLanguage } from '../../languageHandler';
|
||||
import SettingsStore, {SettingLevel} from "../../settings/SettingsStore";
|
||||
import { startAnyRegistrationFlow } from "../../Registration.js";
|
||||
import { messageForSyncError } from '../../utils/ErrorUtils';
|
||||
|
||||
/** constants for MatrixChat.state.view */
|
||||
const VIEWS = {
|
||||
|
@ -178,6 +180,8 @@ export default React.createClass({
|
|||
// When showing Modal dialogs we need to set aria-hidden on the root app element
|
||||
// and disable it when there are no dialogs
|
||||
hideToSRUsers: false,
|
||||
|
||||
syncError: null, // If the current syncing status is ERROR, the error object, otherwise null.
|
||||
};
|
||||
return s;
|
||||
},
|
||||
|
@ -471,7 +475,7 @@ export default React.createClass({
|
|||
action: 'do_after_sync_prepared',
|
||||
deferred_action: payload,
|
||||
});
|
||||
dis.dispatch({action: 'view_set_mxid'});
|
||||
dis.dispatch({action: 'require_registration'});
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -479,7 +483,11 @@ export default React.createClass({
|
|||
case 'logout':
|
||||
Lifecycle.logout();
|
||||
break;
|
||||
case 'require_registration':
|
||||
startAnyRegistrationFlow(payload);
|
||||
break;
|
||||
case 'start_registration':
|
||||
// This starts the full registration flow
|
||||
this._startRegistration(payload.params || {});
|
||||
break;
|
||||
case 'start_login':
|
||||
|
@ -945,7 +953,7 @@ export default React.createClass({
|
|||
});
|
||||
}
|
||||
dis.dispatch({
|
||||
action: 'view_set_mxid',
|
||||
action: 'require_registration',
|
||||
// If the set_mxid dialog is cancelled, view /home because if the browser
|
||||
// was pointing at /user/@someone:domain?action=chat, the URL needs to be
|
||||
// reset so that they can revisit /user/.. // (and trigger
|
||||
|
@ -1132,7 +1140,7 @@ export default React.createClass({
|
|||
*
|
||||
* @param {string} teamToken
|
||||
*/
|
||||
_onLoggedIn: function(teamToken) {
|
||||
_onLoggedIn: async function(teamToken) {
|
||||
this.setState({
|
||||
view: VIEWS.LOGGED_IN,
|
||||
});
|
||||
|
@ -1145,12 +1153,17 @@ export default React.createClass({
|
|||
this._is_registered = false;
|
||||
|
||||
if (this.props.config.welcomeUserId && getCurrentLanguage().startsWith("en")) {
|
||||
createRoom({
|
||||
const roomId = await createRoom({
|
||||
dmUserId: this.props.config.welcomeUserId,
|
||||
// Only view the welcome user if we're NOT looking at a room
|
||||
andView: !this.state.currentRoomId,
|
||||
});
|
||||
return;
|
||||
// if successful, return because we're already
|
||||
// viewing the welcomeUserId room
|
||||
// else, if failed, fall through to view_home_page
|
||||
if (roomId) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// The user has just logged in after registering
|
||||
dis.dispatch({action: 'view_home_page'});
|
||||
|
@ -1232,13 +1245,20 @@ export default React.createClass({
|
|||
return self._loggedInView.child.canResetTimelineInRoom(roomId);
|
||||
});
|
||||
|
||||
cli.on('sync', function(state, prevState) {
|
||||
cli.on('sync', function(state, prevState, data) {
|
||||
// LifecycleStore and others cannot directly subscribe to matrix client for
|
||||
// events because flux only allows store state changes during flux dispatches.
|
||||
// So dispatch directly from here. Ideally we'd use a SyncStateStore that
|
||||
// would do this dispatch and expose the sync state itself (by listening to
|
||||
// its own dispatch).
|
||||
dis.dispatch({action: 'sync_state', prevState, state});
|
||||
|
||||
if (state === "ERROR") {
|
||||
self.setState({syncError: data.error});
|
||||
} else if (self.state.syncError) {
|
||||
self.setState({syncError: null});
|
||||
}
|
||||
|
||||
self.updateStatusIndicator(state, prevState);
|
||||
if (state === "SYNCING" && prevState === "SYNCING") {
|
||||
return;
|
||||
|
@ -1424,7 +1444,7 @@ export default React.createClass({
|
|||
} else if (screen == 'start') {
|
||||
this.showScreen('home');
|
||||
dis.dispatch({
|
||||
action: 'view_set_mxid',
|
||||
action: 'require_registration',
|
||||
});
|
||||
} else if (screen == 'directory') {
|
||||
dis.dispatch({
|
||||
|
@ -1740,8 +1760,15 @@ export default React.createClass({
|
|||
} else {
|
||||
// we think we are logged in, but are still waiting for the /sync to complete
|
||||
const Spinner = sdk.getComponent('elements.Spinner');
|
||||
let errorBox;
|
||||
if (this.state.syncError) {
|
||||
errorBox = <div className="mx_MatrixChat_syncError">
|
||||
{messageForSyncError(this.state.syncError)}
|
||||
</div>;
|
||||
}
|
||||
return (
|
||||
<div className="mx_MatrixChat_splash">
|
||||
{errorBox}
|
||||
<Spinner />
|
||||
<a href="#" className="mx_MatrixChat_splashButtons" onClick={this.onLogoutClick}>
|
||||
{ _t('Logout') }
|
||||
|
|
|
@ -160,7 +160,7 @@ module.exports = React.createClass({
|
|||
|
||||
onInviteButtonClick: function() {
|
||||
if (this.context.matrixClient.isGuest()) {
|
||||
dis.dispatch({action: 'view_set_mxid'});
|
||||
dis.dispatch({action: 'require_registration'});
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -186,6 +186,9 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
onRoomStateMember: function(ev, state, member) {
|
||||
if (member.roomId !== this.props.roomId) {
|
||||
return;
|
||||
}
|
||||
// redraw the badge on the membership list
|
||||
if (this.state.phase === this.Phase.RoomMemberList && member.roomId === this.props.roomId) {
|
||||
this._delayedUpdate();
|
||||
|
|
|
@ -354,7 +354,7 @@ module.exports = React.createClass({
|
|||
// to the directory.
|
||||
if (MatrixClientPeg.get().isGuest()) {
|
||||
if (!room.world_readable && !room.guest_can_join) {
|
||||
dis.dispatch({action: 'view_set_mxid'});
|
||||
dis.dispatch({action: 'require_registration'});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -318,7 +318,7 @@ module.exports = React.createClass({
|
|||
// lazy load members if enabled
|
||||
if (SettingsStore.isFeatureEnabled('feature_lazyloading')) {
|
||||
room.loadMembersIfNeeded().catch((err) => {
|
||||
const errorMessage = `Fetching room members for ${this.roomId} failed.` +
|
||||
const errorMessage = `Fetching room members for ${room.roomId} failed.` +
|
||||
" Room members will appear incomplete.";
|
||||
console.error(errorMessage);
|
||||
console.error(err);
|
||||
|
@ -915,7 +915,7 @@ module.exports = React.createClass({
|
|||
dis.dispatch({action: 'focus_composer'});
|
||||
|
||||
if (MatrixClientPeg.get().isGuest()) {
|
||||
dis.dispatch({action: 'view_set_mxid'});
|
||||
dis.dispatch({action: 'require_registration'});
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -946,7 +946,7 @@ module.exports = React.createClass({
|
|||
|
||||
injectSticker: function(url, info, text) {
|
||||
if (MatrixClientPeg.get().isGuest()) {
|
||||
dis.dispatch({action: 'view_set_mxid'});
|
||||
dis.dispatch({action: 'require_registration'});
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1461,6 +1461,7 @@ module.exports = React.createClass({
|
|||
const RoomPreviewBar = sdk.getComponent("rooms.RoomPreviewBar");
|
||||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
const TimelinePanel = sdk.getComponent("structures.TimelinePanel");
|
||||
const RoomUpgradeWarningBar = sdk.getComponent("rooms.RoomUpgradeWarningBar");
|
||||
|
||||
if (!this.state.room) {
|
||||
if (this.state.roomLoading || this.state.peekLoading) {
|
||||
|
@ -1587,6 +1588,11 @@ module.exports = React.createClass({
|
|||
/>;
|
||||
}
|
||||
|
||||
const showRoomUpgradeBar = (
|
||||
this.state.room.shouldUpgradeToVersion() &&
|
||||
this.state.room.userMayUpgradeRoom(MatrixClientPeg.get().credentials.userId)
|
||||
);
|
||||
|
||||
let aux = null;
|
||||
let hideCancel = false;
|
||||
if (this.state.editingRoomSettings) {
|
||||
|
@ -1598,6 +1604,9 @@ module.exports = React.createClass({
|
|||
} else if (this.state.searching) {
|
||||
hideCancel = true; // has own cancel
|
||||
aux = <SearchBar ref="search_bar" searchInProgress={this.state.searchInProgress} onCancelClick={this.onCancelSearchClick} onSearch={this.onSearch} />;
|
||||
} else if (showRoomUpgradeBar) {
|
||||
aux = <RoomUpgradeWarningBar room={this.state.room} />;
|
||||
hideCancel = true;
|
||||
} else if (this.state.showingPinned) {
|
||||
hideCancel = true; // has own cancel
|
||||
aux = <PinnedEventsPanel room={this.state.room} onCancelClick={this.onPinnedClick} />;
|
||||
|
|
|
@ -76,7 +76,7 @@ const TagPanel = React.createClass({
|
|||
|
||||
_onClientSync(syncState, prevState) {
|
||||
// Consider the client reconnected if there is no error with syncing.
|
||||
// This means the state could be RECONNECTING, SYNCING or PREPARED.
|
||||
// This means the state could be RECONNECTING, SYNCING, PREPARED or CATCHUP.
|
||||
const reconnected = syncState !== "ERROR" && prevState !== syncState;
|
||||
if (reconnected) {
|
||||
// Load joined groups
|
||||
|
|
|
@ -1146,10 +1146,11 @@ var TimelinePanel = React.createClass({
|
|||
// of paginating our way through the entire history of the room.
|
||||
const stickyBottom = !this._timelineWindow.canPaginate(EventTimeline.FORWARDS);
|
||||
|
||||
// If the state is PREPARED, we're still waiting for the js-sdk to sync with
|
||||
// If the state is PREPARED or CATCHUP, we're still waiting for the js-sdk to sync with
|
||||
// the HS and fetch the latest events, so we are effectively forward paginating.
|
||||
const forwardPaginating = (
|
||||
this.state.forwardPaginating || this.state.clientSyncState == 'PREPARED'
|
||||
this.state.forwardPaginating ||
|
||||
['PREPARED', 'CATCHUP'].includes(this.state.clientSyncState)
|
||||
);
|
||||
return (
|
||||
<MessagePanel ref="messagePanel"
|
||||
|
|
|
@ -921,6 +921,25 @@ module.exports = React.createClass({
|
|||
</div>;
|
||||
},
|
||||
|
||||
_renderTermsAndConditionsLinks: function() {
|
||||
if (SdkConfig.get().terms_and_conditions_links) {
|
||||
const tncLinks = [];
|
||||
for (const tncEntry of SdkConfig.get().terms_and_conditions_links) {
|
||||
tncLinks.push(<div key={tncEntry.url}>
|
||||
<a href={tncEntry.url} rel="noopener" target="_blank">{tncEntry.text}</a>
|
||||
</div>);
|
||||
}
|
||||
return <div>
|
||||
<h3>{ _t("Legal") }</h3>
|
||||
<div className="mx_UserSettings_section">
|
||||
{tncLinks}
|
||||
</div>
|
||||
</div>;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
_renderClearCache: function() {
|
||||
return <div>
|
||||
<h3>{ _t("Clear Cache") }</h3>
|
||||
|
@ -1407,6 +1426,8 @@ module.exports = React.createClass({
|
|||
|
||||
{ this._renderDeactivateAccount() }
|
||||
|
||||
{ this._renderTermsAndConditionsLinks() }
|
||||
|
||||
</GeminiScrollbarWrapper>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -93,6 +93,7 @@ module.exports = React.createClass({
|
|||
doingUIAuth: Boolean(this.props.sessionId),
|
||||
hsUrl: this.props.customHsUrl,
|
||||
isUrl: this.props.customIsUrl,
|
||||
flows: null,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -145,11 +146,27 @@ module.exports = React.createClass({
|
|||
});
|
||||
},
|
||||
|
||||
_replaceClient: function() {
|
||||
_replaceClient: async function() {
|
||||
this._matrixClient = Matrix.createClient({
|
||||
baseUrl: this.state.hsUrl,
|
||||
idBaseUrl: this.state.isUrl,
|
||||
});
|
||||
try {
|
||||
await this._makeRegisterRequest({});
|
||||
// This should never succeed since we specified an empty
|
||||
// auth object.
|
||||
console.log("Expecting 401 from register request but got success!");
|
||||
} catch (e) {
|
||||
if (e.httpStatus === 401) {
|
||||
this.setState({
|
||||
flows: e.data.flows,
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
errorText: _t("Unable to query for supported registration methods"),
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onFormSubmit: function(formVals) {
|
||||
|
@ -378,7 +395,7 @@ module.exports = React.createClass({
|
|||
poll={true}
|
||||
/>
|
||||
);
|
||||
} else if (this.state.busy || this.state.teamServerBusy) {
|
||||
} else if (this.state.busy || this.state.teamServerBusy || !this.state.flows) {
|
||||
registerBody = <Spinner />;
|
||||
} else {
|
||||
let serverConfigSection;
|
||||
|
@ -408,6 +425,7 @@ module.exports = React.createClass({
|
|||
onError={this.onFormValidationFailed}
|
||||
onRegisterClick={this.onFormSubmit}
|
||||
onTeamSelected={this.onTeamSelected}
|
||||
flows={this.state.flows}
|
||||
/>
|
||||
{ serverConfigSection }
|
||||
</div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue