Merge remote-tracking branch 'origin/develop' into rav/handle_received_room_key_requests
This commit is contained in:
commit
27e5098e00
71 changed files with 2580 additions and 732 deletions
|
@ -34,6 +34,9 @@ import sdk from '../../index';
|
|||
import * as Rooms from '../../Rooms';
|
||||
import linkifyMatrix from "../../linkify-matrix";
|
||||
import * as Lifecycle from '../../Lifecycle';
|
||||
// LifecycleStore is not used but does listen to and dispatch actions
|
||||
import LifecycleStore from '../../stores/LifecycleStore';
|
||||
import RoomViewStore from '../../stores/RoomViewStore';
|
||||
import PageTypes from '../../PageTypes';
|
||||
|
||||
import createRoom from "../../createRoom";
|
||||
|
@ -103,9 +106,6 @@ module.exports = React.createClass({
|
|||
// What the LoggedInView would be showing if visible
|
||||
page_type: null,
|
||||
|
||||
// If we are viewing a room by alias, this contains the alias
|
||||
currentRoomAlias: null,
|
||||
|
||||
// The ID of the room we're viewing. This is either populated directly
|
||||
// in the case where we view a room by ID or by RoomView when it resolves
|
||||
// what ID an alias points at.
|
||||
|
@ -192,6 +192,9 @@ module.exports = React.createClass({
|
|||
componentWillMount: function() {
|
||||
SdkConfig.put(this.props.config);
|
||||
|
||||
RoomViewStore.addListener(this._onRoomViewStoreUpdated);
|
||||
this._onRoomViewStoreUpdated();
|
||||
|
||||
if (!UserSettingsStore.getLocalSetting('analyticsOptOut', false)) Analytics.enable();
|
||||
|
||||
// Used by _viewRoom before getting state from sync
|
||||
|
@ -293,7 +296,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
Lifecycle.stopMatrixClient(false);
|
||||
Lifecycle.stopMatrixClient();
|
||||
dis.unregister(this.dispatcherRef);
|
||||
UDEHandler.stopListening();
|
||||
window.removeEventListener("focus", this.onFocus);
|
||||
|
@ -323,7 +326,6 @@ module.exports = React.createClass({
|
|||
onAction: function(payload) {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
const TextInputDialog = sdk.getComponent("dialogs.TextInputDialog");
|
||||
|
||||
switch (payload.action) {
|
||||
case 'logout':
|
||||
|
@ -365,17 +367,21 @@ module.exports = React.createClass({
|
|||
// is completed in another browser, we'll be 401ed for using
|
||||
// a guest access token for a non-guest account.
|
||||
// It will be restarted in onReturnToGuestClick
|
||||
Lifecycle.stopMatrixClient(false);
|
||||
Lifecycle.stopMatrixClient();
|
||||
|
||||
this.notifyNewScreen('register');
|
||||
break;
|
||||
case 'start_password_recovery':
|
||||
if (this.state.loggedIn) return;
|
||||
this.setStateForNewScreen({
|
||||
screen: 'forgot_password',
|
||||
});
|
||||
this.notifyNewScreen('forgot_password');
|
||||
break;
|
||||
case 'start_chat':
|
||||
createRoom({
|
||||
dmUserId: payload.user_id,
|
||||
});
|
||||
break;
|
||||
case 'leave_room':
|
||||
this._leaveRoom(payload.room_id);
|
||||
break;
|
||||
|
@ -436,37 +442,36 @@ module.exports = React.createClass({
|
|||
this._viewIndexedRoom(payload.roomIndex);
|
||||
break;
|
||||
case 'view_user_settings':
|
||||
if (MatrixClientPeg.get().isGuest()) {
|
||||
dis.dispatch({
|
||||
action: 'do_after_sync_prepared',
|
||||
deferred_action: {
|
||||
action: 'view_user_settings',
|
||||
},
|
||||
});
|
||||
dis.dispatch({action: 'view_set_mxid'});
|
||||
break;
|
||||
}
|
||||
this._setPage(PageTypes.UserSettings);
|
||||
this.notifyNewScreen('settings');
|
||||
break;
|
||||
case 'view_create_room':
|
||||
//this._setPage(PageTypes.CreateRoom);
|
||||
//this.notifyNewScreen('new');
|
||||
Modal.createDialog(TextInputDialog, {
|
||||
title: _t('Create Room'),
|
||||
description: _t('Room name (optional)'),
|
||||
button: _t('Create Room'),
|
||||
onFinished: (shouldCreate, name) => {
|
||||
if (shouldCreate) {
|
||||
const createOpts = {};
|
||||
if (name) createOpts.name = name;
|
||||
createRoom({createOpts}).done();
|
||||
}
|
||||
},
|
||||
});
|
||||
this._createRoom();
|
||||
break;
|
||||
case 'view_room_directory':
|
||||
this._setPage(PageTypes.RoomDirectory);
|
||||
this.notifyNewScreen('directory');
|
||||
break;
|
||||
case 'view_home_page':
|
||||
if (!this._teamToken) {
|
||||
dis.dispatch({action: 'view_room_directory'});
|
||||
return;
|
||||
}
|
||||
this._setPage(PageTypes.HomePage);
|
||||
this.notifyNewScreen('home');
|
||||
break;
|
||||
case 'view_set_mxid':
|
||||
this._setMxId();
|
||||
break;
|
||||
case 'view_start_chat_or_reuse':
|
||||
this._chatCreateOrReuse(payload.user_id);
|
||||
break;
|
||||
case 'view_create_chat':
|
||||
this._createChat();
|
||||
break;
|
||||
|
@ -508,7 +513,11 @@ module.exports = React.createClass({
|
|||
this._onSetTheme(payload.value);
|
||||
break;
|
||||
case 'on_logging_in':
|
||||
this.setState({loggingIn: true});
|
||||
// We are now logging in, so set the state to reflect that
|
||||
// and also that we're not ready (we'll be marked as logged
|
||||
// in once the login completes, then ready once the sync
|
||||
// completes).
|
||||
this.setState({loggingIn: true, ready: false});
|
||||
break;
|
||||
case 'on_logged_in':
|
||||
this._onLoggedIn(payload.teamToken);
|
||||
|
@ -531,6 +540,10 @@ module.exports = React.createClass({
|
|||
}
|
||||
},
|
||||
|
||||
_onRoomViewStoreUpdated: function() {
|
||||
this.setState({ currentRoomId: RoomViewStore.getRoomId() });
|
||||
},
|
||||
|
||||
_setPage: function(pageType) {
|
||||
this.setState({
|
||||
page_type: pageType,
|
||||
|
@ -553,6 +566,7 @@ module.exports = React.createClass({
|
|||
this.notifyNewScreen('register');
|
||||
},
|
||||
|
||||
// TODO: Move to RoomViewStore
|
||||
_viewNextRoom: function(roomIndexDelta) {
|
||||
const allRooms = RoomListSorter.mostRecentActivityFirst(
|
||||
MatrixClientPeg.get().getRooms(),
|
||||
|
@ -566,15 +580,22 @@ module.exports = React.createClass({
|
|||
}
|
||||
roomIndex = (roomIndex + roomIndexDelta) % allRooms.length;
|
||||
if (roomIndex < 0) roomIndex = allRooms.length - 1;
|
||||
this._viewRoom({ room_id: allRooms[roomIndex].roomId });
|
||||
dis.dispatch({
|
||||
action: 'view_room',
|
||||
room_id: allRooms[roomIndex].roomId,
|
||||
});
|
||||
},
|
||||
|
||||
// TODO: Move to RoomViewStore
|
||||
_viewIndexedRoom: function(roomIndex) {
|
||||
const allRooms = RoomListSorter.mostRecentActivityFirst(
|
||||
MatrixClientPeg.get().getRooms(),
|
||||
);
|
||||
if (allRooms[roomIndex]) {
|
||||
this._viewRoom({ room_id: allRooms[roomIndex].roomId });
|
||||
dis.dispatch({
|
||||
action: 'view_room',
|
||||
room_id: allRooms[roomIndex].roomId,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -658,7 +679,41 @@ module.exports = React.createClass({
|
|||
});
|
||||
},
|
||||
|
||||
_setMxId: function() {
|
||||
const SetMxIdDialog = sdk.getComponent('views.dialogs.SetMxIdDialog');
|
||||
const close = Modal.createDialog(SetMxIdDialog, {
|
||||
homeserverUrl: MatrixClientPeg.get().getHomeserverUrl(),
|
||||
onFinished: (submitted, credentials) => {
|
||||
if (!submitted) {
|
||||
dis.dispatch({
|
||||
action: 'cancel_after_sync_prepared',
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.onRegistered(credentials);
|
||||
},
|
||||
onDifferentServerClicked: (ev) => {
|
||||
dis.dispatch({action: 'start_registration'});
|
||||
close();
|
||||
},
|
||||
onLoginClick: (ev) => {
|
||||
dis.dispatch({action: 'start_login'});
|
||||
close();
|
||||
},
|
||||
}).close;
|
||||
},
|
||||
|
||||
_createChat: function() {
|
||||
if (MatrixClientPeg.get().isGuest()) {
|
||||
dis.dispatch({
|
||||
action: 'do_after_sync_prepared',
|
||||
deferred_action: {
|
||||
action: 'view_create_chat',
|
||||
},
|
||||
});
|
||||
dis.dispatch({action: 'view_set_mxid'});
|
||||
return;
|
||||
}
|
||||
const ChatInviteDialog = sdk.getComponent("dialogs.ChatInviteDialog");
|
||||
Modal.createDialog(ChatInviteDialog, {
|
||||
title: _t('Start a chat'),
|
||||
|
@ -668,6 +723,81 @@ module.exports = React.createClass({
|
|||
});
|
||||
},
|
||||
|
||||
_createRoom: function() {
|
||||
if (MatrixClientPeg.get().isGuest()) {
|
||||
dis.dispatch({
|
||||
action: 'do_after_sync_prepared',
|
||||
deferred_action: {
|
||||
action: 'view_create_room',
|
||||
},
|
||||
});
|
||||
dis.dispatch({action: 'view_set_mxid'});
|
||||
return;
|
||||
}
|
||||
const TextInputDialog = sdk.getComponent("dialogs.TextInputDialog");
|
||||
Modal.createDialog(TextInputDialog, {
|
||||
title: _t('Create Room'),
|
||||
description: _t('Room name (optional)'),
|
||||
button: _t('Create Room'),
|
||||
onFinished: (should_create, name) => {
|
||||
if (should_create) {
|
||||
const createOpts = {};
|
||||
if (name) createOpts.name = name;
|
||||
createRoom({createOpts}).done();
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
_chatCreateOrReuse: function(userId) {
|
||||
const ChatCreateOrReuseDialog = sdk.getComponent(
|
||||
'views.dialogs.ChatCreateOrReuseDialog',
|
||||
);
|
||||
// Use a deferred action to reshow the dialog once the user has registered
|
||||
if (MatrixClientPeg.get().isGuest()) {
|
||||
// No point in making 2 DMs with welcome bot. This assumes view_set_mxid will
|
||||
// result in a new DM with the welcome user.
|
||||
if (userId !== this.props.config.welcomeUserId) {
|
||||
dis.dispatch({
|
||||
action: 'do_after_sync_prepared',
|
||||
deferred_action: {
|
||||
action: 'view_start_chat_or_reuse',
|
||||
user_id: userId,
|
||||
},
|
||||
});
|
||||
}
|
||||
dis.dispatch({
|
||||
action: 'view_set_mxid',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const close = Modal.createDialog(ChatCreateOrReuseDialog, {
|
||||
userId: userId,
|
||||
onFinished: (success) => {
|
||||
if (!success) {
|
||||
// Dialog cancelled, default to home
|
||||
dis.dispatch({ action: 'view_home_page' });
|
||||
}
|
||||
},
|
||||
onNewDMClick: () => {
|
||||
dis.dispatch({
|
||||
action: 'start_chat',
|
||||
user_id: userId,
|
||||
});
|
||||
// Close the dialog, indicate success (calls onFinished(true))
|
||||
close(true);
|
||||
},
|
||||
onExistingRoomSelected: (roomId) => {
|
||||
dis.dispatch({
|
||||
action: 'view_room',
|
||||
room_id: roomId,
|
||||
});
|
||||
close(true);
|
||||
},
|
||||
}).close;
|
||||
},
|
||||
|
||||
_invite: function(roomId) {
|
||||
const ChatInviteDialog = sdk.getComponent("dialogs.ChatInviteDialog");
|
||||
Modal.createDialog(ChatInviteDialog, {
|
||||
|
@ -701,7 +831,7 @@ module.exports = React.createClass({
|
|||
|
||||
d.then(() => {
|
||||
modal.close();
|
||||
if (this.currentRoomId === roomId) {
|
||||
if (this.state.currentRoomId === roomId) {
|
||||
dis.dispatch({action: 'view_next_room'});
|
||||
}
|
||||
}, (err) => {
|
||||
|
@ -796,12 +926,27 @@ module.exports = React.createClass({
|
|||
this._teamToken = teamToken;
|
||||
dis.dispatch({action: 'view_home_page'});
|
||||
} else if (this._is_registered) {
|
||||
this._is_registered = false;
|
||||
// reset the 'have completed first sync' flag,
|
||||
// since we've just logged in and will be about to sync
|
||||
this.firstSyncComplete = false;
|
||||
this.firstSyncPromise = q.defer();
|
||||
|
||||
// Set the display name = user ID localpart
|
||||
MatrixClientPeg.get().setDisplayName(
|
||||
MatrixClientPeg.get().getUserIdLocalpart(),
|
||||
);
|
||||
|
||||
if (this.props.config.welcomeUserId && getCurrentLanguage().startsWith("en")) {
|
||||
createRoom({dmUserId: this.props.config.welcomeUserId});
|
||||
createRoom({
|
||||
dmUserId: this.props.config.welcomeUserId,
|
||||
// Only view the welcome user if we're NOT looking at a room
|
||||
andView: !this.state.currentRoomId,
|
||||
});
|
||||
return;
|
||||
}
|
||||
// The user has just logged in after registering
|
||||
dis.dispatch({action: 'view_room_directory'});
|
||||
dis.dispatch({action: 'view_home_page'});
|
||||
} else {
|
||||
this._showScreenAfterLogin();
|
||||
}
|
||||
|
@ -823,12 +968,8 @@ module.exports = React.createClass({
|
|||
action: 'view_room',
|
||||
room_id: localStorage.getItem('mx_last_room_id'),
|
||||
});
|
||||
} else if (this._teamToken) {
|
||||
// Team token might be set if we're a guest.
|
||||
// Guests do not call _onLoggedIn with a teamToken
|
||||
dis.dispatch({action: 'view_home_page'});
|
||||
} else {
|
||||
dis.dispatch({action: 'view_room_directory'});
|
||||
dis.dispatch({action: 'view_home_page'});
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -842,7 +983,6 @@ module.exports = React.createClass({
|
|||
ready: false,
|
||||
collapse_lhs: false,
|
||||
collapse_rhs: false,
|
||||
currentRoomAlias: null,
|
||||
currentRoomId: null,
|
||||
page_type: PageTypes.RoomDirectory,
|
||||
});
|
||||
|
@ -880,6 +1020,12 @@ module.exports = React.createClass({
|
|||
});
|
||||
|
||||
cli.on('sync', function(state, prevState) {
|
||||
// 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});
|
||||
self.updateStatusIndicator(state, prevState);
|
||||
if (state === "SYNCING" && prevState === "SYNCING") {
|
||||
return;
|
||||
|
@ -957,6 +1103,11 @@ module.exports = React.createClass({
|
|||
dis.dispatch({
|
||||
action: 'view_home_page',
|
||||
});
|
||||
} else if (screen == 'start') {
|
||||
this.showScreen('home');
|
||||
dis.dispatch({
|
||||
action: 'view_set_mxid',
|
||||
});
|
||||
} else if (screen == 'directory') {
|
||||
dis.dispatch({
|
||||
action: 'view_room_directory',
|
||||
|
@ -1000,6 +1151,12 @@ module.exports = React.createClass({
|
|||
}
|
||||
} else if (screen.indexOf('user/') == 0) {
|
||||
const userId = screen.substring(5);
|
||||
|
||||
if (params.action === 'chat') {
|
||||
this._chatCreateOrReuse(userId);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({ viewUserId: userId });
|
||||
this._setPage(PageTypes.UserView);
|
||||
this.notifyNewScreen('user/' + userId);
|
||||
|
@ -1096,6 +1253,8 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
onRegistered: function(credentials, teamToken) {
|
||||
// XXX: These both should be in state or ideally store(s) because we risk not
|
||||
// rendering the most up-to-date view of state otherwise.
|
||||
// teamToken may not be truthy
|
||||
this._teamToken = teamToken;
|
||||
this._is_registered = true;
|
||||
|
@ -1139,7 +1298,15 @@ module.exports = React.createClass({
|
|||
PlatformPeg.get().setNotificationCount(notifCount);
|
||||
}
|
||||
|
||||
document.title = `Riot ${state === "ERROR" ? " [offline]" : ""}${notifCount > 0 ? ` [${notifCount}]` : ""}`;
|
||||
let title = "Riot ";
|
||||
if (state === "ERROR") {
|
||||
title += `[${_t("Offline")}] `;
|
||||
}
|
||||
if (notifCount > 0) {
|
||||
title += `[${notifCount}]`;
|
||||
}
|
||||
|
||||
document.title = title;
|
||||
},
|
||||
|
||||
onUserSettingsClose: function() {
|
||||
|
@ -1157,13 +1324,6 @@ module.exports = React.createClass({
|
|||
}
|
||||
},
|
||||
|
||||
onRoomIdResolved: function(roomId) {
|
||||
// It's the RoomView's resposibility to look up room aliases, but we need the
|
||||
// ID to pass into things like the Member List, so the Room View tells us when
|
||||
// its done that resolution so we can display things that take a room ID.
|
||||
this.setState({currentRoomId: roomId});
|
||||
},
|
||||
|
||||
_makeRegistrationUrl: function(params) {
|
||||
if (this.props.startingFragmentQueryParams.referrer) {
|
||||
params.referrer = this.props.startingFragmentQueryParams.referrer;
|
||||
|
@ -1205,9 +1365,10 @@ module.exports = React.createClass({
|
|||
const LoggedInView = sdk.getComponent('structures.LoggedInView');
|
||||
return (
|
||||
<LoggedInView ref="loggedInView" matrixClient={MatrixClientPeg.get()}
|
||||
onRoomIdResolved={this.onRoomIdResolved}
|
||||
onRoomCreated={this.onRoomCreated}
|
||||
onUserSettingsClose={this.onUserSettingsClose}
|
||||
onRegistered={this.onRegistered}
|
||||
currentRoomId={this.state.currentRoomId}
|
||||
teamToken={this._teamToken}
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue