Merge branch 'develop' into luke/fix-room-list-group-store-leak
This commit is contained in:
commit
874a7bf1de
8 changed files with 68 additions and 33 deletions
|
@ -15,6 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Promise from 'bluebird';
|
import Promise from 'bluebird';
|
||||||
|
import SettingsStore from "./settings/SettingsStore";
|
||||||
const request = require('browser-request');
|
const request = require('browser-request');
|
||||||
|
|
||||||
const SdkConfig = require('./SdkConfig');
|
const SdkConfig = require('./SdkConfig');
|
||||||
|
@ -109,6 +110,7 @@ class ScalarAuthClient {
|
||||||
let url = SdkConfig.get().integrations_ui_url;
|
let url = SdkConfig.get().integrations_ui_url;
|
||||||
url += "?scalar_token=" + encodeURIComponent(this.scalarToken);
|
url += "?scalar_token=" + encodeURIComponent(this.scalarToken);
|
||||||
url += "&room_id=" + encodeURIComponent(roomId);
|
url += "&room_id=" + encodeURIComponent(roomId);
|
||||||
|
url += "&theme=" + encodeURIComponent(SettingsStore.getValue("theme"));
|
||||||
if (id) {
|
if (id) {
|
||||||
url += '&integ_id=' + encodeURIComponent(id);
|
url += '&integ_id=' + encodeURIComponent(id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -557,8 +557,16 @@ const onMessage = function(event) {
|
||||||
//
|
//
|
||||||
// All strings start with the empty string, so for sanity return if the length
|
// All strings start with the empty string, so for sanity return if the length
|
||||||
// of the event origin is 0.
|
// of the event origin is 0.
|
||||||
|
//
|
||||||
|
// TODO -- Scalar postMessage API should be namespaced with event.data.api field
|
||||||
|
// Fix following "if" statement to respond only to specific API messages.
|
||||||
const url = SdkConfig.get().integrations_ui_url;
|
const url = SdkConfig.get().integrations_ui_url;
|
||||||
if (event.origin.length === 0 || !url.startsWith(event.origin) || !event.data.action) {
|
if (
|
||||||
|
event.origin.length === 0 ||
|
||||||
|
!url.startsWith(event.origin) ||
|
||||||
|
!event.data.action ||
|
||||||
|
event.data.api // Ignore messages with specific API set
|
||||||
|
) {
|
||||||
return; // don't log this - debugging APIs like to spam postMessage which floods the log otherwise
|
return; // don't log this - debugging APIs like to spam postMessage which floods the log otherwise
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1068,7 +1068,7 @@ export default React.createClass({
|
||||||
if (!self._loggedInView) {
|
if (!self._loggedInView) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return self._loggedInView.canResetTimelineInRoom(roomId);
|
return self._loggedInView.getDecoratedComponentInstance().canResetTimelineInRoom(roomId);
|
||||||
});
|
});
|
||||||
|
|
||||||
cli.on('sync', function(state, prevState) {
|
cli.on('sync', function(state, prevState) {
|
||||||
|
|
|
@ -854,9 +854,13 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
ev.dataTransfer.dropEffect = 'none';
|
ev.dataTransfer.dropEffect = 'none';
|
||||||
|
|
||||||
const items = ev.dataTransfer.items;
|
const items = [...ev.dataTransfer.items];
|
||||||
if (items.length == 1) {
|
if (items.length >= 1) {
|
||||||
if (items[0].kind == 'file') {
|
const isDraggingFiles = items.every(function(item) {
|
||||||
|
return item.kind == 'file';
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isDraggingFiles) {
|
||||||
this.setState({ draggingFile: true });
|
this.setState({ draggingFile: true });
|
||||||
ev.dataTransfer.dropEffect = 'copy';
|
ev.dataTransfer.dropEffect = 'copy';
|
||||||
}
|
}
|
||||||
|
@ -867,10 +871,8 @@ module.exports = React.createClass({
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
this.setState({ draggingFile: false });
|
this.setState({ draggingFile: false });
|
||||||
const files = ev.dataTransfer.files;
|
const files = [...ev.dataTransfer.files];
|
||||||
if (files.length == 1) {
|
files.forEach(this.uploadFile);
|
||||||
this.uploadFile(files[0]);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onDragLeaveOrEnd: function(ev) {
|
onDragLeaveOrEnd: function(ev) {
|
||||||
|
|
|
@ -374,7 +374,7 @@ export const MsisdnAuthEntry = React.createClass({
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>{ _t("A text message has been sent to %(msisdn)s",
|
<p>{ _t("A text message has been sent to %(msisdn)s",
|
||||||
{ msisdn: <i>this._msisdn</i> },
|
{ msisdn: <i>{ this._msisdn }</i> },
|
||||||
) }
|
) }
|
||||||
</p>
|
</p>
|
||||||
<p>{ _t("Please enter the code it contains:") }</p>
|
<p>{ _t("Please enter the code it contains:") }</p>
|
||||||
|
|
|
@ -27,6 +27,7 @@ import ScalarAuthClient from '../../../ScalarAuthClient';
|
||||||
import ScalarMessaging from '../../../ScalarMessaging';
|
import ScalarMessaging from '../../../ScalarMessaging';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import WidgetUtils from '../../../WidgetUtils';
|
import WidgetUtils from '../../../WidgetUtils';
|
||||||
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
|
||||||
// The maximum number of widgets that can be added in a room
|
// The maximum number of widgets that can be added in a room
|
||||||
const MAX_WIDGETS = 2;
|
const MAX_WIDGETS = 2;
|
||||||
|
@ -131,6 +132,9 @@ module.exports = React.createClass({
|
||||||
'$matrix_room_id': this.props.room.roomId,
|
'$matrix_room_id': this.props.room.roomId,
|
||||||
'$matrix_display_name': user ? user.displayName : this.props.userId,
|
'$matrix_display_name': user ? user.displayName : this.props.userId,
|
||||||
'$matrix_avatar_url': user ? MatrixClientPeg.get().mxcUrlToHttp(user.avatarUrl) : '',
|
'$matrix_avatar_url': user ? MatrixClientPeg.get().mxcUrlToHttp(user.avatarUrl) : '',
|
||||||
|
|
||||||
|
// TODO: Namespace themes through some standard
|
||||||
|
'$theme': SettingsStore.getValue("theme"),
|
||||||
};
|
};
|
||||||
|
|
||||||
app.id = appId;
|
app.id = appId;
|
||||||
|
|
|
@ -89,11 +89,11 @@ module.exports = React.createClass({
|
||||||
this._groupStoreTokens = [];
|
this._groupStoreTokens = [];
|
||||||
// A map between tags which are group IDs and the room IDs of rooms that should be kept
|
// A map between tags which are group IDs and the room IDs of rooms that should be kept
|
||||||
// in the room list when filtering by that tag.
|
// in the room list when filtering by that tag.
|
||||||
this._selectedTagsRoomIdsForGroup = {
|
this._visibleRoomsForGroup = {
|
||||||
// $groupId: [$roomId1, $roomId2, ...],
|
// $groupId: [$roomId1, $roomId2, ...],
|
||||||
};
|
};
|
||||||
// All rooms that should be kept in the room list when filtering
|
// All rooms that should be kept in the room list when filtering
|
||||||
this._selectedTagsRoomIds = [];
|
this._visibleRooms = [];
|
||||||
// When the selected tags are changed, initialise a group store if necessary
|
// When the selected tags are changed, initialise a group store if necessary
|
||||||
this._filterStoreToken = FilterStore.addListener(() => {
|
this._filterStoreToken = FilterStore.addListener(() => {
|
||||||
FilterStore.getSelectedTags().forEach((tag) => {
|
FilterStore.getSelectedTags().forEach((tag) => {
|
||||||
|
@ -109,7 +109,7 @@ module.exports = React.createClass({
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
// Filters themselves have changed, refresh the selected tags
|
// Filters themselves have changed, refresh the selected tags
|
||||||
this.updateSelectedTagsRooms(dmRoomMap, FilterStore.getSelectedTags());
|
this.updateVisibleRooms();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.refreshRoomList();
|
this.refreshRoomList();
|
||||||
|
@ -276,29 +276,30 @@ module.exports = React.createClass({
|
||||||
this.refreshRoomList();
|
this.refreshRoomList();
|
||||||
}, 500),
|
}, 500),
|
||||||
|
|
||||||
// Update which rooms and users should appear in RoomList as dictated by selected tags
|
// Update which rooms and users should appear in RoomList for a given group tag
|
||||||
updateSelectedTagsRooms: function(dmRoomMap, updatedTags) {
|
updateVisibleRoomsForTag: function(dmRoomMap, tag) {
|
||||||
if (!this.mounted) return;
|
if (!this.mounted) return;
|
||||||
updatedTags.forEach((tag) => {
|
// For now, only handle group tags
|
||||||
// For now, only handle group tags
|
const store = this._groupStores[tag];
|
||||||
const store = this._groupStores[tag];
|
if (!store) return;
|
||||||
if (!store) return;
|
|
||||||
|
|
||||||
this._selectedTagsRoomIdsForGroup[tag] = [];
|
this._visibleRoomsForGroup[tag] = [];
|
||||||
store.getGroupRooms().forEach((room) => this._selectedTagsRoomIdsForGroup[tag].push(room.roomId));
|
store.getGroupRooms().forEach((room) => this._visibleRoomsForGroup[tag].push(room.roomId));
|
||||||
store.getGroupMembers().forEach((member) => {
|
store.getGroupMembers().forEach((member) => {
|
||||||
if (member.userId === MatrixClientPeg.get().credentials.userId) return;
|
if (member.userId === MatrixClientPeg.get().credentials.userId) return;
|
||||||
dmRoomMap.getDMRoomsForUserId(member.userId).forEach(
|
dmRoomMap.getDMRoomsForUserId(member.userId).forEach(
|
||||||
(roomId) => this._selectedTagsRoomIdsForGroup[tag].push(roomId),
|
(roomId) => this._visibleRoomsForGroup[tag].push(roomId),
|
||||||
);
|
);
|
||||||
});
|
|
||||||
// TODO: Check if room has been tagged to the group by the user
|
|
||||||
});
|
});
|
||||||
|
// TODO: Check if room has been tagged to the group by the user
|
||||||
|
},
|
||||||
|
|
||||||
this._selectedTagsRoomIds = [];
|
// Update which rooms and users should appear according to which tags are selected
|
||||||
|
updateVisibleRooms: function() {
|
||||||
|
this._visibleRooms = [];
|
||||||
FilterStore.getSelectedTags().forEach((tag) => {
|
FilterStore.getSelectedTags().forEach((tag) => {
|
||||||
(this._selectedTagsRoomIdsForGroup[tag] || []).forEach(
|
(this._visibleRoomsForGroup[tag] || []).forEach(
|
||||||
(roomId) => this._selectedTagsRoomIds.push(roomId),
|
(roomId) => this._visibleRooms.push(roomId),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -311,7 +312,7 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
isRoomInSelectedTags: function(room) {
|
isRoomInSelectedTags: function(room) {
|
||||||
// No selected tags = every room is visible in the list
|
// No selected tags = every room is visible in the list
|
||||||
return this.state.selectedTags.length === 0 || this._selectedTagsRoomIds.includes(room.roomId);
|
return this.state.selectedTags.length === 0 || this._visibleRooms.includes(room.roomId);
|
||||||
},
|
},
|
||||||
|
|
||||||
refreshRoomList: function() {
|
refreshRoomList: function() {
|
||||||
|
|
|
@ -23,6 +23,10 @@ import SettingsStore, {SettingLevel} from "./settings/SettingsStore";
|
||||||
|
|
||||||
const i18nFolder = 'i18n/';
|
const i18nFolder = 'i18n/';
|
||||||
|
|
||||||
|
// Control whether to also return original, untranslated strings
|
||||||
|
// Useful for debugging and testing
|
||||||
|
const ANNOTATE_STRINGS = false;
|
||||||
|
|
||||||
// We use english strings as keys, some of which contain full stops
|
// We use english strings as keys, some of which contain full stops
|
||||||
counterpart.setSeparator('|');
|
counterpart.setSeparator('|');
|
||||||
// Fall back to English
|
// Fall back to English
|
||||||
|
@ -84,7 +88,21 @@ export function _t(text, variables, tags) {
|
||||||
// The translation returns text so there's no XSS vector here (no unsafe HTML, no code execution)
|
// The translation returns text so there's no XSS vector here (no unsafe HTML, no code execution)
|
||||||
const translated = safeCounterpartTranslate(text, args);
|
const translated = safeCounterpartTranslate(text, args);
|
||||||
|
|
||||||
return substitute(translated, variables, tags);
|
let substituted = substitute(translated, variables, tags);
|
||||||
|
|
||||||
|
// For development/testing purposes it is useful to also output the original string
|
||||||
|
// Don't do that for release versions
|
||||||
|
if (ANNOTATE_STRINGS) {
|
||||||
|
if (typeof substituted === 'string') {
|
||||||
|
return `@@${text}##${substituted}@@`
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return <span className='translated-string' data-orig-string={text}>{substituted}</span>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return substituted;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue