From ff0254d3463ffb6fc4263b05525011a8c42d8382 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Mon, 14 May 2018 17:36:57 +0100 Subject: [PATCH 01/37] Fix ContextualMenu imports for TagTile and code block copy button --- src/components/views/elements/TagTile.js | 2 +- src/components/views/messages/TextualBody.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/elements/TagTile.js b/src/components/views/elements/TagTile.js index c5fdea0a54..fb3ddee093 100644 --- a/src/components/views/elements/TagTile.js +++ b/src/components/views/elements/TagTile.js @@ -21,7 +21,7 @@ import { MatrixClient } from 'matrix-js-sdk'; import sdk from '../../../index'; import dis from '../../../dispatcher'; import { isOnlyCtrlOrCmdIgnoreShiftKeyEvent } from '../../../Keyboard'; -import ContextualMenu from '../../structures/ContextualMenu'; +import * as ContextualMenu from '../../structures/ContextualMenu'; import FlairStore from '../../../stores/FlairStore'; import GroupStore from '../../../stores/GroupStore'; diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js index a4a4b4ebe8..bc2a715d31 100644 --- a/src/components/views/messages/TextualBody.js +++ b/src/components/views/messages/TextualBody.js @@ -32,7 +32,7 @@ import SdkConfig from '../../../SdkConfig'; import dis from '../../../dispatcher'; import { _t } from '../../../languageHandler'; import MatrixClientPeg from '../../../MatrixClientPeg'; -import ContextualMenu from '../../structures/ContextualMenu'; +import * as ContextualMenu from '../../structures/ContextualMenu'; import SettingsStore from "../../../settings/SettingsStore"; import PushProcessor from 'matrix-js-sdk/lib/pushprocessor'; import ReplyThread from "../elements/ReplyThread"; From aaffe2a3e1fec8305e890eb9acda599eaabb184b Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Mon, 14 May 2018 18:23:14 +0100 Subject: [PATCH 02/37] Prepare changelog for v0.12.4-rc.4 --- CHANGELOG.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89f3741535..54664ac124 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,44 @@ +Changes in [0.12.4-rc.4](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.12.4-rc.4) (2018-05-14) +=============================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.12.4-rc.3...v0.12.4-rc.4) + + * Update from Weblate. + [\#1904](https://github.com/matrix-org/matrix-react-sdk/pull/1904) + * Correctly identify sticker picker widgets + [\#1894](https://github.com/matrix-org/matrix-react-sdk/pull/1894) + * Quick fix for sticker picker position + [\#1903](https://github.com/matrix-org/matrix-react-sdk/pull/1903) + * Remove redundant logging (currently shown on every render when no sti… + [\#1901](https://github.com/matrix-org/matrix-react-sdk/pull/1901) + * Fix stickers briefly being 2x the size + [\#1899](https://github.com/matrix-org/matrix-react-sdk/pull/1899) + * Send required properties when making requests to widgets over postMessage + [\#1891](https://github.com/matrix-org/matrix-react-sdk/pull/1891) + * Fix room widget second load infini spinner + [\#1897](https://github.com/matrix-org/matrix-react-sdk/pull/1897) + * Update widget state when account data changes + [\#1896](https://github.com/matrix-org/matrix-react-sdk/pull/1896) + * Remove margins when in a ReplyThread to stop them taking so much space + [\#1882](https://github.com/matrix-org/matrix-react-sdk/pull/1882) + * Add setting to enable widget screenshots (if widgets declare support) + [\#1892](https://github.com/matrix-org/matrix-react-sdk/pull/1892) + * T3chguy/replies html tag + [\#1889](https://github.com/matrix-org/matrix-react-sdk/pull/1889) + * Instant Sticker Picker + [\#1888](https://github.com/matrix-org/matrix-react-sdk/pull/1888) + * Update widget 'widgetData' key to 'data' to match spec. + [\#1887](https://github.com/matrix-org/matrix-react-sdk/pull/1887) + * Fix 'state_key' field name. + [\#1886](https://github.com/matrix-org/matrix-react-sdk/pull/1886) + * Improve appearance of short-lived app loading spinner + [\#1885](https://github.com/matrix-org/matrix-react-sdk/pull/1885) + * Take feature_sticker_messagse out of labs + [\#1883](https://github.com/matrix-org/matrix-react-sdk/pull/1883) + * Fix issue incorrect positioning with widget loading indicator + [\#1884](https://github.com/matrix-org/matrix-react-sdk/pull/1884) + * Users should always be able to edit their user/non-room widgets + [\#1879](https://github.com/matrix-org/matrix-react-sdk/pull/1879) + Changes in [0.12.4-rc.3](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.12.4-rc.3) (2018-05-11) =============================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.12.4-rc.2...v0.12.4-rc.3) From 7bfc50bf429dbe5c1046209306cc12e09b23a38c Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Mon, 14 May 2018 18:23:14 +0100 Subject: [PATCH 03/37] v0.12.4-rc.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1125dd3980..77ba18ba04 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "0.12.4-rc.3", + "version": "0.12.4-rc.4", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From 2956c049d62ab8f4416dd9de090f19db5787425c Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 15 May 2018 11:41:16 +0100 Subject: [PATCH 04/37] Wait for echo from server when adding user widgets As hopefully all explained in comments. Fixes https://github.com/vector-im/riot-web/issues/6727 --- src/ScalarMessaging.js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index a163bf7bbd..906dc6fb0f 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -286,6 +286,30 @@ function inviteUser(event, roomId, userId) { }); } +/** + * Returns a promise that resolves when a widget with the given + * ID has been added as a user widget (ie. the accountData event + * arrives) or rejects after a timeout + */ +function waitForUserWidget(widgetId) { + return new Promise((resolve, reject) => { + let timerId; + function onAccountData(ev) { + if (ev.getContent()[widgetId] !== undefined) { + MatrixClientPeg.get().removeListener('accountData', onAccountData); + clearTimeout(timerId); + resolve(); + } + } + timerId = setTimeout(() => { + console.log("Timed out waiting for widget ID " + widgetId + " to appear"); + MatrixClientPeg.get().removeListener('accountData', onAccountData); + reject(); + }, 10000); + MatrixClientPeg.get().on('accountData', onAccountData); + }); +} + function setWidget(event, roomId) { const widgetId = event.data.widget_id; const widgetType = event.data.type; @@ -355,7 +379,15 @@ function setWidget(event, roomId) { }; } + // This starts listening for when the echo comes back from the server + // since the widget won't appear added until this happens. If we don't + // wait for this, the action will complete but if the user is fast enough, + // the widget still won't actually be there. + // start listening now otherwise we could race + const widgetAddPromise = waitForUserWidget(widgetId); client.setAccountData('m.widgets', userWidgets).then(() => { + return widgetAddPromise; + }).then(() => { sendResponse(event, { success: true, }); @@ -373,6 +405,7 @@ function setWidget(event, roomId) { // TODO - Room widgets need to be moved to 'm.widget' state events // https://docs.google.com/document/d/1uPF7XWY_dXTKVKV7jZQ2KmsI19wn9-kFRgQ1tFQP7wQ/edit?usp=sharing client.sendStateEvent(roomId, "im.vector.modular.widgets", content, widgetId).done(() => { + // XXX: We should probably wait for the echo of the state event to come back from the server, sendResponse(event, { success: true, }); From 142ce4c2567ae1db25d2105c050ecb4b2eec5863 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 15 May 2018 11:50:24 +0100 Subject: [PATCH 05/37] better comment --- src/ScalarMessaging.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 906dc6fb0f..5b81e7e7bf 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -406,6 +406,7 @@ function setWidget(event, roomId) { // https://docs.google.com/document/d/1uPF7XWY_dXTKVKV7jZQ2KmsI19wn9-kFRgQ1tFQP7wQ/edit?usp=sharing client.sendStateEvent(roomId, "im.vector.modular.widgets", content, widgetId).done(() => { // XXX: We should probably wait for the echo of the state event to come back from the server, + // as we do with user widgets. sendResponse(event, { success: true, }); From f4d69e26e980e5aa58bfe3baa213d3b32d782171 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 15 May 2018 12:06:23 +0100 Subject: [PATCH 06/37] PR feedback --- src/ScalarMessaging.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 5b81e7e7bf..a229ecf693 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -293,18 +293,22 @@ function inviteUser(event, roomId, userId) { */ function waitForUserWidget(widgetId) { return new Promise((resolve, reject) => { + if (ev.getContent() && ev.getContent()[widgetId] !== undefined) { + resolve(); + return; + } + let timerId; function onAccountData(ev) { - if (ev.getContent()[widgetId] !== undefined) { + if (ev.getContent() && ev.getContent()[widgetId] !== undefined) { MatrixClientPeg.get().removeListener('accountData', onAccountData); clearTimeout(timerId); resolve(); } } timerId = setTimeout(() => { - console.log("Timed out waiting for widget ID " + widgetId + " to appear"); MatrixClientPeg.get().removeListener('accountData', onAccountData); - reject(); + reject(new Error("Timed out waiting for widget ID " + widgetId + " to appear")); }, 10000); MatrixClientPeg.get().on('accountData', onAccountData); }); @@ -383,10 +387,8 @@ function setWidget(event, roomId) { // since the widget won't appear added until this happens. If we don't // wait for this, the action will complete but if the user is fast enough, // the widget still won't actually be there. - // start listening now otherwise we could race - const widgetAddPromise = waitForUserWidget(widgetId); client.setAccountData('m.widgets', userWidgets).then(() => { - return widgetAddPromise; + return waitForUserWidget(widgetId); }).then(() => { sendResponse(event, { success: true, From 272ba5b004f33c444b2c63a419810c479b5cb5fc Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 15 May 2018 13:15:40 +0100 Subject: [PATCH 07/37] Implement opt-in analytics with cookie bar --- src/components/structures/LoggedInView.js | 5 +- src/components/structures/MatrixChat.js | 32 +++++++++- src/components/views/globals/CookieBar.js | 73 +++++++++++++++++++++++ src/i18n/strings/en_EN.json | 5 +- src/settings/Settings.js | 9 ++- 5 files changed, 118 insertions(+), 6 deletions(-) create mode 100644 src/components/views/globals/CookieBar.js diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index d9ac9de693..abb2eb92aa 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -266,6 +266,7 @@ const LoggedInView = React.createClass({ const GroupView = sdk.getComponent('structures.GroupView'); const MyGroups = sdk.getComponent('structures.MyGroups'); const MatrixToolbar = sdk.getComponent('globals.MatrixToolbar'); + const CookieBar = sdk.getComponent('globals.CookieBar'); const NewVersionBar = sdk.getComponent('globals.NewVersionBar'); const UpdateCheckBar = sdk.getComponent('globals.UpdateCheckBar'); const PasswordNagBar = sdk.getComponent('globals.PasswordNagBar'); @@ -353,7 +354,9 @@ const LoggedInView = React.createClass({ let topBar; const isGuest = this.props.matrixClient.isGuest(); - if (this.props.hasNewVersion) { + if (this.props.showCookieBar) { + topBar = ; + } else if (this.props.hasNewVersion) { topBar = ; diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 3005bc86ad..051b9ed10b 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -165,6 +165,8 @@ export default React.createClass({ newVersionReleaseNotes: null, checkingForUpdate: null, + showCookieBar: false, + // Parameters used in the registration dance with the IS register_client_secret: null, register_session_id: null, @@ -227,8 +229,6 @@ export default React.createClass({ componentWillMount: function() { SdkConfig.put(this.props.config); - if (!SettingsStore.getValue("analyticsOptOut")) Analytics.enable(); - // Used by _viewRoom before getting state from sync this.firstSyncComplete = false; this.firstSyncPromise = Promise.defer(); @@ -361,6 +361,16 @@ export default React.createClass({ // loadSession as there's logic there to ask the user if they want // to try logging out. }); + + if (SettingsStore.getValue("showCookieBar")) { + this.setState({ + showCookieBar: true, + }); + } + + if (SettingsStore.getValue("analyticsOptIn")) { + Analytics.enable(); + } }, componentWillUnmount: function() { @@ -673,6 +683,23 @@ export default React.createClass({ hideToSRUsers: false, }); break; + case 'accept_cookies': + SettingsStore.setValue("analyticsOptIn", null, SettingLevel.DEVICE, true); + SettingsStore.setValue("showCookieBar", null, SettingLevel.DEVICE, false); + + this.setState({ + showCookieBar: false, + }); + Analytics.enable(); + break; + case 'reject_cookies': + SettingsStore.setValue("analyticsOptIn", null, SettingLevel.DEVICE, false); + SettingsStore.setValue("showCookieBar", null, SettingLevel.DEVICE, false); + + this.setState({ + showCookieBar: false, + }); + break; } }, @@ -1621,6 +1648,7 @@ export default React.createClass({ onRegistered={this.onRegistered} currentRoomId={this.state.currentRoomId} teamToken={this._teamToken} + showCookieBar={this.state.showCookieBar} {...this.props} {...this.state} /> diff --git a/src/components/views/globals/CookieBar.js b/src/components/views/globals/CookieBar.js new file mode 100644 index 0000000000..f1fbbcc83a --- /dev/null +++ b/src/components/views/globals/CookieBar.js @@ -0,0 +1,73 @@ +/* +Copyright 2018 New Vector Ltd. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from 'react'; +import dis from '../../../dispatcher'; +import { _t } from '../../../languageHandler'; +import sdk from '../../../index'; + +const PrivacyLink = (sub) => + + { sub } + ; + +export default React.createClass({ + onAccept: function() { + dis.dispatch({ + action: 'accept_cookies', + }); + }, + + onReject: function() { + dis.dispatch({ + action: 'reject_cookies', + }); + }, + + render: function() { + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); + const toolbarClasses = "mx_MatrixToolbar"; + return ( +
+ Warning +
+ { _t( + "Help us improve Riot by sending usage data. " + + "This will use a cookie " + + "(see our cookie and " + + "privacy policies)", + {}, + { + // XXX: We need to link to the page that explains our cookies + 'CookieLink': PrivacyLink, + 'PrivacyLink': PrivacyLink, + }, + ) } +
+ + { _t("Send usage data") } + + + + +
+ ); + }, +}); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 9b932ef2b6..0126661a07 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -210,7 +210,8 @@ "Mirror local video feed": "Mirror local video feed", "Disable Community Filter Panel": "Disable Community Filter Panel", "Disable Peer-to-Peer for 1:1 calls": "Disable Peer-to-Peer for 1:1 calls", - "Opt out of analytics": "Opt out of analytics", + "Send analytics data": "Send analytics data", + "Show cookie bar": "Show cookie bar", "Never send encrypted messages to unverified devices from this device": "Never send encrypted messages to unverified devices from this device", "Never send encrypted messages to unverified devices in this room from this device": "Never send encrypted messages to unverified devices in this room from this device", "Enable inline URL previews by default": "Enable inline URL previews by default", @@ -637,6 +638,8 @@ "Something went wrong when trying to get your communities.": "Something went wrong when trying to get your communities.", "Display your community flair in rooms configured to show it.": "Display your community flair in rooms configured to show it.", "You're not currently a member of any communities.": "You're not currently a member of any communities.", + "Help us improve Riot by sending usage data. This will use a cookie (see our cookie and privacy policies)": "Help us improve Riot by sending usage data. This will use a cookie (see our cookie and privacy policies)", + "Send usage data": "Send usage data", "You are not receiving desktop notifications": "You are not receiving desktop notifications", "Enable them now": "Enable them now", "What's New": "What's New", diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 663318f990..8f50885c14 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -213,11 +213,16 @@ export const SETTINGS = { supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, default: "en", }, - "analyticsOptOut": { + "analyticsOptIn": { supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, - displayName: _td('Opt out of analytics'), + displayName: _td('Send analytics data'), default: false, }, + "showCookieBar": { + supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, + displayName: _td('Show cookie bar'), + default: true, + }, "autocompleteDelay": { supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, default: 200, From d0ec467c34d80b9954af28559a7f9e75f4694d73 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 15 May 2018 14:13:56 +0100 Subject: [PATCH 08/37] Oops, actually get account data event. Also ignore any account data events that aren;t widgets. --- src/ScalarMessaging.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index a229ecf693..796252fc1b 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -293,13 +293,20 @@ function inviteUser(event, roomId, userId) { */ function waitForUserWidget(widgetId) { return new Promise((resolve, reject) => { - if (ev.getContent() && ev.getContent()[widgetId] !== undefined) { + const currentAccountDataEvent = MatrixClientPeg.get().getAccountData('m.widgets'); + if ( + currentAccountDataEvent && + currentAccountDataEvent.getContent() && + currentAccountDataEvent.getContent()[widgetId] !== undefined + ) { resolve(); return; } let timerId; function onAccountData(ev) { + if (ev.getType() != 'm.widgets') return; + if (ev.getContent() && ev.getContent()[widgetId] !== undefined) { MatrixClientPeg.get().removeListener('accountData', onAccountData); clearTimeout(timerId); From e9336eab63daa5ad04cac28b50a3ff52bb7ab5cb Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 15 May 2018 14:18:02 +0100 Subject: [PATCH 09/37] lint --- src/ScalarMessaging.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 796252fc1b..5940565517 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -290,6 +290,9 @@ function inviteUser(event, roomId, userId) { * Returns a promise that resolves when a widget with the given * ID has been added as a user widget (ie. the accountData event * arrives) or rejects after a timeout + * + * @param {string} widgetId The ID of the widget to wait for + * @returns {Promise} that resolves when the widget is available */ function waitForUserWidget(widgetId) { return new Promise((resolve, reject) => { @@ -303,7 +306,6 @@ function waitForUserWidget(widgetId) { return; } - let timerId; function onAccountData(ev) { if (ev.getType() != 'm.widgets') return; @@ -313,7 +315,7 @@ function waitForUserWidget(widgetId) { resolve(); } } - timerId = setTimeout(() => { + const timerId = setTimeout(() => { MatrixClientPeg.get().removeListener('accountData', onAccountData); reject(new Error("Timed out waiting for widget ID " + widgetId + " to appear")); }, 10000); From 7bfe84f8beec1aecd3a6d465f7a0dfc378e3e7a5 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 15 May 2018 14:53:49 +0100 Subject: [PATCH 10/37] Catch errors adding widget --- src/ScalarMessaging.js | 2 ++ src/i18n/strings/en_EN.json | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 5940565517..bc5e6b7fe1 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -404,6 +404,8 @@ function setWidget(event, roomId) { }); dis.dispatch({ action: "user_widget_updated" }); + }).catch((e) => { + sendError(event, _t('Error adding widget')); }); } else { // Room widget if (!roomId) { diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 9b932ef2b6..e78a06cccd 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -103,6 +103,7 @@ "You need to be logged in.": "You need to be logged in.", "You need to be able to invite users to do that.": "You need to be able to invite users to do that.", "Unable to create widget.": "Unable to create widget.", + "Error adding widget": "Error adding widget", "Missing roomId.": "Missing roomId.", "Failed to send request.": "Failed to send request.", "This room is not recognised.": "This room is not recognised.", @@ -190,7 +191,6 @@ "Message Replies": "Message Replies", "Message Pinning": "Message Pinning", "Tag Panel": "Tag Panel", - "Sticker Messages": "Sticker Messages", "Disable Emoji suggestions while typing": "Disable Emoji suggestions while typing", "Use compact timeline layout": "Use compact timeline layout", "Hide removed messages": "Hide removed messages", @@ -566,8 +566,6 @@ "Download %(text)s": "Download %(text)s", "Invalid file%(extra)s": "Invalid file%(extra)s", "Error decrypting image": "Error decrypting image", - "This image cannot be displayed.": "This image cannot be displayed.", - "Image '%(Body)s' cannot be displayed.": "Image '%(Body)s' cannot be displayed.", "Error decrypting video": "Error decrypting video", "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s changed the avatar for %(roomName)s", "%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s removed the room avatar.", @@ -815,8 +813,8 @@ "Encryption key request": "Encryption key request", "Sign out": "Sign out", "Log out and remove encryption keys?": "Log out and remove encryption keys?", - "Send Logs": "Send Logs", "Clear Storage and Sign Out": "Clear Storage and Sign Out", + "Send Logs": "Send Logs", "Refresh": "Refresh", "Unable to restore session": "Unable to restore session", "We encountered an error trying to restore your previous session.": "We encountered an error trying to restore your previous session.", From 5b781043a5b61ec2307a89d212d79faa3750a46c Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 15 May 2018 15:02:24 +0100 Subject: [PATCH 11/37] just use the one if statement --- src/ScalarMessaging.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index bc5e6b7fe1..ba60af29d1 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -307,9 +307,7 @@ function waitForUserWidget(widgetId) { } function onAccountData(ev) { - if (ev.getType() != 'm.widgets') return; - - if (ev.getContent() && ev.getContent()[widgetId] !== undefined) { + if (ev.getType() === 'm.widgets' && ev.getContent() && ev.getContent()[widgetId] !== undefined) { MatrixClientPeg.get().removeListener('accountData', onAccountData); clearTimeout(timerId); resolve(); From 464e093f40b2fdeb2e2c3f374295a20de9d31071 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 15 May 2018 15:14:33 +0100 Subject: [PATCH 12/37] log exception --- src/ScalarMessaging.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index ba60af29d1..961f7a13d8 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -403,6 +403,7 @@ function setWidget(event, roomId) { dis.dispatch({ action: "user_widget_updated" }); }).catch((e) => { + console.log("Error adding widget", e); sendError(event, _t('Error adding widget')); }); } else { // Room widget From 9d5ba25131648ce0121fb15471241eecbbee9a30 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 15 May 2018 15:19:28 +0100 Subject: [PATCH 13/37] oh, sendError does support sending the error --- src/ScalarMessaging.js | 3 +-- src/i18n/strings/en_EN.json | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 961f7a13d8..0c10642cd7 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -403,8 +403,7 @@ function setWidget(event, roomId) { dis.dispatch({ action: "user_widget_updated" }); }).catch((e) => { - console.log("Error adding widget", e); - sendError(event, _t('Error adding widget')); + sendError(event, _t('Unable to create widget.'), e); }); } else { // Room widget if (!roomId) { diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index e78a06cccd..957deb35c5 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -103,7 +103,6 @@ "You need to be logged in.": "You need to be logged in.", "You need to be able to invite users to do that.": "You need to be able to invite users to do that.", "Unable to create widget.": "Unable to create widget.", - "Error adding widget": "Error adding widget", "Missing roomId.": "Missing roomId.", "Failed to send request.": "Failed to send request.", "This room is not recognised.": "This room is not recognised.", From 0c22343bb895f118df613896d63e4cfd61f08ef0 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 15 May 2018 15:38:47 +0100 Subject: [PATCH 14/37] Remove cookie bar setting from UserSettings --- src/i18n/strings/en_EN.json | 1 - src/settings/Settings.js | 1 - 2 files changed, 2 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 0126661a07..448f5e3a1c 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -211,7 +211,6 @@ "Disable Community Filter Panel": "Disable Community Filter Panel", "Disable Peer-to-Peer for 1:1 calls": "Disable Peer-to-Peer for 1:1 calls", "Send analytics data": "Send analytics data", - "Show cookie bar": "Show cookie bar", "Never send encrypted messages to unverified devices from this device": "Never send encrypted messages to unverified devices from this device", "Never send encrypted messages to unverified devices in this room from this device": "Never send encrypted messages to unverified devices in this room from this device", "Enable inline URL previews by default": "Enable inline URL previews by default", diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 8f50885c14..b1bc4161fd 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -220,7 +220,6 @@ export const SETTINGS = { }, "showCookieBar": { supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, - displayName: _td('Show cookie bar'), default: true, }, "autocompleteDelay": { From c191464e972f1298e81ebd46e253381e1eb2d6bd Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 15 May 2018 15:39:12 +0100 Subject: [PATCH 15/37] Fix UserSettings for new analyticsOptIn --- src/components/structures/UserSettings.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index 35a55284fd..c8ce79905d 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -86,9 +86,9 @@ const SIMPLE_SETTINGS = [ // These settings must be defined in SettingsStore const ANALYTICS_SETTINGS = [ { - id: 'analyticsOptOut', + id: 'analyticsOptIn', fn: function(checked) { - Analytics[checked ? 'disable' : 'enable'](); + checked ? Analytics.enable() : Analytics.disable(); }, }, ]; From b64e10a0951031a144b1521bd3c63e9a3b8faae7 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 15 May 2018 15:54:14 +0100 Subject: [PATCH 16/37] Prepare changelog for v0.12.4-rc.5 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54664ac124..36e256f10c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +Changes in [0.12.4-rc.5](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.12.4-rc.5) (2018-05-15) +=============================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.12.4-rc.4...v0.12.4-rc.5) + + * Wait for echo from server when adding user widgets + [\#1905](https://github.com/matrix-org/matrix-react-sdk/pull/1905) + Changes in [0.12.4-rc.4](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.12.4-rc.4) (2018-05-14) =============================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.12.4-rc.3...v0.12.4-rc.4) From db092c81d340176d08504012a7cb97ed19874beb Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 15 May 2018 15:54:15 +0100 Subject: [PATCH 17/37] v0.12.4-rc.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 77ba18ba04..96c7e94ad1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "0.12.4-rc.4", + "version": "0.12.4-rc.5", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From bb5ae741bca14dd42064790a6930b470ceed655d Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 15 May 2018 17:12:59 +0100 Subject: [PATCH 18/37] Wait for deletion of widgets as well addition We were previously waiting for them to appear which is silly if we were deleting them. --- src/ScalarMessaging.js | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 0c10642cd7..14d363894e 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -292,22 +292,30 @@ function inviteUser(event, roomId, userId) { * arrives) or rejects after a timeout * * @param {string} widgetId The ID of the widget to wait for + * @param {boolean} add True to wait for the widget to be added, + * false to wait for it to be deleted. * @returns {Promise} that resolves when the widget is available */ -function waitForUserWidget(widgetId) { +function waitForUserWidget(widgetId, add) { return new Promise((resolve, reject) => { const currentAccountDataEvent = MatrixClientPeg.get().getAccountData('m.widgets'); - if ( - currentAccountDataEvent && - currentAccountDataEvent.getContent() && - currentAccountDataEvent.getContent()[widgetId] !== undefined - ) { + + function satisfiesCondition(ev) { + if (!ev || !currentAccountDataEvent.getContent()) return false; + if (add) { + return ev.getContent()[widgetId] !== undefined; + } else { + return ev.getContent()[widgetId] === undefined; + } + } + + if (satisfiesCondition(currentAccountDataEvent)) { resolve(); return; } function onAccountData(ev) { - if (ev.getType() === 'm.widgets' && ev.getContent() && ev.getContent()[widgetId] !== undefined) { + if (satisfiesCondition(currentAccountDataEvent)) { MatrixClientPeg.get().removeListener('accountData', onAccountData); clearTimeout(timerId); resolve(); @@ -395,7 +403,7 @@ function setWidget(event, roomId) { // wait for this, the action will complete but if the user is fast enough, // the widget still won't actually be there. client.setAccountData('m.widgets', userWidgets).then(() => { - return waitForUserWidget(widgetId); + return waitForUserWidget(widgetId, widgetUrl !== null); }).then(() => { sendResponse(event, { success: true, From e4a221e42ded1641fdc1ef4f067fc17b3555f25a Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 15 May 2018 17:28:55 +0100 Subject: [PATCH 19/37] More helpful function name --- src/ScalarMessaging.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 14d363894e..01ee140eb3 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -300,7 +300,9 @@ function waitForUserWidget(widgetId, add) { return new Promise((resolve, reject) => { const currentAccountDataEvent = MatrixClientPeg.get().getAccountData('m.widgets'); - function satisfiesCondition(ev) { + // Tests an account data event, returning true if it's in the state + // we're waiting for it to be in + function eventInIntendedState(ev) { if (!ev || !currentAccountDataEvent.getContent()) return false; if (add) { return ev.getContent()[widgetId] !== undefined; From fadf264a1bb763c4ce65be873a8e9d0b204e07b5 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 15 May 2018 17:34:02 +0100 Subject: [PATCH 20/37] Rename uses of function too --- src/ScalarMessaging.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 01ee140eb3..9457e6ccfb 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -311,13 +311,13 @@ function waitForUserWidget(widgetId, add) { } } - if (satisfiesCondition(currentAccountDataEvent)) { + if (eventInIntendedState(currentAccountDataEvent)) { resolve(); return; } function onAccountData(ev) { - if (satisfiesCondition(currentAccountDataEvent)) { + if (eventInIntendedState(currentAccountDataEvent)) { MatrixClientPeg.get().removeListener('accountData', onAccountData); clearTimeout(timerId); resolve(); From 1a3777ad0c4b34c3c31d49222231841ed695578d Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 15 May 2018 18:03:40 +0100 Subject: [PATCH 21/37] Prepare changelog for v0.12.4-rc.6 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36e256f10c..225755207a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +Changes in [0.12.4-rc.6](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.12.4-rc.6) (2018-05-15) +=============================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.12.4-rc.5...v0.12.4-rc.6) + + * Wait for deletion of widgets as well addition + [\#1907](https://github.com/matrix-org/matrix-react-sdk/pull/1907) + Changes in [0.12.4-rc.5](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.12.4-rc.5) (2018-05-15) =============================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.12.4-rc.4...v0.12.4-rc.5) From a0b6bd183c35704908476105338990d7f6eabc91 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 15 May 2018 18:03:40 +0100 Subject: [PATCH 22/37] v0.12.4-rc.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 96c7e94ad1..671b0cf92c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "0.12.4-rc.5", + "version": "0.12.4-rc.6", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From e98b31958be34769f17c7309692b186ff82cbbe9 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 16 May 2018 10:41:18 +0100 Subject: [PATCH 23/37] Allow arbitrary hrefs for cookie/privacy links --- src/components/views/globals/CookieBar.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/views/globals/CookieBar.js b/src/components/views/globals/CookieBar.js index f1fbbcc83a..7625518252 100644 --- a/src/components/views/globals/CookieBar.js +++ b/src/components/views/globals/CookieBar.js @@ -19,11 +19,11 @@ import dis from '../../../dispatcher'; import { _t } from '../../../languageHandler'; import sdk from '../../../index'; -const PrivacyLink = (sub) => +const makeLink = (href) => (sub) => { sub } ; @@ -56,8 +56,8 @@ export default React.createClass({ {}, { // XXX: We need to link to the page that explains our cookies - 'CookieLink': PrivacyLink, - 'PrivacyLink': PrivacyLink, + 'CookieLink': makeLink("https://riot.im/privacy"), + 'PrivacyLink': makeLink("https://riot.im/privacy"), }, ) } From 7bd9863e6a2784916a3ede759256dff3332c62a5 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 16 May 2018 11:49:05 +0100 Subject: [PATCH 24/37] Prepare changelog for v0.12.4 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 225755207a..a20b902a6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +Changes in [0.12.4](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.12.4) (2018-05-16) +===================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.12.4-rc.6...v0.12.4) + + * No changes from rc.5 + Changes in [0.12.4-rc.6](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.12.4-rc.6) (2018-05-15) =============================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.12.4-rc.5...v0.12.4-rc.6) From bf0ec249b686ac89d4344fd654ffd9bc5cfbef62 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 16 May 2018 11:49:06 +0100 Subject: [PATCH 25/37] v0.12.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 671b0cf92c..60f65f4c39 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "0.12.4-rc.6", + "version": "0.12.4", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From ac1cd384e75c1b5c67507e519dca1f6e68592d5e Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 15 May 2018 13:15:40 +0100 Subject: [PATCH 26/37] Implement opt-in analytics with cookie bar --- src/components/structures/LoggedInView.js | 5 +- src/components/structures/MatrixChat.js | 32 +++++++++- src/components/views/globals/CookieBar.js | 73 +++++++++++++++++++++++ src/i18n/strings/en_EN.json | 5 +- src/settings/Settings.js | 9 ++- 5 files changed, 118 insertions(+), 6 deletions(-) create mode 100644 src/components/views/globals/CookieBar.js diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index d9ac9de693..abb2eb92aa 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -266,6 +266,7 @@ const LoggedInView = React.createClass({ const GroupView = sdk.getComponent('structures.GroupView'); const MyGroups = sdk.getComponent('structures.MyGroups'); const MatrixToolbar = sdk.getComponent('globals.MatrixToolbar'); + const CookieBar = sdk.getComponent('globals.CookieBar'); const NewVersionBar = sdk.getComponent('globals.NewVersionBar'); const UpdateCheckBar = sdk.getComponent('globals.UpdateCheckBar'); const PasswordNagBar = sdk.getComponent('globals.PasswordNagBar'); @@ -353,7 +354,9 @@ const LoggedInView = React.createClass({ let topBar; const isGuest = this.props.matrixClient.isGuest(); - if (this.props.hasNewVersion) { + if (this.props.showCookieBar) { + topBar = ; + } else if (this.props.hasNewVersion) { topBar = ; diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 3005bc86ad..051b9ed10b 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -165,6 +165,8 @@ export default React.createClass({ newVersionReleaseNotes: null, checkingForUpdate: null, + showCookieBar: false, + // Parameters used in the registration dance with the IS register_client_secret: null, register_session_id: null, @@ -227,8 +229,6 @@ export default React.createClass({ componentWillMount: function() { SdkConfig.put(this.props.config); - if (!SettingsStore.getValue("analyticsOptOut")) Analytics.enable(); - // Used by _viewRoom before getting state from sync this.firstSyncComplete = false; this.firstSyncPromise = Promise.defer(); @@ -361,6 +361,16 @@ export default React.createClass({ // loadSession as there's logic there to ask the user if they want // to try logging out. }); + + if (SettingsStore.getValue("showCookieBar")) { + this.setState({ + showCookieBar: true, + }); + } + + if (SettingsStore.getValue("analyticsOptIn")) { + Analytics.enable(); + } }, componentWillUnmount: function() { @@ -673,6 +683,23 @@ export default React.createClass({ hideToSRUsers: false, }); break; + case 'accept_cookies': + SettingsStore.setValue("analyticsOptIn", null, SettingLevel.DEVICE, true); + SettingsStore.setValue("showCookieBar", null, SettingLevel.DEVICE, false); + + this.setState({ + showCookieBar: false, + }); + Analytics.enable(); + break; + case 'reject_cookies': + SettingsStore.setValue("analyticsOptIn", null, SettingLevel.DEVICE, false); + SettingsStore.setValue("showCookieBar", null, SettingLevel.DEVICE, false); + + this.setState({ + showCookieBar: false, + }); + break; } }, @@ -1621,6 +1648,7 @@ export default React.createClass({ onRegistered={this.onRegistered} currentRoomId={this.state.currentRoomId} teamToken={this._teamToken} + showCookieBar={this.state.showCookieBar} {...this.props} {...this.state} /> diff --git a/src/components/views/globals/CookieBar.js b/src/components/views/globals/CookieBar.js new file mode 100644 index 0000000000..f1fbbcc83a --- /dev/null +++ b/src/components/views/globals/CookieBar.js @@ -0,0 +1,73 @@ +/* +Copyright 2018 New Vector Ltd. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from 'react'; +import dis from '../../../dispatcher'; +import { _t } from '../../../languageHandler'; +import sdk from '../../../index'; + +const PrivacyLink = (sub) => + + { sub } + ; + +export default React.createClass({ + onAccept: function() { + dis.dispatch({ + action: 'accept_cookies', + }); + }, + + onReject: function() { + dis.dispatch({ + action: 'reject_cookies', + }); + }, + + render: function() { + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); + const toolbarClasses = "mx_MatrixToolbar"; + return ( +
+ Warning +
+ { _t( + "Help us improve Riot by sending usage data. " + + "This will use a cookie " + + "(see our cookie and " + + "privacy policies)", + {}, + { + // XXX: We need to link to the page that explains our cookies + 'CookieLink': PrivacyLink, + 'PrivacyLink': PrivacyLink, + }, + ) } +
+ + { _t("Send usage data") } + + + + +
+ ); + }, +}); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 957deb35c5..8f7d1c36eb 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -209,7 +209,8 @@ "Mirror local video feed": "Mirror local video feed", "Disable Community Filter Panel": "Disable Community Filter Panel", "Disable Peer-to-Peer for 1:1 calls": "Disable Peer-to-Peer for 1:1 calls", - "Opt out of analytics": "Opt out of analytics", + "Send analytics data": "Send analytics data", + "Show cookie bar": "Show cookie bar", "Never send encrypted messages to unverified devices from this device": "Never send encrypted messages to unverified devices from this device", "Never send encrypted messages to unverified devices in this room from this device": "Never send encrypted messages to unverified devices in this room from this device", "Enable inline URL previews by default": "Enable inline URL previews by default", @@ -634,6 +635,8 @@ "Something went wrong when trying to get your communities.": "Something went wrong when trying to get your communities.", "Display your community flair in rooms configured to show it.": "Display your community flair in rooms configured to show it.", "You're not currently a member of any communities.": "You're not currently a member of any communities.", + "Help us improve Riot by sending usage data. This will use a cookie (see our cookie and privacy policies)": "Help us improve Riot by sending usage data. This will use a cookie (see our cookie and privacy policies)", + "Send usage data": "Send usage data", "You are not receiving desktop notifications": "You are not receiving desktop notifications", "Enable them now": "Enable them now", "What's New": "What's New", diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 663318f990..8f50885c14 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -213,11 +213,16 @@ export const SETTINGS = { supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, default: "en", }, - "analyticsOptOut": { + "analyticsOptIn": { supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, - displayName: _td('Opt out of analytics'), + displayName: _td('Send analytics data'), default: false, }, + "showCookieBar": { + supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, + displayName: _td('Show cookie bar'), + default: true, + }, "autocompleteDelay": { supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, default: 200, From aa4bbbc3db3b8b505f1fa78f4b718ad7662e6f10 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 15 May 2018 15:38:47 +0100 Subject: [PATCH 27/37] Remove cookie bar setting from UserSettings --- src/i18n/strings/en_EN.json | 1 - src/settings/Settings.js | 1 - 2 files changed, 2 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 8f7d1c36eb..70eccca6f1 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -210,7 +210,6 @@ "Disable Community Filter Panel": "Disable Community Filter Panel", "Disable Peer-to-Peer for 1:1 calls": "Disable Peer-to-Peer for 1:1 calls", "Send analytics data": "Send analytics data", - "Show cookie bar": "Show cookie bar", "Never send encrypted messages to unverified devices from this device": "Never send encrypted messages to unverified devices from this device", "Never send encrypted messages to unverified devices in this room from this device": "Never send encrypted messages to unverified devices in this room from this device", "Enable inline URL previews by default": "Enable inline URL previews by default", diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 8f50885c14..b1bc4161fd 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -220,7 +220,6 @@ export const SETTINGS = { }, "showCookieBar": { supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, - displayName: _td('Show cookie bar'), default: true, }, "autocompleteDelay": { From d01e7388393b70e76203964500dec98863056264 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 15 May 2018 15:39:12 +0100 Subject: [PATCH 28/37] Fix UserSettings for new analyticsOptIn --- src/components/structures/UserSettings.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index 35a55284fd..c8ce79905d 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -86,9 +86,9 @@ const SIMPLE_SETTINGS = [ // These settings must be defined in SettingsStore const ANALYTICS_SETTINGS = [ { - id: 'analyticsOptOut', + id: 'analyticsOptIn', fn: function(checked) { - Analytics[checked ? 'disable' : 'enable'](); + checked ? Analytics.enable() : Analytics.disable(); }, }, ]; From 4e6594d64b58dcd1bc9b0303e0fcef0a2348d057 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 16 May 2018 10:41:18 +0100 Subject: [PATCH 29/37] Allow arbitrary hrefs for cookie/privacy links --- src/components/views/globals/CookieBar.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/views/globals/CookieBar.js b/src/components/views/globals/CookieBar.js index f1fbbcc83a..7625518252 100644 --- a/src/components/views/globals/CookieBar.js +++ b/src/components/views/globals/CookieBar.js @@ -19,11 +19,11 @@ import dis from '../../../dispatcher'; import { _t } from '../../../languageHandler'; import sdk from '../../../index'; -const PrivacyLink = (sub) => +const makeLink = (href) => (sub) => { sub } ; @@ -56,8 +56,8 @@ export default React.createClass({ {}, { // XXX: We need to link to the page that explains our cookies - 'CookieLink': PrivacyLink, - 'PrivacyLink': PrivacyLink, + 'CookieLink': makeLink("https://riot.im/privacy"), + 'PrivacyLink': makeLink("https://riot.im/privacy"), }, ) } From d15051a635633f95a6e058e1c8c565448ae4fa32 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 16 May 2018 15:49:23 +0100 Subject: [PATCH 30/37] Add policyLink configuration to piwik Also: - Make CookieBar ES6 class - Alter phrasing on CookieBar - Conditionaly display longer "...(See our ++cookie and privacy policies++)." if policy link is configured. --- src/components/structures/LoggedInView.js | 3 +- src/components/views/globals/CookieBar.js | 55 ++++++++++++----------- src/i18n/strings/en_EN.json | 5 ++- 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index abb2eb92aa..c1d30391ab 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -355,7 +355,8 @@ const LoggedInView = React.createClass({ let topBar; const isGuest = this.props.matrixClient.isGuest(); if (this.props.showCookieBar) { - topBar = ; + const policyUrl = this.props.config.piwik ? (this.props.config.piwik.policyUrl || null) : null; + topBar = ; } else if (this.props.hasNewVersion) { topBar = (sub) => - - { sub } - ; +export default class CookieBar extends React.Component { + static propTypes = { + policyUrl: PropTypes.string, + } -export default React.createClass({ - onAccept: function() { + constructor() { + super(); + } + + onAccept() { dis.dispatch({ action: 'accept_cookies', }); - }, + } - onReject: function() { + onReject() { dis.dispatch({ action: 'reject_cookies', }); - }, + } - render: function() { + render() { const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const toolbarClasses = "mx_MatrixToolbar"; return (
Warning
- { _t( - "Help us improve Riot by sending usage data. " + - "This will use a cookie " + - "(see our cookie and " + - "privacy policies)", + { this.props.policyUrl ? _t( + "Help improve Riot by sending usage data? " + + "This will use a cookie. " + + "(See our cookie and privacy policies).", {}, { // XXX: We need to link to the page that explains our cookies - 'CookieLink': makeLink("https://riot.im/privacy"), - 'PrivacyLink': makeLink("https://riot.im/privacy"), + 'PolicyLink': (sub) => + { sub } + + , }, - ) } + ) : _t("Help improve Riot by sending usage data? This will use a cookie.") }
- { _t("Send usage data") } + { _t("Yes please") }
); - }, -}); + } +} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 70eccca6f1..239b45c32e 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -634,8 +634,9 @@ "Something went wrong when trying to get your communities.": "Something went wrong when trying to get your communities.", "Display your community flair in rooms configured to show it.": "Display your community flair in rooms configured to show it.", "You're not currently a member of any communities.": "You're not currently a member of any communities.", - "Help us improve Riot by sending usage data. This will use a cookie (see our cookie and privacy policies)": "Help us improve Riot by sending usage data. This will use a cookie (see our cookie and privacy policies)", - "Send usage data": "Send usage data", + "Help improve Riot by sending usage data? This will use a cookie. (See our cookie and privacy policies).": "Help improve Riot by sending usage data? This will use a cookie. (See our cookie and privacy policies).", + "Help improve Riot by sending usage data? This will use a cookie.": "Help improve Riot by sending usage data? This will use a cookie.", + "Yes please": "Yes please", "You are not receiving desktop notifications": "You are not receiving desktop notifications", "Enable them now": "Enable them now", "What's New": "What's New", From 0bda607bb2fb22eb622cb2d5db253f0a1dd6cbad Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 16 May 2018 15:53:43 +0100 Subject: [PATCH 31/37] Only show cookie bar if analytics configured --- src/components/structures/LoggedInView.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index c1d30391ab..2dd5a75c47 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -354,8 +354,10 @@ const LoggedInView = React.createClass({ let topBar; const isGuest = this.props.matrixClient.isGuest(); - if (this.props.showCookieBar) { - const policyUrl = this.props.config.piwik ? (this.props.config.piwik.policyUrl || null) : null; + if (this.props.showCookieBar && + this.props.config.piwik + ) { + const policyUrl = this.props.config.piwik.policyUrl || null; topBar = ; } else if (this.props.hasNewVersion) { topBar = Date: Wed, 16 May 2018 18:57:53 +0100 Subject: [PATCH 32/37] Specify valid address types to "Start a chat" dialog fixes https://github.com/vector-im/riot-web/issues/5459 --- src/RoomInvite.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/RoomInvite.js b/src/RoomInvite.js index 31541148d9..0bcc08eb06 100644 --- a/src/RoomInvite.js +++ b/src/RoomInvite.js @@ -57,6 +57,7 @@ export function showStartChatInviteDialog() { title: _t('Start a chat'), description: _t("Who would you like to communicate with?"), placeholder: _t("Email, name or matrix ID"), + validAddressTypes: ['mx-user-id', 'email'], button: _t("Start Chat"), onFinished: _onStartChatFinished, }); From e53497421e0d0a1974205821619676244ef28802 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 17 May 2018 16:47:17 +0100 Subject: [PATCH 33/37] Fix image size jumping regression Fixes https://github.com/vector-im/riot-web/issues/6654 --- src/components/views/messages/MImageBody.js | 3 ++- src/components/views/messages/MStickerBody.js | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/messages/MImageBody.js b/src/components/views/messages/MImageBody.js index 6cc492acf8..f59b3a9e2c 100644 --- a/src/components/views/messages/MImageBody.js +++ b/src/components/views/messages/MImageBody.js @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2018 New Vector Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -140,7 +141,6 @@ export default class extends React.Component { } onImageLoad() { - this.fixupHeight(); this.props.onWidgetLoad(); } @@ -208,6 +208,7 @@ export default class extends React.Component { }).done(); } this._afterComponentDidMount(); + this.fixupHeight(); } // To be overridden by subclasses (e.g. MStickerBody) for further diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js index 3a412fc2e2..aaad5ba75e 100644 --- a/src/components/views/messages/MStickerBody.js +++ b/src/components/views/messages/MStickerBody.js @@ -40,7 +40,6 @@ export default class MStickerBody extends MImageBody { } _onImageLoad() { - this.fixupHeight(); this.setState({ placeholderClasses: 'mx_MStickerBody_placeholder_invisible', }); From a7006307bf3631824cd484d3b51cec6d8124ed9c Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 17 May 2018 16:50:16 +0100 Subject: [PATCH 34/37] Call afterComponentDidMount() after componentDidMount --- src/components/views/messages/MImageBody.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/MImageBody.js b/src/components/views/messages/MImageBody.js index f59b3a9e2c..8045d43104 100644 --- a/src/components/views/messages/MImageBody.js +++ b/src/components/views/messages/MImageBody.js @@ -207,8 +207,8 @@ export default class extends React.Component { }); }).done(); } - this._afterComponentDidMount(); this.fixupHeight(); + this._afterComponentDidMount(); } // To be overridden by subclasses (e.g. MStickerBody) for further From 43dbf306b057f6415a3ab7bebcebdcbfd16e7ec0 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 17 May 2018 17:04:38 +0100 Subject: [PATCH 35/37] Prepare changelog for v0.12.5 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a20b902a6e..b161a9d908 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +Changes in [0.12.5](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.12.5) (2018-05-17) +===================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.12.4...v0.12.5) + + * Fix image size jumping regression + [\#1909](https://github.com/matrix-org/matrix-react-sdk/pull/1909) + Changes in [0.12.4](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.12.4) (2018-05-16) ===================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.12.4-rc.6...v0.12.4) From fa7f6c2c4cd1c938e4365bd2380264b1245cc44f Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 17 May 2018 17:04:39 +0100 Subject: [PATCH 36/37] v0.12.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 60f65f4c39..6c34979c43 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "0.12.4", + "version": "0.12.5", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From 4a9f4ba5eb889be78bba574ef8c3ea6269ef1775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Sch=C3=BCrmann?= Date: Thu, 17 May 2018 20:12:51 +0200 Subject: [PATCH 37/37] Fix vector-im/riot-web#6523 Emoji rendering destroys paragraphs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This regression was probably introduced in 4f4441fb07dcdfb831e4b54b9f8d7e611c172f29 and is caused by the fact that the variable `isHtml` conflates two different meanings: - The event contains an HTML message - The event message is displayed using HTML This is an important difference. Plain text messages that contain emojies are rendered with an HTML string and thus have to be sanitized etc. But they must not use the MarkDown CSS styles for HTML messages. The MarkDown CSS styles include `whitespace: normal` because HTML events use `
`-tags for line breaks. Plain text messages with emojies obviously don't use `
`-tags, so these styles must not be applied. Signed-off-by: Jonas Schürmann --- src/HtmlUtils.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js index 58572cf144..7ca404be31 100644 --- a/src/HtmlUtils.js +++ b/src/HtmlUtils.js @@ -413,12 +413,13 @@ class TextHighlighter extends BaseHighlighter { * opts.stripReplyFallback: optional argument specifying the event is a reply and so fallback needs removing */ export function bodyToHtml(content, highlights, opts={}) { - let isHtml = content.format === "org.matrix.custom.html" && content.formatted_body; + const isHtmlMessage = content.format === "org.matrix.custom.html" && content.formatted_body; let bodyHasEmoji = false; let strippedBody; let safeBody; + let isDisplayedWithHtml; // XXX: We sanitize the HTML whilst also highlighting its text nodes, to avoid accidentally trying // to highlight HTML tags themselves. However, this does mean that we don't highlight textnodes which // are interrupted by HTML tags (not that we did before) - e.g. foobar won't get highlighted @@ -439,17 +440,18 @@ export function bodyToHtml(content, highlights, opts={}) { if (opts.stripReplyFallback && formattedBody) formattedBody = ReplyThread.stripHTMLReply(formattedBody); strippedBody = opts.stripReplyFallback ? ReplyThread.stripPlainReply(content.body) : content.body; - bodyHasEmoji = containsEmoji(isHtml ? formattedBody : content.body); + bodyHasEmoji = containsEmoji(isHtmlMessage ? formattedBody : content.body); // Only generate safeBody if the message was sent as org.matrix.custom.html - if (isHtml) { + if (isHtmlMessage) { + isDisplayedWithHtml = true; safeBody = sanitizeHtml(formattedBody, sanitizeHtmlParams); } else { // ... or if there are emoji, which we insert as HTML alongside the // escaped plaintext body. if (bodyHasEmoji) { - isHtml = true; + isDisplayedWithHtml = true; safeBody = sanitizeHtml(escape(strippedBody), sanitizeHtmlParams); } } @@ -475,10 +477,10 @@ export function bodyToHtml(content, highlights, opts={}) { const className = classNames({ 'mx_EventTile_body': true, 'mx_EventTile_bigEmoji': emojiBody, - 'markdown-body': isHtml, + 'markdown-body': isHtmlMessage, }); - return isHtml ? + return isDisplayedWithHtml ? : { strippedBody }; }