diff --git a/.eslintignore.errorfiles b/.eslintignore.errorfiles index 02629ea169..7d998f8c4b 100644 --- a/.eslintignore.errorfiles +++ b/.eslintignore.errorfiles @@ -1,8 +1,6 @@ # autogenerated file: run scripts/generate-eslint-error-ignore-file to update. src/component-index.js -src/components/structures/BottomLeftMenu.js -src/components/structures/CreateRoom.js src/components/structures/RoomDirectory.js src/components/structures/RoomStatusBar.js src/components/structures/RoomView.js @@ -18,53 +16,38 @@ src/components/views/dialogs/UnknownDeviceDialog.js src/components/views/elements/AddressSelector.js src/components/views/elements/DirectorySearchBox.js src/components/views/elements/MemberEventListSummary.js -src/components/views/elements/TintableSvg.js src/components/views/elements/UserSelector.js src/components/views/globals/MatrixToolbar.js src/components/views/globals/NewVersionBar.js src/components/views/globals/UpdateCheckBar.js src/components/views/messages/MFileBody.js -src/components/views/messages/RoomAvatarEvent.js src/components/views/messages/TextualBody.js src/components/views/room_settings/ColorSettings.js src/components/views/rooms/Autocomplete.js src/components/views/rooms/AuxPanel.js -src/components/views/rooms/EntityTile.js src/components/views/rooms/LinkPreviewWidget.js src/components/views/rooms/MemberDeviceInfo.js src/components/views/rooms/MemberInfo.js src/components/views/rooms/MemberList.js -src/components/views/rooms/SlateMessageComposer.js -src/components/views/rooms/PinnedEventTile.js src/components/views/rooms/RoomList.js src/components/views/rooms/RoomPreviewBar.js -src/components/views/rooms/SearchableEntityList.js src/components/views/rooms/SearchBar.js src/components/views/rooms/SearchResultTile.js -src/components/views/rooms/TopUnreadMessagesBar.js -src/components/views/rooms/UserTile.js +src/components/views/rooms/SlateMessageComposer.js src/components/views/settings/ChangeAvatar.js src/components/views/settings/ChangePassword.js src/components/views/settings/DevicesPanel.js src/components/views/settings/Notifications.js -src/GroupAddressPicker.js src/HtmlUtils.js src/ImageUtils.js -src/linkify-matrix.js src/Markdown.js -src/MatrixClientPeg.js src/notifications/ContentRules.js src/notifications/PushRuleVectorState.js -src/notifications/VectorPushRulesDefinitions.js -src/Notifier.js src/PlatformPeg.js -src/Presence.js src/rageshake/rageshake.js src/rageshake/submit-rageshake.js src/ratelimitedfunc.js -src/Roles.js src/Rooms.js -src/UiEffects.js src/Unread.js src/utils/DecryptFile.js src/utils/DirectoryUtils.js @@ -72,16 +55,10 @@ src/utils/DMRoomMap.js src/utils/FormattingUtils.js src/utils/MultiInviter.js src/utils/Receipt.js -src/VectorConferenceHandler.js src/Velociraptor.js -src/WhoIsTyping.js -src/wrappers/withMatrixClient.js test/components/structures/MessagePanel-test.js -test/components/structures/ScrollPanel-test.js -test/components/structures/TimelinePanel-test.js test/components/views/dialogs/InteractiveAuthDialog-test.js test/components/views/rooms/MessageComposerInput-test.js -test/components/views/rooms/RoomSettings-test.js test/mock-clock.js test/notifications/ContentRules-test.js test/notifications/PushRuleVectorState-test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 01cd3be22f..de10ef48be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,39 @@ +Changes in [1.5.3](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v1.5.3) (2019-09-16) +=================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v1.5.3-rc.3...v1.5.3) + + * Release: Directory should use the alias or server information to join the + room + [\#3448](https://github.com/matrix-org/matrix-react-sdk/pull/3448) + +Changes in [1.5.3-rc.3](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v1.5.3-rc.3) (2019-09-13) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v1.5.3-rc.2...v1.5.3-rc.3) + + * js-sdk rc.1 for report API + +Changes in [1.5.3-rc.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v1.5.3-rc.2) (2019-09-13) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v1.5.3-rc.1...v1.5.3-rc.2) + + * Fix: stop propagation click handler for doesn't run + [\#3443](https://github.com/matrix-org/matrix-react-sdk/pull/3443) + * Add way to report the content of a message + [\#3442](https://github.com/matrix-org/matrix-react-sdk/pull/3442) + * Fix synapse deactivate button for release + [\#3436](https://github.com/matrix-org/matrix-react-sdk/pull/3436) + * Fix: clicking on a room directory item takes you to the room + [\#3440](https://github.com/matrix-org/matrix-react-sdk/pull/3440) + +Changes in [1.5.3-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v1.5.3-rc.1) (2019-09-12) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v1.5.2...v1.5.3-rc.1) + + * Fix: only hide clear filter button when blurred & no more search term + [\#3435](https://github.com/matrix-org/matrix-react-sdk/pull/3435) + * Dont wrap text in room directory buttons + [\#3434](https://github.com/matrix-org/matrix-react-sdk/pull/3434) + Changes in [1.5.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v1.5.2) (2019-09-12) =================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v1.5.2-rc.1...v1.5.2) diff --git a/package.json b/package.json index 32bf8f75b7..958b782ac3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "1.5.2", + "version": "1.5.3", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { @@ -84,8 +84,8 @@ "isomorphic-fetch": "^2.2.1", "linkifyjs": "^2.1.6", "lodash": "^4.17.14", - "lolex": "2.3.2", - "matrix-js-sdk": "2.3.1", + "lolex": "4.2", + "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", "optimist": "^0.6.1", "pako": "^1.0.5", "png-chunks-extract": "^1.0.0", @@ -97,7 +97,7 @@ "react-addons-css-transition-group": "15.6.2", "react-beautiful-dnd": "^4.0.1", "react-dom": "^16.9.0", - "react-gemini-scrollbar": "github:matrix-org/react-gemini-scrollbar#f644523", + "react-gemini-scrollbar": "github:matrix-org/react-gemini-scrollbar#9cf17f63b7c0b0ec5f31df27da0f82f7238dc594", "resize-observer-polyfill": "^1.5.0", "sanitize-html": "^1.18.4", "slate": "^0.41.2", @@ -150,6 +150,7 @@ "matrix-mock-request": "^1.2.3", "matrix-react-test-utils": "^0.2.2", "mocha": "^5.0.5", + "react-test-renderer": "^16.9.0", "require-json": "0.0.1", "rimraf": "^2.4.3", "sinon": "^5.0.7", diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js index 27c4f40669..bebb254afc 100644 --- a/src/MatrixClientPeg.js +++ b/src/MatrixClientPeg.js @@ -16,9 +16,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -'use strict'; - -import Matrix from 'matrix-js-sdk'; +import {MatrixClient, MemoryStore} from 'matrix-js-sdk'; import utils from 'matrix-js-sdk/lib/utils'; import EventTimeline from 'matrix-js-sdk/lib/models/event-timeline'; @@ -27,7 +25,6 @@ import sdk from './index'; import createMatrixClient from './utils/createMatrixClient'; import SettingsStore from './settings/SettingsStore'; import MatrixActionCreators from './actions/MatrixActionCreators'; -import {phasedRollOutExpiredForUser} from "./PhasedRollOut"; import Modal from './Modal'; import {verificationMethods} from 'matrix-js-sdk/lib/crypto'; import MatrixClientBackedSettingsHandler from "./settings/handlers/MatrixClientBackedSettingsHandler"; @@ -87,7 +84,7 @@ class MatrixClientPeg { MatrixActionCreators.stop(); } - /* + /** * If we've registered a user ID we set this to the ID of the * user we've just registered. If they then go & log in, we * can send them to the welcome user (obviously this doesn't @@ -99,7 +96,7 @@ class MatrixClientPeg { this._justRegisteredUserId = uid; } - /* + /** * Returns true if the current user has just been registered by this * client as determined by setJustRegisteredUserId() * @@ -112,7 +109,7 @@ class MatrixClientPeg { ); } - /** + /* * Replace this MatrixClientPeg's client with a client instance that has * homeserver / identity server URLs and active credentials */ @@ -131,7 +128,7 @@ class MatrixClientPeg { } catch (err) { if (dbType === 'indexeddb') { console.error('Error starting matrixclient store - falling back to memory store', err); - this.matrixClient.store = new Matrix.MemoryStore({ + this.matrixClient.store = new MemoryStore({ localStorage: global.localStorage, }); } else { @@ -195,7 +192,7 @@ class MatrixClientPeg { }; } - /** + /* * Return the server name of the user's homeserver * Throws an error if unable to deduce the homeserver name * (eg. if the user is not logged in) diff --git a/src/Notifier.js b/src/Notifier.js index 0b0a5f6990..cca0ea2b89 100644 --- a/src/Notifier.js +++ b/src/Notifier.js @@ -112,7 +112,7 @@ const Notifier = { console.warn(`${roomId} has custom notification sound event, but no url key`); return null; } - + if (!content.url.startsWith("mxc://")) { console.warn(`${roomId} has custom notification sound event, but url is not a mxc url`); return null; @@ -203,7 +203,8 @@ const Notifier = { // The permission request was dismissed or denied // TODO: Support alternative branding in messaging const description = result === 'denied' - ? _t('Riot does not have permission to send you notifications - please check your browser settings') + ? _t('Riot does not have permission to send you notifications - ' + + 'please check your browser settings') : _t('Riot was not given permission to send notifications - please try again'); const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog'); Modal.createTrackedDialog('Unable to enable Notifications', result, ErrorDialog, { diff --git a/src/Presence.js b/src/Presence.js index 8e00e95cdf..ca3db9b762 100644 --- a/src/Presence.js +++ b/src/Presence.js @@ -15,8 +15,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -const MatrixClientPeg = require("./MatrixClientPeg"); -const dis = require("./dispatcher"); +import MatrixClientPeg from "./MatrixClientPeg"; +import dis from "./dispatcher"; import Timer from './utils/Timer'; // Time in ms after that a user is considered as unavailable/away @@ -24,7 +24,6 @@ const UNAVAILABLE_TIME_MS = 3 * 60 * 1000; // 3 mins const PRESENCE_STATES = ["online", "offline", "unavailable"]; class Presence { - constructor() { this._activitySignal = null; this._unavailableTimer = null; @@ -43,7 +42,7 @@ class Presence { try { await this._unavailableTimer.finished(); this.setState("unavailable"); - } catch(e) { /* aborted, stop got called */ } + } catch (e) { /* aborted, stop got called */ } } } @@ -88,7 +87,7 @@ class Presence { if (PRESENCE_STATES.indexOf(newState) === -1) { throw new Error("Bad presence state: " + newState); } - const old_state = this.state; + const oldState = this.state; this.state = newState; if (MatrixClientPeg.get().isGuest()) { @@ -98,9 +97,9 @@ class Presence { try { await MatrixClientPeg.get().setPresence(this.state); console.log("Presence: %s", newState); - } catch(err) { + } catch (err) { console.error("Failed to set presence: %s", err); - this.state = old_state; + this.state = oldState; } } } diff --git a/src/Roles.js b/src/Roles.js index 438b6c1236..10c4ceaf1e 100644 --- a/src/Roles.js +++ b/src/Roles.js @@ -26,7 +26,7 @@ export function levelRoleMap(usersDefault) { } export function textualPowerLevel(level, usersDefault) { - const LEVEL_ROLE_MAP = this.levelRoleMap(usersDefault); + const LEVEL_ROLE_MAP = levelRoleMap(usersDefault); if (LEVEL_ROLE_MAP[level]) { return LEVEL_ROLE_MAP[level] + (level !== undefined ? ` (${level})` : ` (${usersDefault})`); } else { diff --git a/src/VectorConferenceHandler.js b/src/VectorConferenceHandler.js index e839d3f78b..37b3a7ddad 100644 --- a/src/VectorConferenceHandler.js +++ b/src/VectorConferenceHandler.js @@ -14,12 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -"use strict"; - import Promise from 'bluebird'; -const Matrix = require("matrix-js-sdk"); -const Room = Matrix.Room; -const CallHandler = require('./CallHandler'); +import {createNewMatrixCall, Room} from "matrix-js-sdk"; +import CallHandler from './CallHandler'; +import MatrixClientPeg from "./MatrixClientPeg"; // FIXME: this is Riot (Vector) specific code, but will be removed shortly when // we switch over to jitsi entirely for video conferencing. @@ -45,7 +43,7 @@ ConferenceCall.prototype.setup = function() { // return a call for *this* room to be placed. We also tack on // confUserId to speed up lookups (else we'd need to loop every room // looking for a 1:1 room with this conf user ID!) - const call = Matrix.createNewMatrixCall(self.client, room.roomId); + const call = createNewMatrixCall(self.client, room.roomId); call.confUserId = self.confUserId; call.groupRoomId = self.groupRoomId; return call; @@ -84,7 +82,7 @@ ConferenceCall.prototype._getConferenceUserRoom = function() { preset: "private_chat", invite: [this.confUserId], }).then(function(res) { - return new Room(res.room_id, null, client.getUserId()); + return new Room(res.room_id, null, MatrixClientPeg.get().getUserId()); }); }; diff --git a/src/WhoIsTyping.js b/src/WhoIsTyping.js index 78ca77ce5a..eb09685cbe 100644 --- a/src/WhoIsTyping.js +++ b/src/WhoIsTyping.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -const MatrixClientPeg = require("./MatrixClientPeg"); +import MatrixClientPeg from "./MatrixClientPeg"; import { _t } from './languageHandler'; module.exports = { @@ -33,6 +33,9 @@ module.exports = { /** * Given a Room object and, optionally, a list of userID strings * to exclude, return a list of user objects who are typing. + * @param {Room} room: room object to get users from. + * @param {string[]} exclude: list of user mxids to exclude. + * @returns {string[]} list of user objects who are typing. */ usersTyping: function(room, exclude) { const whoIsTyping = []; @@ -46,7 +49,7 @@ module.exports = { const userId = memberKeys[i]; if (room.currentState.members[userId].typing) { - if (exclude.indexOf(userId) == -1) { + if (exclude.indexOf(userId) === -1) { whoIsTyping.push(room.currentState.members[userId]); } } @@ -60,16 +63,19 @@ module.exports = { if (whoIsTyping.length > limit) { othersCount = whoIsTyping.length - limit + 1; } - if (whoIsTyping.length == 0) { + if (whoIsTyping.length === 0) { return ''; - } else if (whoIsTyping.length == 1) { + } else if (whoIsTyping.length === 1) { return _t('%(displayName)s is typing …', {displayName: whoIsTyping[0].name}); } const names = whoIsTyping.map(function(m) { return m.name; }); if (othersCount>=1) { - return _t('%(names)s and %(count)s others are typing …', {names: names.slice(0, limit - 1).join(', '), count: othersCount}); + return _t('%(names)s and %(count)s others are typing …', { + names: names.slice(0, limit - 1).join(', '), + count: othersCount, + }); } else { const lastPerson = names.pop(); return _t('%(names)s and %(lastPerson)s are typing …', {names: names.join(', '), lastPerson: lastPerson}); diff --git a/src/components/structures/ContextualMenu.js b/src/components/structures/ContextualMenu.js index 3ce52247d9..27a202785b 100644 --- a/src/components/structures/ContextualMenu.js +++ b/src/components/structures/ContextualMenu.js @@ -20,6 +20,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import PropTypes from 'prop-types'; import classNames from 'classnames'; +import {focusCapturedRef} from "../../utils/Accessibility"; // Shamelessly ripped off Modal.js. There's probably a better way // of doing reusable widgets like dialog boxes & menus where we go and @@ -83,6 +84,9 @@ export default class ContextualMenu extends React.Component { // We don't need to clean up when unmounting, so ignore if (!element) return; + // For screen readers to find the thing + focusCapturedRef(element); + this.setState({ contextMenuRect: element.getBoundingClientRect(), }); @@ -206,7 +210,7 @@ export default class ContextualMenu extends React.Component { // FIXME: If a menu uses getDefaultProps it clobbers the onFinished // property set here so you can't close the menu from a button click! return
-
+
{ chevron }
diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index d205326d0d..306ef03fb1 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -286,7 +286,10 @@ export default createReactClass({ // the first thing to do is to try the token params in the query-string // if the session isn't soft logged out (ie: is a clean session being logged in) if (!Lifecycle.isSoftLogout()) { - Lifecycle.attemptTokenLogin(this.props.realQueryParams).then((loggedIn) => { + Lifecycle.attemptTokenLogin( + this.props.realQueryParams, + this.props.defaultDeviceDisplayName, + ).then((loggedIn) => { if (loggedIn) { this.props.onTokenLoginCompleted(); diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js index f81c0c94c0..84f402e484 100644 --- a/src/components/structures/RoomDirectory.js +++ b/src/components/structures/RoomDirectory.js @@ -389,13 +389,7 @@ module.exports = createReactClass({ }, onJoinClick: function(ev, room) { - this.props.onFinished(); - MatrixClientPeg.get().joinRoom(room.room_id); - dis.dispatch({ - action: 'view_room', - room_id: room.room_id, - joining: true, - }); + this.showRoom(room, null, true); ev.stopPropagation(); }, diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 0ca1cb9996..faa6f2564a 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -42,8 +42,6 @@ import EditorStateTransfer from '../../utils/EditorStateTransfer'; const PAGINATE_SIZE = 20; const INITIAL_SIZE = 20; -const READ_MARKER_INVIEW_THRESHOLD_MS = 1 * 1000; -const READ_MARKER_OUTOFVIEW_THRESHOLD_MS = 30 * 1000; const READ_RECEIPT_INTERVAL_MS = 500; const DEBUG = false; @@ -191,6 +189,12 @@ const TimelinePanel = createReactClass({ // always show timestamps on event tiles? alwaysShowTimestamps: SettingsStore.getValue("alwaysShowTimestamps"), + + // how long to show the RM for when it's visible in the window + readMarkerInViewThresholdMs: SettingsStore.getValue("readMarkerInViewThresholdMs"), + + // how long to show the RM for when it's scrolled off-screen + readMarkerOutOfViewThresholdMs: SettingsStore.getValue("readMarkerOutOfViewThresholdMs"), }; }, @@ -593,8 +597,8 @@ const TimelinePanel = createReactClass({ _readMarkerTimeout(readMarkerPosition) { return readMarkerPosition === 0 ? - READ_MARKER_INVIEW_THRESHOLD_MS : - READ_MARKER_OUTOFVIEW_THRESHOLD_MS; + this.state.readMarkerInViewThresholdMs : + this.state.readMarkerOutOfViewThresholdMs; }, updateReadMarkerOnUserActivity: async function() { diff --git a/src/components/views/dialogs/AddressPickerDialog.js b/src/components/views/dialogs/AddressPickerDialog.js index 32c5cf6900..1eac07dbfd 100644 --- a/src/components/views/dialogs/AddressPickerDialog.js +++ b/src/components/views/dialogs/AddressPickerDialog.js @@ -80,7 +80,7 @@ module.exports = createReactClass({ let validAddressTypes = this.props.validAddressTypes; // Remove email from validAddressTypes if no IS is configured. It may be added at a later stage by the user if (!MatrixClientPeg.get().getIdentityServerUrl() && validAddressTypes.includes("email")) { - validAddressTypes = validAddressTypes.splice(validAddressTypes.indexOf("email"), 1); + validAddressTypes = validAddressTypes.filter(type => type !== "email"); } return { diff --git a/src/components/views/rooms/BasicMessageComposer.js b/src/components/views/rooms/BasicMessageComposer.js index eabb97a6f5..110df355fe 100644 --- a/src/components/views/rooms/BasicMessageComposer.js +++ b/src/components/views/rooms/BasicMessageComposer.js @@ -179,6 +179,7 @@ export default class BasicMessageEditor extends React.Component { const {partCreator} = model; const text = event.clipboardData.getData("text/plain"); if (text) { + this._modifiedFlag = true; const range = getRangeForSelection(this._editorRef, model, document.getSelection()); const parts = parsePlainTextMessage(text, partCreator); replaceRangeAndMoveCaret(range, parts); diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js index 93a3fdf75f..37f280761b 100644 --- a/src/components/views/rooms/MemberInfo.js +++ b/src/components/views/rooms/MemberInfo.js @@ -643,7 +643,11 @@ module.exports = createReactClass({ _calculateOpsPermissions: async function(member) { let canDeactivate = false; if (this.context.matrixClient) { - canDeactivate = await this.context.matrixClient.isSynapseAdministrator(); + try { + canDeactivate = await this.context.matrixClient.isSynapseAdministrator(); + } catch (e) { + console.error(e); + } } const defaultPerms = { diff --git a/src/components/views/settings/account/PhoneNumbers.js b/src/components/views/settings/account/PhoneNumbers.js index 8f91eb22cc..f814561c97 100644 --- a/src/components/views/settings/account/PhoneNumbers.js +++ b/src/components/views/settings/account/PhoneNumbers.js @@ -176,6 +176,7 @@ export default class PhoneNumbers extends React.Component { this.setState({continueDisabled: true}); const token = this.state.newPhoneNumberCode; + const address = this.state.verifyMsisdn; this.state.addTask.haveMsisdnToken(token).then(() => { this.setState({ addTask: null, @@ -188,7 +189,7 @@ export default class PhoneNumbers extends React.Component { }); const msisdns = [ ...this.props.msisdns, - { address: this.state.verifyMsisdn, medium: "msisdn" }, + { address, medium: "msisdn" }, ]; this.props.onMsisdnsChange(msisdns); }).catch((err) => { @@ -272,8 +273,8 @@ export default class PhoneNumbers extends React.Component { onChange={this._onChangeNewPhoneNumber} />
- {addVerifySection} + {addVerifySection}
); } diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js index 6507854e59..6528c86f19 100644 --- a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js @@ -69,7 +69,12 @@ export default class PreferencesUserSettingsTab extends React.Component { alwaysShowMenuBarSupported: false, minimizeToTray: true, minimizeToTraySupported: false, - autocompleteDelay: SettingsStore.getValueAt(SettingLevel.DEVICE, 'autocompleteDelay').toString(10), + autocompleteDelay: + SettingsStore.getValueAt(SettingLevel.DEVICE, 'autocompleteDelay').toString(10), + readMarkerInViewThresholdMs: + SettingsStore.getValueAt(SettingLevel.DEVICE, 'readMarkerInViewThresholdMs').toString(10), + readMarkerOutOfViewThresholdMs: + SettingsStore.getValueAt(SettingLevel.DEVICE, 'readMarkerOutOfViewThresholdMs').toString(10), }; } @@ -124,6 +129,16 @@ export default class PreferencesUserSettingsTab extends React.Component { SettingsStore.setValue("autocompleteDelay", null, SettingLevel.DEVICE, e.target.value); }; + _onReadMarkerInViewThresholdMs = (e) => { + this.setState({readMarkerInViewThresholdMs: e.target.value}); + SettingsStore.setValue("readMarkerInViewThresholdMs", null, SettingLevel.DEVICE, e.target.value); + }; + + _onReadMarkerOutOfViewThresholdMs = (e) => { + this.setState({readMarkerOutOfViewThresholdMs: e.target.value}); + SettingsStore.setValue("readMarkerOutOfViewThresholdMs", null, SettingLevel.DEVICE, e.target.value); + }; + _renderGroup(settingIds) { const SettingsFlag = sdk.getComponent("views.elements.SettingsFlag"); return settingIds.map(i => ); @@ -178,6 +193,18 @@ export default class PreferencesUserSettingsTab extends React.Component { type='number' value={this.state.autocompleteDelay} onChange={this._onAutocompleteDelayChange} /> + + ); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index e0b792c126..7ca31a0f94 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -637,6 +637,8 @@ "Timeline": "Timeline", "Room list": "Room list", "Autocomplete delay (ms)": "Autocomplete delay (ms)", + "Read Marker lifetime (ms)": "Read Marker lifetime (ms)", + "Read Marker off-screen lifetime (ms)": "Read Marker off-screen lifetime (ms)", "Unignore": "Unignore", "": "", "Import E2E room keys": "Import E2E room keys", diff --git a/src/linkify-matrix.js b/src/linkify-matrix.js index 50d50f219a..a9e894d582 100644 --- a/src/linkify-matrix.js +++ b/src/linkify-matrix.js @@ -44,7 +44,7 @@ function matrixLinkify(linkify) { const S_ROOMALIAS_COLON = new linkify.parser.State(); const S_ROOMALIAS_COLON_NUM = new linkify.parser.State(ROOMALIAS); - const roomname_tokens = [ + const roomnameTokens = [ TT.DOT, TT.PLUS, TT.NUM, @@ -58,8 +58,8 @@ function matrixLinkify(linkify) { TT.LOCALHOST, ]; - S_HASH.on(roomname_tokens, S_HASH_NAME); - S_HASH_NAME.on(roomname_tokens, S_HASH_NAME); + S_HASH.on(roomnameTokens, S_HASH_NAME); + S_HASH_NAME.on(roomnameTokens, S_HASH_NAME); S_HASH_NAME.on(TT.DOMAIN, S_HASH_NAME); S_HASH_NAME.on(TT.COLON, S_HASH_NAME_COLON); @@ -92,7 +92,7 @@ function matrixLinkify(linkify) { const S_USERID_COLON = new linkify.parser.State(); const S_USERID_COLON_NUM = new linkify.parser.State(USERID); - const username_tokens = [ + const usernameTokens = [ TT.DOT, TT.UNDERSCORE, TT.PLUS, @@ -100,12 +100,12 @@ function matrixLinkify(linkify) { TT.DOMAIN, TT.TLD, - // as in roomname_tokens + // as in roomnameTokens TT.LOCALHOST, ]; - S_AT.on(username_tokens, S_AT_NAME); - S_AT_NAME.on(username_tokens, S_AT_NAME); + S_AT.on(usernameTokens, S_AT_NAME); + S_AT_NAME.on(usernameTokens, S_AT_NAME); S_AT_NAME.on(TT.DOMAIN, S_AT_NAME); S_AT_NAME.on(TT.COLON, S_AT_NAME_COLON); @@ -138,7 +138,7 @@ function matrixLinkify(linkify) { const S_GROUPID_COLON = new linkify.parser.State(); const S_GROUPID_COLON_NUM = new linkify.parser.State(GROUPID); - const groupid_tokens = [ + const groupIdTokens = [ TT.DOT, TT.UNDERSCORE, TT.PLUS, @@ -146,12 +146,12 @@ function matrixLinkify(linkify) { TT.DOMAIN, TT.TLD, - // as in roomname_tokens + // as in roomnameTokens TT.LOCALHOST, ]; - S_PLUS.on(groupid_tokens, S_PLUS_NAME); - S_PLUS_NAME.on(groupid_tokens, S_PLUS_NAME); + S_PLUS.on(groupIdTokens, S_PLUS_NAME); + S_PLUS_NAME.on(groupIdTokens, S_PLUS_NAME); S_PLUS_NAME.on(TT.DOMAIN, S_PLUS_NAME); S_PLUS_NAME.on(TT.COLON, S_PLUS_NAME_COLON); @@ -179,14 +179,14 @@ const escapeRegExp = function(string) { // Recognise URLs from both our local vector and official vector as vector. // anyone else really should be using matrix.to. -matrixLinkify.VECTOR_URL_PATTERN = "^(?:https?:\/\/)?(?:" +matrixLinkify.VECTOR_URL_PATTERN = "^(?:https?://)?(?:" + escapeRegExp(window.location.host + window.location.pathname) + "|" + "(?:www\\.)?(?:riot|vector)\\.im/(?:app|beta|staging|develop)/" + ")(#.*)"; -matrixLinkify.MATRIXTO_URL_PATTERN = "^(?:https?:\/\/)?(?:www\\.)?matrix\\.to/#/(([#@!+]).*)"; +matrixLinkify.MATRIXTO_URL_PATTERN = "^(?:https?://)?(?:www\\.)?matrix\\.to/#/(([#@!+]).*)"; matrixLinkify.MATRIXTO_MD_LINK_PATTERN = - '\\[([^\\]]*)\\]\\((?:https?:\/\/)?(?:www\\.)?matrix\\.to/#/([#@!+][^\\)]*)\\)'; + '\\[([^\\]]*)\\]\\((?:https?://)?(?:www\\.)?matrix\\.to/#/([#@!+][^\\)]*)\\)'; matrixLinkify.MATRIXTO_BASE_URL= baseUrl; const matrixToEntityMap = { diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 7b049208aa..e0ff16c538 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -284,6 +284,14 @@ export const SETTINGS = { supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, default: 200, }, + "readMarkerInViewThresholdMs": { + supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, + default: 3000, + }, + "readMarkerOutOfViewThresholdMs": { + supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, + default: 30000, + }, "blacklistUnverifiedDevices": { // We specifically want to have room-device > device so that users may set a device default // with a per-room override. diff --git a/src/stores/RoomListStore.js b/src/stores/RoomListStore.js index 6d41532852..980753551a 100644 --- a/src/stores/RoomListStore.js +++ b/src/stores/RoomListStore.js @@ -327,7 +327,7 @@ class RoomListStore extends Store { } else if (tags.length === 0) { tags.push("im.vector.fake.recent"); } - } else { + } else if (myMembership) { // null-guard as null means it was peeked tags.push("im.vector.fake.archived"); } diff --git a/src/utils/WidgetUtils.js b/src/utils/WidgetUtils.js index 06b4eed55b..237db82365 100644 --- a/src/utils/WidgetUtils.js +++ b/src/utils/WidgetUtils.js @@ -100,11 +100,14 @@ export default class WidgetUtils { } const testUrl = url.parse(testUrlString); - let scalarUrls = SdkConfig.get().integrations_widgets_urls; if (!scalarUrls || scalarUrls.length === 0) { const defaultManager = IntegrationManagers.sharedInstance().getPrimaryManager(); - if (defaultManager) scalarUrls = [defaultManager.apiUrl]; + if (defaultManager) { + scalarUrls = [defaultManager.apiUrl]; + } else { + scalarUrls = []; + } } for (let i = 0; i < scalarUrls.length; i++) { diff --git a/test/components/views/elements/MemberEventListSummary-test.js b/test/components/views/elements/MemberEventListSummary-test.js index d1e112735d..09a4739f06 100644 --- a/test/components/views/elements/MemberEventListSummary-test.js +++ b/test/components/views/elements/MemberEventListSummary-test.js @@ -112,7 +112,7 @@ describe('MemberEventListSummary', function() { threshold: 3, }; - const renderer = ReactTestUtils.createRenderer(); + const renderer = testUtils.getRenderer(); renderer.render(); const result = renderer.getRenderOutput(); @@ -134,7 +134,7 @@ describe('MemberEventListSummary', function() { threshold: 3, }; - const renderer = ReactTestUtils.createRenderer(); + const renderer = testUtils.getRenderer(); renderer.render(); const result = renderer.getRenderOutput(); diff --git a/test/test-utils.js b/test/test-utils.js index f60cab3bc2..ff800132b9 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -9,6 +9,7 @@ import dis from '../src/dispatcher'; import jssdk from 'matrix-js-sdk'; import {makeType} from "../src/utils/TypeUtils"; import {ValidatedServerConfig} from "../src/utils/AutoDiscoveryUtils"; +import ShallowRenderer from 'react-test-renderer/shallow'; const MatrixEvent = jssdk.MatrixEvent; /** @@ -31,6 +32,10 @@ export function beforeEach(context) { console.log(new Array(1 + desc.length).join("=")); } +export function getRenderer() { + // Old: ReactTestUtils.createRenderer(); + return new ShallowRenderer(); +} /** * Stub out the MatrixClient, and configure the MatrixClientPeg object to diff --git a/yarn.lock b/yarn.lock index 77abb011a5..ac1adf1d20 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4930,10 +4930,10 @@ loglevel@1.6.1: resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa" integrity sha1-4PyVEztu8nbNyIh82vJKpvFW+Po= -lolex@2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.3.2.tgz#85f9450425103bf9e7a60668ea25dc43274ca807" - integrity sha512-A5pN2tkFj7H0dGIAM6MFvHKMJcPnjZsOMvR7ujCjfgW5TbV6H9vb1PgxLtHvjqNZTHsUolz+6/WEO0N1xNx2ng== +lolex@4.2: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-4.2.0.tgz#ddbd7f6213ca1ea5826901ab1222b65d714b3cd7" + integrity sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg== lolex@^2.4.2: version "2.7.5" @@ -5049,10 +5049,9 @@ mathml-tag-names@^2.0.1: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.1.tgz#6dff66c99d55ecf739ca53c492e626f1d12a33cc" integrity sha512-pWB896KPGSGkp1XtyzRBftpTzwSOL0Gfk0wLvxt4f2mgzjY19o0LxJ3U25vNWTzsh7da+KTbuXQoQ3lOJZ8WHw== -matrix-js-sdk@2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-2.3.1.tgz#c0ebe90d43611cf28422317ec0c04f5d41acb2ad" - integrity sha512-lf2pGHp0o4bDVrSZ5ReLAkMMiX9PngGMxNAtzztdDvQ20lfYZvhwif9PUbi3tt8kwXlfs7s34eWxz5Rg37mdGg== +"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": + version "2.3.2" + resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/55b4595bbf52cdbf91edd7d326f72aabd6709dac" dependencies: another-json "^0.2.0" babel-runtime "^6.26.0" @@ -6379,17 +6378,7 @@ react-beautiful-dnd@^4.0.1: redux-thunk "^2.2.0" reselect "^3.0.1" -react-dom@^16.4.2: - version "16.8.6" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f" - integrity sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - scheduler "^0.13.6" - -react-dom@^16.9.0: +react-dom@^16.4.2, react-dom@^16.9.0: version "16.9.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.9.0.tgz#5e65527a5e26f22ae3701131bcccaee9fb0d3962" integrity sha512-YFT2rxO9hM70ewk9jq0y6sQk8cL02xm4+IzYBz75CQGlClQQ1Bxq0nhHF6OtSbit+AIahujJgb/CPRibFkMNJQ== @@ -6399,9 +6388,9 @@ react-dom@^16.9.0: prop-types "^15.6.2" scheduler "^0.15.0" -"react-gemini-scrollbar@github:matrix-org/react-gemini-scrollbar#f644523": +"react-gemini-scrollbar@github:matrix-org/react-gemini-scrollbar#9cf17f63b7c0b0ec5f31df27da0f82f7238dc594": version "2.1.5" - resolved "https://codeload.github.com/matrix-org/react-gemini-scrollbar/tar.gz/f64452388011d37d8a4427ba769153c30700ab8c" + resolved "https://codeload.github.com/matrix-org/react-gemini-scrollbar/tar.gz/9cf17f63b7c0b0ec5f31df27da0f82f7238dc594" dependencies: gemini-scrollbar matrix-org/gemini-scrollbar#91e1e566 @@ -6415,6 +6404,11 @@ react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16" integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA== +react-is@^16.9.0: + version "16.9.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb" + integrity sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw== + react-lifecycles-compat@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" @@ -6442,6 +6436,16 @@ react-redux@^5.0.6: react-is "^16.6.0" react-lifecycles-compat "^3.0.0" +react-test-renderer@^16.9.0: + version "16.9.0" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.9.0.tgz#7ed657a374af47af88f66f33a3ef99c9610c8ae9" + integrity sha512-R62stB73qZyhrJo7wmCW9jgl/07ai+YzvouvCXIJLBkRlRqLx4j9RqcLEAfNfU3OxTGucqR2Whmn3/Aad6L3hQ== + dependencies: + object-assign "^4.1.1" + prop-types "^15.6.2" + react-is "^16.9.0" + scheduler "^0.15.0" + react-transition-group@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-1.2.1.tgz#e11f72b257f921b213229a774df46612346c7ca6" @@ -6453,17 +6457,7 @@ react-transition-group@^1.2.0: prop-types "^15.5.6" warning "^3.0.0" -react@^16.4.2: - version "16.8.6" - resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe" - integrity sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - scheduler "^0.13.6" - -react@^16.9.0: +react@^16.4.2, react@^16.9.0: version "16.9.0" resolved "https://registry.yarnpkg.com/react/-/react-16.9.0.tgz#40ba2f9af13bc1a38d75dbf2f4359a5185c4f7aa" integrity sha512-+7LQnFBwkiw+BobzOF6N//BdoNw0ouwmSJTEm9cglOOmsg/TMiFHZLe2sEoN5M7LgJTj9oHH0gxklfnQe66S1w== @@ -6916,14 +6910,6 @@ sax@^1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -scheduler@^0.13.6: - version "0.13.6" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.6.tgz#466a4ec332467b31a91b9bf74e5347072e4cd889" - integrity sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - scheduler@^0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.15.0.tgz#6bfcf80ff850b280fed4aeecc6513bc0b4f17f8e"