From 272ba5b004f33c444b2c63a419810c479b5cb5fc Mon Sep 17 00:00:00 2001
From: Luke Barnard <luke@matrix.org>
Date: Tue, 15 May 2018 13:15:40 +0100
Subject: [PATCH 01/10] 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 = <CookieBar />;
+        } else if (this.props.hasNewVersion) {
             topBar = <NewVersionBar version={this.props.version} newVersion={this.props.newVersion}
                                     releaseNotes={this.props.newVersionReleaseNotes}
             />;
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) =>
+    <a
+        className="mx_MatrixToolbar_link"
+        target="_blank"
+        href="https://riot.im/privacy"
+    >
+        { sub }
+    </a>;
+
+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 (
+            <div className={toolbarClasses}>
+                <img className="mx_MatrixToolbar_warning" src="img/warning.svg" width="24" height="23" alt="Warning" />
+                <div className="mx_MatrixToolbar_content">
+                    { _t(
+                        "Help us improve Riot by sending usage data. " +
+                        "This will use a cookie " +
+                        "(see our <CookieLink>cookie</CookieLink> and " +
+                        "<PrivacyLink>privacy</PrivacyLink> policies)",
+                        {},
+                        {
+                            // XXX: We need to link to the page that explains our cookies
+                            'CookieLink': PrivacyLink,
+                            'PrivacyLink': PrivacyLink,
+                        },
+                    ) }
+                </div>
+                <AccessibleButton element='button' className="mx_MatrixToolbar_action" onClick={this.onAccept}>
+                    { _t("Send usage data") }
+                </AccessibleButton>
+                <AccessibleButton className="mx_MatrixToolbar_close" onClick={this.onReject}>
+                    <img src="img/cancel.svg" width="18" height="18" />
+                </AccessibleButton>
+            </div>
+        );
+    },
+});
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 <CookieLink>cookie</CookieLink> and <PrivacyLink>privacy</PrivacyLink> policies)": "Help us improve Riot by sending usage data. This will use a cookie (see our <CookieLink>cookie</CookieLink> and <PrivacyLink>privacy</PrivacyLink> 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 0c22343bb895f118df613896d63e4cfd61f08ef0 Mon Sep 17 00:00:00 2001
From: Luke Barnard <luke@matrix.org>
Date: Tue, 15 May 2018 15:38:47 +0100
Subject: [PATCH 02/10] 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 <luke@matrix.org>
Date: Tue, 15 May 2018 15:39:12 +0100
Subject: [PATCH 03/10] 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 e98b31958be34769f17c7309692b186ff82cbbe9 Mon Sep 17 00:00:00 2001
From: Luke Barnard <luke@matrix.org>
Date: Wed, 16 May 2018 10:41:18 +0100
Subject: [PATCH 04/10] 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) =>
     <a
         className="mx_MatrixToolbar_link"
         target="_blank"
-        href="https://riot.im/privacy"
+        href={href}
     >
         { sub }
     </a>;
@@ -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"),
                         },
                     ) }
                 </div>

From ac1cd384e75c1b5c67507e519dca1f6e68592d5e Mon Sep 17 00:00:00 2001
From: Luke Barnard <luke@matrix.org>
Date: Tue, 15 May 2018 13:15:40 +0100
Subject: [PATCH 05/10] 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 = <CookieBar />;
+        } else if (this.props.hasNewVersion) {
             topBar = <NewVersionBar version={this.props.version} newVersion={this.props.newVersion}
                                     releaseNotes={this.props.newVersionReleaseNotes}
             />;
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) =>
+    <a
+        className="mx_MatrixToolbar_link"
+        target="_blank"
+        href="https://riot.im/privacy"
+    >
+        { sub }
+    </a>;
+
+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 (
+            <div className={toolbarClasses}>
+                <img className="mx_MatrixToolbar_warning" src="img/warning.svg" width="24" height="23" alt="Warning" />
+                <div className="mx_MatrixToolbar_content">
+                    { _t(
+                        "Help us improve Riot by sending usage data. " +
+                        "This will use a cookie " +
+                        "(see our <CookieLink>cookie</CookieLink> and " +
+                        "<PrivacyLink>privacy</PrivacyLink> policies)",
+                        {},
+                        {
+                            // XXX: We need to link to the page that explains our cookies
+                            'CookieLink': PrivacyLink,
+                            'PrivacyLink': PrivacyLink,
+                        },
+                    ) }
+                </div>
+                <AccessibleButton element='button' className="mx_MatrixToolbar_action" onClick={this.onAccept}>
+                    { _t("Send usage data") }
+                </AccessibleButton>
+                <AccessibleButton className="mx_MatrixToolbar_close" onClick={this.onReject}>
+                    <img src="img/cancel.svg" width="18" height="18" />
+                </AccessibleButton>
+            </div>
+        );
+    },
+});
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 <CookieLink>cookie</CookieLink> and <PrivacyLink>privacy</PrivacyLink> policies)": "Help us improve Riot by sending usage data. This will use a cookie (see our <CookieLink>cookie</CookieLink> and <PrivacyLink>privacy</PrivacyLink> 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 <luke@matrix.org>
Date: Tue, 15 May 2018 15:38:47 +0100
Subject: [PATCH 06/10] 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 <luke@matrix.org>
Date: Tue, 15 May 2018 15:39:12 +0100
Subject: [PATCH 07/10] 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 <luke@matrix.org>
Date: Wed, 16 May 2018 10:41:18 +0100
Subject: [PATCH 08/10] 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) =>
     <a
         className="mx_MatrixToolbar_link"
         target="_blank"
-        href="https://riot.im/privacy"
+        href={href}
     >
         { sub }
     </a>;
@@ -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"),
                         },
                     ) }
                 </div>

From d15051a635633f95a6e058e1c8c565448ae4fa32 Mon Sep 17 00:00:00 2001
From: Luke Barnard <luke@matrix.org>
Date: Wed, 16 May 2018 15:49:23 +0100
Subject: [PATCH 09/10] 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 = <CookieBar />;
+            const policyUrl = this.props.config.piwik ? (this.props.config.piwik.policyUrl || null) : null;
+            topBar = <CookieBar policyUrl={policyUrl} />;
         } else if (this.props.hasNewVersion) {
             topBar = <NewVersionBar version={this.props.version} newVersion={this.props.newVersion}
                                     releaseNotes={this.props.newVersionReleaseNotes}
diff --git a/src/components/views/globals/CookieBar.js b/src/components/views/globals/CookieBar.js
index 7625518252..8fab64be67 100644
--- a/src/components/views/globals/CookieBar.js
+++ b/src/components/views/globals/CookieBar.js
@@ -15,59 +15,64 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import dis from '../../../dispatcher';
 import { _t } from '../../../languageHandler';
 import sdk from '../../../index';
 
-const makeLink = (href) => (sub) =>
-    <a
-        className="mx_MatrixToolbar_link"
-        target="_blank"
-        href={href}
-    >
-        { sub }
-    </a>;
+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 (
             <div className={toolbarClasses}>
                 <img className="mx_MatrixToolbar_warning" src="img/warning.svg" width="24" height="23" alt="Warning" />
                 <div className="mx_MatrixToolbar_content">
-                    { _t(
-                        "Help us improve Riot by sending usage data. " +
-                        "This will use a cookie " +
-                        "(see our <CookieLink>cookie</CookieLink> and " +
-                        "<PrivacyLink>privacy</PrivacyLink> policies)",
+                    { this.props.policyUrl ? _t(
+                        "Help improve Riot by sending usage data? " +
+                        "This will use a cookie. " +
+                        "(See our <PolicyLink>cookie and privacy policies</PolicyLink>).",
                         {},
                         {
                             // 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) => <a
+                                    className="mx_MatrixToolbar_link"
+                                    target="_blank"
+                                    href={this.props.policyUrl}
+                                >
+                                    { sub }
+                                </a>
+                            ,
                         },
-                    ) }
+                    ) : _t("Help improve Riot by sending usage data? This will use a cookie.") }
                 </div>
                 <AccessibleButton element='button' className="mx_MatrixToolbar_action" onClick={this.onAccept}>
-                    { _t("Send usage data") }
+                    { _t("Yes please") }
                 </AccessibleButton>
                 <AccessibleButton className="mx_MatrixToolbar_close" onClick={this.onReject}>
                     <img src="img/cancel.svg" width="18" height="18" />
                 </AccessibleButton>
             </div>
         );
-    },
-});
+    }
+}
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 <CookieLink>cookie</CookieLink> and <PrivacyLink>privacy</PrivacyLink> policies)": "Help us improve Riot by sending usage data. This will use a cookie (see our <CookieLink>cookie</CookieLink> and <PrivacyLink>privacy</PrivacyLink> policies)",
-    "Send usage data": "Send usage data",
+    "Help improve Riot by sending usage data? This will use a cookie. (See our <PolicyLink>cookie and privacy policies</PolicyLink>).": "Help improve Riot by sending usage data? This will use a cookie. (See our <PolicyLink>cookie and privacy policies</PolicyLink>).",
+    "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 <luke@matrix.org>
Date: Wed, 16 May 2018 15:53:43 +0100
Subject: [PATCH 10/10] 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 = <CookieBar policyUrl={policyUrl} />;
         } else if (this.props.hasNewVersion) {
             topBar = <NewVersionBar version={this.props.version} newVersion={this.props.newVersion}