Merge branch 'develop' of github.com:vector-im/riot-web into forward_message
This commit is contained in:
commit
eaeac1230f
311 changed files with 674 additions and 720 deletions
|
@ -1,90 +0,0 @@
|
|||
/*
|
||||
Copyright 2015, 2016 OpenMarket Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* THIS FILE IS AUTO-GENERATED
|
||||
* You can edit it you like, but your changes will be overwritten,
|
||||
* so you'd just be trying to swim upstream like a salmon.
|
||||
* You are not a salmon.
|
||||
*
|
||||
* To update it, run:
|
||||
* ./reskindex.js -h header
|
||||
*/
|
||||
|
||||
module.exports.components = require('matrix-react-sdk/lib/component-index').components;
|
||||
|
||||
import structures$BottomLeftMenu from './components/structures/BottomLeftMenu';
|
||||
structures$BottomLeftMenu && (module.exports.components['structures.BottomLeftMenu'] = structures$BottomLeftMenu);
|
||||
import structures$CompatibilityPage from './components/structures/CompatibilityPage';
|
||||
structures$CompatibilityPage && (module.exports.components['structures.CompatibilityPage'] = structures$CompatibilityPage);
|
||||
import structures$HomePage from './components/structures/HomePage';
|
||||
structures$HomePage && (module.exports.components['structures.HomePage'] = structures$HomePage);
|
||||
import structures$LeftPanel from './components/structures/LeftPanel';
|
||||
structures$LeftPanel && (module.exports.components['structures.LeftPanel'] = structures$LeftPanel);
|
||||
import structures$RightPanel from './components/structures/RightPanel';
|
||||
structures$RightPanel && (module.exports.components['structures.RightPanel'] = structures$RightPanel);
|
||||
import structures$RoomDirectory from './components/structures/RoomDirectory';
|
||||
structures$RoomDirectory && (module.exports.components['structures.RoomDirectory'] = structures$RoomDirectory);
|
||||
import structures$RoomSubList from './components/structures/RoomSubList';
|
||||
structures$RoomSubList && (module.exports.components['structures.RoomSubList'] = structures$RoomSubList);
|
||||
import structures$RoomSubListHeader from './components/structures/RoomSubListHeader';
|
||||
structures$RoomSubListHeader && (module.exports.components['structures.RoomSubListHeader'] = structures$RoomSubListHeader);
|
||||
import structures$SearchBox from './components/structures/SearchBox';
|
||||
structures$SearchBox && (module.exports.components['structures.SearchBox'] = structures$SearchBox);
|
||||
import structures$ViewSource from './components/structures/ViewSource';
|
||||
structures$ViewSource && (module.exports.components['structures.ViewSource'] = structures$ViewSource);
|
||||
import views$context_menus$MessageContextMenu from './components/views/context_menus/MessageContextMenu';
|
||||
views$context_menus$MessageContextMenu && (module.exports.components['views.context_menus.MessageContextMenu'] = views$context_menus$MessageContextMenu);
|
||||
import views$context_menus$RoomTileContextMenu from './components/views/context_menus/RoomTileContextMenu';
|
||||
views$context_menus$RoomTileContextMenu && (module.exports.components['views.context_menus.RoomTileContextMenu'] = views$context_menus$RoomTileContextMenu);
|
||||
import views$dialogs$BugReportDialog from './components/views/dialogs/BugReportDialog';
|
||||
views$dialogs$BugReportDialog && (module.exports.components['views.dialogs.BugReportDialog'] = views$dialogs$BugReportDialog);
|
||||
import views$dialogs$ChangelogDialog from './components/views/dialogs/ChangelogDialog';
|
||||
views$dialogs$ChangelogDialog && (module.exports.components['views.dialogs.ChangelogDialog'] = views$dialogs$ChangelogDialog);
|
||||
import views$directory$NetworkDropdown from './components/views/directory/NetworkDropdown';
|
||||
views$directory$NetworkDropdown && (module.exports.components['views.directory.NetworkDropdown'] = views$directory$NetworkDropdown);
|
||||
import views$elements$ImageView from './components/views/elements/ImageView';
|
||||
views$elements$ImageView && (module.exports.components['views.elements.ImageView'] = views$elements$ImageView);
|
||||
import views$elements$Spinner from './components/views/elements/Spinner';
|
||||
views$elements$Spinner && (module.exports.components['views.elements.Spinner'] = views$elements$Spinner);
|
||||
import views$globals$GuestWarningBar from './components/views/globals/GuestWarningBar';
|
||||
views$globals$GuestWarningBar && (module.exports.components['views.globals.GuestWarningBar'] = views$globals$GuestWarningBar);
|
||||
import views$globals$MatrixToolbar from './components/views/globals/MatrixToolbar';
|
||||
views$globals$MatrixToolbar && (module.exports.components['views.globals.MatrixToolbar'] = views$globals$MatrixToolbar);
|
||||
import views$globals$NewVersionBar from './components/views/globals/NewVersionBar';
|
||||
views$globals$NewVersionBar && (module.exports.components['views.globals.NewVersionBar'] = views$globals$NewVersionBar);
|
||||
import views$login$VectorCustomServerDialog from './components/views/login/VectorCustomServerDialog';
|
||||
views$login$VectorCustomServerDialog && (module.exports.components['views.login.VectorCustomServerDialog'] = views$login$VectorCustomServerDialog);
|
||||
import views$login$VectorLoginFooter from './components/views/login/VectorLoginFooter';
|
||||
views$login$VectorLoginFooter && (module.exports.components['views.login.VectorLoginFooter'] = views$login$VectorLoginFooter);
|
||||
import views$login$VectorLoginHeader from './components/views/login/VectorLoginHeader';
|
||||
views$login$VectorLoginHeader && (module.exports.components['views.login.VectorLoginHeader'] = views$login$VectorLoginHeader);
|
||||
import views$messages$DateSeparator from './components/views/messages/DateSeparator';
|
||||
views$messages$DateSeparator && (module.exports.components['views.messages.DateSeparator'] = views$messages$DateSeparator);
|
||||
import views$messages$MessageTimestamp from './components/views/messages/MessageTimestamp';
|
||||
views$messages$MessageTimestamp && (module.exports.components['views.messages.MessageTimestamp'] = views$messages$MessageTimestamp);
|
||||
import views$rooms$DNDRoomTile from './components/views/rooms/DNDRoomTile';
|
||||
views$rooms$DNDRoomTile && (module.exports.components['views.rooms.DNDRoomTile'] = views$rooms$DNDRoomTile);
|
||||
import views$rooms$RoomDropTarget from './components/views/rooms/RoomDropTarget';
|
||||
views$rooms$RoomDropTarget && (module.exports.components['views.rooms.RoomDropTarget'] = views$rooms$RoomDropTarget);
|
||||
import views$rooms$RoomTooltip from './components/views/rooms/RoomTooltip';
|
||||
views$rooms$RoomTooltip && (module.exports.components['views.rooms.RoomTooltip'] = views$rooms$RoomTooltip);
|
||||
import views$rooms$SearchBar from './components/views/rooms/SearchBar';
|
||||
views$rooms$SearchBar && (module.exports.components['views.rooms.SearchBar'] = views$rooms$SearchBar);
|
||||
import views$settings$IntegrationsManager from './components/views/settings/IntegrationsManager';
|
||||
views$settings$IntegrationsManager && (module.exports.components['views.settings.IntegrationsManager'] = views$settings$IntegrationsManager);
|
||||
import views$settings$Notifications from './components/views/settings/Notifications';
|
||||
views$settings$Notifications && (module.exports.components['views.settings.Notifications'] = views$settings$Notifications);
|
|
@ -19,11 +19,9 @@ limitations under the License.
|
|||
var React = require('react');
|
||||
var DragDropContext = require('react-dnd').DragDropContext;
|
||||
var HTML5Backend = require('react-dnd-html5-backend');
|
||||
var KeyCode = require('matrix-react-sdk/lib/KeyCode');
|
||||
var sdk = require('matrix-react-sdk')
|
||||
var dis = require('matrix-react-sdk/lib/dispatcher');
|
||||
|
||||
|
||||
var VectorConferenceHandler = require('../../VectorConferenceHandler');
|
||||
var CallHandler = require("matrix-react-sdk/lib/CallHandler");
|
||||
|
||||
|
@ -42,10 +40,6 @@ var LeftPanel = React.createClass({
|
|||
};
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this.focusedElement = null;
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
},
|
||||
|
@ -68,91 +62,6 @@ var LeftPanel = React.createClass({
|
|||
}
|
||||
},
|
||||
|
||||
_onFocus: function(ev) {
|
||||
this.focusedElement = ev.target;
|
||||
},
|
||||
|
||||
_onBlur: function(ev) {
|
||||
this.focusedElement = null;
|
||||
},
|
||||
|
||||
_onKeyDown: function(ev) {
|
||||
if (!this.focusedElement) return;
|
||||
let handled = false;
|
||||
|
||||
switch (ev.keyCode) {
|
||||
case KeyCode.UP:
|
||||
this._onMoveFocus(true);
|
||||
handled = true;
|
||||
break;
|
||||
case KeyCode.DOWN:
|
||||
this._onMoveFocus(false);
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
_onMoveFocus: function(up) {
|
||||
var element = this.focusedElement;
|
||||
|
||||
// unclear why this isn't needed
|
||||
// var descending = (up == this.focusDirection) ? this.focusDescending : !this.focusDescending;
|
||||
// this.focusDirection = up;
|
||||
|
||||
var descending = false; // are we currently descending or ascending through the DOM tree?
|
||||
var classes;
|
||||
|
||||
do {
|
||||
var child = up ? element.lastElementChild : element.firstElementChild;
|
||||
var sibling = up ? element.previousElementSibling : element.nextElementSibling;
|
||||
|
||||
if (descending) {
|
||||
if (child) {
|
||||
element = child;
|
||||
}
|
||||
else if (sibling) {
|
||||
element = sibling;
|
||||
}
|
||||
else {
|
||||
descending = false;
|
||||
element = element.parentElement;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (sibling) {
|
||||
element = sibling;
|
||||
descending = true;
|
||||
}
|
||||
else {
|
||||
element = element.parentElement;
|
||||
}
|
||||
}
|
||||
|
||||
if (element) {
|
||||
classes = element.classList;
|
||||
if (classes.contains("mx_LeftPanel")) { // we hit the top
|
||||
element = up ? element.lastElementChild : element.firstElementChild;
|
||||
descending = true;
|
||||
}
|
||||
}
|
||||
|
||||
} while(element && !(
|
||||
classes.contains("mx_RoomTile") ||
|
||||
classes.contains("mx_SearchBox_search") ||
|
||||
classes.contains("mx_RoomSubList_ellipsis")));
|
||||
|
||||
if (element) {
|
||||
element.focus();
|
||||
this.focusedElement = element;
|
||||
this.focusedDescending = descending;
|
||||
}
|
||||
},
|
||||
|
||||
_recheckCallElement: function(selectedRoomId) {
|
||||
// if we aren't viewing a room with an ongoing call, but there is an
|
||||
// active call, show the call element - we need to do this to make
|
||||
|
@ -211,8 +120,7 @@ var LeftPanel = React.createClass({
|
|||
}
|
||||
|
||||
return (
|
||||
<aside className={classes} style={{ opacity: this.props.opacity }}
|
||||
onKeyDown={ this._onKeyDown } onFocus={ this._onFocus } onBlur={ this._onBlur }>
|
||||
<aside className={classes} style={{ opacity: this.props.opacity }}>
|
||||
<SearchBox collapsed={ this.props.collapsed } onSearch={ this.onSearch } />
|
||||
{ collapseButton }
|
||||
{ callPreview }
|
||||
|
|
|
@ -60,6 +60,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this._unmounted = false;
|
||||
this.nextBatch = null;
|
||||
this.filterTimeout = null;
|
||||
this.scrollPanel = null;
|
||||
|
@ -97,6 +98,10 @@ module.exports = React.createClass({
|
|||
// sideOpacity: 1.0,
|
||||
// middleOpacity: 1.0,
|
||||
// });
|
||||
if (this.filterTimeout) {
|
||||
clearTimeout(this.filterTimeout);
|
||||
}
|
||||
this._unmounted = true;
|
||||
},
|
||||
|
||||
refreshRoomList: function() {
|
||||
|
@ -139,6 +144,11 @@ module.exports = React.createClass({
|
|||
return;
|
||||
}
|
||||
|
||||
if (this._unmounted) {
|
||||
// if we've been unmounted, we don't care either.
|
||||
return;
|
||||
}
|
||||
|
||||
this.nextBatch = data.next_batch;
|
||||
this.setState((s) => {
|
||||
s.publicRooms.push(...data.chunk);
|
||||
|
@ -156,6 +166,12 @@ module.exports = React.createClass({
|
|||
// requests either
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._unmounted) {
|
||||
// if we've been unmounted, we don't care either.
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({ loading: false });
|
||||
console.error("Failed to get publicRooms: %s", JSON.stringify(err));
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
|
@ -204,7 +220,7 @@ module.exports = React.createClass({
|
|||
}).done(() => {
|
||||
modal.close();
|
||||
this.refreshRoomList();
|
||||
}, function(err) {
|
||||
}, (err) => {
|
||||
modal.close();
|
||||
this.refreshRoomList();
|
||||
console.error("Failed to " + step + ": " + err);
|
||||
|
|
|
@ -27,10 +27,9 @@ var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
|||
var RoomNotifs = require('matrix-react-sdk/lib/RoomNotifs');
|
||||
var FormattingUtils = require('matrix-react-sdk/lib/utils/FormattingUtils');
|
||||
var AccessibleButton = require('matrix-react-sdk/lib/components/views/elements/AccessibleButton');
|
||||
var ConstantTimeDispatcher = require('matrix-react-sdk/lib/ConstantTimeDispatcher');
|
||||
var RoomSubListHeader = require('./RoomSubListHeader.js');
|
||||
import Modal from 'matrix-react-sdk/lib/Modal';
|
||||
|
||||
// turn this on for drag & drop console debugging galore
|
||||
// turn this on for drop & drag console debugging galore
|
||||
var debug = false;
|
||||
|
||||
const TRUNCATE_AT = 10;
|
||||
|
@ -73,12 +72,14 @@ var RoomSubList = React.createClass({
|
|||
|
||||
order: React.PropTypes.string.isRequired,
|
||||
|
||||
// undefined if no room is selected (eg we are showing settings)
|
||||
selectedRoom: React.PropTypes.string,
|
||||
|
||||
startAsHidden: React.PropTypes.bool,
|
||||
showSpinner: React.PropTypes.bool, // true to show a spinner if 0 elements when expanded
|
||||
collapsed: React.PropTypes.bool.isRequired, // is LeftPanel collapsed?
|
||||
onHeaderClick: React.PropTypes.func,
|
||||
alwaysShowHeader: React.PropTypes.bool,
|
||||
selectedRoom: React.PropTypes.string,
|
||||
incomingCall: React.PropTypes.object,
|
||||
onShowMoreRooms: React.PropTypes.func,
|
||||
searchFilter: React.PropTypes.string,
|
||||
|
@ -100,31 +101,13 @@ var RoomSubList = React.createClass({
|
|||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
constantTimeDispatcher.register("RoomSubList.sort", this.props.tagName, this.onSort);
|
||||
constantTimeDispatcher.register("RoomSubList.refreshHeader", this.props.tagName, this.onRefresh);
|
||||
this.sortList(this.applySearchFilter(this.props.list, this.props.searchFilter), this.props.order);
|
||||
this._fixUndefinedOrder(this.props.list);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
constantTimeDispatcher.unregister("RoomSubList.sort", this.props.tagName, this.onSort);
|
||||
constantTimeDispatcher.unregister("RoomSubList.refreshHeader", this.props.tagName, this.onRefresh);
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function(newProps) {
|
||||
// order the room list appropriately before we re-render
|
||||
//if (debug) console.log("received new props, list = " + newProps.list);
|
||||
this.sortList(this.applySearchFilter(newProps.list, newProps.searchFilter), newProps.order);
|
||||
this._fixUndefinedOrder(newProps.list);
|
||||
},
|
||||
|
||||
onSort: function() {
|
||||
this.sortList(this.applySearchFilter(this.props.list, this.props.searchFilter), this.props.order);
|
||||
// we deliberately don't waste time trying to fix undefined ordering here
|
||||
},
|
||||
|
||||
onRefresh: function() {
|
||||
this.forceUpdate();
|
||||
},
|
||||
|
||||
applySearchFilter: function(list, filter) {
|
||||
|
@ -137,7 +120,7 @@ var RoomSubList = React.createClass({
|
|||
// The header is collapsable if it is hidden or not stuck
|
||||
// The dataset elements are added in the RoomList _initAndPositionStickyHeaders method
|
||||
isCollapsableOnClick: function() {
|
||||
var stuck = this.refs.header.refs.header.dataset.stuck;
|
||||
var stuck = this.refs.header.dataset.stuck;
|
||||
if (this.state.hidden || stuck === undefined || stuck === "none") {
|
||||
return true;
|
||||
} else {
|
||||
|
@ -160,15 +143,14 @@ var RoomSubList = React.createClass({
|
|||
this.props.onHeaderClick(isHidden);
|
||||
} else {
|
||||
// The header is stuck, so the click is to be interpreted as a scroll to the header
|
||||
this.props.onHeaderClick(this.state.hidden, this.refs.header.refs.header.dataset.originalPosition);
|
||||
this.props.onHeaderClick(this.state.hidden, this.refs.header.dataset.originalPosition);
|
||||
}
|
||||
},
|
||||
|
||||
onRoomTileClick(roomId, ev) {
|
||||
onRoomTileClick(roomId) {
|
||||
dis.dispatch({
|
||||
action: 'view_room',
|
||||
room_id: roomId,
|
||||
clear_search: (ev && (ev.keyCode == 13 || ev.keyCode == 32)),
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -230,6 +212,9 @@ var RoomSubList = React.createClass({
|
|||
if (order === "manual") comparator = this.manualComparator;
|
||||
if (order === "recent") comparator = this.recentsComparator;
|
||||
|
||||
// Fix undefined orders here, and make sure the backend gets updated as well
|
||||
this._fixUndefinedOrder(list);
|
||||
|
||||
//if (debug) console.log("sorting list for sublist " + this.props.label + " with length " + list.length + ", this.props.list = " + this.props.list);
|
||||
this.setState({ sortedList: list.sort(comparator) });
|
||||
},
|
||||
|
@ -264,9 +249,10 @@ var RoomSubList = React.createClass({
|
|||
|
||||
if (badges) {
|
||||
result[0] += notificationCount;
|
||||
if (highlight) {
|
||||
result[1] = true;
|
||||
}
|
||||
}
|
||||
|
||||
result[1] |= highlight;
|
||||
}
|
||||
return result;
|
||||
}, [0, false]);
|
||||
|
@ -374,6 +360,7 @@ var RoomSubList = React.createClass({
|
|||
var self = this;
|
||||
var DNDRoomTile = sdk.getComponent("rooms.DNDRoomTile");
|
||||
return this.state.sortedList.map(function(room) {
|
||||
var selected = room.roomId == self.props.selectedRoom;
|
||||
// XXX: is it evil to pass in self as a prop to RoomTile?
|
||||
return (
|
||||
<DNDRoomTile
|
||||
|
@ -381,7 +368,9 @@ var RoomSubList = React.createClass({
|
|||
roomSubList={ self }
|
||||
key={ room.roomId }
|
||||
collapsed={ self.props.collapsed || false}
|
||||
selectedRoom={ self.props.selectedRoom }
|
||||
selected={ selected }
|
||||
unread={ Unread.doesRoomHaveUnreadMessages(room) }
|
||||
highlight={ room.getUnreadNotificationCount('highlight') > 0 || self.props.label === 'Invites' }
|
||||
isInvite={ self.props.label === 'Invites' }
|
||||
refreshSubList={ self._updateSubListCount }
|
||||
incomingCall={ null }
|
||||
|
@ -391,6 +380,70 @@ var RoomSubList = React.createClass({
|
|||
});
|
||||
},
|
||||
|
||||
_getHeaderJsx: function() {
|
||||
var TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||
|
||||
var subListNotifications = this.roomNotificationCount();
|
||||
var subListNotifCount = subListNotifications[0];
|
||||
var subListNotifHighlight = subListNotifications[1];
|
||||
|
||||
var roomCount = this.props.list.length > 0 ? this.props.list.length : '';
|
||||
|
||||
var chevronClasses = classNames({
|
||||
'mx_RoomSubList_chevron': true,
|
||||
'mx_RoomSubList_chevronRight': this.state.hidden,
|
||||
'mx_RoomSubList_chevronDown': !this.state.hidden,
|
||||
});
|
||||
|
||||
var badgeClasses = classNames({
|
||||
'mx_RoomSubList_badge': true,
|
||||
'mx_RoomSubList_badgeHighlight': subListNotifHighlight,
|
||||
});
|
||||
|
||||
var badge;
|
||||
if (subListNotifCount > 0) {
|
||||
badge = <div className={badgeClasses}>{ FormattingUtils.formatCount(subListNotifCount) }</div>;
|
||||
}
|
||||
|
||||
// When collapsed, allow a long hover on the header to show user
|
||||
// the full tag name and room count
|
||||
var title;
|
||||
if (this.props.collapsed) {
|
||||
title = this.props.label;
|
||||
if (roomCount !== '') {
|
||||
title += " [" + roomCount + "]";
|
||||
}
|
||||
}
|
||||
|
||||
var incomingCall;
|
||||
if (this.props.incomingCall) {
|
||||
var self = this;
|
||||
// Check if the incoming call is for this section
|
||||
var incomingCallRoom = this.props.list.filter(function(room) {
|
||||
return self.props.incomingCall.roomId === room.roomId;
|
||||
});
|
||||
|
||||
if (incomingCallRoom.length === 1) {
|
||||
var IncomingCallBox = sdk.getComponent("voip.IncomingCallBox");
|
||||
incomingCall = <IncomingCallBox className="mx_RoomSubList_incomingCall" incomingCall={ this.props.incomingCall }/>;
|
||||
}
|
||||
}
|
||||
|
||||
var tabindex = this.props.searchFilter === "" ? "0" : "-1";
|
||||
|
||||
return (
|
||||
<div className="mx_RoomSubList_labelContainer" title={ title } ref="header">
|
||||
<AccessibleButton onClick={ this.onClick } className="mx_RoomSubList_label" tabIndex={tabindex}>
|
||||
{ this.props.collapsed ? '' : this.props.label }
|
||||
<div className="mx_RoomSubList_roomCount">{ roomCount }</div>
|
||||
<div className={chevronClasses}></div>
|
||||
{ badge }
|
||||
{ incomingCall }
|
||||
</AccessibleButton>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
_createOverflowTile: function(overflowCount, totalCount) {
|
||||
var content = <div className="mx_RoomSubList_chevronDown"></div>;
|
||||
|
||||
|
@ -446,7 +499,7 @@ var RoomSubList = React.createClass({
|
|||
// gets triggered and another list is passed in. Doing it one at a time means that
|
||||
// we always correctly calculate the highest order for the list - stops multiple
|
||||
// rooms getting the same order. This is only really relevant for the first time this
|
||||
// is run with historical room tag data, after that there should only be one undefined
|
||||
// is run with historical room tag data, after that there should only be undefined
|
||||
// in the list at a time anyway.
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (list[i].tags[self.props.tagName] && list[i].tags[self.props.tagName].order === undefined) {
|
||||
|
@ -480,16 +533,6 @@ var RoomSubList = React.createClass({
|
|||
target = <RoomDropTarget label={ 'Drop here to ' + this.props.verb }/>;
|
||||
}
|
||||
|
||||
var roomCount = this.props.list.length > 0 ? this.props.list.length : '';
|
||||
|
||||
var isIncomingCallRoom;
|
||||
if (this.props.incomingCall) {
|
||||
// Check if the incoming call is for this section
|
||||
isIncomingCallRoom = this.props.list.find(room=>{
|
||||
return this.props.incomingCall.roomId === room.roomId;
|
||||
}) ? true : false;
|
||||
}
|
||||
|
||||
if (this.state.sortedList.length > 0 || this.props.editable) {
|
||||
var subList;
|
||||
var classes = "mx_RoomSubList";
|
||||
|
@ -508,19 +551,7 @@ var RoomSubList = React.createClass({
|
|||
|
||||
return connectDropTarget(
|
||||
<div>
|
||||
<RoomSubListHeader
|
||||
ref='header'
|
||||
label={ this.props.label }
|
||||
tagName={ this.props.tagName }
|
||||
roomCount={ roomCount }
|
||||
collapsed={ this.props.collapsed }
|
||||
hidden={ this.state.hidden }
|
||||
incomingCall={ this.props.incomingCall }
|
||||
isIncomingCallRoom={ isIncomingCallRoom }
|
||||
roomNotificationCount={ this.roomNotificationCount() }
|
||||
onClick={ this.onClick }
|
||||
onHeaderClick={ this.props.onHeaderClick }
|
||||
/>
|
||||
{ this._getHeaderJsx() }
|
||||
{ subList }
|
||||
</div>
|
||||
);
|
||||
|
@ -529,20 +560,7 @@ var RoomSubList = React.createClass({
|
|||
var Loader = sdk.getComponent("elements.Spinner");
|
||||
return (
|
||||
<div className="mx_RoomSubList">
|
||||
{ this.props.alwaysShowHeader ?
|
||||
<RoomSubListHeader
|
||||
ref='header'
|
||||
label={ this.props.label }
|
||||
tagName={ this.props.tagName }
|
||||
roomCount={ roomCount }
|
||||
collapsed={ this.props.collapsed }
|
||||
hidden={ this.state.hidden }
|
||||
isIncomingCallRoom={ isIncomingCallRoom }
|
||||
roomNotificationCount={ this.roomNotificationCount() }
|
||||
onClick={ this.onClick }
|
||||
onHeaderClick={ this.props.onHeaderClick }
|
||||
/>
|
||||
: undefined }
|
||||
{ this.props.alwaysShowHeader ? this._getHeaderJsx() : undefined }
|
||||
{ (this.props.showSpinner && !this.state.hidden) ? <Loader /> : undefined }
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,121 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var ReactDOM = require('react-dom');
|
||||
var classNames = require('classnames');
|
||||
var sdk = require('matrix-react-sdk')
|
||||
var FormattingUtils = require('matrix-react-sdk/lib/utils/FormattingUtils');
|
||||
var RoomNotifs = require('matrix-react-sdk/lib/RoomNotifs');
|
||||
var AccessibleButton = require('matrix-react-sdk/lib/components/views/elements/AccessibleButton');
|
||||
var ConstantTimeDispatcher = require('matrix-react-sdk/lib/ConstantTimeDispatcher');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'RoomSubListHeader',
|
||||
|
||||
propTypes: {
|
||||
label: React.PropTypes.string.isRequired,
|
||||
tagName: React.PropTypes.string,
|
||||
roomCount: React.PropTypes.oneOfType([
|
||||
React.PropTypes.string,
|
||||
React.PropTypes.number
|
||||
]),
|
||||
collapsed: React.PropTypes.bool.isRequired, // is LeftPanel collapsed?
|
||||
incomingCall: React.PropTypes.object,
|
||||
isIncomingCallRoom: React.PropTypes.bool,
|
||||
roomNotificationCount: React.PropTypes.array,
|
||||
hidden: React.PropTypes.bool,
|
||||
onClick: React.PropTypes.func,
|
||||
onHeaderClick: React.PropTypes.func,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
onHeaderClick: function() {}, // NOP
|
||||
};
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
// constantTimeDispatcher.register("RoomSubList.refreshHeader", this.props.tagName, this.onRefresh);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
// constantTimeDispatcher.unregister("RoomSubList.refreshHeader", this.props.tagName, this.onRefresh);
|
||||
},
|
||||
|
||||
// onRefresh: function() {
|
||||
// this.forceUpdate();
|
||||
// },
|
||||
|
||||
render: function() {
|
||||
var TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||
|
||||
var subListNotifications = this.props.roomNotificationCount;
|
||||
var subListNotifCount = subListNotifications[0];
|
||||
var subListNotifHighlight = subListNotifications[1];
|
||||
|
||||
var chevronClasses = classNames({
|
||||
'mx_RoomSubList_chevron': true,
|
||||
'mx_RoomSubList_chevronRight': this.props.hidden,
|
||||
'mx_RoomSubList_chevronDown': !this.props.hidden,
|
||||
});
|
||||
|
||||
var badgeClasses = classNames({
|
||||
'mx_RoomSubList_badge': true,
|
||||
'mx_RoomSubList_badgeHighlight': subListNotifHighlight,
|
||||
});
|
||||
|
||||
var badge;
|
||||
if (subListNotifCount > 0) {
|
||||
badge = <div className={badgeClasses}>{ FormattingUtils.formatCount(subListNotifCount) }</div>;
|
||||
}
|
||||
else if (subListNotifHighlight) {
|
||||
badge = <div className={badgeClasses}>!</div>;
|
||||
}
|
||||
|
||||
// When collapsed, allow a long hover on the header to show user
|
||||
// the full tag name and room count
|
||||
var title;
|
||||
var roomCount = this.props.roomCount;
|
||||
if (this.props.collapsed) {
|
||||
title = this.props.label;
|
||||
if (roomCount !== '') {
|
||||
title += " [" + roomCount + "]";
|
||||
}
|
||||
}
|
||||
|
||||
var incomingCall;
|
||||
if (this.props.isIncomingCallRoom) {
|
||||
var IncomingCallBox = sdk.getComponent("voip.IncomingCallBox");
|
||||
incomingCall = <IncomingCallBox className="mx_RoomSubList_incomingCall" incomingCall={ this.props.incomingCall }/>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mx_RoomSubList_labelContainer" title={ title } ref="header">
|
||||
<AccessibleButton onClick={ this.props.onClick } className="mx_RoomSubList_label" tabIndex="0">
|
||||
{ this.props.collapsed ? '' : this.props.label }
|
||||
<div className="mx_RoomSubList_roomCount">{ roomCount }</div>
|
||||
<div className={chevronClasses}></div>
|
||||
{ badge }
|
||||
</AccessibleButton>
|
||||
{ incomingCall }
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
|
@ -21,7 +21,6 @@ var sdk = require('matrix-react-sdk')
|
|||
var dis = require('matrix-react-sdk/lib/dispatcher');
|
||||
var rate_limited_func = require('matrix-react-sdk/lib/ratelimitedfunc');
|
||||
var AccessibleButton = require('matrix-react-sdk/lib/components/views/elements/AccessibleButton');
|
||||
var KeyCode = require('matrix-react-sdk/lib/KeyCode');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'SearchBox',
|
||||
|
@ -39,23 +38,25 @@ module.exports = React.createClass({
|
|||
|
||||
componentDidMount: function() {
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
document.addEventListener('keydown', this._onKeyDown);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
dis.unregister(this.dispatcherRef);
|
||||
document.removeEventListener('keydown', this._onKeyDown);
|
||||
},
|
||||
|
||||
onAction: function(payload) {
|
||||
// Disabling this as I find it really really annoying, and was used to the
|
||||
// previous behaviour - see https://github.com/vector-im/riot-web/issues/3348
|
||||
/*
|
||||
switch (payload.action) {
|
||||
// Clear up the text field when a room is selected.
|
||||
case 'view_room':
|
||||
if (payload.clear_search && this.refs.search) {
|
||||
if (this.refs.search) {
|
||||
this._clearSearch();
|
||||
}
|
||||
break;
|
||||
}
|
||||
*/
|
||||
},
|
||||
|
||||
onChange: function() {
|
||||
|
@ -89,38 +90,6 @@ module.exports = React.createClass({
|
|||
this.onChange();
|
||||
},
|
||||
|
||||
_onKeyDown: function(ev) {
|
||||
let handled = false;
|
||||
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
|
||||
let ctrlCmdOnly;
|
||||
if (isMac) {
|
||||
ctrlCmdOnly = ev.metaKey && !ev.altKey && !ev.ctrlKey && !ev.shiftKey;
|
||||
} else {
|
||||
ctrlCmdOnly = ev.ctrlKey && !ev.altKey && !ev.metaKey && !ev.shiftKey;
|
||||
}
|
||||
|
||||
switch (ev.keyCode) {
|
||||
case KeyCode.ESCAPE:
|
||||
this._clearSearch();
|
||||
dis.dispatch({action: 'focus_composer'});
|
||||
break;
|
||||
case KeyCode.KEY_K:
|
||||
if (ctrlCmdOnly) {
|
||||
if (this.refs.search) {
|
||||
this.refs.search.focus();
|
||||
this.refs.search.select();
|
||||
}
|
||||
handled = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var TintableSvg = sdk.getComponent('elements.TintableSvg');
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ module.exports = React.createClass({
|
|||
render: function() {
|
||||
var date = new Date(this.props.ts);
|
||||
return (
|
||||
<span className="mx_MessageTimestamp" title={ DateUtils.formatDate(date) }>
|
||||
<span className="mx_MessageTimestamp" title={ DateUtils.formatFullDate(date) }>
|
||||
{ DateUtils.formatTime(date) }
|
||||
</span>
|
||||
);
|
||||
|
|
|
@ -160,7 +160,8 @@ hr.mx_RoomView_myReadMarker {
|
|||
border-bottom: solid 1px $accent-color;
|
||||
margin-top: 0px;
|
||||
position: relative;
|
||||
top: 5px;
|
||||
top: -1px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.mx_RoomView_statusArea {
|
||||
|
@ -171,7 +172,7 @@ hr.mx_RoomView_myReadMarker {
|
|||
|
||||
max-height: 0px;
|
||||
background-color: $primary-bg-color;
|
||||
z-index: 5;
|
||||
z-index: 1000;
|
||||
overflow: hidden;
|
||||
|
||||
-webkit-transition: all .2s ease-out;
|
||||
|
@ -259,4 +260,4 @@ hr.mx_RoomView_myReadMarker {
|
|||
|
||||
.mx_RoomView_ongoingConfCallNotification a {
|
||||
color: $accent-fg-color ! important;
|
||||
}
|
||||
}
|
|
@ -219,6 +219,10 @@ input.mx_UserSettings_phoneNumberField {
|
|||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.mx_UserSettings_avatarPicker_edit img {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_UserSettings_avatarPicker_edit > input {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -184,7 +184,7 @@ limitations under the License.
|
|||
}
|
||||
|
||||
.mx_Login_field_prefix {
|
||||
height: 33px;
|
||||
height: 34px;
|
||||
padding: 0px 5px;
|
||||
line-height: 33px;
|
||||
|
||||
|
@ -197,7 +197,7 @@ limitations under the License.
|
|||
}
|
||||
|
||||
.mx_Login_field_suffix {
|
||||
height: 33px;
|
||||
height: 34px;
|
||||
padding: 0px 5px;
|
||||
line-height: 33px;
|
||||
|
||||
|
@ -211,11 +211,16 @@ limitations under the License.
|
|||
}
|
||||
|
||||
.mx_Login_username {
|
||||
height: 16px;
|
||||
flex-shrink: 1;
|
||||
min-width: 0px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.mx_Login_phoneNumberField {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.mx_Login_field_has_prefix {
|
||||
border-top-left-radius: 0px;
|
||||
border-bottom-left-radius: 0px;
|
||||
|
@ -226,8 +231,23 @@ limitations under the License.
|
|||
border-bottom-right-radius: 0px;
|
||||
}
|
||||
|
||||
.mx_Login_phoneSection {
|
||||
display:flex;
|
||||
}
|
||||
|
||||
.mx_Login_phoneCountry {
|
||||
margin-bottom: 14px;
|
||||
width: 150px;
|
||||
|
||||
/* To override mx_Login_field_prefix */
|
||||
text-align: left;
|
||||
padding: 0px;
|
||||
background-color: $primary-bg-color;
|
||||
}
|
||||
|
||||
.mx_Login_field_prefix .mx_Dropdown_input {
|
||||
/* To use prefix border instead of dropdown border */
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.mx_Login_phoneCountry .mx_Dropdown_option {
|
||||
|
@ -240,6 +260,6 @@ limitations under the License.
|
|||
}
|
||||
|
||||
.mx_Login_phoneCountry .mx_Dropdown_option img {
|
||||
margin: 4px;
|
||||
margin: 3px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
|
|
@ -48,6 +48,14 @@ limitations under the License.
|
|||
width: 0
|
||||
}
|
||||
|
||||
.mx_Dropdown.left_aligned .mx_Dropdown_arrow {
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.mx_Dropdown.left_aligned .mx_Dropdown_input > .mx_Dropdown_option {
|
||||
padding-left: 25px;
|
||||
}
|
||||
|
||||
.mx_Dropdown_option {
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
|
@ -55,9 +63,15 @@ limitations under the License.
|
|||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.mx_Dropdown_option div {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mx_Dropdown_option img {
|
||||
margin: 5px;
|
||||
width: 25px;
|
||||
width: 27px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ limitations under the License.
|
|||
|
||||
.mx_TextualEvent.mx_MemberEventListSummary_summary {
|
||||
font-size: 14px;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.mx_MemberEventListSummary_avatars {
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<link rel="apple-touch-icon" sizes="144x144" href="vector-icons/apple-touch-icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="vector-icons/apple-touch-icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="vector-icons/apple-touch-icon-180x180.png">
|
||||
<link rel="manifest" href="vector-icons/manifest.json">
|
||||
<link rel="manifest" href="manifest.json">
|
||||
<link rel="shortcut icon" href="vector-icons/favicon.ico">
|
||||
<meta name="apple-mobile-web-app-title" content="Riot">
|
||||
<meta name="application-name" content="Riot">
|
||||
|
|
|
@ -103,7 +103,7 @@ function checkBrowserFeatures(featureList) {
|
|||
|
||||
var validBrowser = checkBrowserFeatures([
|
||||
"displaytable", "flexbox", "es5object", "es5function", "localstorage",
|
||||
"objectfit"
|
||||
"objectfit", "indexeddb", "webworkers",
|
||||
]);
|
||||
|
||||
// Parse the given window.location and return parameters that can be used when calling
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -20,13 +20,11 @@ limitations under the License.
|
|||
import VectorBasePlatform from './VectorBasePlatform';
|
||||
import dis from 'matrix-react-sdk/lib/dispatcher';
|
||||
import q from 'q';
|
||||
|
||||
const electron = require('electron');
|
||||
const remote = electron.remote;
|
||||
import electron, {remote} from 'electron';
|
||||
|
||||
remote.autoUpdater.on('update-downloaded', onUpdateDownloaded);
|
||||
|
||||
function onUpdateDownloaded(ev, releaseNotes, ver, date, updateURL) {
|
||||
function onUpdateDownloaded(ev: Event, releaseNotes: string, ver: string, date: Date, updateURL: string) {
|
||||
dis.dispatch({
|
||||
action: 'new_version',
|
||||
currentVersion: remote.app.getVersion(),
|
||||
|
@ -35,7 +33,7 @@ function onUpdateDownloaded(ev, releaseNotes, ver, date, updateURL) {
|
|||
});
|
||||
}
|
||||
|
||||
function platformFriendlyName() {
|
||||
function platformFriendlyName(): string {
|
||||
console.log(window.process);
|
||||
switch (window.process.platform) {
|
||||
case 'darwin':
|
||||
|
@ -72,11 +70,11 @@ export default class ElectronPlatform extends VectorBasePlatform {
|
|||
}
|
||||
}
|
||||
|
||||
supportsNotifications() : boolean {
|
||||
supportsNotifications(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
maySendNotifications() : boolean {
|
||||
maySendNotifications(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -100,7 +98,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
|
|||
icon: avatarUrl,
|
||||
tag: 'vector',
|
||||
silent: true, // we play our own sounds
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
notification.onclick = function() {
|
||||
|
@ -123,7 +121,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
|
|||
notif.close();
|
||||
}
|
||||
|
||||
getAppVersion() {
|
||||
getAppVersion(): Promise<string> {
|
||||
return q(remote.app.getVersion());
|
||||
}
|
||||
|
||||
|
@ -140,15 +138,15 @@ export default class ElectronPlatform extends VectorBasePlatform {
|
|||
electron.ipcRenderer.send('install_update');
|
||||
}
|
||||
|
||||
getDefaultDeviceDisplayName() {
|
||||
getDefaultDeviceDisplayName(): string {
|
||||
return 'Riot Desktop on ' + platformFriendlyName();
|
||||
}
|
||||
|
||||
screenCaptureErrorString() {
|
||||
screenCaptureErrorString(): ?string {
|
||||
return null;
|
||||
}
|
||||
|
||||
requestNotificationPermission() : Promise {
|
||||
requestNotificationPermission(): Promise<string> {
|
||||
return q('granted');
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ export default class VectorBasePlatform extends BasePlatform {
|
|||
* Get a sensible default display name for the
|
||||
* device Vector is running on
|
||||
*/
|
||||
getDefaultDeviceDisplayName() {
|
||||
getDefaultDeviceDisplayName(): string {
|
||||
return "Unknown device";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ export default class WebPlatform extends VectorBasePlatform {
|
|||
}
|
||||
|
||||
this.favicon.badge(notif, {
|
||||
bgColor: bgColor
|
||||
bgColor: bgColor,
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn(`Failed to set badge count: ${e.message}`);
|
||||
|
@ -75,7 +75,7 @@ export default class WebPlatform extends VectorBasePlatform {
|
|||
* Returns true if the platform supports displaying
|
||||
* notifications, otherwise false.
|
||||
*/
|
||||
supportsNotifications() : boolean {
|
||||
supportsNotifications(): boolean {
|
||||
return Boolean(global.Notification);
|
||||
}
|
||||
|
||||
|
@ -83,8 +83,8 @@ export default class WebPlatform extends VectorBasePlatform {
|
|||
* Returns true if the application currently has permission
|
||||
* to display notifications. Otherwise false.
|
||||
*/
|
||||
maySendNotifications() : boolean {
|
||||
return global.Notification.permission == 'granted';
|
||||
maySendNotifications(): boolean {
|
||||
return global.Notification.permission === 'granted';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,7 +94,7 @@ export default class WebPlatform extends VectorBasePlatform {
|
|||
* that is 'granted' if the user allowed the request or
|
||||
* 'denied' otherwise.
|
||||
*/
|
||||
requestNotificationPermission() : Promise {
|
||||
requestNotificationPermission(): Promise<string> {
|
||||
// annoyingly, the latest spec says this returns a
|
||||
// promise, but this is only supported in Chrome 46
|
||||
// and Firefox 47, so adapt the callback API.
|
||||
|
@ -113,13 +113,13 @@ export default class WebPlatform extends VectorBasePlatform {
|
|||
icon: avatarUrl,
|
||||
tag: "vector",
|
||||
silent: true, // we play our own sounds
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
notification.onclick = function() {
|
||||
dis.dispatch({
|
||||
action: 'view_room',
|
||||
room_id: room.roomId
|
||||
room_id: room.roomId,
|
||||
});
|
||||
global.focus();
|
||||
notification.close();
|
||||
|
@ -132,7 +132,7 @@ export default class WebPlatform extends VectorBasePlatform {
|
|||
}, 5 * 1000);
|
||||
}
|
||||
|
||||
_getVersion() {
|
||||
_getVersion(): Promise<string> {
|
||||
const deferred = q.defer();
|
||||
|
||||
// We add a cachebuster to the request to make sure that we know about
|
||||
|
@ -148,19 +148,19 @@ export default class WebPlatform extends VectorBasePlatform {
|
|||
},
|
||||
(err, response, body) => {
|
||||
if (err || response.status < 200 || response.status >= 300) {
|
||||
if (err == null) err = { status: response.status };
|
||||
if (err === null) err = { status: response.status };
|
||||
deferred.reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
const ver = body.trim();
|
||||
deferred.resolve(ver);
|
||||
}
|
||||
},
|
||||
);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
getAppVersion() {
|
||||
getAppVersion(): Promise<string> {
|
||||
if (this.runningVersion !== null) {
|
||||
return q(this.runningVersion);
|
||||
}
|
||||
|
@ -169,9 +169,9 @@ export default class WebPlatform extends VectorBasePlatform {
|
|||
|
||||
pollForUpdate() {
|
||||
this._getVersion().done((ver) => {
|
||||
if (this.runningVersion == null) {
|
||||
if (this.runningVersion === null) {
|
||||
this.runningVersion = ver;
|
||||
} else if (this.runningVersion != ver) {
|
||||
} else if (this.runningVersion !== ver) {
|
||||
dis.dispatch({
|
||||
action: 'new_version',
|
||||
currentVersion: this.runningVersion,
|
||||
|
@ -187,19 +187,18 @@ export default class WebPlatform extends VectorBasePlatform {
|
|||
window.location.reload();
|
||||
}
|
||||
|
||||
getDefaultDeviceDisplayName() {
|
||||
getDefaultDeviceDisplayName(): string {
|
||||
// strip query-string and fragment from uri
|
||||
let u = url.parse(window.location.href);
|
||||
const u = url.parse(window.location.href);
|
||||
u.search = "";
|
||||
u.hash = "";
|
||||
let app_name = u.format();
|
||||
const appName = u.format();
|
||||
|
||||
let ua = new UAParser();
|
||||
return app_name + " via " + ua.getBrowser().name +
|
||||
" on " + ua.getOS().name;
|
||||
const ua = new UAParser();
|
||||
return `${appName} via ${ua.getBrowser().name} on ${ua.getOS().name}`;
|
||||
}
|
||||
|
||||
screenCaptureErrorString() {
|
||||
screenCaptureErrorString(): ?string {
|
||||
// it won't work at all if you're not on HTTPS so whine whine whine
|
||||
if (!global.window || global.window.location.protocol !== "https:") {
|
||||
return "You need to be using HTTPS to place a screen-sharing call.";
|
||||
|
|
|
@ -37,8 +37,12 @@ import q from "q";
|
|||
// actually timestamps. We then purge the remaining logs. We also do this
|
||||
// purge on startup to prevent logs from accumulating.
|
||||
|
||||
// the frequency with which we flush to indexeddb
|
||||
const FLUSH_RATE_MS = 30 * 1000;
|
||||
|
||||
// the length of log data we keep in indexeddb (and include in the reports)
|
||||
const MAX_LOG_SIZE = 1024 * 1024 * 1; // 1 MB
|
||||
|
||||
// A class which monkey-patches the global console and stores log lines.
|
||||
class ConsoleLogger {
|
||||
constructor() {
|
||||
|
@ -232,7 +236,6 @@ class IndexedDBLogStore {
|
|||
* is a big string with all the new-line delimited logs.
|
||||
*/
|
||||
async consume() {
|
||||
const MAX_LOG_SIZE = 1024 * 1024 * 50; // 50 MB
|
||||
const db = this.db;
|
||||
|
||||
// Returns: a string representing the concatenated logs for this ID.
|
||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
import pako from 'pako';
|
||||
import q from "q";
|
||||
|
||||
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
||||
import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg';
|
||||
|
||||
import rageshake from './rageshake'
|
||||
|
@ -64,6 +65,8 @@ export default async function sendBugReport(bugReportEndpoint, opts) {
|
|||
userAgent = window.navigator.userAgent;
|
||||
}
|
||||
|
||||
const client = MatrixClientPeg.get();
|
||||
|
||||
console.log("Sending bug report.");
|
||||
|
||||
const body = new FormData();
|
||||
|
@ -72,6 +75,11 @@ export default async function sendBugReport(bugReportEndpoint, opts) {
|
|||
body.append('version', version);
|
||||
body.append('user_agent', userAgent);
|
||||
|
||||
if (client) {
|
||||
body.append('user_id', client.credentials.userId);
|
||||
body.append('device_id', client.deviceId);
|
||||
}
|
||||
|
||||
if (opts.sendLogs) {
|
||||
progressCallback("Collecting logs");
|
||||
const logs = await rageshake.getLogsForReport();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue