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) 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": { 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 }; } 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, }); diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index d9ac9de693..2dd5a75c47 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,12 @@ const LoggedInView = React.createClass({ let topBar; const isGuest = this.props.matrixClient.isGuest(); - if (this.props.hasNewVersion) { + if (this.props.showCookieBar && + this.props.config.piwik + ) { + const policyUrl = this.props.config.piwik.policyUrl || null; + 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/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(); }, }, ]; diff --git a/src/components/views/globals/CookieBar.js b/src/components/views/globals/CookieBar.js new file mode 100644 index 0000000000..8fab64be67 --- /dev/null +++ b/src/components/views/globals/CookieBar.js @@ -0,0 +1,78 @@ +/* +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 PropTypes from 'prop-types'; +import dis from '../../../dispatcher'; +import { _t } from '../../../languageHandler'; +import sdk from '../../../index'; + +export default class CookieBar extends React.Component { + static propTypes = { + policyUrl: PropTypes.string, + } + + constructor() { + super(); + } + + onAccept() { + dis.dispatch({ + action: 'accept_cookies', + }); + } + + onReject() { + dis.dispatch({ + action: 'reject_cookies', + }); + } + + render() { + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); + const toolbarClasses = "mx_MatrixToolbar"; + return ( +
+ Warning +
+ { 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 + 'PolicyLink': (sub) => + { sub } + + , + }, + ) : _t("Help improve Riot by sending usage data? This will use a cookie.") } +
+ + { _t("Yes please") } + + + + +
+ ); + } +} diff --git a/src/components/views/messages/MImageBody.js b/src/components/views/messages/MImageBody.js index 03dad5e439..f27124238e 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. @@ -210,6 +211,7 @@ export default class extends React.Component { }); }).done(); } + this.fixupHeight(); this._afterComponentDidMount(); } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 957deb35c5..239b45c32e 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -209,7 +209,7 @@ "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", "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 +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 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", diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 663318f990..b1bc4161fd 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -213,11 +213,15 @@ 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, + default: true, + }, "autocompleteDelay": { supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, default: 200,