diff --git a/.travis-test-riot.sh b/.travis-test-riot.sh index 6cd073a1f8..88b3719b3a 100755 --- a/.travis-test-riot.sh +++ b/.travis-test-riot.sh @@ -27,7 +27,7 @@ npm run build npm run test popd -if [ "$TRAVIS_BRANCH" != "experimental" ] +if [ "$TRAVIS_BRANCH" = "develop" ] then # run end to end tests git clone https://github.com/matrix-org/matrix-react-end-to-end-tests.git --branch master diff --git a/CHANGELOG.md b/CHANGELOG.md index dae09ee2f1..1486578025 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,78 @@ +Changes in [0.14.5](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.14.5) (2018-11-19) +===================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.14.5-rc.2...v0.14.5) + + * No changes since rc.1 + +Changes in [0.14.5-rc.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.14.5-rc.2) (2018-11-15) +=============================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.14.5-rc.1...v0.14.5-rc.2) + + * Update to js-sdk v0.14.0-rc.1 which uses the new Olm API + (v0.14.0-rc.1 was broken because of this). + +Changes in [0.14.5-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.14.5-rc.1) (2018-11-15) +=============================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.14.4...v0.14.5-rc.1) + + * Update from Weblate. + [\#2278](https://github.com/matrix-org/matrix-react-sdk/pull/2278) + * Support room IDs and event permalinks in the join command + [\#2272](https://github.com/matrix-org/matrix-react-sdk/pull/2272) + * Align encrypted event buttons in Safari + [\#2274](https://github.com/matrix-org/matrix-react-sdk/pull/2274) + * Align buttons in encrypted event dialog + [\#2273](https://github.com/matrix-org/matrix-react-sdk/pull/2273) + * Add visible guest warning to encourage login + [\#2268](https://github.com/matrix-org/matrix-react-sdk/pull/2268) + * Regenerate the room list when m.fully_read is issued + [\#2266](https://github.com/matrix-org/matrix-react-sdk/pull/2266) + * Remove the request-only stuff we don't need anymore + [\#2263](https://github.com/matrix-org/matrix-react-sdk/pull/2263) + * Improve performance of room list and fix timestamp ordering when pinning + rooms + [\#2265](https://github.com/matrix-org/matrix-react-sdk/pull/2265) + * Add options to pin unread/mentioned rooms to the top of the room list + [\#1936](https://github.com/matrix-org/matrix-react-sdk/pull/1936) + * only run e2e tests on PRs targeted on develop + [\#2261](https://github.com/matrix-org/matrix-react-sdk/pull/2261) + * Fix and test matrix.to alias permalinks + [\#2254](https://github.com/matrix-org/matrix-react-sdk/pull/2254) + * click-through svg on tag tile context menu to make it less weird + [\#2257](https://github.com/matrix-org/matrix-react-sdk/pull/2257) + * Hide Matthew's Time Machine + [\#2256](https://github.com/matrix-org/matrix-react-sdk/pull/2256) + * Update babel-eslint to 8.1.1 + [\#2255](https://github.com/matrix-org/matrix-react-sdk/pull/2255) + * Support routing matrix.to links to joinable rooms + [\#2250](https://github.com/matrix-org/matrix-react-sdk/pull/2250) + * Fix autoreplacement of ascii emoji + [\#2253](https://github.com/matrix-org/matrix-react-sdk/pull/2253) + * Repair DevTools button padding by centralizing styles + [\#2252](https://github.com/matrix-org/matrix-react-sdk/pull/2252) + * Redirect widgets to another location before deleting them + [\#2232](https://github.com/matrix-org/matrix-react-sdk/pull/2232) + * disable e2e tests for PRs targeted at experimental (redesign) + [\#2251](https://github.com/matrix-org/matrix-react-sdk/pull/2251) + * Fix emoji replacement in composer + [\#2247](https://github.com/matrix-org/matrix-react-sdk/pull/2247) + * Add a devtools button to roomsettings + [\#2249](https://github.com/matrix-org/matrix-react-sdk/pull/2249) + * Add warning when administrator leaves community (#5724) + [\#2242](https://github.com/matrix-org/matrix-react-sdk/pull/2242) + +Changes in [0.14.4](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.14.4) (2018-11-13) +===================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.14.3...v0.14.4) + + * Include change that was supposed to be included in orevious version + +Changes in [0.14.3](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.14.3) (2018-11-13) +===================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.14.2...v0.14.3) + + * Add banner with login/register links for users who aren't logged in + Changes in [0.14.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.14.2) (2018-10-29) ===================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.14.2-rc.1...v0.14.2) diff --git a/karma.conf.js b/karma.conf.js index 41ddbdf249..4d699599cb 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -199,25 +199,12 @@ module.exports = function (config) { 'matrix-react-sdk': path.resolve('test/skinned-sdk.js'), 'sinon': 'sinon/pkg/sinon.js', - - // To make webpack happy - // Related: https://github.com/request/request/issues/1529 - // (there's no mock available for fs, so we fake a mock by using - // an in-memory version of fs) - "fs": "memfs", }, modules: [ path.resolve('./test'), "node_modules" ], }, - node: { - // Because webpack is made of fail - // https://github.com/request/request/issues/1529 - // Note: 'mock' is the new 'empty' - net: 'mock', - tls: 'mock' - }, devtool: 'inline-source-map', externals: { // Don't try to bundle electron: leave it as a commonjs dependency diff --git a/package.json b/package.json index b72080cd36..d2e54a2621 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "0.14.2", + "version": "0.14.5", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { @@ -75,8 +75,7 @@ "linkifyjs": "^2.1.6", "lodash": "^4.13.1", "lolex": "2.3.2", - "matrix-js-sdk": "matrix-org/matrix-js-sdk#develop", - "memfs": "^2.10.1", + "matrix-js-sdk": "0.14.0", "optimist": "^0.6.1", "pako": "^1.0.5", "prop-types": "^15.5.8", diff --git a/res/css/structures/_HomePage.scss b/res/css/structures/_HomePage.scss index cdac1bcc8a..dc3158b39d 100644 --- a/res/css/structures/_HomePage.scss +++ b/res/css/structures/_HomePage.scss @@ -33,3 +33,16 @@ limitations under the License. .mx_HomePage_body { // margin-left: 63px; } + +.mx_HomePage_guest_warning { + display: flex; + background-color: $secondary-accent-color; + border: 1px solid $accent-color; + margin: 20px; + padding: 20px 40px; + border-radius: 5px; +} + +.mx_HomePage_guest_warning img { + padding-right: 10px; +} diff --git a/res/css/structures/login/_Login.scss b/res/css/structures/login/_Login.scss index 84b8306a74..1264d2a30f 100644 --- a/res/css/structures/login/_Login.scss +++ b/res/css/structures/login/_Login.scss @@ -142,6 +142,17 @@ limitations under the License. color: $primary-fg-color; } +.mx_Login_sso_link { + display: block; + text-align: center; + font-size: 15px; + margin-bottom: 20px; +} + +.mx_Login_sso_link:link { + color: $primary-fg-color; +} + .mx_Login_loader { display: inline; position: relative; diff --git a/res/css/views/dialogs/_EncryptedEventDialog.scss b/res/css/views/dialogs/_EncryptedEventDialog.scss index b4dd353370..58ed8b2527 100644 --- a/res/css/views/dialogs/_EncryptedEventDialog.scss +++ b/res/css/views/dialogs/_EncryptedEventDialog.scss @@ -24,4 +24,8 @@ limitations under the License. @mixin mx_DialogButton; background-color: $primary-bg-color; color: $accent-color; -} \ No newline at end of file +} + +.mx_EncryptedEventDialog button { + margin-top: 0px; +} diff --git a/res/css/views/login/_InteractiveAuthEntryComponents.scss b/res/css/views/login/_InteractiveAuthEntryComponents.scss index 183b5cd251..e2ea7d86fb 100644 --- a/res/css/views/login/_InteractiveAuthEntryComponents.scss +++ b/res/css/views/login/_InteractiveAuthEntryComponents.scss @@ -35,8 +35,24 @@ limitations under the License. margin-bottom: 5px; } +.mx_InteractiveAuthEntryComponents_termsSubmit { + margin-top: 20px; + margin-bottom: 5px; + display: block; + width: 100%; +} + // XXX: This should be a common button class .mx_InteractiveAuthEntryComponents_msisdnSubmit:disabled { background-color: $light-fg-color; cursor: default; } + +.mx_InteractiveAuthEntryComponents_termsSubmit:disabled { + background-color: $accent-color-50pct; + cursor: default; +} + +.mx_InteractiveAuthEntryComponents_termsPolicy { + display: block; +} \ No newline at end of file diff --git a/res/css/views/messages/_MImageBody.scss b/res/css/views/messages/_MImageBody.scss index 4c763c5991..a5a1e66a3b 100644 --- a/res/css/views/messages/_MImageBody.scss +++ b/res/css/views/messages/_MImageBody.scss @@ -46,3 +46,14 @@ limitations under the License. .mx_MImageBody_thumbnail_spinner > * { transform: translate(-50%, -50%); } + +.mx_MImageBody_gifLabel { + position: absolute; + display: block; + top: 0px; + left: 14px; + padding: 5px; + border-radius: 5px; + background: $imagebody-giflabel; + border: 2px solid $imagebody-giflabel-border; +} diff --git a/res/css/views/rooms/_MemberDeviceInfo.scss b/res/css/views/rooms/_MemberDeviceInfo.scss index 5888820e0d..d4e4bb1adf 100644 --- a/res/css/views/rooms/_MemberDeviceInfo.scss +++ b/res/css/views/rooms/_MemberDeviceInfo.scss @@ -19,7 +19,6 @@ limitations under the License. } .mx_MemberDeviceInfo.mx_DeviceVerifyButtons { - padding: 6px 0; display: flex; flex-wrap: wrap; justify-content: space-between; diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index 8ab338790e..b773d7c720 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -12,6 +12,7 @@ $light-fg-color: #747474; // button UI (white-on-green in light skin) $accent-fg-color: $primary-bg-color; $accent-color: #76CFA6; +$accent-color-50pct: #76CFA67F; $selection-fg-color: $primary-fg-color; @@ -143,6 +144,9 @@ $lightbox-bg-color: #454545; $lightbox-fg-color: #ffffff; $lightbox-border-color: #ffffff; +$imagebody-giflabel: rgba(1, 1, 1, 0.7); +$imagebody-giflabel-border: rgba(1, 1, 1, 0.2); + // unused? $progressbar-color: #000; diff --git a/res/themes/light/css/_base.scss b/res/themes/light/css/_base.scss index c7fd38259c..49347492ff 100644 --- a/res/themes/light/css/_base.scss +++ b/res/themes/light/css/_base.scss @@ -18,6 +18,7 @@ $focus-bg-color: #dddddd; // button UI (white-on-green in light skin) $accent-fg-color: #ffffff; $accent-color: #76CFA6; +$accent-color-50pct: #76CFA67F; $selection-fg-color: $primary-bg-color; @@ -148,6 +149,9 @@ $lightbox-bg-color: #454545; $lightbox-fg-color: #ffffff; $lightbox-border-color: #ffffff; +$imagebody-giflabel: rgba(0, 0, 0, 0.7); +$imagebody-giflabel-border: rgba(0, 0, 0, 0.2); + // unused? $progressbar-color: #000; diff --git a/src/Login.js b/src/Login.js index 61a14959d8..ec55a1e8c7 100644 --- a/src/Login.js +++ b/src/Login.js @@ -16,7 +16,6 @@ limitations under the License. */ import Matrix from "matrix-js-sdk"; -import { _t } from "./languageHandler"; import Promise from 'bluebird'; import url from 'url'; @@ -225,19 +224,18 @@ export default class Login { }); } - redirectToCas() { + getSsoLoginUrl(loginType) { const client = this._createTemporaryClient(); const parsedUrl = url.parse(window.location.href, true); // XXX: at this point, the fragment will always be #/login, which is no // use to anyone. Ideally, we would get the intended fragment from // MatrixChat.screenAfterLogin so that you could follow #/room links etc - // through a CAS login. + // through an SSO login. parsedUrl.hash = ""; parsedUrl.query["homeserver"] = client.getHomeserverUrl(); parsedUrl.query["identityServer"] = client.getIdentityServerUrl(); - const casUrl = client.getCasLoginUrl(url.format(parsedUrl)); - window.location.href = casUrl; + return client.getSsoLoginUrl(url.format(parsedUrl), loginType); } } diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js index 04b3b47e43..9a77901d2e 100644 --- a/src/MatrixClientPeg.js +++ b/src/MatrixClientPeg.js @@ -23,10 +23,12 @@ import Matrix from 'matrix-js-sdk'; import utils from 'matrix-js-sdk/lib/utils'; import EventTimeline from 'matrix-js-sdk/lib/models/event-timeline'; import EventTimelineSet from 'matrix-js-sdk/lib/models/event-timeline-set'; +import sdk from './index'; import createMatrixClient from './utils/createMatrixClient'; import SettingsStore from './settings/SettingsStore'; import MatrixActionCreators from './actions/MatrixActionCreators'; import {phasedRollOutExpiredForUser} from "./PhasedRollOut"; +import Modal from './Modal'; interface MatrixClientCreds { homeserverUrl: string, @@ -116,6 +118,14 @@ class MatrixClientPeg { await this.matrixClient.initCrypto(); } } catch (e) { + if (e.name === 'InvalidCryptoStoreError') { + // The js-sdk found a crypto DB too new for it to use + const CryptoStoreTooNewDialog = + sdk.getComponent("views.dialogs.CryptoStoreTooNewDialog"); + Modal.createDialog(CryptoStoreTooNewDialog, { + host: window.location.host, + }); + } // this can happen for a number of reasons, the most likely being // that the olm library was missing. It's not fatal. console.warn("Unable to initialise e2e: " + e); diff --git a/src/Registration.js b/src/Registration.js index 070178fecb..f86c9cc618 100644 --- a/src/Registration.js +++ b/src/Registration.js @@ -45,7 +45,7 @@ export async function startAnyRegistrationFlow(options) { // caution though. const hasIlagFlow = flows.some((flow) => { return flow.stages.every((stage) => { - return ['m.login.dummy', 'm.login.recaptcha'].includes(stage); + return ['m.login.dummy', 'm.login.recaptcha', 'm.login.terms'].includes(stage); }); }); diff --git a/src/SlashCommands.js b/src/SlashCommands.js index 3a8e77293b..8a34ba7ab1 100644 --- a/src/SlashCommands.js +++ b/src/SlashCommands.js @@ -24,6 +24,8 @@ import sdk from './index'; import {_t, _td} from './languageHandler'; import Modal from './Modal'; import SettingsStore, {SettingLevel} from './settings/SettingsStore'; +import {MATRIXTO_URL_PATTERN} from "./linkify-matrix"; +import * as querystring from "querystring"; class Command { @@ -153,11 +155,24 @@ export const CommandMap = { description: _td('Joins room with given alias'), runFn: function(roomId, args) { if (args) { - const matches = args.match(/^(\S+)$/); - if (matches) { - let roomAlias = matches[1]; - if (roomAlias[0] !== '#') return reject(this.getUsage()); + // Note: we support 2 versions of this command. The first is + // the public-facing one for most users and the other is a + // power-user edition where someone may join via permalink or + // room ID with optional servers. Practically, this results + // in the following variations: + // /join #example:example.org + // /join !example:example.org + // /join !example:example.org altserver.com elsewhere.ca + // /join https://matrix.to/#/!example:example.org?via=altserver.com + // The command also supports event permalinks transparently: + // /join https://matrix.to/#/!example:example.org/$something:example.org + // /join https://matrix.to/#/!example:example.org/$something:example.org?via=altserver.com + const params = args.split(' '); + if (params.length < 1) return reject(this.getUsage()); + const matrixToMatches = params[0].match(MATRIXTO_URL_PATTERN); + if (params[0][0] === '#') { + let roomAlias = params[0]; if (!roomAlias.includes(':')) { roomAlias += ':' + MatrixClientPeg.get().getDomain(); } @@ -167,7 +182,65 @@ export const CommandMap = { room_alias: roomAlias, auto_join: true, }); + return success(); + } else if (params[0][0] === '!') { + const roomId = params[0]; + const viaServers = params.splice(0); + dis.dispatch({ + action: 'view_room', + room_id: roomId, + opts: { + // These are passed down to the js-sdk's /join call + server_name: viaServers, + }, + auto_join: true, + }); + return success(); + } else if (matrixToMatches) { + let entity = matrixToMatches[1]; + let eventId = null; + let viaServers = []; + + if (entity[0] !== '!' && entity[0] !== '#') return reject(this.getUsage()); + + if (entity.indexOf('?') !== -1) { + const parts = entity.split('?'); + entity = parts[0]; + + const parsed = querystring.parse(parts[1]); + viaServers = parsed["via"]; + if (typeof viaServers === 'string') viaServers = [viaServers]; + } + + // We quietly support event ID permalinks too + if (entity.indexOf('/$') !== -1) { + const parts = entity.split("/$"); + entity = parts[0]; + eventId = `$${parts[1]}`; + } + + const dispatch = { + action: 'view_room', + auto_join: true, + }; + + if (entity[0] === '!') dispatch["room_id"] = entity; + else dispatch["room_alias"] = entity; + + if (eventId) { + dispatch["event_id"] = eventId; + dispatch["highlighted"] = true; + } + + if (viaServers) { + dispatch["opts"] = { + // These are passed down to the js-sdk's /join call + server_name: viaServers, + }; + } + + dis.dispatch(dispatch); return success(); } } @@ -492,6 +565,7 @@ export const CommandMap = { const aliases = { j: "join", newballsplease: "discardsession", + goto: "join", // because it handles event permalinks magically }; diff --git a/src/actions/MatrixActionCreators.js b/src/actions/MatrixActionCreators.js index 31bcac3e52..c1d42ffd0d 100644 --- a/src/actions/MatrixActionCreators.js +++ b/src/actions/MatrixActionCreators.js @@ -62,6 +62,35 @@ function createAccountDataAction(matrixClient, accountDataEvent) { }; } +/** + * @typedef RoomAccountDataAction + * @type {Object} + * @property {string} action 'MatrixActions.Room.accountData'. + * @property {MatrixEvent} event the MatrixEvent that triggered the dispatch. + * @property {string} event_type the type of the MatrixEvent, e.g. "m.direct". + * @property {Object} event_content the content of the MatrixEvent. + * @property {Room} room the room where the account data was changed. + */ + +/** + * Create a MatrixActions.Room.accountData action that represents a MatrixClient `Room.accountData` + * matrix event. + * + * @param {MatrixClient} matrixClient the matrix client. + * @param {MatrixEvent} accountDataEvent the account data event. + * @param {Room} room the room where account data was changed + * @returns {RoomAccountDataAction} an action of type MatrixActions.Room.accountData. + */ +function createRoomAccountDataAction(matrixClient, accountDataEvent, room) { + return { + action: 'MatrixActions.Room.accountData', + event: accountDataEvent, + event_type: accountDataEvent.getType(), + event_content: accountDataEvent.getContent(), + room: room, + }; +} + /** * @typedef RoomAction * @type {Object} @@ -201,6 +230,7 @@ export default { start(matrixClient) { this._addMatrixClientListener(matrixClient, 'sync', createSyncAction); this._addMatrixClientListener(matrixClient, 'accountData', createAccountDataAction); + this._addMatrixClientListener(matrixClient, 'Room.accountData', createRoomAccountDataAction); this._addMatrixClientListener(matrixClient, 'Room', createRoomAction); this._addMatrixClientListener(matrixClient, 'Room.tags', createRoomTagsAction); this._addMatrixClientListener(matrixClient, 'Room.timeline', createRoomTimelineAction); diff --git a/src/components/structures/HomePage.js b/src/components/structures/HomePage.js index 89053b35c7..01aabf6115 100644 --- a/src/components/structures/HomePage.js +++ b/src/components/structures/HomePage.js @@ -23,6 +23,8 @@ import request from 'browser-request'; import { _t } from '../../languageHandler'; import sanitizeHtml from 'sanitize-html'; import sdk from '../../index'; +import { MatrixClient } from 'matrix-js-sdk'; +import dis from '../../dispatcher'; class HomePage extends React.Component { static displayName = 'HomePage'; @@ -37,6 +39,10 @@ class HomePage extends React.Component { homePageUrl: PropTypes.string, }; + static contextTypes = { + matrixClient: PropTypes.instanceOf(MatrixClient), + }; + state = { iframeSrc: '', page: '', @@ -85,10 +91,47 @@ class HomePage extends React.Component { this._unmounted = true; } + onLoginClick() { + dis.dispatch({ action: 'start_login' }); + } + + onRegisterClick() { + dis.dispatch({ action: 'start_registration' }); + } + render() { + let guestWarning = ""; + if (this.context.matrixClient.isGuest()) { + guestWarning = ( +
+ +
+
+ { _t("You are currently using Riot anonymously as a guest.") } +
+
+ { _t( + 'If you would like to create a Matrix account you can register now.', + {}, + { 'a': (sub) => { sub } }, + ) } +
+
+ { _t( + 'If you already have a Matrix account you can log in instead.', + {}, + { 'a': (sub) => { sub } }, + ) } +
+
+
+ ); + } + if (this.state.iframeSrc) { return (
+ { guestWarning }