Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Weblate 2017-09-04 10:27:17 +00:00
commit d305f8aacb
39 changed files with 277 additions and 125 deletions

View file

@ -6,7 +6,6 @@ src/autocomplete/Autocompleter.js
src/autocomplete/Components.js src/autocomplete/Components.js
src/autocomplete/DuckDuckGoProvider.js src/autocomplete/DuckDuckGoProvider.js
src/autocomplete/EmojiProvider.js src/autocomplete/EmojiProvider.js
src/autocomplete/RoomProvider.js
src/autocomplete/UserProvider.js src/autocomplete/UserProvider.js
src/CallHandler.js src/CallHandler.js
src/component-index.js src/component-index.js
@ -35,7 +34,6 @@ src/components/views/create_room/RoomAlias.js
src/components/views/dialogs/ChatCreateOrReuseDialog.js src/components/views/dialogs/ChatCreateOrReuseDialog.js
src/components/views/dialogs/DeactivateAccountDialog.js src/components/views/dialogs/DeactivateAccountDialog.js
src/components/views/dialogs/InteractiveAuthDialog.js src/components/views/dialogs/InteractiveAuthDialog.js
src/components/views/dialogs/SetMxIdDialog.js
src/components/views/dialogs/UnknownDeviceDialog.js src/components/views/dialogs/UnknownDeviceDialog.js
src/components/views/elements/AccessibleButton.js src/components/views/elements/AccessibleButton.js
src/components/views/elements/ActionButton.js src/components/views/elements/ActionButton.js
@ -89,7 +87,6 @@ src/components/views/rooms/MemberList.js
src/components/views/rooms/MemberTile.js src/components/views/rooms/MemberTile.js
src/components/views/rooms/MessageComposer.js src/components/views/rooms/MessageComposer.js
src/components/views/rooms/MessageComposerInput.js src/components/views/rooms/MessageComposerInput.js
src/components/views/rooms/MessageComposerInputOld.js
src/components/views/rooms/PresenceLabel.js src/components/views/rooms/PresenceLabel.js
src/components/views/rooms/ReadReceiptMarker.js src/components/views/rooms/ReadReceiptMarker.js
src/components/views/rooms/RoomList.js src/components/views/rooms/RoomList.js
@ -100,7 +97,6 @@ src/components/views/rooms/RoomTile.js
src/components/views/rooms/RoomTopicEditor.js src/components/views/rooms/RoomTopicEditor.js
src/components/views/rooms/SearchableEntityList.js src/components/views/rooms/SearchableEntityList.js
src/components/views/rooms/SearchResultTile.js src/components/views/rooms/SearchResultTile.js
src/components/views/rooms/TabCompleteBar.js
src/components/views/rooms/TopUnreadMessagesBar.js src/components/views/rooms/TopUnreadMessagesBar.js
src/components/views/rooms/UserTile.js src/components/views/rooms/UserTile.js
src/components/views/settings/AddPhoneNumber.js src/components/views/settings/AddPhoneNumber.js
@ -128,8 +124,6 @@ src/Roles.js
src/Rooms.js src/Rooms.js
src/ScalarAuthClient.js src/ScalarAuthClient.js
src/ScalarMessaging.js src/ScalarMessaging.js
src/TabComplete.js
src/TabCompleteEntries.js
src/TextForEvent.js src/TextForEvent.js
src/Tinter.js src/Tinter.js
src/UiEffects.js src/UiEffects.js
@ -142,7 +136,7 @@ src/utils/Receipt.js
src/Velociraptor.js src/Velociraptor.js
src/VelocityBounce.js src/VelocityBounce.js
src/WhoIsTyping.js src/WhoIsTyping.js
src/wrappers/WithMatrixClient.js src/wrappers/withMatrixClient.js
test/all-tests.js test/all-tests.js
test/components/structures/login/Registration-test.js test/components/structures/login/Registration-test.js
test/components/structures/MessagePanel-test.js test/components/structures/MessagePanel-test.js

View file

@ -1,3 +1,76 @@
Changes in [0.10.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.10.2) (2017-08-24)
=====================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.10.1...v0.10.2)
* Force update on timelinepanel when event decrypted
[\#1334](https://github.com/matrix-org/matrix-react-sdk/pull/1334)
* Dispatch incoming_call synchronously
[\#1337](https://github.com/matrix-org/matrix-react-sdk/pull/1337)
* Fix React crying on machines without internet due to return undefined
[\#1335](https://github.com/matrix-org/matrix-react-sdk/pull/1335)
* Catch the promise rejection if scalar fails
[\#1333](https://github.com/matrix-org/matrix-react-sdk/pull/1333)
* Update from Weblate.
[\#1329](https://github.com/matrix-org/matrix-react-sdk/pull/1329)
Changes in [0.10.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.10.1) (2017-08-23)
=====================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.10.1-rc.1...v0.10.1)
* [No changes]
Changes in [0.10.1-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.10.1-rc.1) (2017-08-22)
===============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.10.0-rc.2...v0.10.1-rc.1)
* Matthew/multiple widgets
[\#1327](https://github.com/matrix-org/matrix-react-sdk/pull/1327)
* Fix proptypes on UserPickerDialog
[\#1326](https://github.com/matrix-org/matrix-react-sdk/pull/1326)
* AppsDrawer: Remove unnecessary bind
[\#1325](https://github.com/matrix-org/matrix-react-sdk/pull/1325)
* Position add app widget link
[\#1322](https://github.com/matrix-org/matrix-react-sdk/pull/1322)
* Remove app tile beta tag.
[\#1323](https://github.com/matrix-org/matrix-react-sdk/pull/1323)
* Add missing translation.
[\#1324](https://github.com/matrix-org/matrix-react-sdk/pull/1324)
* Note that apps are not E2EE
[\#1319](https://github.com/matrix-org/matrix-react-sdk/pull/1319)
* Only render appTile body (including warnings) if drawer shown.
[\#1321](https://github.com/matrix-org/matrix-react-sdk/pull/1321)
* Timeline improvements
[\#1320](https://github.com/matrix-org/matrix-react-sdk/pull/1320)
* Add a space between widget name and "widget" in widget event tiles
[\#1318](https://github.com/matrix-org/matrix-react-sdk/pull/1318)
* Move manage integrations button from settings page to room header as a
stand-alone component
[\#1286](https://github.com/matrix-org/matrix-react-sdk/pull/1286)
* Don't apply case logic to app names
[\#1316](https://github.com/matrix-org/matrix-react-sdk/pull/1316)
* Stop integ manager opening on every room switch
[\#1315](https://github.com/matrix-org/matrix-react-sdk/pull/1315)
* Add behaviour to toggle app draw on app tile header click
[\#1313](https://github.com/matrix-org/matrix-react-sdk/pull/1313)
* Change OOO so that MELS generation will continue over hidden events
[\#1308](https://github.com/matrix-org/matrix-react-sdk/pull/1308)
* Implement TextualEvent tiles for im.vector.modular.widgets
[\#1312](https://github.com/matrix-org/matrix-react-sdk/pull/1312)
* Don't show widget security warning to the person that added it to the room
[\#1314](https://github.com/matrix-org/matrix-react-sdk/pull/1314)
* remove unused strings introduced by string change
[\#1311](https://github.com/matrix-org/matrix-react-sdk/pull/1311)
* hotfix bad fn signature regression
[\#1310](https://github.com/matrix-org/matrix-react-sdk/pull/1310)
* Show a dialog if the maximum number of widgets allowed has been reached.
[\#1291](https://github.com/matrix-org/matrix-react-sdk/pull/1291)
* Fix Robot translation
[\#1309](https://github.com/matrix-org/matrix-react-sdk/pull/1309)
* Refactor ChatInviteDialog to be UserPickerDialog
[\#1300](https://github.com/matrix-org/matrix-react-sdk/pull/1300)
* Update Link to Translation status
[\#1302](https://github.com/matrix-org/matrix-react-sdk/pull/1302)
Changes in [0.9.7](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.9.7) (2017-06-22) Changes in [0.9.7](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.9.7) (2017-06-22)
=================================================================================================== ===================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.9.6...v0.9.7) [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.9.6...v0.9.7)

View file

@ -1,6 +1,6 @@
{ {
"name": "matrix-react-sdk", "name": "matrix-react-sdk",
"version": "0.9.7", "version": "0.10.2",
"description": "SDK for matrix.org using React", "description": "SDK for matrix.org using React",
"author": "matrix.org", "author": "matrix.org",
"repository": { "repository": {
@ -66,7 +66,7 @@
"isomorphic-fetch": "^2.2.1", "isomorphic-fetch": "^2.2.1",
"linkifyjs": "^2.1.3", "linkifyjs": "^2.1.3",
"lodash": "^4.13.1", "lodash": "^4.13.1",
"matrix-js-sdk": "matrix-org/matrix-js-sdk#develop", "matrix-js-sdk": "0.8.2",
"optimist": "^0.6.1", "optimist": "^0.6.1",
"prop-types": "^15.5.8", "prop-types": "^15.5.8",
"react": "^15.4.0", "react": "^15.4.0",

View file

@ -1,6 +1,7 @@
/* /*
Copyright 2015, 2016 OpenMarket Ltd Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017 Vector Creations Ltd Copyright 2017 Vector Creations Ltd
Copyright 2017 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -33,9 +34,16 @@ import Modal from './Modal';
* } * }
*/ */
const MAX_PENDING_ENCRYPTED = 20;
const Notifier = { const Notifier = {
notifsByRoom: {}, notifsByRoom: {},
// A list of event IDs that we've received but need to wait until
// they're decrypted until we decide whether to notify for them
// or not
pendingEncryptedEventIds: [],
notificationMessageForEvent: function(ev) { notificationMessageForEvent: function(ev) {
return TextForEvent.textForEvent(ev); return TextForEvent.textForEvent(ev);
}, },
@ -89,17 +97,18 @@ const Notifier = {
_playAudioNotification: function(ev, room) { _playAudioNotification: function(ev, room) {
const e = document.getElementById("messageAudio"); const e = document.getElementById("messageAudio");
if (e) { if (e) {
e.load();
e.play(); e.play();
} }
}, },
start: function() { start: function() {
this.boundOnRoomTimeline = this.onRoomTimeline.bind(this); this.boundOnEvent = this.onEvent.bind(this);
this.boundOnSyncStateChange = this.onSyncStateChange.bind(this); this.boundOnSyncStateChange = this.onSyncStateChange.bind(this);
this.boundOnRoomReceipt = this.onRoomReceipt.bind(this); this.boundOnRoomReceipt = this.onRoomReceipt.bind(this);
MatrixClientPeg.get().on('Room.timeline', this.boundOnRoomTimeline); this.boundOnEventDecrypted = this.onEventDecrypted.bind(this);
MatrixClientPeg.get().on('event', this.boundOnEvent);
MatrixClientPeg.get().on('Room.receipt', this.boundOnRoomReceipt); MatrixClientPeg.get().on('Room.receipt', this.boundOnRoomReceipt);
MatrixClientPeg.get().on('Event.decrypted', this.boundOnEventDecrypted);
MatrixClientPeg.get().on("sync", this.boundOnSyncStateChange); MatrixClientPeg.get().on("sync", this.boundOnSyncStateChange);
this.toolbarHidden = false; this.toolbarHidden = false;
this.isSyncing = false; this.isSyncing = false;
@ -107,8 +116,9 @@ const Notifier = {
stop: function() { stop: function() {
if (MatrixClientPeg.get() && this.boundOnRoomTimeline) { if (MatrixClientPeg.get() && this.boundOnRoomTimeline) {
MatrixClientPeg.get().removeListener('Room.timeline', this.boundOnRoomTimeline); MatrixClientPeg.get().removeListener('Event', this.boundOnEvent);
MatrixClientPeg.get().removeListener('Room.receipt', this.boundOnRoomReceipt); MatrixClientPeg.get().removeListener('Room.receipt', this.boundOnRoomReceipt);
MatrixClientPeg.get().removeListener('Event.decrypted', this.boundOnEventDecrypted);
MatrixClientPeg.get().removeListener('sync', this.boundOnSyncStateChange); MatrixClientPeg.get().removeListener('sync', this.boundOnSyncStateChange);
} }
this.isSyncing = false; this.isSyncing = false;
@ -237,23 +247,30 @@ const Notifier = {
} }
}, },
onRoomTimeline: function(ev, room, toStartOfTimeline, removed, data) { onEvent: function(ev) {
if (toStartOfTimeline) return;
if (!room) return;
if (!this.isSyncing) return; // don't alert for any messages initially if (!this.isSyncing) return; // don't alert for any messages initially
if (ev.sender && ev.sender.userId === MatrixClientPeg.get().credentials.userId) return; if (ev.sender && ev.sender.userId === MatrixClientPeg.get().credentials.userId) return;
if (data.timeline.getTimelineSet() !== room.getUnfilteredTimelineSet()) return;
const actions = MatrixClientPeg.get().getPushActionsForEvent(ev); // If it's an encrypted event and the type is still 'm.room.encrypted',
if (actions && actions.notify) { // it hasn't yet been decrypted, so wait until it is.
if (this.isEnabled()) { if (ev.isBeingDecrypted() || ev.isDecryptionFailure()) {
this._displayPopupNotification(ev, room); this.pendingEncryptedEventIds.push(ev.getId());
} // don't let the list fill up indefinitely
if (actions.tweaks.sound && this.isAudioEnabled()) { while (this.pendingEncryptedEventIds.length > MAX_PENDING_ENCRYPTED) {
PlatformPeg.get().loudNotification(ev, room); this.pendingEncryptedEventIds.shift();
this._playAudioNotification(ev, room);
} }
return;
} }
this._evaluateEvent(ev);
},
onEventDecrypted: function(ev) {
const idx = this.pendingEncryptedEventIds.indexOf(ev.getId());
if (idx === -1) return;
this.pendingEncryptedEventIds.splice(idx, 1);
this._evaluateEvent(ev);
}, },
onRoomReceipt: function(ev, room) { onRoomReceipt: function(ev, room) {
@ -273,6 +290,20 @@ const Notifier = {
delete this.notifsByRoom[room.roomId]; delete this.notifsByRoom[room.roomId];
} }
}, },
_evaluateEvent: function(ev) {
const room = MatrixClientPeg.get().getRoom(ev.getRoomId());
const actions = MatrixClientPeg.get().getPushActionsForEvent(ev);
if (actions && actions.notify) {
if (this.isEnabled()) {
this._displayPopupNotification(ev, room);
}
if (actions.tweaks.sound && this.isAudioEnabled()) {
PlatformPeg.get().loudNotification(ev, room);
this._playAudioNotification(ev, room);
}
}
}
}; };
if (!global.mxNotifier) { if (!global.mxNotifier) {

View file

@ -244,15 +244,16 @@ function textForPowerEvent(event) {
} }
return _t('%(senderName)s changed the power level of %(powerLevelDiffText)s.', { return _t('%(senderName)s changed the power level of %(powerLevelDiffText)s.', {
senderName: senderName, senderName: senderName,
powerLevelDiffText: diff.join(", ") powerLevelDiffText: diff.join(", "),
}); });
} }
function textForWidgetEvent(event) { function textForWidgetEvent(event) {
const senderName = event.sender ? event.sender.name : event.getSender(); const senderName = event.getSender();
const previousContent = event.getPrevContent() || {}; const {name: prevName, type: prevType, url: prevUrl} = event.getPrevContent();
const {name, type, url} = event.getContent() || {}; const {name, type, url} = event.getContent() || {};
let widgetName = name || previousContent.name || type || previousContent.type || '';
let widgetName = name || prevName || type || prevType || '';
// Apply sentence case to widget name // Apply sentence case to widget name
if (widgetName && widgetName.length > 0) { if (widgetName && widgetName.length > 0) {
widgetName = widgetName[0].toUpperCase() + widgetName.slice(1) + ' '; widgetName = widgetName[0].toUpperCase() + widgetName.slice(1) + ' ';
@ -261,9 +262,15 @@ function textForWidgetEvent(event) {
// If the widget was removed, its content should be {}, but this is sufficiently // If the widget was removed, its content should be {}, but this is sufficiently
// equivalent to that condition. // equivalent to that condition.
if (url) { if (url) {
return _t('%(widgetName)s widget added by %(senderName)s', { if (prevUrl) {
widgetName, senderName, return _t('%(widgetName)s widget modified by %(senderName)s', {
}); widgetName, senderName,
});
} else {
return _t('%(widgetName)s widget added by %(senderName)s', {
widgetName, senderName,
});
}
} else { } else {
return _t('%(widgetName)s widget removed by %(senderName)s', { return _t('%(widgetName)s widget removed by %(senderName)s', {
widgetName, senderName, widgetName, senderName,

View file

@ -1068,10 +1068,13 @@ module.exports = React.createClass({
self.setState({ready: true}); self.setState({ready: true});
}); });
cli.on('Call.incoming', function(call) { cli.on('Call.incoming', function(call) {
// we dispatch this synchronously to make sure that the event
// handlers on the call are set up immediately (so that if
// we get an immediate hangup, we don't get a stuck call)
dis.dispatch({ dis.dispatch({
action: 'incoming_call', action: 'incoming_call',
call: call, call: call,
}); }, true);
}); });
cli.on('Session.logged_out', function(call) { cli.on('Session.logged_out', function(call) {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");

View file

@ -65,7 +65,7 @@ module.exports = React.createClass({
suppressFirstDateSeparator: React.PropTypes.bool, suppressFirstDateSeparator: React.PropTypes.bool,
// whether to show read receipts // whether to show read receipts
manageReadReceipts: React.PropTypes.bool, showReadReceipts: React.PropTypes.bool,
// true if updates to the event list should cause the scroll panel to // true if updates to the event list should cause the scroll panel to
// scroll down when we are at the bottom of the window. See ScrollPanel // scroll down when we are at the bottom of the window. See ScrollPanel
@ -491,7 +491,7 @@ module.exports = React.createClass({
var scrollToken = mxEv.status ? undefined : eventId; var scrollToken = mxEv.status ? undefined : eventId;
var readReceipts; var readReceipts;
if (this.props.manageReadReceipts) { if (this.props.showReadReceipts) {
readReceipts = this._getReadReceiptsForEvent(mxEv); readReceipts = this._getReadReceiptsForEvent(mxEv);
} }
ret.push( ret.push(

View file

@ -20,6 +20,8 @@ limitations under the License.
// - Drag and drop // - Drag and drop
// - File uploading - uploadFile() // - File uploading - uploadFile()
import shouldHideEvent from "../../shouldHideEvent";
var React = require("react"); var React = require("react");
var ReactDOM = require("react-dom"); var ReactDOM = require("react-dom");
import Promise from 'bluebird'; import Promise from 'bluebird';
@ -143,6 +145,8 @@ module.exports = React.createClass({
MatrixClientPeg.get().on("RoomMember.membership", this.onRoomMemberMembership); MatrixClientPeg.get().on("RoomMember.membership", this.onRoomMemberMembership);
MatrixClientPeg.get().on("accountData", this.onAccountData); MatrixClientPeg.get().on("accountData", this.onAccountData);
this._syncedSettings = UserSettingsStore.getSyncedSettings();
// Start listening for RoomViewStore updates // Start listening for RoomViewStore updates
this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate); this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate);
this._onRoomViewStoreUpdate(true); this._onRoomViewStoreUpdate(true);
@ -497,8 +501,7 @@ module.exports = React.createClass({
// update unread count when scrolled up // update unread count when scrolled up
if (!this.state.searchResults && this.state.atEndOfLiveTimeline) { if (!this.state.searchResults && this.state.atEndOfLiveTimeline) {
// no change // no change
} } else if (!shouldHideEvent(ev, this._syncedSettings)) {
else {
this.setState((state, props) => { this.setState((state, props) => {
return {numUnreadMessages: state.numUnreadMessages + 1}; return {numUnreadMessages: state.numUnreadMessages + 1};
}); });
@ -1716,7 +1719,8 @@ module.exports = React.createClass({
var messagePanel = ( var messagePanel = (
<TimelinePanel ref={this._gatherTimelinePanelRef} <TimelinePanel ref={this._gatherTimelinePanelRef}
timelineSet={this.state.room.getUnfilteredTimelineSet()} timelineSet={this.state.room.getUnfilteredTimelineSet()}
manageReadReceipts={!UserSettingsStore.getSyncedSetting('hideReadReceipts', false)} showReadReceipts={!UserSettingsStore.getSyncedSetting('hideReadReceipts', false)}
manageReadReceipts={true}
manageReadMarkers={true} manageReadMarkers={true}
hidden={hideMessagePanel} hidden={hideMessagePanel}
highlightedEventId={highlightedEventId} highlightedEventId={highlightedEventId}

View file

@ -59,6 +59,7 @@ var TimelinePanel = React.createClass({
// that room. // that room.
timelineSet: React.PropTypes.object.isRequired, timelineSet: React.PropTypes.object.isRequired,
showReadReceipts: React.PropTypes.bool,
// Enable managing RRs and RMs. These require the timelineSet to have a room. // Enable managing RRs and RMs. These require the timelineSet to have a room.
manageReadReceipts: React.PropTypes.bool, manageReadReceipts: React.PropTypes.bool,
manageReadMarkers: React.PropTypes.bool, manageReadMarkers: React.PropTypes.bool,
@ -197,6 +198,7 @@ var TimelinePanel = React.createClass({
MatrixClientPeg.get().on("Room.receipt", this.onRoomReceipt); MatrixClientPeg.get().on("Room.receipt", this.onRoomReceipt);
MatrixClientPeg.get().on("Room.localEchoUpdated", this.onLocalEchoUpdated); MatrixClientPeg.get().on("Room.localEchoUpdated", this.onLocalEchoUpdated);
MatrixClientPeg.get().on("Room.accountData", this.onAccountData); MatrixClientPeg.get().on("Room.accountData", this.onAccountData);
MatrixClientPeg.get().on("Event.decrypted", this.onEventDecrypted);
MatrixClientPeg.get().on("sync", this.onSync); MatrixClientPeg.get().on("sync", this.onSync);
this._initTimeline(this.props); this._initTimeline(this.props);
@ -266,6 +268,7 @@ var TimelinePanel = React.createClass({
client.removeListener("Room.receipt", this.onRoomReceipt); client.removeListener("Room.receipt", this.onRoomReceipt);
client.removeListener("Room.localEchoUpdated", this.onLocalEchoUpdated); client.removeListener("Room.localEchoUpdated", this.onLocalEchoUpdated);
client.removeListener("Room.accountData", this.onAccountData); client.removeListener("Room.accountData", this.onAccountData);
client.removeListener("Event.decrypted", this.onEventDecrypted);
client.removeListener("sync", this.onSync); client.removeListener("sync", this.onSync);
} }
}, },
@ -341,9 +344,16 @@ var TimelinePanel = React.createClass({
newState[canPaginateOtherWayKey] = true; newState[canPaginateOtherWayKey] = true;
} }
this.setState(newState); // Don't resolve until the setState has completed: we need to let
// the component update before we consider the pagination completed,
return r; // otherwise we'll end up paginating in all the history the js-sdk
// has in memory because we never gave the component a chance to scroll
// itself into the right place
return new Promise((resolve) => {
this.setState(newState, () => {
resolve(r);
});
});
}); });
}, },
@ -503,6 +513,18 @@ var TimelinePanel = React.createClass({
}, this.props.onReadMarkerUpdated); }, this.props.onReadMarkerUpdated);
}, },
onEventDecrypted: function(ev) {
// Need to update as we don't display event tiles for events that
// haven't yet been decrypted. The event will have just been updated
// in place so we just need to re-render.
// TODO: We should restrict this to only events in our timeline,
// but possibly the event tile itself should just update when this
// happens to save us re-rendering the whole timeline.
if (ev.getRoomId() === this.props.timelineSet.room.roomId) {
this.forceUpdate();
}
},
onSync: function(state, prevState, data) { onSync: function(state, prevState, data) {
this.setState({clientSyncState: state}); this.setState({clientSyncState: state});
}, },
@ -1126,8 +1148,8 @@ var TimelinePanel = React.createClass({
readMarkerEventId={ this.state.readMarkerEventId } readMarkerEventId={ this.state.readMarkerEventId }
readMarkerVisible={ this.state.readMarkerVisible } readMarkerVisible={ this.state.readMarkerVisible }
suppressFirstDateSeparator={ this.state.canBackPaginate } suppressFirstDateSeparator={ this.state.canBackPaginate }
showUrlPreview = { this.props.showUrlPreview } showUrlPreview={ this.props.showUrlPreview }
manageReadReceipts = { this.props.manageReadReceipts } showReadReceipts={ this.props.showReadReceipts }
ourUserId={ MatrixClientPeg.get().credentials.userId } ourUserId={ MatrixClientPeg.get().credentials.userId }
stickyBottom={ stickyBottom } stickyBottom={ stickyBottom }
onScroll={ this.onMessageListScroll } onScroll={ this.onMessageListScroll }

View file

@ -1,5 +1,6 @@
/* /*
Copyright 2015, 2016 OpenMarket Ltd Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -136,16 +137,15 @@ module.exports = React.createClass({
}); });
}, },
onHsUrlChanged: function(newHsUrl) { onServerConfigChange: function(config) {
this.setState({ const newState = {};
enteredHomeserverUrl: newHsUrl if (config.hsUrl !== undefined) {
}); newState.enteredHomeserverUrl = config.hsUrl;
}, }
if (config.isUrl !== undefined) {
onIsUrlChanged: function(newIsUrl) { newState.enteredIdentityServerUrl = config.isUrl;
this.setState({ }
enteredIdentityServerUrl: newIsUrl this.setState(newState);
});
}, },
showErrorDialog: function(body, title) { showErrorDialog: function(body, title) {
@ -170,7 +170,7 @@ module.exports = React.createClass({
else if (this.state.progress === "sent_email") { else if (this.state.progress === "sent_email") {
resetPasswordJsx = ( resetPasswordJsx = (
<div> <div>
{ _t('An email has been sent to') } {this.state.email}. { _t('Once you&#39;ve followed the link it contains, click below') }. { _t('An email has been sent to') } {this.state.email}. { _t("Once you've followed the link it contains, click below") }.
<br /> <br />
<input className="mx_Login_submit" type="button" onClick={this.onVerify} <input className="mx_Login_submit" type="button" onClick={this.onVerify}
value={ _t('I have verified my email address') } /> value={ _t('I have verified my email address') } />
@ -221,8 +221,7 @@ module.exports = React.createClass({
defaultIsUrl={this.props.defaultIsUrl} defaultIsUrl={this.props.defaultIsUrl}
customHsUrl={this.props.customHsUrl} customHsUrl={this.props.customHsUrl}
customIsUrl={this.props.customIsUrl} customIsUrl={this.props.customIsUrl}
onHsUrlChanged={this.onHsUrlChanged} onServerConfigChange={this.onServerConfigChange}
onIsUrlChanged={this.onIsUrlChanged}
delayTimeMs={0}/> delayTimeMs={0}/>
<div className="mx_Login_error"> <div className="mx_Login_error">
</div> </div>

View file

@ -72,8 +72,17 @@ export default React.createClass({
// Returns true if props.url is a scalar URL, typically https://scalar.vector.im/api // Returns true if props.url is a scalar URL, typically https://scalar.vector.im/api
isScalarUrl: function() { isScalarUrl: function() {
const scalarUrl = SdkConfig.get().integrations_rest_url; let scalarUrls = SdkConfig.get().integrations_widgets_urls;
return scalarUrl && this.props.url.startsWith(scalarUrl); if (!scalarUrls || scalarUrls.length == 0) {
scalarUrls = [SdkConfig.get().integrations_rest_url];
}
for (let i = 0; i < scalarUrls.length; i++) {
if (this.props.url.startsWith(scalarUrls[i])) {
return true;
}
}
return false;
}, },
isMixedContent: function() { isMixedContent: function() {

View file

@ -75,7 +75,7 @@ export default class ManageIntegsButton extends React.Component {
} }
render() { render() {
let integrationsButton; let integrationsButton = <div />;
let integrationsError; let integrationsError;
if (this.scalarClient !== null) { if (this.scalarClient !== null) {
if (this.state.showIntegrationsError && this.state.scalarError) { if (this.state.showIntegrationsError && this.state.scalarError) {

View file

@ -17,6 +17,7 @@ limitations under the License.
'use strict'; 'use strict';
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom';
import { _t, _tJsx } from '../../../languageHandler'; import { _t, _tJsx } from '../../../languageHandler';
var DIV_ID = 'mx_recaptcha'; var DIV_ID = 'mx_recaptcha';
@ -66,11 +67,10 @@ module.exports = React.createClass({
// * jumping straight to a hosted captcha page (but we don't support that yet) // * jumping straight to a hosted captcha page (but we don't support that yet)
// * embedding the captcha in an iframe (if that works) // * embedding the captcha in an iframe (if that works)
// * using a better captcha lib // * using a better captcha lib
warning.innerHTML = _tJsx( ReactDOM.render(_tJsx(
"Robot check is currently unavailable on desktop - please use a <a>web browser</a>", "Robot check is currently unavailable on desktop - please use a <a>web browser</a>",
/<a>(.*?)<\/a>/, /<a>(.*?)<\/a>/,
(sub) => { return "<a href='https://riot.im/app'>{ sub }</a>"; } (sub) => { return <a href='https://riot.im/app'>{ sub }</a>; }), warning);
);
this.refs.recaptchaContainer.appendChild(warning); this.refs.recaptchaContainer.appendChild(warning);
} }
else { else {

View file

@ -53,14 +53,14 @@ module.exports = React.createClass({
this.scalarClient = null; this.scalarClient = null;
if (SdkConfig.get().integrations_ui_url && SdkConfig.get().integrations_rest_url) { if (SdkConfig.get().integrations_ui_url && SdkConfig.get().integrations_rest_url) {
this.scalarClient = new ScalarAuthClient(); this.scalarClient = new ScalarAuthClient();
this.scalarClient.connect().done(() => { this.scalarClient.connect().then(() => {
this.forceUpdate(); this.forceUpdate();
// TODO -- Handle Scalar errors }).catch((e) => {
// }, console.log("Failed to connect to integrations server");
// (err) => { // TODO -- Handle Scalar errors
// this.setState({ // this.setState({
// scalar_error: err, // scalar_error: err,
// }); // });
}); });
} }

View file

@ -143,7 +143,6 @@ export default class Autocomplete extends React.Component {
return null; return null;
} }
this.setSelection(selectionOffset); this.setSelection(selectionOffset);
return selectionOffset === COMPOSER_SELECTED ? null : this.state.completionList[selectionOffset - 1];
} }
// called from MessageComposerInput // called from MessageComposerInput
@ -155,7 +154,6 @@ export default class Autocomplete extends React.Component {
return null; return null;
} }
this.setSelection(selectionOffset); this.setSelection(selectionOffset);
return selectionOffset === COMPOSER_SELECTED ? null : this.state.completionList[selectionOffset - 1];
} }
onEscape(e): boolean { onEscape(e): boolean {
@ -201,6 +199,9 @@ export default class Autocomplete extends React.Component {
setSelection(selectionOffset: number) { setSelection(selectionOffset: number) {
this.setState({selectionOffset, hide: false}); this.setState({selectionOffset, hide: false});
if (this.props.onSelectionChange) {
this.props.onSelectionChange(this.state.completionList[selectionOffset - 1]);
}
} }
componentDidUpdate() { componentDidUpdate() {

View file

@ -949,8 +949,7 @@ export default class MessageComposerInput extends React.Component {
}; };
moveAutocompleteSelection = (up) => { moveAutocompleteSelection = (up) => {
const completion = up ? this.autocomplete.onUpArrow() : this.autocomplete.onDownArrow(); up ? this.autocomplete.onUpArrow() : this.autocomplete.onDownArrow();
return this.setDisplayedCompletion(completion);
}; };
onEscape = async (e) => { onEscape = async (e) => {
@ -1133,6 +1132,7 @@ export default class MessageComposerInput extends React.Component {
<Autocomplete <Autocomplete
ref={(e) => this.autocomplete = e} ref={(e) => this.autocomplete = e}
onConfirm={this.setDisplayedCompletion} onConfirm={this.setDisplayedCompletion}
onSelectionChange={this.setDisplayedCompletion}
query={this.getAutocompleteQuery(content)} query={this.getAutocompleteQuery(content)}
selection={selection}/> selection={selection}/>
</div> </div>

View file

@ -123,7 +123,19 @@ module.exports = React.createClass({
} }
var newElement = ReactDOM.findDOMNode(this); var newElement = ReactDOM.findDOMNode(this);
var startTopOffset = oldTop - newElement.offsetParent.getBoundingClientRect().top; let startTopOffset;
if (!newElement.offsetParent) {
// this seems to happen sometimes for reasons I don't understand
// the docs for `offsetParent` say it may be null if `display` is
// `none`, but I can't see why that would happen.
console.warn(
`ReadReceiptMarker for ${this.props.member.userId} in ` +
`${this.props.member.roomId} has no offsetParent`,
);
startTopOffset = 0;
} else {
startTopOffset = oldTop - newElement.offsetParent.getBoundingClientRect().top;
}
var startStyles = []; var startStyles = [];
var enterTransitionOpts = []; var enterTransitionOpts = [];
@ -131,13 +143,12 @@ module.exports = React.createClass({
if (oldInfo && oldInfo.left) { if (oldInfo && oldInfo.left) {
// start at the old height and in the old h pos // start at the old height and in the old h pos
var leftOffset = oldInfo.left;
startStyles.push({ top: startTopOffset+"px", startStyles.push({ top: startTopOffset+"px",
left: oldInfo.left+"px" }); left: oldInfo.left+"px" });
var reorderTransitionOpts = { var reorderTransitionOpts = {
duration: 100, duration: 100,
easing: 'easeOut' easing: 'easeOut',
}; };
enterTransitionOpts.push(reorderTransitionOpts); enterTransitionOpts.push(reorderTransitionOpts);
@ -175,7 +186,7 @@ module.exports = React.createClass({
if (this.props.timestamp) { if (this.props.timestamp) {
title = _t( title = _t(
"Seen by %(userName)s at %(dateTime)s", "Seen by %(userName)s at %(dateTime)s",
{userName: this.props.member.userId, dateTime: DateUtils.formatDate(new Date(this.props.timestamp), this.props.showTwelveHour)} {userName: this.props.member.userId, dateTime: DateUtils.formatDate(new Date(this.props.timestamp), this.props.showTwelveHour)},
); );
} }

View file

@ -555,6 +555,7 @@ module.exports = React.createClass({
label={ _t('Invites') } label={ _t('Invites') }
editable={ false } editable={ false }
order="recent" order="recent"
isInvite={true}
selectedRoom={ self.props.selectedRoom } selectedRoom={ self.props.selectedRoom }
incomingCall={ self.state.incomingCall } incomingCall={ self.state.incomingCall }
collapsed={ self.props.collapsed } collapsed={ self.props.collapsed }

View file

@ -179,7 +179,7 @@
"Profile": "Profil", "Profile": "Profil",
"Refer a friend to Riot:": "Freunde zu Riot einladen:", "Refer a friend to Riot:": "Freunde zu Riot einladen:",
"rejected": "abgelehnt", "rejected": "abgelehnt",
"Once you&#39;ve followed the link it contains, click below": "Nachdem du dem darin enthaltenen Link gefolgt bist, klicke unten", "Once you've followed the link it contains, click below": "Nachdem du dem darin enthaltenen Link gefolgt bist, klicke unten",
"rejected the invitation.": "lehnte die Einladung ab.", "rejected the invitation.": "lehnte die Einladung ab.",
"Reject invitation": "Einladung ablehnen", "Reject invitation": "Einladung ablehnen",
"Remove Contact Information?": "Kontakt-Informationen entfernen?", "Remove Contact Information?": "Kontakt-Informationen entfernen?",

View file

@ -688,7 +688,7 @@
"No display name": "Χωρίς όνομα", "No display name": "Χωρίς όνομα",
"No users have specific privileges in this room": "Κανένας χρήστης δεν έχει συγκεκριμένα δικαιώματα σε αυτό το δωμάτιο", "No users have specific privileges in this room": "Κανένας χρήστης δεν έχει συγκεκριμένα δικαιώματα σε αυτό το δωμάτιο",
"Once encryption is enabled for a room it cannot be turned off again (for now)": "Μόλις ενεργοποιηθεί η κρυπτογράφηση για ένα δωμάτιο, δεν μπορεί να απενεργοποιηθεί ξανά (για τώρα)", "Once encryption is enabled for a room it cannot be turned off again (for now)": "Μόλις ενεργοποιηθεί η κρυπτογράφηση για ένα δωμάτιο, δεν μπορεί να απενεργοποιηθεί ξανά (για τώρα)",
"Once you&#39;ve followed the link it contains, click below": "Μόλις ακολουθήσετε τον σύνδεσμο που περιέχει, κάντε κλικ παρακάτω", "Once you've followed the link it contains, click below": "Μόλις ακολουθήσετε τον σύνδεσμο που περιέχει, κάντε κλικ παρακάτω",
"Only people who have been invited": "Μόνο άτομα που έχουν προσκληθεί", "Only people who have been invited": "Μόνο άτομα που έχουν προσκληθεί",
"Otherwise, <a>click here</a> to send a bug report.": "Διαφορετικά, κάντε <a>κλικ εδώ</a> για να αποστείλετε μια αναφορά σφάλματος.", "Otherwise, <a>click here</a> to send a bug report.": "Διαφορετικά, κάντε <a>κλικ εδώ</a> για να αποστείλετε μια αναφορά σφάλματος.",
"%(senderName)s placed a %(callType)s call.": "Ο %(senderName)s πραγματοποίησε μια %(callType)s κλήση.", "%(senderName)s placed a %(callType)s call.": "Ο %(senderName)s πραγματοποίησε μια %(callType)s κλήση.",

View file

@ -440,7 +440,7 @@
"OK": "OK", "OK": "OK",
"olm version:": "olm version:", "olm version:": "olm version:",
"Once encryption is enabled for a room it cannot be turned off again (for now)": "Once encryption is enabled for a room it cannot be turned off again (for now)", "Once encryption is enabled for a room it cannot be turned off again (for now)": "Once encryption is enabled for a room it cannot be turned off again (for now)",
"Once you&#39;ve followed the link it contains, click below": "Once you&#39;ve followed the link it contains, click below", "Once you've followed the link it contains, click below": "Once you've followed the link it contains, click below",
"Only people who have been invited": "Only people who have been invited", "Only people who have been invited": "Only people who have been invited",
"Operation failed": "Operation failed", "Operation failed": "Operation failed",
"Otherwise, <a>click here</a> to send a bug report.": "Otherwise, <a>click here</a> to send a bug report.", "Otherwise, <a>click here</a> to send a bug report.": "Otherwise, <a>click here</a> to send a bug report.",
@ -969,5 +969,6 @@
"Hide avatars in user and room mentions": "Hide avatars in user and room mentions", "Hide avatars in user and room mentions": "Hide avatars in user and room mentions",
"%(widgetName)s widget added by %(senderName)s": "%(widgetName)s widget added by %(senderName)s", "%(widgetName)s widget added by %(senderName)s": "%(widgetName)s widget added by %(senderName)s",
"%(widgetName)s widget removed by %(senderName)s": "%(widgetName)s widget removed by %(senderName)s", "%(widgetName)s widget removed by %(senderName)s": "%(widgetName)s widget removed by %(senderName)s",
"%(widgetName)s widget modified by %(senderName)s": "%(widgetName)s widget modified by %(senderName)s",
"Robot check is currently unavailable on desktop - please use a <a>web browser</a>": "Robot check is currently unavailable on desktop - please use a <a>web browser</a>" "Robot check is currently unavailable on desktop - please use a <a>web browser</a>": "Robot check is currently unavailable on desktop - please use a <a>web browser</a>"
} }

View file

@ -402,7 +402,7 @@
"OK": "OK", "OK": "OK",
"olm version:": "olm version:", "olm version:": "olm version:",
"Once encryption is enabled for a room it cannot be turned off again (for now)": "Once encryption is enabled for a room it cannot be turned off again (for now)", "Once encryption is enabled for a room it cannot be turned off again (for now)": "Once encryption is enabled for a room it cannot be turned off again (for now)",
"Once you&#39;ve followed the link it contains, click below": "Once you&#39;ve followed the link it contains, click below", "Once you've followed the link it contains, click below": "Once you've followed the link it contains, click below",
"Only people who have been invited": "Only people who have been invited", "Only people who have been invited": "Only people who have been invited",
"Operation failed": "Operation failed", "Operation failed": "Operation failed",
"Password": "Password", "Password": "Password",

View file

@ -658,7 +658,7 @@
"Hide join/leave messages (invites/kicks/bans unaffected)": "Ocultar mensajes de entrada/salida (no afecta invitaciones/kicks/bans)", "Hide join/leave messages (invites/kicks/bans unaffected)": "Ocultar mensajes de entrada/salida (no afecta invitaciones/kicks/bans)",
"Hide avatar and display name changes": "Ocultar cambios de avatar y nombre visible", "Hide avatar and display name changes": "Ocultar cambios de avatar y nombre visible",
"Matrix Apps": "Aplicaciones Matrix", "Matrix Apps": "Aplicaciones Matrix",
"Once you&#39;ve followed the link it contains, click below": "Cuando haya seguido el enlace que contiene, haga click debajo", "Once you've followed the link it contains, click below": "Cuando haya seguido el enlace que contiene, haga click debajo",
"Sets the room topic": "Configura el tema de la sala", "Sets the room topic": "Configura el tema de la sala",
"Show Apps": "Mostrar aplicaciones", "Show Apps": "Mostrar aplicaciones",
"To get started, please pick a username!": "Para empezar, ¡por favor elija un nombre de usuario!", "To get started, please pick a username!": "Para empezar, ¡por favor elija un nombre de usuario!",

View file

@ -495,7 +495,7 @@
"No users have specific privileges in this room": "Ez dago gela honetan baimen zehatzik duen erabiltzailerik", "No users have specific privileges in this room": "Ez dago gela honetan baimen zehatzik duen erabiltzailerik",
"olm version:": "olm bertsioa:", "olm version:": "olm bertsioa:",
"Once encryption is enabled for a room it cannot be turned off again (for now)": "Behin gela batean zifratzea gaituta ezin da gero desgaitu (oraingoz)", "Once encryption is enabled for a room it cannot be turned off again (for now)": "Behin gela batean zifratzea gaituta ezin da gero desgaitu (oraingoz)",
"Once you&#39;ve followed the link it contains, click below": "Behin dakarren esteka jarraitu duzula, egin klik azpian", "Once you've followed the link it contains, click below": "Behin dakarren esteka jarraitu duzula, egin klik azpian",
"Otherwise, <a>click here</a> to send a bug report.": "Bestela, <a>bidali arazte-txosten bat</a>.", "Otherwise, <a>click here</a> to send a bug report.": "Bestela, <a>bidali arazte-txosten bat</a>.",
"Server may be unavailable, overloaded, or you hit a bug.": "Agian zerbitzaria ez dago eskuragarri, edo gainezka dago, edo akats bat aurkitu duzu.", "Server may be unavailable, overloaded, or you hit a bug.": "Agian zerbitzaria ez dago eskuragarri, edo gainezka dago, edo akats bat aurkitu duzu.",
"Changing password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "Oraingoz pasahitza aldatzeak gailu guztietako muturretik muturrerako zifratze-gakoak berrezarriko ditu, eta ezin izango dituzu zifratutako txatetako historialak irakurri ez badituzu aurretik zure gelako gakoak esportatzen eta aldaketa eta gero berriro inportatzen. Etorkizunean hau hobetuko da.", "Changing password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "Oraingoz pasahitza aldatzeak gailu guztietako muturretik muturrerako zifratze-gakoak berrezarriko ditu, eta ezin izango dituzu zifratutako txatetako historialak irakurri ez badituzu aurretik zure gelako gakoak esportatzen eta aldaketa eta gero berriro inportatzen. Etorkizunean hau hobetuko da.",

View file

@ -1 +1 @@
{} {}

View file

@ -393,7 +393,7 @@
"Mute": "Couper le son", "Mute": "Couper le son",
"No users have specific privileges in this room": "Aucun utilisateur na de privilège spécifique dans ce salon", "No users have specific privileges in this room": "Aucun utilisateur na de privilège spécifique dans ce salon",
"olm version:": "version de olm :", "olm version:": "version de olm :",
"Once you&#39;ve followed the link it contains, click below": "Une fois que vous aurez suivi le lien quil contient, cliquez ci-dessous", "Once you've followed the link it contains, click below": "Une fois que vous aurez suivi le lien quil contient, cliquez ci-dessous",
"%(senderName)s placed a %(callType)s call.": "%(senderName)s a placé un appel %(callType)s.", "%(senderName)s placed a %(callType)s call.": "%(senderName)s a placé un appel %(callType)s.",
"Please check your email and click on the link it contains. Once this is done, click continue.": "Veuillez vérifier vos e-mails et cliquer sur le lien que vous avez reçu. Puis cliquez sur continuer.", "Please check your email and click on the link it contains. Once this is done, click continue.": "Veuillez vérifier vos e-mails et cliquer sur le lien que vous avez reçu. Puis cliquez sur continuer.",
"Power level must be positive integer.": "Le niveau d'autorité doit être un entier positif.", "Power level must be positive integer.": "Le niveau d'autorité doit être un entier positif.",

View file

@ -443,7 +443,7 @@
"No users have specific privileges in this room": "Egy felhasználónak sincsenek specifikus jogosultságai ebben a szobában", "No users have specific privileges in this room": "Egy felhasználónak sincsenek specifikus jogosultságai ebben a szobában",
"olm version:": "olm verzió:", "olm version:": "olm verzió:",
"Once encryption is enabled for a room it cannot be turned off again (for now)": "Ha egyszer bekapcsolod a titkosítást a szobába utána nem lehet kikapcsolni (egyenlőre)", "Once encryption is enabled for a room it cannot be turned off again (for now)": "Ha egyszer bekapcsolod a titkosítást a szobába utána nem lehet kikapcsolni (egyenlőre)",
"Once you&#39;ve followed the link it contains, click below": "Miután a linket követted, kattints alulra", "Once you've followed the link it contains, click below": "Miután a linket követted, kattints alulra",
"Only people who have been invited": "Csak akiket meghívtak", "Only people who have been invited": "Csak akiket meghívtak",
"Otherwise, <a>click here</a> to send a bug report.": "Különben hiba jelentés küldéséhez <a>kattints ide</a>.", "Otherwise, <a>click here</a> to send a bug report.": "Különben hiba jelentés küldéséhez <a>kattints ide</a>.",
"Password": "Jelszó", "Password": "Jelszó",

View file

@ -452,7 +452,7 @@
"People": "사람들", "People": "사람들",
"Phone": "전화", "Phone": "전화",
"Once encryption is enabled for a room it cannot be turned off again (for now)": "방을 암호화하면 암호화를 도중에 끌 수 없어요. (현재로서는)", "Once encryption is enabled for a room it cannot be turned off again (for now)": "방을 암호화하면 암호화를 도중에 끌 수 없어요. (현재로서는)",
"Once you&#39;ve followed the link it contains, click below": "포함된 주소를 따라가서, 아래를 누르세요", "Once you've followed the link it contains, click below": "포함된 주소를 따라가서, 아래를 누르세요",
"Only people who have been invited": "초대받은 사람만", "Only people who have been invited": "초대받은 사람만",
"Otherwise, <a>click here</a> to send a bug report.": "그 밖에는, <a>여기를 눌러</a> 오류 보고서를 보내주세요.", "Otherwise, <a>click here</a> to send a bug report.": "그 밖에는, <a>여기를 눌러</a> 오류 보고서를 보내주세요.",
"%(senderName)s placed a %(callType)s call.": "%(senderName)s님이 %(callType)s 전화를 걸었어요.", "%(senderName)s placed a %(callType)s call.": "%(senderName)s님이 %(callType)s 전화를 걸었어요.",

View file

@ -427,7 +427,7 @@
"OK": "LABI", "OK": "LABI",
"olm version:": "olm versija:", "olm version:": "olm versija:",
"Once encryption is enabled for a room it cannot be turned off again (for now)": "Tiklīdz istabai tiks iespējota šifrēšana, tā vairs nebūs atslēdzama (pašlaik)", "Once encryption is enabled for a room it cannot be turned off again (for now)": "Tiklīdz istabai tiks iespējota šifrēšana, tā vairs nebūs atslēdzama (pašlaik)",
"Once you&#39;ve followed the link it contains, click below": "Tiklīdz sekoji saturā esošajai saitei, noklikšķini zemāk", "Once you've followed the link it contains, click below": "Tiklīdz sekoji saturā esošajai saitei, noklikšķini zemāk",
"Only people who have been invited": "Vienīgi personas, kuras ir tikušas uzaicinātas", "Only people who have been invited": "Vienīgi personas, kuras ir tikušas uzaicinātas",
"Operation failed": "Darbība neizdevās", "Operation failed": "Darbība neizdevās",
"Otherwise, <a>click here</a> to send a bug report.": "pretējā gadījumā, <a>klikšķini šeit</a>, lai nosūtītu paziņojumu par kļūdu.", "Otherwise, <a>click here</a> to send a bug report.": "pretējā gadījumā, <a>klikšķini šeit</a>, lai nosūtītu paziņojumu par kļūdu.",

View file

@ -1 +1 @@
{} {}

View file

@ -502,7 +502,7 @@
"New passwords don't match": "Nieuwe wachtwoorden komen niet overeen", "New passwords don't match": "Nieuwe wachtwoorden komen niet overeen",
"New passwords must match each other.": "Nieuwe wachtwoorden moeten overeenkomen.", "New passwords must match each other.": "Nieuwe wachtwoorden moeten overeenkomen.",
"Once encryption is enabled for a room it cannot be turned off again (for now)": "Zodra versleuteling in een kamer is ingeschakeld kan het niet meer worden uitgeschakeld (voor nu)", "Once encryption is enabled for a room it cannot be turned off again (for now)": "Zodra versleuteling in een kamer is ingeschakeld kan het niet meer worden uitgeschakeld (voor nu)",
"Once you&#39;ve followed the link it contains, click below": "Zodra je de link dat het bevat hebt gevolgd, klik hieronder", "Once you've followed the link it contains, click below": "Zodra je de link dat het bevat hebt gevolgd, klik hieronder",
"Only people who have been invited": "Alleen personen die zijn uitgenodigd", "Only people who have been invited": "Alleen personen die zijn uitgenodigd",
"Otherwise, <a>click here</a> to send a bug report.": "Klik anders <a>hier</a> om een foutmelding te versturen.", "Otherwise, <a>click here</a> to send a bug report.": "Klik anders <a>hier</a> om een foutmelding te versturen.",
"Please check your email and click on the link it contains. Once this is done, click continue.": "Bekijk je e-mail en klik op de link die het bevat. Zodra dit klaar is, klik op verder gaan.", "Please check your email and click on the link it contains. Once this is done, click continue.": "Bekijk je e-mail en klik op de link die het bevat. Zodra dit klaar is, klik op verder gaan.",

View file

@ -149,7 +149,7 @@
"No users have specific privileges in this room": "Nenhum/a usuário/a possui privilégios específicos nesta sala", "No users have specific privileges in this room": "Nenhum/a usuário/a possui privilégios específicos nesta sala",
"olm version: ": "Versão do olm: ", "olm version: ": "Versão do olm: ",
"Once encryption is enabled for a room it cannot be turned off again (for now)": "Assim que a criptografia é ativada para uma sala, ela não poderá ser desativada novamente (ainda)", "Once encryption is enabled for a room it cannot be turned off again (for now)": "Assim que a criptografia é ativada para uma sala, ela não poderá ser desativada novamente (ainda)",
"Once you&#39;ve followed the link it contains, click below": "Quando você tiver clicado no link que está no email, clique o botão abaixo", "Once you've followed the link it contains, click below": "Quando você tiver clicado no link que está no email, clique o botão abaixo",
"Only people who have been invited": "Apenas pessoas que tenham sido convidadas", "Only people who have been invited": "Apenas pessoas que tenham sido convidadas",
"or": "ou", "or": "ou",
"other": "outro", "other": "outro",

View file

@ -149,7 +149,7 @@
"No users have specific privileges in this room": "Nenhum/a usuário/a possui privilégios específicos nesta sala", "No users have specific privileges in this room": "Nenhum/a usuário/a possui privilégios específicos nesta sala",
"olm version: ": "Versão do olm: ", "olm version: ": "Versão do olm: ",
"Once encryption is enabled for a room it cannot be turned off again (for now)": "Assim que a criptografia é ativada para uma sala, ela não poderá ser desativada novamente (ainda)", "Once encryption is enabled for a room it cannot be turned off again (for now)": "Assim que a criptografia é ativada para uma sala, ela não poderá ser desativada novamente (ainda)",
"Once you&#39;ve followed the link it contains, click below": "Quando você tiver clicado no link que está no email, clique o botão abaixo", "Once you've followed the link it contains, click below": "Quando você tiver clicado no link que está no email, clique o botão abaixo",
"Only people who have been invited": "Apenas pessoas que tenham sido convidadas", "Only people who have been invited": "Apenas pessoas que tenham sido convidadas",
"or": "ou", "or": "ou",
"other": "outro", "other": "outro",

View file

@ -702,7 +702,7 @@
"Jump to first unread message.": "Перейти к первому непрочитанному сообщению.", "Jump to first unread message.": "Перейти к первому непрочитанному сообщению.",
"Message not sent due to unknown devices being present": "Сообщение не отправлено из-за присутствия неизвестных устройств", "Message not sent due to unknown devices being present": "Сообщение не отправлено из-за присутствия неизвестных устройств",
"Mobile phone number (optional)": "Номер мобильного телефона (не обязательно)", "Mobile phone number (optional)": "Номер мобильного телефона (не обязательно)",
"Once you&#39;ve followed the link it contains, click below": "После перехода по ссылке, нажмите на кнопку ниже", "Once you've followed the link it contains, click below": "После перехода по ссылке, нажмите на кнопку ниже",
"Password:": "Пароль:", "Password:": "Пароль:",
"Privacy warning": "Предупреждение о конфиденциальности", "Privacy warning": "Предупреждение о конфиденциальности",
"Privileged Users": "Привилегированные пользователи", "Privileged Users": "Привилегированные пользователи",

View file

@ -427,7 +427,7 @@
"OK": "OK", "OK": "OK",
"olm version:": "olm-version:", "olm version:": "olm-version:",
"Once encryption is enabled for a room it cannot be turned off again (for now)": "När kryptering aktiveras i ett rum kan det inte deaktiveras (tills vidare)", "Once encryption is enabled for a room it cannot be turned off again (for now)": "När kryptering aktiveras i ett rum kan det inte deaktiveras (tills vidare)",
"Once you&#39;ve followed the link it contains, click below": "När du har följt länken i meddelandet, klicka här", "Once you've followed the link it contains, click below": "När du har följt länken i meddelandet, klicka här",
"Only people who have been invited": "Endast inbjudna", "Only people who have been invited": "Endast inbjudna",
"Operation failed": "Handlingen misslyckades", "Operation failed": "Handlingen misslyckades",
"Otherwise, <a>click here</a> to send a bug report.": "Annars kan du <a>klicka här</a> för att skicka en buggrapport.", "Otherwise, <a>click here</a> to send a bug report.": "Annars kan du <a>klicka här</a> för att skicka en buggrapport.",

View file

@ -251,7 +251,7 @@
"NOT verified": "ยังไม่ได้ยืนยัน", "NOT verified": "ยังไม่ได้ยืนยัน",
"No more results": "ไม่มีผลลัพธ์อื่น", "No more results": "ไม่มีผลลัพธ์อื่น",
"No results": "ไม่มีผลลัพธ์", "No results": "ไม่มีผลลัพธ์",
"Once you&#39;ve followed the link it contains, click below": "หลังจากคุณเปิดลิงก์ข้างในแล้ว คลิกข้างล่าง", "Once you've followed the link it contains, click below": "หลังจากคุณเปิดลิงก์ข้างในแล้ว คลิกข้างล่าง",
"Passwords can't be empty": "รหัสผ่านต้องไม่ว่าง", "Passwords can't be empty": "รหัสผ่านต้องไม่ว่าง",
"People": "บุคคล", "People": "บุคคล",
"Permissions": "สิทธิ์", "Permissions": "สิทธิ์",

View file

@ -424,7 +424,7 @@
"OK": "Tamam", "OK": "Tamam",
"olm version:": "olm versiyon:", "olm version:": "olm versiyon:",
"Once encryption is enabled for a room it cannot be turned off again (for now)": "Bu oda için şifreleme etkinleştirildikten sonra tekrar kapatılamaz (şimdilik)", "Once encryption is enabled for a room it cannot be turned off again (for now)": "Bu oda için şifreleme etkinleştirildikten sonra tekrar kapatılamaz (şimdilik)",
"Once you&#39;ve followed the link it contains, click below": "Bir kere &#39; içerdiği bağlantıyı takip ettikten sonra , aşağıya tıklayın", "Once you've followed the link it contains, click below": "Bir kere ' içerdiği bağlantıyı takip ettikten sonra , aşağıya tıklayın",
"Only people who have been invited": "Sadece davet edilmiş insanlar", "Only people who have been invited": "Sadece davet edilmiş insanlar",
"Operation failed": "Operasyon başarısız oldu", "Operation failed": "Operasyon başarısız oldu",
"Otherwise, <a>click here</a> to send a bug report.": "Aksi taktirde , bir hata raporu göndermek için <a> buraya tıklayın </a>.", "Otherwise, <a>click here</a> to send a bug report.": "Aksi taktirde , bir hata raporu göndermek için <a> buraya tıklayın </a>.",

View file

@ -556,7 +556,7 @@
"No users have specific privileges in this room": "此房間中沒有使用者有指定的權限", "No users have specific privileges in this room": "此房間中沒有使用者有指定的權限",
"olm version:": "olm 版本:", "olm version:": "olm 版本:",
"Once encryption is enabled for a room it cannot be turned off again (for now)": "這個房間只要啟用加密就不能再關掉了(從現在開始)", "Once encryption is enabled for a room it cannot be turned off again (for now)": "這個房間只要啟用加密就不能再關掉了(從現在開始)",
"Once you&#39;ve followed the link it contains, click below": "一旦您跟著它所包含的連結,點選下方", "Once you've followed the link it contains, click below": "一旦您跟著它所包含的連結,點選下方",
"Only people who have been invited": "僅有被邀請的夥伴", "Only people who have been invited": "僅有被邀請的夥伴",
"Otherwise, <a>click here</a> to send a bug report.": "否則,請<a>點選此處</a>來傳送錯誤報告。", "Otherwise, <a>click here</a> to send a bug report.": "否則,請<a>點選此處</a>來傳送錯誤報告。",
"Password": "密碼", "Password": "密碼",

View file

@ -231,35 +231,31 @@ export function getCurrentLanguage() {
} }
function getLangsJson() { function getLangsJson() {
const deferred = Promise.defer(); return new Promise((resolve, reject) => {
request(
request( { method: "GET", url: i18nFolder + 'languages.json' },
{ method: "GET", url: i18nFolder + 'languages.json' }, (err, response, body) => {
(err, response, body) => { if (err || response.status < 200 || response.status >= 300) {
if (err || response.status < 200 || response.status >= 300) { reject({err: err, response: response});
deferred.reject({err: err, response: response}); return;
return; }
resolve(JSON.parse(body));
} }
deferred.resolve(JSON.parse(body)); );
} });
);
return deferred.promise;
} }
function getLanguage(langPath) { function getLanguage(langPath) {
const deferred = Promise.defer(); return new Promise((resolve, reject) => {
request(
let response_return = {}; { method: "GET", url: langPath },
request( (err, response, body) => {
{ method: "GET", url: langPath }, if (err || response.status < 200 || response.status >= 300) {
(err, response, body) => { reject({err: err, response: response});
if (err || response.status < 200 || response.status >= 300) { return;
deferred.reject({err: err, response: response}); }
return; resolve(JSON.parse(body));
} }
);
deferred.resolve(JSON.parse(body)); });
}
);
return deferred.promise;
} }