Merge branch 'develop' of github.com:matrix-org/matrix-react-sdk into webrtc_settings
This commit is contained in:
commit
a4b2bacc7e
47 changed files with 1090 additions and 1059 deletions
|
@ -59,6 +59,8 @@ var FilePanel = React.createClass({
|
|||
var client = MatrixClientPeg.get();
|
||||
var room = client.getRoom(roomId);
|
||||
|
||||
this.noRoom = !room;
|
||||
|
||||
if (room) {
|
||||
var filter = new Matrix.Filter(client.credentials.userId);
|
||||
filter.setDefinition(
|
||||
|
@ -82,13 +84,22 @@ var FilePanel = React.createClass({
|
|||
console.error("Failed to get or create file panel filter", error);
|
||||
}
|
||||
);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
console.error("Failed to add filtered timelineSet for FilePanel as no room!");
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
if (MatrixClientPeg.get().isGuest()) {
|
||||
return <div className="mx_FilePanel mx_RoomView_messageListWrapper">
|
||||
<div className="mx_RoomView_empty">You must <a href="#/register">register</a> to use this functionality</div>
|
||||
</div>;
|
||||
} else if (this.noRoom) {
|
||||
return <div className="mx_FilePanel mx_RoomView_messageListWrapper">
|
||||
<div className="mx_RoomView_empty">You must join the room to see its files</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
// wrap a TimelinePanel with the jump-to-event bits turned off.
|
||||
var TimelinePanel = sdk.getComponent("structures.TimelinePanel");
|
||||
var Loader = sdk.getComponent("elements.Spinner");
|
||||
|
|
|
@ -112,18 +112,6 @@ export default React.createClass({
|
|||
var handled = false;
|
||||
|
||||
switch (ev.keyCode) {
|
||||
case KeyCode.ESCAPE:
|
||||
|
||||
// Implemented this way so possible handling for other pages is neater
|
||||
switch (this.props.page_type) {
|
||||
case PageTypes.UserSettings:
|
||||
this.props.onUserSettingsClose();
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case KeyCode.UP:
|
||||
case KeyCode.DOWN:
|
||||
if (ev.altKey && !ev.shiftKey && !ev.ctrlKey && !ev.metaKey) {
|
||||
|
|
|
@ -17,27 +17,24 @@ limitations under the License.
|
|||
|
||||
import q from 'q';
|
||||
|
||||
var React = require('react');
|
||||
var Matrix = require("matrix-js-sdk");
|
||||
import React from 'react';
|
||||
import Matrix from "matrix-js-sdk";
|
||||
|
||||
var MatrixClientPeg = require("../../MatrixClientPeg");
|
||||
var PlatformPeg = require("../../PlatformPeg");
|
||||
var SdkConfig = require("../../SdkConfig");
|
||||
var ContextualMenu = require("./ContextualMenu");
|
||||
var RoomListSorter = require("../../RoomListSorter");
|
||||
var UserActivity = require("../../UserActivity");
|
||||
var Presence = require("../../Presence");
|
||||
var dis = require("../../dispatcher");
|
||||
import MatrixClientPeg from "../../MatrixClientPeg";
|
||||
import PlatformPeg from "../../PlatformPeg";
|
||||
import SdkConfig from "../../SdkConfig";
|
||||
import * as RoomListSorter from "../../RoomListSorter";
|
||||
import dis from "../../dispatcher";
|
||||
|
||||
var Modal = require("../../Modal");
|
||||
var Tinter = require("../../Tinter");
|
||||
var sdk = require('../../index');
|
||||
var Rooms = require('../../Rooms');
|
||||
var linkifyMatrix = require("../../linkify-matrix");
|
||||
var Lifecycle = require('../../Lifecycle');
|
||||
var PageTypes = require('../../PageTypes');
|
||||
import Modal from "../../Modal";
|
||||
import Tinter from "../../Tinter";
|
||||
import sdk from '../../index';
|
||||
import * as Rooms from '../../Rooms';
|
||||
import linkifyMatrix from "../../linkify-matrix";
|
||||
import * as Lifecycle from '../../Lifecycle';
|
||||
import PageTypes from '../../PageTypes';
|
||||
|
||||
var createRoom = require("../../createRoom");
|
||||
import createRoom from "../../createRoom";
|
||||
import * as UDEHandler from '../../UnknownDeviceErrorHandler';
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
@ -89,7 +86,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
getInitialState: function() {
|
||||
var s = {
|
||||
const s = {
|
||||
loading: true,
|
||||
screen: undefined,
|
||||
screenAfterLogin: this.props.initialScreenAfterLogin,
|
||||
|
@ -156,11 +153,9 @@ module.exports = React.createClass({
|
|||
return this.state.register_hs_url;
|
||||
} else if (MatrixClientPeg.get()) {
|
||||
return MatrixClientPeg.get().getHomeserverUrl();
|
||||
}
|
||||
else if (window.localStorage && window.localStorage.getItem("mx_hs_url")) {
|
||||
} else if (window.localStorage && window.localStorage.getItem("mx_hs_url")) {
|
||||
return window.localStorage.getItem("mx_hs_url");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return this.getDefaultHsUrl();
|
||||
}
|
||||
},
|
||||
|
@ -178,11 +173,9 @@ module.exports = React.createClass({
|
|||
return this.state.register_is_url;
|
||||
} else if (MatrixClientPeg.get()) {
|
||||
return MatrixClientPeg.get().getIdentityServerUrl();
|
||||
}
|
||||
else if (window.localStorage && window.localStorage.getItem("mx_is_url")) {
|
||||
} else if (window.localStorage && window.localStorage.getItem("mx_is_url")) {
|
||||
return window.localStorage.getItem("mx_is_url");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return this.getDefaultIsUrl();
|
||||
}
|
||||
},
|
||||
|
@ -324,28 +317,14 @@ module.exports = React.createClass({
|
|||
onAction: function(payload) {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
var roomIndexDelta = 1;
|
||||
const TextInputDialog = sdk.getComponent("dialogs.TextInputDialog");
|
||||
|
||||
var self = this;
|
||||
switch (payload.action) {
|
||||
case 'logout':
|
||||
Lifecycle.logout();
|
||||
break;
|
||||
case 'start_registration':
|
||||
const params = payload.params || {};
|
||||
this.setStateForNewScreen({
|
||||
screen: 'register',
|
||||
// these params may be undefined, but if they are,
|
||||
// unset them from our state: we don't want to
|
||||
// resume a previous registration session if the
|
||||
// user just clicked 'register'
|
||||
register_client_secret: params.client_secret,
|
||||
register_session_id: params.session_id,
|
||||
register_hs_url: params.hs_url,
|
||||
register_is_url: params.is_url,
|
||||
register_id_sid: params.sid,
|
||||
});
|
||||
this.notifyNewScreen('register');
|
||||
this._startRegistration(payload.params || {});
|
||||
break;
|
||||
case 'start_login':
|
||||
if (MatrixClientPeg.get() &&
|
||||
|
@ -362,7 +341,7 @@ module.exports = React.createClass({
|
|||
break;
|
||||
case 'start_post_registration':
|
||||
this.setState({ // don't clobber loggedIn status
|
||||
screen: 'post_registration'
|
||||
screen: 'post_registration',
|
||||
});
|
||||
break;
|
||||
case 'start_upgrade_registration':
|
||||
|
@ -392,33 +371,7 @@ module.exports = React.createClass({
|
|||
this.notifyNewScreen('forgot_password');
|
||||
break;
|
||||
case 'leave_room':
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: "Leave room",
|
||||
description: "Are you sure you want to leave the room?",
|
||||
onFinished: (should_leave) => {
|
||||
if (should_leave) {
|
||||
const d = MatrixClientPeg.get().leave(payload.room_id);
|
||||
|
||||
// FIXME: controller shouldn't be loading a view :(
|
||||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
const modal = Modal.createDialog(Loader, null, 'mx_Dialog_spinner');
|
||||
|
||||
d.then(() => {
|
||||
modal.close();
|
||||
if (this.currentRoomId === payload.room_id) {
|
||||
dis.dispatch({action: 'view_next_room'});
|
||||
}
|
||||
}, (err) => {
|
||||
modal.close();
|
||||
console.error("Failed to leave room " + payload.room_id + " " + err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Failed to leave room",
|
||||
description: (err && err.message ? err.message : "Server may be unavailable, overloaded, or you hit a bug."),
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
this._leaveRoom(payload.room_id);
|
||||
break;
|
||||
case 'reject_invite':
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
|
@ -439,11 +392,11 @@ module.exports = React.createClass({
|
|||
modal.close();
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Failed to reject invitation",
|
||||
description: err.toString()
|
||||
description: err.toString(),
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
break;
|
||||
case 'view_user':
|
||||
|
@ -468,30 +421,13 @@ module.exports = React.createClass({
|
|||
this._viewRoom(payload);
|
||||
break;
|
||||
case 'view_prev_room':
|
||||
roomIndexDelta = -1;
|
||||
this._viewNextRoom(-1);
|
||||
break;
|
||||
case 'view_next_room':
|
||||
var allRooms = RoomListSorter.mostRecentActivityFirst(
|
||||
MatrixClientPeg.get().getRooms()
|
||||
);
|
||||
var roomIndex = -1;
|
||||
for (var i = 0; i < allRooms.length; ++i) {
|
||||
if (allRooms[i].roomId == this.state.currentRoomId) {
|
||||
roomIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
roomIndex = (roomIndex + roomIndexDelta) % allRooms.length;
|
||||
if (roomIndex < 0) roomIndex = allRooms.length - 1;
|
||||
this._viewRoom({ room_id: allRooms[roomIndex].roomId });
|
||||
this._viewNextRoom(1);
|
||||
break;
|
||||
case 'view_indexed_room':
|
||||
var allRooms = RoomListSorter.mostRecentActivityFirst(
|
||||
MatrixClientPeg.get().getRooms()
|
||||
);
|
||||
var roomIndex = payload.roomIndex;
|
||||
if (allRooms[roomIndex]) {
|
||||
this._viewRoom({ room_id: allRooms[roomIndex].roomId });
|
||||
}
|
||||
this._viewIndexedRoom(payload.roomIndex);
|
||||
break;
|
||||
case 'view_user_settings':
|
||||
this._setPage(PageTypes.UserSettings);
|
||||
|
@ -500,19 +436,17 @@ module.exports = React.createClass({
|
|||
case 'view_create_room':
|
||||
//this._setPage(PageTypes.CreateRoom);
|
||||
//this.notifyNewScreen('new');
|
||||
|
||||
var TextInputDialog = sdk.getComponent("dialogs.TextInputDialog");
|
||||
Modal.createDialog(TextInputDialog, {
|
||||
title: "Create Room",
|
||||
description: "Room name (optional)",
|
||||
button: "Create Room",
|
||||
onFinished: (should_create, name) => {
|
||||
if (should_create) {
|
||||
onFinished: (shouldCreate, name) => {
|
||||
if (shouldCreate) {
|
||||
const createOpts = {};
|
||||
if (name) createOpts.name = name;
|
||||
createRoom({createOpts}).done();
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
break;
|
||||
case 'view_room_directory':
|
||||
|
@ -583,7 +517,7 @@ module.exports = React.createClass({
|
|||
case 'new_version':
|
||||
this.onVersion(
|
||||
payload.currentVersion, payload.newVersion,
|
||||
payload.releaseNotes
|
||||
payload.releaseNotes,
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
@ -595,6 +529,47 @@ module.exports = React.createClass({
|
|||
});
|
||||
},
|
||||
|
||||
_startRegistration: function(params) {
|
||||
this.setStateForNewScreen({
|
||||
screen: 'register',
|
||||
// these params may be undefined, but if they are,
|
||||
// unset them from our state: we don't want to
|
||||
// resume a previous registration session if the
|
||||
// user just clicked 'register'
|
||||
register_client_secret: params.client_secret,
|
||||
register_session_id: params.session_id,
|
||||
register_hs_url: params.hs_url,
|
||||
register_is_url: params.is_url,
|
||||
register_id_sid: params.sid,
|
||||
});
|
||||
this.notifyNewScreen('register');
|
||||
},
|
||||
|
||||
_viewNextRoom: function(roomIndexDelta) {
|
||||
const allRooms = RoomListSorter.mostRecentActivityFirst(
|
||||
MatrixClientPeg.get().getRooms(),
|
||||
);
|
||||
let roomIndex = -1;
|
||||
for (let i = 0; i < allRooms.length; ++i) {
|
||||
if (allRooms[i].roomId == this.state.currentRoomId) {
|
||||
roomIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
roomIndex = (roomIndex + roomIndexDelta) % allRooms.length;
|
||||
if (roomIndex < 0) roomIndex = allRooms.length - 1;
|
||||
this._viewRoom({ room_id: allRooms[roomIndex].roomId });
|
||||
},
|
||||
|
||||
_viewIndexedRoom: function(roomIndex) {
|
||||
const allRooms = RoomListSorter.mostRecentActivityFirst(
|
||||
MatrixClientPeg.get().getRooms(),
|
||||
);
|
||||
if (allRooms[roomIndex]) {
|
||||
this._viewRoom({ room_id: allRooms[roomIndex].roomId });
|
||||
}
|
||||
},
|
||||
|
||||
// switch view to the given room
|
||||
//
|
||||
// @param {Object} room_info Object containing data about the room to be joined
|
||||
|
@ -614,7 +589,7 @@ module.exports = React.createClass({
|
|||
_viewRoom: function(room_info) {
|
||||
this.focusComposer = true;
|
||||
|
||||
var newState = {
|
||||
const newState = {
|
||||
initialEventId: room_info.event_id,
|
||||
highlightedEventId: room_info.event_id,
|
||||
initialEventPixelOffset: undefined,
|
||||
|
@ -634,7 +609,7 @@ module.exports = React.createClass({
|
|||
//
|
||||
// TODO: do this in RoomView rather than here
|
||||
if (!room_info.event_id && this.refs.loggedInView) {
|
||||
var scrollState = this.refs.loggedInView.getScrollStateForRoom(room_info.room_id);
|
||||
const scrollState = this.refs.loggedInView.getScrollStateForRoom(room_info.room_id);
|
||||
if (scrollState) {
|
||||
newState.initialEventId = scrollState.focussedEvent;
|
||||
newState.initialEventPixelOffset = scrollState.pixelOffset;
|
||||
|
@ -676,14 +651,14 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
_createChat: function() {
|
||||
var ChatInviteDialog = sdk.getComponent("dialogs.ChatInviteDialog");
|
||||
const ChatInviteDialog = sdk.getComponent("dialogs.ChatInviteDialog");
|
||||
Modal.createDialog(ChatInviteDialog, {
|
||||
title: "Start a new chat",
|
||||
});
|
||||
},
|
||||
|
||||
_invite: function(roomId) {
|
||||
var ChatInviteDialog = sdk.getComponent("dialogs.ChatInviteDialog");
|
||||
const ChatInviteDialog = sdk.getComponent("dialogs.ChatInviteDialog");
|
||||
Modal.createDialog(ChatInviteDialog, {
|
||||
title: "Invite new room members",
|
||||
button: "Send Invites",
|
||||
|
@ -692,6 +667,41 @@ module.exports = React.createClass({
|
|||
});
|
||||
},
|
||||
|
||||
_leaveRoom: function(roomId) {
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
|
||||
const roomToLeave = MatrixClientPeg.get().getRoom(roomId);
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: "Leave room",
|
||||
description: <span>Are you sure you want to leave the room <i>{roomToLeave.name}</i>?</span>,
|
||||
onFinished: (shouldLeave) => {
|
||||
if (shouldLeave) {
|
||||
const d = MatrixClientPeg.get().leave(roomId);
|
||||
|
||||
// FIXME: controller shouldn't be loading a view :(
|
||||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
const modal = Modal.createDialog(Loader, null, 'mx_Dialog_spinner');
|
||||
|
||||
d.then(() => {
|
||||
modal.close();
|
||||
if (this.currentRoomId === roomId) {
|
||||
dis.dispatch({action: 'view_next_room'});
|
||||
}
|
||||
}, (err) => {
|
||||
modal.close();
|
||||
console.error("Failed to leave room " + roomId + " " + err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Failed to leave room",
|
||||
description: (err && err.message ? err.message :
|
||||
"Server may be unavailable, overloaded, or you hit a bug."),
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the sessionloader has finished
|
||||
*/
|
||||
|
@ -710,6 +720,8 @@ module.exports = React.createClass({
|
|||
|
||||
/**
|
||||
* Called whenever someone changes the theme
|
||||
*
|
||||
* @param {string} theme new theme
|
||||
*/
|
||||
_onSetTheme: function(theme) {
|
||||
if (!theme) {
|
||||
|
@ -718,12 +730,12 @@ module.exports = React.createClass({
|
|||
|
||||
// look for the stylesheet elements.
|
||||
// styleElements is a map from style name to HTMLLinkElement.
|
||||
var styleElements = Object.create(null);
|
||||
var i, a;
|
||||
for (i = 0; (a = document.getElementsByTagName("link")[i]); i++) {
|
||||
var href = a.getAttribute("href");
|
||||
const styleElements = Object.create(null);
|
||||
let a;
|
||||
for (let i = 0; (a = document.getElementsByTagName("link")[i]); i++) {
|
||||
const href = a.getAttribute("href");
|
||||
// shouldn't we be using the 'title' tag rather than the href?
|
||||
var match = href.match(/^bundles\/.*\/theme-(.*)\.css$/);
|
||||
const match = href.match(/^bundles\/.*\/theme-(.*)\.css$/);
|
||||
if (match) {
|
||||
styleElements[match[1]] = a;
|
||||
}
|
||||
|
@ -746,14 +758,15 @@ module.exports = React.createClass({
|
|||
// abuse the tinter to change all the SVG's #fff to #2d2d2d
|
||||
// XXX: obviously this shouldn't be hardcoded here.
|
||||
Tinter.tintSvgWhite('#2d2d2d');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Tinter.tintSvgWhite('#ffffff');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a new logged in session has started
|
||||
*
|
||||
* @param {string} teamToken
|
||||
*/
|
||||
_onLoggedIn: function(teamToken) {
|
||||
this.setState({
|
||||
|
@ -767,8 +780,12 @@ module.exports = React.createClass({
|
|||
this._teamToken = teamToken;
|
||||
dis.dispatch({action: 'view_home_page'});
|
||||
} else if (this._is_registered) {
|
||||
if (this.props.config.welcomeUserId) {
|
||||
createRoom({dmUserId: this.props.config.welcomeUserId});
|
||||
return;
|
||||
}
|
||||
// The user has just logged in after registering
|
||||
dis.dispatch({action: 'view_user_settings'});
|
||||
dis.dispatch({action: 'view_room_directory'});
|
||||
} else {
|
||||
this._showScreenAfterLogin();
|
||||
}
|
||||
|
@ -780,7 +797,7 @@ module.exports = React.createClass({
|
|||
if (this.state.screenAfterLogin && this.state.screenAfterLogin.screen) {
|
||||
this.showScreen(
|
||||
this.state.screenAfterLogin.screen,
|
||||
this.state.screenAfterLogin.params
|
||||
this.state.screenAfterLogin.params,
|
||||
);
|
||||
this.notifyNewScreen(this.state.screenAfterLogin.screen);
|
||||
this.setState({screenAfterLogin: null});
|
||||
|
@ -821,8 +838,8 @@ module.exports = React.createClass({
|
|||
* (useful for setting listeners)
|
||||
*/
|
||||
_onWillStartClient() {
|
||||
var self = this;
|
||||
var cli = MatrixClientPeg.get();
|
||||
const self = this;
|
||||
const cli = MatrixClientPeg.get();
|
||||
|
||||
// Allow the JS SDK to reap timeline events. This reduces the amount of
|
||||
// memory consumed as the JS SDK stores multiple distinct copies of room
|
||||
|
@ -863,17 +880,17 @@ module.exports = React.createClass({
|
|||
cli.on('Call.incoming', function(call) {
|
||||
dis.dispatch({
|
||||
action: 'incoming_call',
|
||||
call: call
|
||||
call: call,
|
||||
});
|
||||
});
|
||||
cli.on('Session.logged_out', function(call) {
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Signed Out",
|
||||
description: "For security, this session has been signed out. Please sign in again."
|
||||
description: "For security, this session has been signed out. Please sign in again.",
|
||||
});
|
||||
dis.dispatch({
|
||||
action: 'logout'
|
||||
action: 'logout',
|
||||
});
|
||||
});
|
||||
cli.on("accountData", function(ev) {
|
||||
|
@ -896,17 +913,17 @@ module.exports = React.createClass({
|
|||
if (screen == 'register') {
|
||||
dis.dispatch({
|
||||
action: 'start_registration',
|
||||
params: params
|
||||
params: params,
|
||||
});
|
||||
} else if (screen == 'login') {
|
||||
dis.dispatch({
|
||||
action: 'start_login',
|
||||
params: params
|
||||
params: params,
|
||||
});
|
||||
} else if (screen == 'forgot_password') {
|
||||
dis.dispatch({
|
||||
action: 'start_password_recovery',
|
||||
params: params
|
||||
params: params,
|
||||
});
|
||||
} else if (screen == 'new') {
|
||||
dis.dispatch({
|
||||
|
@ -929,26 +946,26 @@ module.exports = React.createClass({
|
|||
action: 'start_post_registration',
|
||||
});
|
||||
} else if (screen.indexOf('room/') == 0) {
|
||||
var segments = screen.substring(5).split('/');
|
||||
var roomString = segments[0];
|
||||
var eventId = segments[1]; // undefined if no event id given
|
||||
const segments = screen.substring(5).split('/');
|
||||
const roomString = segments[0];
|
||||
const eventId = segments[1]; // undefined if no event id given
|
||||
|
||||
// FIXME: sort_out caseConsistency
|
||||
var third_party_invite = {
|
||||
const thirdPartyInvite = {
|
||||
inviteSignUrl: params.signurl,
|
||||
invitedEmail: params.email,
|
||||
};
|
||||
var oob_data = {
|
||||
const oobData = {
|
||||
name: params.room_name,
|
||||
avatarUrl: params.room_avatar_url,
|
||||
inviterName: params.inviter_name,
|
||||
};
|
||||
|
||||
var payload = {
|
||||
const payload = {
|
||||
action: 'view_room',
|
||||
event_id: eventId,
|
||||
third_party_invite: third_party_invite,
|
||||
oob_data: oob_data,
|
||||
third_party_invite: thirdPartyInvite,
|
||||
oob_data: oobData,
|
||||
};
|
||||
if (roomString[0] == '#') {
|
||||
payload.room_alias = roomString;
|
||||
|
@ -962,19 +979,18 @@ module.exports = React.createClass({
|
|||
dis.dispatch(payload);
|
||||
}
|
||||
} else if (screen.indexOf('user/') == 0) {
|
||||
var userId = screen.substring(5);
|
||||
const userId = screen.substring(5);
|
||||
this.setState({ viewUserId: userId });
|
||||
this._setPage(PageTypes.UserView);
|
||||
this.notifyNewScreen('user/' + userId);
|
||||
var member = new Matrix.RoomMember(null, userId);
|
||||
const member = new Matrix.RoomMember(null, userId);
|
||||
if (member) {
|
||||
dis.dispatch({
|
||||
action: 'view_user',
|
||||
member: member,
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
console.info("Ignoring showScreen for '%s'", screen);
|
||||
}
|
||||
},
|
||||
|
@ -993,7 +1009,7 @@ module.exports = React.createClass({
|
|||
onUserClick: function(event, userId) {
|
||||
event.preventDefault();
|
||||
|
||||
var member = new Matrix.RoomMember(null, userId);
|
||||
const member = new Matrix.RoomMember(null, userId);
|
||||
if (!member) { return; }
|
||||
dis.dispatch({
|
||||
action: 'view_user',
|
||||
|
@ -1003,17 +1019,17 @@ module.exports = React.createClass({
|
|||
|
||||
onLogoutClick: function(event) {
|
||||
dis.dispatch({
|
||||
action: 'logout'
|
||||
action: 'logout',
|
||||
});
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
},
|
||||
|
||||
handleResize: function(e) {
|
||||
var hideLhsThreshold = 1000;
|
||||
var showLhsThreshold = 1000;
|
||||
var hideRhsThreshold = 820;
|
||||
var showRhsThreshold = 820;
|
||||
const hideLhsThreshold = 1000;
|
||||
const showLhsThreshold = 1000;
|
||||
const hideRhsThreshold = 820;
|
||||
const showRhsThreshold = 820;
|
||||
|
||||
if (this.state.width > hideLhsThreshold && window.innerWidth <= hideLhsThreshold) {
|
||||
dis.dispatch({ action: 'hide_left_panel' });
|
||||
|
@ -1031,10 +1047,10 @@ module.exports = React.createClass({
|
|||
this.setState({width: window.innerWidth});
|
||||
},
|
||||
|
||||
onRoomCreated: function(room_id) {
|
||||
onRoomCreated: function(roomId) {
|
||||
dis.dispatch({
|
||||
action: "view_room",
|
||||
room_id: room_id,
|
||||
room_id: roomId,
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -1068,7 +1084,7 @@ module.exports = React.createClass({
|
|||
onFinishPostRegistration: function() {
|
||||
// Don't confuse this with "PageType" which is the middle window to show
|
||||
this.setState({
|
||||
screen: undefined
|
||||
screen: undefined,
|
||||
});
|
||||
this.showScreen("settings");
|
||||
},
|
||||
|
@ -1083,10 +1099,10 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
updateStatusIndicator: function(state, prevState) {
|
||||
var notifCount = 0;
|
||||
let notifCount = 0;
|
||||
|
||||
var rooms = MatrixClientPeg.get().getRooms();
|
||||
for (var i = 0; i < rooms.length; ++i) {
|
||||
const rooms = MatrixClientPeg.get().getRooms();
|
||||
for (let i = 0; i < rooms.length; ++i) {
|
||||
if (rooms[i].hasMembershipState(MatrixClientPeg.get().credentials.userId, 'invite')) {
|
||||
notifCount++;
|
||||
} else if (rooms[i].getUnreadNotificationCount()) {
|
||||
|
@ -1113,19 +1129,18 @@ module.exports = React.createClass({
|
|||
action: 'view_room',
|
||||
room_id: this.state.currentRoomId,
|
||||
});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
dis.dispatch({
|
||||
action: 'view_room_directory',
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onRoomIdResolved: function(room_id) {
|
||||
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: room_id});
|
||||
this.setState({currentRoomId: roomId});
|
||||
},
|
||||
|
||||
_makeRegistrationUrl: function(params) {
|
||||
|
@ -1148,14 +1163,20 @@ module.exports = React.createClass({
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// needs to be before normal PageTypes as you are logged in technically
|
||||
else if (this.state.screen == 'post_registration') {
|
||||
if (this.state.screen == 'post_registration') {
|
||||
const PostRegistration = sdk.getComponent('structures.login.PostRegistration');
|
||||
return (
|
||||
<PostRegistration
|
||||
onComplete={this.onFinishPostRegistration} />
|
||||
);
|
||||
} else if (this.state.loggedIn && this.state.ready) {
|
||||
}
|
||||
|
||||
// `ready` and `loggedIn` may be set before `page_type` (because the
|
||||
// latter is set via the dispatcher). If we don't yet have a `page_type`,
|
||||
// keep showing the spinner for now.
|
||||
if (this.state.loggedIn && this.state.ready && this.state.page_type) {
|
||||
/* for now, we stuff the entirety of our props and state into the LoggedInView.
|
||||
* we should go through and figure out what we actually need to pass down, as well
|
||||
* as using something like redux to avoid having a billion bits of state kicking around.
|
||||
|
@ -1237,5 +1258,5 @@ module.exports = React.createClass({
|
|||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -271,6 +271,7 @@ module.exports = React.createClass({
|
|||
|
||||
this._updateConfCallNotification();
|
||||
|
||||
window.addEventListener('beforeunload', this.onPageUnload);
|
||||
window.addEventListener('resize', this.onResize);
|
||||
this.onResize();
|
||||
|
||||
|
@ -353,6 +354,7 @@ module.exports = React.createClass({
|
|||
MatrixClientPeg.get().removeListener("accountData", this.onAccountData);
|
||||
}
|
||||
|
||||
window.removeEventListener('beforeunload', this.onPageUnload);
|
||||
window.removeEventListener('resize', this.onResize);
|
||||
|
||||
document.removeEventListener("keydown", this.onKeyDown);
|
||||
|
@ -365,6 +367,17 @@ module.exports = React.createClass({
|
|||
// Tinter.tint(); // reset colourscheme
|
||||
},
|
||||
|
||||
onPageUnload(event) {
|
||||
if (ContentMessages.getCurrentUploads().length > 0) {
|
||||
return event.returnValue =
|
||||
'You seem to be uploading files, are you sure you want to quit?';
|
||||
} else if (this._getCallForRoom() && this.state.callState !== 'ended') {
|
||||
return event.returnValue =
|
||||
'You seem to be in a call, are you sure you want to quit?';
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
onKeyDown: function(ev) {
|
||||
let handled = false;
|
||||
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
|
||||
|
@ -1759,6 +1772,7 @@ module.exports = React.createClass({
|
|||
oobData={this.props.oobData}
|
||||
editing={this.state.editingRoomSettings}
|
||||
saving={this.state.uploadingRoomSettings}
|
||||
inRoom={myMember && myMember.membership === 'join'}
|
||||
collapsedRhs={ this.props.collapsedRhs }
|
||||
onSearchClick={this.onSearchClick}
|
||||
onSettingsClick={this.onSettingsClick}
|
||||
|
|
|
@ -177,8 +177,8 @@ var TimelinePanel = React.createClass({
|
|||
componentWillMount: function() {
|
||||
debuglog("TimelinePanel: mounting");
|
||||
|
||||
this.last_rr_sent_event_id = undefined;
|
||||
this.last_rm_sent_event_id = undefined;
|
||||
this.lastRRSentEventId = undefined;
|
||||
this.lastRMSentEventId = undefined;
|
||||
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
MatrixClientPeg.get().on("Room.timeline", this.onRoomTimeline);
|
||||
|
@ -504,12 +504,13 @@ var TimelinePanel = React.createClass({
|
|||
// very possible have logged out within that timeframe, so check
|
||||
// we still have a client.
|
||||
const cli = MatrixClientPeg.get();
|
||||
// if no client or client is guest don't send RR
|
||||
// if no client or client is guest don't send RR or RM
|
||||
if (!cli || cli.isGuest()) return;
|
||||
|
||||
var currentReadUpToEventId = this._getCurrentReadReceipt(true);
|
||||
var currentReadUpToEventIndex = this._indexForEventId(currentReadUpToEventId);
|
||||
let shouldSendRR = true;
|
||||
|
||||
const currentRREventId = this._getCurrentReadReceipt(true);
|
||||
const currentRREventIndex = this._indexForEventId(currentRREventId);
|
||||
// We want to avoid sending out read receipts when we are looking at
|
||||
// events in the past which are before the latest RR.
|
||||
//
|
||||
|
@ -523,43 +524,60 @@ var TimelinePanel = React.createClass({
|
|||
// RRs) - but that is a bit of a niche case. It will sort itself out when
|
||||
// the user eventually hits the live timeline.
|
||||
//
|
||||
if (currentReadUpToEventId && currentReadUpToEventIndex === null &&
|
||||
if (currentRREventId && currentRREventIndex === null &&
|
||||
this._timelineWindow.canPaginate(EventTimeline.FORWARDS)) {
|
||||
return;
|
||||
shouldSendRR = false;
|
||||
}
|
||||
|
||||
var lastReadEventIndex = this._getLastDisplayedEventIndex({
|
||||
ignoreOwn: true
|
||||
const lastReadEventIndex = this._getLastDisplayedEventIndex({
|
||||
ignoreOwn: true,
|
||||
});
|
||||
if (lastReadEventIndex === null) return;
|
||||
if (lastReadEventIndex === null) {
|
||||
shouldSendRR = false;
|
||||
}
|
||||
let lastReadEvent = this.state.events[lastReadEventIndex];
|
||||
shouldSendRR = shouldSendRR &&
|
||||
// Only send a RR if the last read event is ahead in the timeline relative to
|
||||
// the current RR event.
|
||||
lastReadEventIndex > currentRREventIndex &&
|
||||
// Only send a RR if the last RR set != the one we would send
|
||||
this.lastRRSentEventId != lastReadEvent.getId();
|
||||
|
||||
var lastReadEvent = this.state.events[lastReadEventIndex];
|
||||
// Only send a RM if the last RM sent != the one we would send
|
||||
const shouldSendRM =
|
||||
this.lastRMSentEventId != this.state.readMarkerEventId;
|
||||
|
||||
// we also remember the last read receipt we sent to avoid spamming the
|
||||
// same one at the server repeatedly
|
||||
if ((lastReadEventIndex > currentReadUpToEventIndex &&
|
||||
this.last_rr_sent_event_id != lastReadEvent.getId()) ||
|
||||
this.last_rm_sent_event_id != this.state.readMarkerEventId) {
|
||||
|
||||
this.last_rr_sent_event_id = lastReadEvent.getId();
|
||||
this.last_rm_sent_event_id = this.state.readMarkerEventId;
|
||||
if (shouldSendRR || shouldSendRM) {
|
||||
if (shouldSendRR) {
|
||||
this.lastRRSentEventId = lastReadEvent.getId();
|
||||
} else {
|
||||
lastReadEvent = null;
|
||||
}
|
||||
this.lastRMSentEventId = this.state.readMarkerEventId;
|
||||
|
||||
debuglog('TimelinePanel: Sending Read Markers for ',
|
||||
this.props.timelineSet.room.roomId,
|
||||
'rm', this.state.readMarkerEventId,
|
||||
lastReadEvent ? 'rr ' + lastReadEvent.getId() : '',
|
||||
);
|
||||
MatrixClientPeg.get().setRoomReadMarkers(
|
||||
this.props.timelineSet.room.roomId,
|
||||
this.state.readMarkerEventId,
|
||||
lastReadEvent
|
||||
lastReadEvent, // Could be null, in which case no RR is sent
|
||||
).catch((e) => {
|
||||
// /read_markers API is not implemented on this HS, fallback to just RR
|
||||
if (e.errcode === 'M_UNRECOGNIZED') {
|
||||
if (e.errcode === 'M_UNRECOGNIZED' && lastReadEvent) {
|
||||
return MatrixClientPeg.get().sendReadReceipt(
|
||||
lastReadEvent
|
||||
lastReadEvent,
|
||||
).catch(() => {
|
||||
this.last_rr_sent_event_id = undefined;
|
||||
this.lastRRSentEventId = undefined;
|
||||
});
|
||||
}
|
||||
// it failed, so allow retries next time the user is active
|
||||
this.last_rr_sent_event_id = undefined;
|
||||
this.last_rm_sent_event_id = undefined;
|
||||
this.lastRRSentEventId = undefined;
|
||||
this.lastRMSentEventId = undefined;
|
||||
});
|
||||
|
||||
// do a quick-reset of our unreadNotificationCount to avoid having
|
||||
|
@ -572,7 +590,6 @@ var TimelinePanel = React.createClass({
|
|||
this.props.timelineSet.room.setUnreadNotificationCount('highlight', 0);
|
||||
dis.dispatch({
|
||||
action: 'on_room_read',
|
||||
room: this.props.timelineSet.room,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ const Email = require('../../email');
|
|||
const AddThreepid = require('../../AddThreepid');
|
||||
const SdkConfig = require('../../SdkConfig');
|
||||
import AccessibleButton from '../views/elements/AccessibleButton';
|
||||
import * as FormattingUtils from '../../utils/FormattingUtils';
|
||||
|
||||
// if this looks like a release, use the 'version' from package.json; else use
|
||||
// the git sha. Prepend version with v, to look like riot-web version
|
||||
|
@ -37,7 +38,7 @@ const REACT_SDK_VERSION = 'dist' in packageJson ? packageJson.version : packageJ
|
|||
|
||||
// Simple method to help prettify GH Release Tags and Commit Hashes.
|
||||
const semVerRegex = /^v?(\d+\.\d+\.\d+(?:-rc.+)?)(?:-(?:\d+-g)?([0-9a-fA-F]+))?(?:-dirty)?$/i;
|
||||
const gHVersionLabel = function(repo, token) {
|
||||
const gHVersionLabel = function(repo, token='') {
|
||||
const match = token.match(semVerRegex);
|
||||
let url;
|
||||
if (match && match[1]) { // basic semVer string possibly with commit hash
|
||||
|
@ -47,7 +48,7 @@ const gHVersionLabel = function(repo, token) {
|
|||
} else {
|
||||
url = `https://github.com/${repo}/commit/${token.split('-')[0]}`;
|
||||
}
|
||||
return <a href={url}>{token}</a>;
|
||||
return <a target="_blank" rel="noopener" href={url}>{token}</a>;
|
||||
};
|
||||
|
||||
// Enumerate some simple 'flip a bit' UI settings (if any).
|
||||
|
@ -151,10 +152,10 @@ module.exports = React.createClass({
|
|||
getInitialState: function() {
|
||||
return {
|
||||
avatarUrl: null,
|
||||
threePids: [],
|
||||
threepids: [],
|
||||
phase: "UserSettings.LOADING", // LOADING, DISPLAY
|
||||
email_add_pending: false,
|
||||
vectorVersion: null,
|
||||
vectorVersion: undefined,
|
||||
rejectingInvites: false,
|
||||
mediaDevices: null,
|
||||
};
|
||||
|
@ -618,7 +619,12 @@ module.exports = React.createClass({
|
|||
_renderCryptoInfo: function() {
|
||||
const client = MatrixClientPeg.get();
|
||||
const deviceId = client.deviceId;
|
||||
const identityKey = client.getDeviceEd25519Key() || "<not supported>";
|
||||
let identityKey = client.getDeviceEd25519Key();
|
||||
if (!identityKey) {
|
||||
identityKey = "<not supported>";
|
||||
} else {
|
||||
identityKey = FormattingUtils.formatCryptoKey(identityKey);
|
||||
}
|
||||
|
||||
let importExportButtons = null;
|
||||
|
||||
|
@ -930,6 +936,7 @@ module.exports = React.createClass({
|
|||
addEmailSection = (
|
||||
<div className="mx_UserSettings_profileTableRow" key="_newEmail">
|
||||
<div className="mx_UserSettings_profileLabelCell">
|
||||
<label>Email</label>
|
||||
</div>
|
||||
<div className="mx_UserSettings_profileInputCell">
|
||||
<EditableText
|
||||
|
@ -1080,7 +1087,7 @@ module.exports = React.createClass({
|
|||
? gHVersionLabel('matrix-org/matrix-react-sdk', REACT_SDK_VERSION)
|
||||
: REACT_SDK_VERSION
|
||||
}<br/>
|
||||
riot-web version: {(this.state.vectorVersion !== null)
|
||||
riot-web version: {(this.state.vectorVersion !== undefined)
|
||||
? gHVersionLabel('vector-im/riot-web', this.state.vectorVersion)
|
||||
: 'unknown'
|
||||
}<br/>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue