diff --git a/.buildkite/pipeline.yaml b/.buildkite/pipeline.yaml index ac05da02e3..946e417676 100644 --- a/.buildkite/pipeline.yaml +++ b/.buildkite/pipeline.yaml @@ -79,3 +79,13 @@ steps: - docker#v3.0.1: image: "node:10" propagate-environment: true + + - wait + + - label: "🐴 Trigger riot-web" + trigger: "riot-web" + branches: "develop" + build: + branch: "develop" + message: "[react-sdk] ${BUILDKITE_MESSAGE}" + async: true diff --git a/.eslintignore.errorfiles b/.eslintignore.errorfiles index 2224ef67bc..ffe0ade5cc 100644 --- a/.eslintignore.errorfiles +++ b/.eslintignore.errorfiles @@ -10,7 +10,6 @@ src/components/structures/RoomStatusBar.js src/components/structures/RoomView.js src/components/structures/ScrollPanel.js src/components/structures/SearchBox.js -src/components/structures/TimelinePanel.js src/components/structures/UploadBar.js src/components/views/avatars/BaseAvatar.js src/components/views/avatars/MemberAvatar.js diff --git a/.gitignore b/.gitignore index 7a3b1061b0..33e8bfc7ac 100644 --- a/.gitignore +++ b/.gitignore @@ -9,9 +9,6 @@ package-lock.json /git-revision.txt /matrix-react-sdk-*.tgz -# test reports created by karma -/karma-reports - /.idea /src/component-index.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 4536064675..4d9a01e668 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,196 @@ +Changes in [1.1.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v1.1.0) (2019-05-07) +=================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v1.1.0-rc.1...v1.1.0) + + * Relax password requirements to score of 3 out of 4 + [\#2949](https://github.com/matrix-org/matrix-react-sdk/pull/2949) + * Restore access to message quote option on first click + [\#2948](https://github.com/matrix-org/matrix-react-sdk/pull/2948) + * Check for `room` in all `Room.timeline*` handlers + [\#2946](https://github.com/matrix-org/matrix-react-sdk/pull/2946) + +Changes in [1.1.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v1.1.0-rc.1) (2019-04-30) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v1.0.7...v1.1.0-rc.1) + + * Add important info to new preview bar + [\#2936](https://github.com/matrix-org/matrix-react-sdk/pull/2936) + * Add a message action bar + [\#2935](https://github.com/matrix-org/matrix-react-sdk/pull/2935) + * Trigger riot-web build + [\#2934](https://github.com/matrix-org/matrix-react-sdk/pull/2934) + * Input validation tooltips for registration + [\#2933](https://github.com/matrix-org/matrix-react-sdk/pull/2933) + * Also say "Connect ..." on remaining key backup buttons + [\#2931](https://github.com/matrix-org/matrix-react-sdk/pull/2931) + * Mark a few CSS classes as not selectable + [\#2929](https://github.com/matrix-org/matrix-react-sdk/pull/2929) + * Cleanup message composer render() method + [\#2883](https://github.com/matrix-org/matrix-react-sdk/pull/2883) + * Redesigned room preview bar + [\#2925](https://github.com/matrix-org/matrix-react-sdk/pull/2925) + * Prevent user pills containing only emoji from embiggening + [\#2907](https://github.com/matrix-org/matrix-react-sdk/pull/2907) + * Make alt-enter insert new line on macOS + [\#2923](https://github.com/matrix-org/matrix-react-sdk/pull/2923) + * Test `defaultServerName` before showing it on forgot password + [\#2924](https://github.com/matrix-org/matrix-react-sdk/pull/2924) + * Add a function to append/overwrite objects in the config on the fly + [\#2922](https://github.com/matrix-org/matrix-react-sdk/pull/2922) + * use SdkConfig brand name instead of static "Riot" + [\#2921](https://github.com/matrix-org/matrix-react-sdk/pull/2921) + * Use dedicated permalink creators in search results with multiple rooms + [\#2898](https://github.com/matrix-org/matrix-react-sdk/pull/2898) + * Clarify that use backup means restore + [\#2917](https://github.com/matrix-org/matrix-react-sdk/pull/2917) + * Fix key backup status when missing device + [\#2919](https://github.com/matrix-org/matrix-react-sdk/pull/2919) + * Ensure `` tags appear bold for all browsers + [\#2918](https://github.com/matrix-org/matrix-react-sdk/pull/2918) + * Add a link in room settings to get at the tombstoned room if it exists + [\#2908](https://github.com/matrix-org/matrix-react-sdk/pull/2908) + * Add a generic error page element for startup errors + [\#2915](https://github.com/matrix-org/matrix-react-sdk/pull/2915) + * Add strings for js-sdk autodiscovery errors + [\#2916](https://github.com/matrix-org/matrix-react-sdk/pull/2916) + * Focus the composer view on file upload + [\#2914](https://github.com/matrix-org/matrix-react-sdk/pull/2914) + * use medium agent for e2e tests + [\#2911](https://github.com/matrix-org/matrix-react-sdk/pull/2911) + * adjust prop in HeaderButton + [\#2912](https://github.com/matrix-org/matrix-react-sdk/pull/2912) + * Remove breadcrumb scroll tolerances and use sensible defaults + [\#2913](https://github.com/matrix-org/matrix-react-sdk/pull/2913) + * Fix having to click the member list button twice to show it after having + changed room. + [\#2906](https://github.com/matrix-org/matrix-react-sdk/pull/2906) + * Add period to the end of upgrade notice + [\#2909](https://github.com/matrix-org/matrix-react-sdk/pull/2909) + * Remove duplicate space in credits + [\#2889](https://github.com/matrix-org/matrix-react-sdk/pull/2889) + * Handle M_UNSUPPORTED_ROOM_VERSION in invites and room creation + [\#2905](https://github.com/matrix-org/matrix-react-sdk/pull/2905) + * Re-enable E2E tests + [\#2867](https://github.com/matrix-org/matrix-react-sdk/pull/2867) + * Remove BottomLeftMenu and supporting bits + [\#2903](https://github.com/matrix-org/matrix-react-sdk/pull/2903) + * Fix for retina thumbnails being massive + [\#2439](https://github.com/matrix-org/matrix-react-sdk/pull/2439) + * Send breadcrumb updates only when they change + [\#2894](https://github.com/matrix-org/matrix-react-sdk/pull/2894) + * Add some tolerances to breadcrumb scrolling + [\#2892](https://github.com/matrix-org/matrix-react-sdk/pull/2892) + * Fix validation to avoid `undefined` class on fields + [\#2902](https://github.com/matrix-org/matrix-react-sdk/pull/2902) + * Always return a client from onRegistered + [\#2895](https://github.com/matrix-org/matrix-react-sdk/pull/2895) + * Fix room upgrade warnings popping up in upgraded rooms + [\#2897](https://github.com/matrix-org/matrix-react-sdk/pull/2897) + * Fix style lint errors & enable on CI + [\#2901](https://github.com/matrix-org/matrix-react-sdk/pull/2901) + * Add stylelint + [\#2900](https://github.com/matrix-org/matrix-react-sdk/pull/2900) + * Key backup: Handle case where your onw sig is invalid + [\#2899](https://github.com/matrix-org/matrix-react-sdk/pull/2899) + * Simplify settings dialog CSS + [\#2891](https://github.com/matrix-org/matrix-react-sdk/pull/2891) + * Fix upload cancel in e2e rooms + [\#2893](https://github.com/matrix-org/matrix-react-sdk/pull/2893) + * Set E2E room status to warning when crypto is disabled + [\#2890](https://github.com/matrix-org/matrix-react-sdk/pull/2890) + * Move SettingsDialog width override to fixedWidth + [\#2888](https://github.com/matrix-org/matrix-react-sdk/pull/2888) + * Prevent the permalink creator from causing cascading failure + [\#2882](https://github.com/matrix-org/matrix-react-sdk/pull/2882) + * Don't include all networks by default in the room directory + [\#2881](https://github.com/matrix-org/matrix-react-sdk/pull/2881) + * Fix fixed width dialogs + [\#2886](https://github.com/matrix-org/matrix-react-sdk/pull/2886) + * Fix settings dialog layout + [\#2885](https://github.com/matrix-org/matrix-react-sdk/pull/2885) + * Update from Weblate + [\#2884](https://github.com/matrix-org/matrix-react-sdk/pull/2884) + * Design tweaks to dialogs + [\#2868](https://github.com/matrix-org/matrix-react-sdk/pull/2868) + * Remove 'try the app' link from login + [\#2880](https://github.com/matrix-org/matrix-react-sdk/pull/2880) + * Track store failures after startup + [\#2870](https://github.com/matrix-org/matrix-react-sdk/pull/2870) + * Translate vertical scrolling to horizontal movement in breadcrumbs + [\#2877](https://github.com/matrix-org/matrix-react-sdk/pull/2877) + * Add telemetry for breadcrumbs and have the setting apply without refresh + [\#2873](https://github.com/matrix-org/matrix-react-sdk/pull/2873) + * Fix a few bugs introduced in file upload rework + [\#2879](https://github.com/matrix-org/matrix-react-sdk/pull/2879) + * Sync breadcrumb rooms through account data + [\#2875](https://github.com/matrix-org/matrix-react-sdk/pull/2875) + * Scroll breadcrumbs to the left when they change + [\#2878](https://github.com/matrix-org/matrix-react-sdk/pull/2878) + * Add an indicator to show a room is a direct chat in breadcrumbs + [\#2874](https://github.com/matrix-org/matrix-react-sdk/pull/2874) + * Use the most recent version of the room in breadcrumbs + [\#2872](https://github.com/matrix-org/matrix-react-sdk/pull/2872) + * Autohide the scrollbar on breadcrumbs + [\#2876](https://github.com/matrix-org/matrix-react-sdk/pull/2876) + * Ensure the page URL is redacted before tracking analytics events + [\#2871](https://github.com/matrix-org/matrix-react-sdk/pull/2871) + * fix NPE for rooms with redacted tombstones + [\#2869](https://github.com/matrix-org/matrix-react-sdk/pull/2869) + * Don't re-init the stickerpicker unless something actually changes + [\#2862](https://github.com/matrix-org/matrix-react-sdk/pull/2862) + * Add option to rotate images + [\#2855](https://github.com/matrix-org/matrix-react-sdk/pull/2855) + * Add badges to breadcrumb rooms + [\#2861](https://github.com/matrix-org/matrix-react-sdk/pull/2861) + * Include the current power level in the selector + [\#2866](https://github.com/matrix-org/matrix-react-sdk/pull/2866) + * Apply 50% opacity to left breadcrumbs + [\#2860](https://github.com/matrix-org/matrix-react-sdk/pull/2860) + * Small scroll fixes + [\#2865](https://github.com/matrix-org/matrix-react-sdk/pull/2865) + * Put the stickerpicker below dialogs + [\#2863](https://github.com/matrix-org/matrix-react-sdk/pull/2863) + * Logging tweaks + [\#2864](https://github.com/matrix-org/matrix-react-sdk/pull/2864) + * Implement redesigned upload confirmation screens + [\#2858](https://github.com/matrix-org/matrix-react-sdk/pull/2858) + * Use Field component in bug report dialog + [\#2859](https://github.com/matrix-org/matrix-react-sdk/pull/2859) + * Notify user when crypto data is missing + [\#2841](https://github.com/matrix-org/matrix-react-sdk/pull/2841) + * Update from Weblate + [\#2857](https://github.com/matrix-org/matrix-react-sdk/pull/2857) + * Download PDFs as blobs to avoid empty grey screens + [\#2847](https://github.com/matrix-org/matrix-react-sdk/pull/2847) + * Set title attribute on images in lightbox + [\#2848](https://github.com/matrix-org/matrix-react-sdk/pull/2848) + * Add MemberInfo for 3pid invites and support revoking those invites + [\#2843](https://github.com/matrix-org/matrix-react-sdk/pull/2843) + * round scrollTop upwards to prevent never detecting bottom + [\#2846](https://github.com/matrix-org/matrix-react-sdk/pull/2846) + * Notifier is how singleton is known outside of this module + [\#2845](https://github.com/matrix-org/matrix-react-sdk/pull/2845) + * Delay `Notifier` check until we have push rules + [\#2844](https://github.com/matrix-org/matrix-react-sdk/pull/2844) + * BACAT Scrolling + [\#2842](https://github.com/matrix-org/matrix-react-sdk/pull/2842) + * Handle storage fallback cases in consistency check + [\#2840](https://github.com/matrix-org/matrix-react-sdk/pull/2840) + * Handle all the segments of a v3 event ID + [\#2827](https://github.com/matrix-org/matrix-react-sdk/pull/2827) + * Add custom tooltips and scrolling to breadcrumbs + [\#2839](https://github.com/matrix-org/matrix-react-sdk/pull/2839) + * Check if the message panel is at the end of the timeline on init + [\#2829](https://github.com/matrix-org/matrix-react-sdk/pull/2829) + * Persist breadcrumb state between sessions + [\#2837](https://github.com/matrix-org/matrix-react-sdk/pull/2837) + * Always append the current room to the breadcrumbs + [\#2838](https://github.com/matrix-org/matrix-react-sdk/pull/2838) + * Alert the user to unread notifications in prior versions of rooms + [\#2831](https://github.com/matrix-org/matrix-react-sdk/pull/2831) + * Filter out upgraded rooms from autocomplete results + [\#2830](https://github.com/matrix-org/matrix-react-sdk/pull/2830) + Changes in [1.0.7](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v1.0.7) (2019-04-08) =================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v1.0.6...v1.0.7) diff --git a/docs/settings.md b/docs/settings.md index c88888663b..1ba8981f84 100644 --- a/docs/settings.md +++ b/docs/settings.md @@ -229,7 +229,7 @@ Controllers are notified of changes by the `SettingsStore`, and are given the op ### Features -Features automatically get considered as `disabled` if they are not listed in the `SdkConfig` or `enable_labs` is +Features automatically get considered as `disabled` if they are not listed in the `SdkConfig` or `enableLabs` is false/not set. Features are always checked against the configuration before going through the level order as they have the option of being forced-on or forced-off for the application. This is done by the `features` section and looks something like this: @@ -260,4 +260,4 @@ In practice, handlers which rely on remote changes (account data, room events, e generalized `WatchManager` - a class specifically designed to deduplicate the logic of managing watchers. The handlers which are localized to the local client (device) generally just trigger the `WatchManager` when they manipulate the setting themselves as there's nothing to really 'watch'. - \ No newline at end of file + diff --git a/karma.conf.js b/karma.conf.js index b687be78fa..e2728cdc09 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -94,7 +94,7 @@ module.exports = function (config) { // test results reporter to use // possible values: 'dots', 'progress' // available reporters: https://npmjs.org/browse/keyword/karma-reporter - reporters: ['logcapture', 'spec', 'junit', 'summary'], + reporters: ['logcapture', 'spec', 'summary'], specReporter: { suppressErrorSummary: false, // do print error summary @@ -156,10 +156,6 @@ module.exports = function (config) { // how many browser should be started simultaneous concurrency: Infinity, - junitReporter: { - outputDir: 'karma-reports', - }, - webpack: { module: { rules: [ diff --git a/package.json b/package.json index d844566f3a..991080cb7e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "1.0.7", + "version": "1.1.0", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { @@ -80,7 +80,7 @@ "linkifyjs": "^2.1.6", "lodash": "^4.13.1", "lolex": "2.3.2", - "matrix-js-sdk": "1.0.4", + "matrix-js-sdk": "1.1.0", "optimist": "^0.6.1", "pako": "^1.0.5", "png-chunks-extract": "^1.0.0", @@ -136,7 +136,6 @@ "karma": "^4.0.1", "karma-chrome-launcher": "^2.2.0", "karma-cli": "^1.0.1", - "karma-junit-reporter": "^2.0.0", "karma-logcapture-reporter": "0.0.1", "karma-mocha": "^1.3.0", "karma-sourcemap-loader": "^0.3.7", diff --git a/res/css/_components.scss b/res/css/_components.scss index 1f896d270d..36648f4982 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -100,6 +100,7 @@ @import "./views/elements/_ToggleSwitch.scss"; @import "./views/elements/_ToolTipButton.scss"; @import "./views/elements/_Tooltip.scss"; +@import "./views/elements/_Validation.scss"; @import "./views/globals/_MatrixToolbar.scss"; @import "./views/groups/_GroupPublicityToggle.scss"; @import "./views/groups/_GroupRoomList.scss"; @@ -112,7 +113,10 @@ @import "./views/messages/_MNoticeBody.scss"; @import "./views/messages/_MStickerBody.scss"; @import "./views/messages/_MTextBody.scss"; +@import "./views/messages/_MessageActionBar.scss"; @import "./views/messages/_MessageTimestamp.scss"; +@import "./views/messages/_ReactionsRow.scss"; +@import "./views/messages/_ReactionsRowButton.scss"; @import "./views/messages/_RoomAvatarEvent.scss"; @import "./views/messages/_SenderProfile.scss"; @import "./views/messages/_TextualEvent.scss"; diff --git a/res/css/views/auth/_AuthBody.scss b/res/css/views/auth/_AuthBody.scss index fa034095b6..16ac876869 100644 --- a/res/css/views/auth/_AuthBody.scss +++ b/res/css/views/auth/_AuthBody.scss @@ -130,3 +130,27 @@ limitations under the License. .mx_AuthBody_spinner { margin: 1em 0; } + +.mx_AuthBody_passwordScore { + width: 100%; + appearance: none; + height: 4px; + border: 0; + border-radius: 2px; + position: absolute; + top: -12px; + + &::-moz-progress-bar { + border-radius: 2px; + background-color: $accent-color; + } + + &::-webkit-progress-bar, + &::-webkit-progress-value { + border-radius: 2px; + } + + &::-webkit-progress-value { + background-color: $accent-color; + } +} diff --git a/res/css/views/avatars/_BaseAvatar.scss b/res/css/views/avatars/_BaseAvatar.scss index 91b2d6c426..a085034758 100644 --- a/res/css/views/avatars/_BaseAvatar.scss +++ b/res/css/views/avatars/_BaseAvatar.scss @@ -26,6 +26,7 @@ limitations under the License. // https://bugzilla.mozilla.org/show_bug.cgi?id=1535053 // https://bugzilla.mozilla.org/show_bug.cgi?id=255139 display: inline-block; + user-select: none; } .mx_BaseAvatar_initial { diff --git a/res/css/views/elements/_Field.scss b/res/css/views/elements/_Field.scss index 20b1efd28b..147bb3b471 100644 --- a/res/css/views/elements/_Field.scss +++ b/res/css/views/elements/_Field.scss @@ -168,6 +168,7 @@ limitations under the License. .mx_Field_tooltip { margin-top: -12px; margin-left: 4px; + width: 200px; } .mx_Field_tooltip.mx_Field_valid { diff --git a/res/css/views/elements/_Tooltip.scss b/res/css/views/elements/_Tooltip.scss index 2f35bd338e..43ddf6dde5 100644 --- a/res/css/views/elements/_Tooltip.scss +++ b/res/css/views/elements/_Tooltip.scss @@ -50,7 +50,6 @@ limitations under the License. .mx_Tooltip { display: none; - animation: mx_fadein 0.2s; position: fixed; border: 1px solid $menu-border-color; border-radius: 4px; @@ -66,4 +65,12 @@ limitations under the License. max-width: 200px; word-break: break-word; margin-right: 50px; + + &.mx_Tooltip_visible { + animation: mx_fadein 0.2s forwards; + } + + &.mx_Tooltip_invisible { + animation: mx_fadeout 0.1s forwards; + } } diff --git a/res/css/views/elements/_Validation.scss b/res/css/views/elements/_Validation.scss new file mode 100644 index 0000000000..1f9bd880e6 --- /dev/null +++ b/res/css/views/elements/_Validation.scss @@ -0,0 +1,69 @@ +/* +Copyright 2019 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. +*/ + +.mx_Validation { + position: relative; +} + +.mx_Validation_details { + padding-left: 20px; + margin: 0; +} + +.mx_Validation_description + .mx_Validation_details { + margin: 1em 0 0; +} + +.mx_Validation_detail { + position: relative; + font-weight: normal; + list-style: none; + margin-bottom: 0.5em; + + &:last-child { + margin-bottom: 0; + } + + &::before { + content: ""; + position: absolute; + width: 14px; + height: 14px; + top: 0; + left: -18px; + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + } + + &.mx_Validation_valid { + color: $input-valid-border-color; + + &::before { + mask-image: url('$(res)/img/feather-customised/check.svg'); + background-color: $input-valid-border-color; + } + } + + &.mx_Validation_invalid { + color: $input-invalid-border-color; + + &::before { + mask-image: url('$(res)/img/feather-customised/x.svg'); + background-color: $input-invalid-border-color; + } + } +} diff --git a/res/css/views/messages/_MessageActionBar.scss b/res/css/views/messages/_MessageActionBar.scss new file mode 100644 index 0000000000..877e1916fc --- /dev/null +++ b/res/css/views/messages/_MessageActionBar.scss @@ -0,0 +1,84 @@ +/* +Copyright 2019 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. +*/ + +.mx_MessageActionBar { + position: absolute; + visibility: hidden; + cursor: pointer; + display: flex; + height: 24px; + line-height: 24px; + border-radius: 4px; + background: $message-action-bar-bg-color; + top: -13px; + right: 8px; + user-select: none; + + > * { + display: inline-block; + position: relative; + width: 27px; + border: 1px solid $message-action-bar-border-color; + margin-left: -1px; + + &:hover { + border-color: $message-action-bar-hover-border-color; + z-index: 1; + } + + &:first-child { + border-radius: 3px 0 0 3px; + } + + &:last-child { + border-radius: 0 3px 3px 0; + } + + &:only-child { + border-radius: 3px; + } + } +} + +.mx_MessageActionBar_maskButton::after { + content: ''; + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + mask-repeat: no-repeat; + mask-position: center; + background-color: $message-action-bar-fg-color; +} + +.mx_MessageActionBar_replyButton::after { + mask-image: url('$(res)/img/reply.svg'); +} + +.mx_MessageActionBar_optionsButton::after { + mask-image: url('$(res)/img/icon_context.svg'); +} + +.mx_MessageActionBar_reactionDimension { + width: 42px; + display: flex; + justify-content: space-evenly; +} + +.mx_MessageActionBar_reactionDisabled { + opacity: 0.4; +} diff --git a/res/css/views/messages/_ReactionsRow.scss b/res/css/views/messages/_ReactionsRow.scss new file mode 100644 index 0000000000..fb66ffbb8c --- /dev/null +++ b/res/css/views/messages/_ReactionsRow.scss @@ -0,0 +1,19 @@ +/* +Copyright 2019 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. +*/ + +.mx_ReactionsRow { + margin: 6px 0; +} diff --git a/res/css/views/messages/_ReactionsRowButton.scss b/res/css/views/messages/_ReactionsRowButton.scss new file mode 100644 index 0000000000..49e3930979 --- /dev/null +++ b/res/css/views/messages/_ReactionsRowButton.scss @@ -0,0 +1,36 @@ +/* +Copyright 2019 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. +*/ + +.mx_ReactionsRowButton { + display: inline-block; + height: 20px; + line-height: 21px; + margin-right: 6px; + padding: 0 6px; + border: 1px solid $reaction-row-button-border-color; + border-radius: 10px; + background-color: $reaction-row-button-bg-color; + cursor: pointer; + + &:hover { + border-color: $reaction-row-button-hover-border-color; + } + + &.mx_ReactionsRowButton_selected { + background-color: $reaction-row-button-selected-bg-color; + border-color: $reaction-row-button-selected-border-color; + } +} diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index 42eab24051..f4c12bb734 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -31,6 +31,7 @@ limitations under the License. top: 14px; left: 8px; cursor: pointer; + user-select: none; } .mx_EventTile.mx_EventTile_info .mx_EventTile_avatar { @@ -62,6 +63,7 @@ limitations under the License. vertical-align: top; height: 16px; overflow: hidden; + user-select: none; img { vertical-align: -2px; @@ -80,6 +82,7 @@ limitations under the License. width: 46px; /* 8 + 30 (avatar) + 8 */ text-align: center; position: absolute; + user-select: none; } .mx_EventTile_line, .mx_EventTile_reply { @@ -118,7 +121,7 @@ limitations under the License. } .mx_EventTile:hover .mx_EventTile_line, -.mx_EventTile.menu .mx_EventTile_line +.mx_EventTile.mx_EventTile_actionBarFocused .mx_EventTile_line { background-color: $event-selected-color; } @@ -203,7 +206,7 @@ limitations under the License. // Explicit relationships so that it doesn't apply to nested EventTile components (e.g in Replies) .mx_EventTile_last > div > a > .mx_MessageTimestamp, .mx_EventTile:hover > div > a > .mx_MessageTimestamp, -.mx_EventTile.menu > div > a > .mx_MessageTimestamp { +.mx_EventTile.mx_EventTile_actionBarFocused > div > a > .mx_MessageTimestamp { visibility: visible; } @@ -216,24 +219,8 @@ limitations under the License. width: auto; } -.mx_EventTile_editButton { - position: absolute; - display: inline-block; - visibility: hidden; - cursor: pointer; - top: 6px; - right: 6px; - width: 19px; - height: 19px; - background-image: url($edit-button-url); - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.mx_EventTile:hover .mx_EventTile_editButton, -.mx_EventTile.menu .mx_EventTile_editButton { +.mx_EventTile:hover .mx_MessageActionBar, +.mx_EventTile.mx_EventTile_actionBarFocused .mx_MessageActionBar { visibility: visible; } @@ -243,6 +230,7 @@ limitations under the License. width: 14px; height: 14px; top: 29px; + user-select: none; } .mx_EventTile_continuation .mx_EventTile_readAvatars, @@ -550,10 +538,6 @@ limitations under the License. top: 3px; } - .mx_EventTile_editButton { - top: 3px; - } - .mx_EventTile_readAvatars { top: 27px; } diff --git a/res/img/feather-customised/check.svg b/res/img/feather-customised/check.svg new file mode 100644 index 0000000000..5c600f8649 --- /dev/null +++ b/res/img/feather-customised/check.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/feather-customised/x.svg b/res/img/feather-customised/x.svg new file mode 100644 index 0000000000..5468caa8aa --- /dev/null +++ b/res/img/feather-customised/x.svg @@ -0,0 +1,4 @@ + + + + diff --git a/res/img/icon_context_message.svg b/res/img/icon_context_message.svg deleted file mode 100644 index f2ceccfa78..0000000000 --- a/res/img/icon_context_message.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - ED5D3E59-2561-4AC1-9B43-82FBC51767FC - Created with sketchtool. - - - - - - - - - - diff --git a/res/img/reply.svg b/res/img/reply.svg new file mode 100644 index 0000000000..8cbbad3550 --- /dev/null +++ b/res/img/reply.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index c433a028a3..592b1a1887 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -40,7 +40,7 @@ $tagpanel-bg-color: $base-color; $selected-color: $room-highlight-color; // selected for hoverover & selected event tiles -$event-selected-color: #111316; +$event-selected-color: $header-panel-bg-color; // used for the hairline dividers in RoomView $primary-hairline-color: $header-panel-border-color; @@ -146,6 +146,17 @@ $room-warning-bg-color: $header-panel-bg-color; $dark-panel-bg-color: $header-panel-bg-color; $panel-gradient: rgba(34, 38, 46, 0), rgba(34, 38, 46, 1); +$message-action-bar-bg-color: $header-panel-bg-color; +$message-action-bar-fg-color: $header-panel-text-primary-color; +$message-action-bar-border-color: #616b7f; +$message-action-bar-hover-border-color: $header-panel-text-primary-color; + +$reaction-row-button-bg-color: $header-panel-bg-color; +$reaction-row-button-border-color: #616b7f; +$reaction-row-button-hover-border-color: $header-panel-text-primary-color; +$reaction-row-button-selected-bg-color: #1f6954; +$reaction-row-button-selected-border-color: $accent-color; + // ***** Mixins! ***** @define-mixin mx_DialogButton { diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index ca2e4cf58d..adadd39333 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -11,7 +11,7 @@ $font-family: 'Nunito', Arial, Helvetica, Sans-Serif; $accent-color: #03b381; $notice-primary-color: #ff4b55; $notice-secondary-color: #61708b; -$header-panel-bg-color: #f2f5f8; +$header-panel-bg-color: #f3f8fd; // typical text (dark-on-white in light skin) $primary-fg-color: #2e2f32; @@ -66,14 +66,14 @@ $droptarget-bg-color: rgba(255,255,255,0.5); $selected-color: $secondary-accent-color; // selected for hoverover & selected event tiles -$event-selected-color: #f7f7f7; +$event-selected-color: $header-panel-bg-color; // used for the hairline dividers in RoomView $primary-hairline-color: #e5e5e5; // used for the border of input text fields $input-border-color: #e7e7e7; -$input-darker-bg-color: rgba(193, 201, 214, 0.29); +$input-darker-bg-color: #e3e8f0; $input-darker-fg-color: #9fa9ba; $input-lighter-bg-color: #f2f5f8; $input-lighter-fg-color: $input-darker-fg-color; @@ -153,7 +153,7 @@ $roomheader-button-color: #91A1C0; $groupheader-button-color: #91A1C0; $rightpanel-button-color: #91A1C0; $composer-button-color: #91A1C0; -$roomtopic-color: #9fa9ba; +$roomtopic-color: #9e9e9e; $eventtile-meta-color: $roomtopic-color; $composer-e2e-icon-color: #c9ced6; @@ -203,7 +203,6 @@ $event-redacted-border-color: #cccccc; // event timestamp $event-timestamp-color: #acacac; -$edit-button-url: "$(res)/img/icon_context_message.svg"; $copy-button-url: "$(res)/img/icon_copy_message.svg"; // e2e @@ -255,6 +254,17 @@ $authpage-secondary-color: #61708b; $dark-panel-bg-color: $secondary-accent-color; $panel-gradient: rgba(242, 245, 248, 0), rgba(242, 245, 248, 1); +$message-action-bar-bg-color: $primary-bg-color; +$message-action-bar-fg-color: $primary-fg-color; +$message-action-bar-border-color: #e9edf1; +$message-action-bar-hover-border-color: #b8c1d2; + +$reaction-row-button-bg-color: $header-panel-bg-color; +$reaction-row-button-border-color: #e9edf1; +$reaction-row-button-hover-border-color: #bebebe; +$reaction-row-button-selected-bg-color: #e9fff9; +$reaction-row-button-selected-border-color: $accent-color; + // ***** Mixins! ***** @define-mixin mx_DialogButton { diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 33f1bac090..277985ba1d 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -50,7 +50,6 @@ import SettingsStore, {SettingLevel} from "../../settings/SettingsStore"; import { startAnyRegistrationFlow } from "../../Registration.js"; import { messageForSyncError } from '../../utils/ErrorUtils'; import ResizeNotifier from "../../utils/ResizeNotifier"; -import TimelineExplosionDialog from "../views/dialogs/TimelineExplosionDialog"; const AutoDiscovery = Matrix.AutoDiscovery; @@ -250,17 +249,6 @@ export default React.createClass({ return this.state.defaultIsUrl || "https://vector.im"; }, - /** - * Whether to skip the server details phase of registration and start at the - * actual form. - * @return {boolean} - * If there was a configured default HS or default server name, skip the - * the server details. - */ - skipServerDetailsForRegistration() { - return !!this.state.defaultHsUrl; - }, - componentWillMount: function() { SdkConfig.put(this.props.config); @@ -1307,17 +1295,6 @@ export default React.createClass({ return self._loggedInView.child.canResetTimelineInRoom(roomId); }); - cli.on('sync.unexpectedError', function(err) { - if (err.message && err.message.includes("live timeline ") && err.message.includes(" is no longer live ")) { - console.error("Caught timeline explosion - trying to ask user for more information"); - if (Modal.hasDialogs()) { - console.warn("User has another dialog open - skipping prompt"); - return; - } - Modal.createTrackedDialog('Timeline exploded', '', TimelineExplosionDialog, {}); - } - }); - cli.on('sync', function(state, prevState, data) { // LifecycleStore and others cannot directly subscribe to matrix client for // events because flux only allows store state changes during flux dispatches. @@ -1985,7 +1962,6 @@ export default React.createClass({ defaultServerDiscoveryError={this.state.defaultServerDiscoveryError} defaultHsUrl={this.getDefaultHsUrl()} defaultIsUrl={this.getDefaultIsUrl()} - skipServerDetails={this.skipServerDetailsForRegistration()} brand={this.props.config.brand} customHsUrl={this.getCurrentHsUrl()} customIsUrl={this.getCurrentIsUrl()} diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index aba7964a15..aa278f2349 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -44,11 +44,10 @@ const READ_RECEIPT_INTERVAL_MS = 500; const DEBUG = false; +let debuglog = function() {}; if (DEBUG) { // using bind means that we get to keep useful line numbers in the console - var debuglog = console.log.bind(console); -} else { - var debuglog = function() {}; + debuglog = console.log.bind(console); } /* @@ -56,7 +55,7 @@ if (DEBUG) { * * Also responsible for handling and sending read receipts. */ -var TimelinePanel = React.createClass({ +const TimelinePanel = React.createClass({ displayName: 'TimelinePanel', propTypes: { @@ -445,6 +444,7 @@ var TimelinePanel = React.createClass({ const updatedState = {events: events}; + let callRMUpdated; if (this.props.manageReadMarkers) { // when a new event arrives when the user is not watching the // window, but the window is in its auto-scroll mode, make sure the @@ -456,7 +456,7 @@ var TimelinePanel = React.createClass({ // const myUserId = MatrixClientPeg.get().credentials.userId; const sender = ev.sender ? ev.sender.userId : null; - var callRMUpdated = false; + callRMUpdated = false; if (sender != myUserId && !UserActivity.sharedInstance().userActiveRecently()) { updatedState.readMarkerVisible = true; } else if (lastEv && this.getReadMarkerPosition() === 0) { @@ -566,7 +566,7 @@ var TimelinePanel = React.createClass({ UserActivity.sharedInstance().timeWhileActiveRecently(this._readMarkerActivityTimer); try { await this._readMarkerActivityTimer.finished(); - } catch(e) { continue; /* aborted */ } + } catch (e) { continue; /* aborted */ } // outside of try/catch to not swallow errors this.updateReadMarker(); } @@ -578,7 +578,7 @@ var TimelinePanel = React.createClass({ UserActivity.sharedInstance().timeWhileActiveNow(this._readReceiptActivityTimer); try { await this._readReceiptActivityTimer.finished(); - } catch(e) { continue; /* aborted */ } + } catch (e) { continue; /* aborted */ } // outside of try/catch to not swallow errors this.sendReadReceipt(); } @@ -732,7 +732,8 @@ var TimelinePanel = React.createClass({ const events = this._timelineWindow.getEvents(); // first find where the current RM is - for (var i = 0; i < events.length; i++) { + let i; + for (i = 0; i < events.length; i++) { if (events[i].getId() == this.state.readMarkerEventId) { break; } @@ -744,7 +745,7 @@ var TimelinePanel = React.createClass({ // now think about advancing it const myUserId = MatrixClientPeg.get().credentials.userId; for (i++; i < events.length; i++) { - var ev = events[i]; + const ev = events[i]; if (!ev.sender || ev.sender.userId != myUserId) { break; } @@ -752,7 +753,7 @@ var TimelinePanel = React.createClass({ // i is now the first unread message which we didn't send ourselves. i--; - var ev = events[i]; + const ev = events[i]; this._setReadMarker(ev.getId(), ev.getTs()); }, @@ -882,7 +883,7 @@ var TimelinePanel = React.createClass({ return ret; }, - /** + /* * called by the parent component when PageUp/Down/etc is pressed. * * We pass it down to the scroll panel. @@ -975,11 +976,10 @@ var TimelinePanel = React.createClass({ }; const onError = (error) => { - this.setState({timelineLoading: false}); + this.setState({ timelineLoading: false }); console.error( `Error loading timeline panel at ${eventId}: ${error}`, ); - const msg = error.message ? error.message : JSON.stringify(error); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); let onFinished; @@ -997,9 +997,18 @@ var TimelinePanel = React.createClass({ }); }; } - const message = (error.errcode == 'M_FORBIDDEN') - ? _t("Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.") - : _t("Tried to load a specific point in this room's timeline, but was unable to find it."); + let message; + if (error.errcode == 'M_FORBIDDEN') { + message = _t( + "Tried to load a specific point in this room's timeline, but you " + + "do not have permission to view the message in question.", + ); + } else { + message = _t( + "Tried to load a specific point in this room's timeline, but was " + + "unable to find it.", + ); + } Modal.createTrackedDialog('Failed to load timeline position', '', ErrorDialog, { title: _t("Failed to load timeline position"), description: message, @@ -1104,12 +1113,13 @@ var TimelinePanel = React.createClass({ }, /** - * get the id of the event corresponding to our user's latest read-receipt. + * Get the id of the event corresponding to our user's latest read-receipt. * * @param {Boolean} ignoreSynthesized If true, return only receipts that * have been sent by the server, not * implicit ones generated by the JS * SDK. + * @return {String} the event ID */ _getCurrentReadReceipt: function(ignoreSynthesized) { const client = MatrixClientPeg.get(); diff --git a/src/components/structures/auth/Registration.js b/src/components/structures/auth/Registration.js index 0d36e592f8..708118bb22 100644 --- a/src/components/structures/auth/Registration.js +++ b/src/components/structures/auth/Registration.js @@ -28,8 +28,6 @@ import SdkConfig from '../../../SdkConfig'; import { messageForResourceLimitError } from '../../../utils/ErrorUtils'; import * as ServerType from '../../views/auth/ServerTypeSelector'; -const MIN_PASSWORD_LENGTH = 6; - // Phases // Show controls to configure server details const PHASE_SERVER_DETAILS = 0; @@ -60,7 +58,6 @@ module.exports = React.createClass({ customIsUrl: PropTypes.string, defaultHsUrl: PropTypes.string, defaultIsUrl: PropTypes.string, - skipServerDetails: PropTypes.bool, brand: PropTypes.string, email: PropTypes.string, // registration shouldn't know or care how login is done. @@ -71,26 +68,6 @@ module.exports = React.createClass({ getInitialState: function() { const serverType = ServerType.getTypeFromHsUrl(this.props.customHsUrl); - const customURLsAllowed = !SdkConfig.get()['disable_custom_urls']; - let initialPhase = this.getDefaultPhaseForServerType(serverType); - if ( - // if we have these two, skip to the good bit - // (they could come in from the URL params in a - // registration email link) - (this.props.clientSecret && this.props.sessionId) || - // if custom URLs aren't allowed, skip to form - !customURLsAllowed || - // if other logic says to, skip to form - this.props.skipServerDetails - ) { - // TODO: It would seem we've now added enough conditions here that the initial - // phase will _always_ be the form. It's tempting to remove the complexity and - // just do that, but we keep tweaking and changing auth, so let's wait until - // things settle a bit. - // Filed https://github.com/vector-im/riot-web/issues/8886 to track this. - initialPhase = PHASE_REGISTRATION; - } - return { busy: false, errorText: null, @@ -113,7 +90,7 @@ module.exports = React.createClass({ hsUrl: this.props.customHsUrl, isUrl: this.props.customIsUrl, // Phase of the overall registration dialog. - phase: initialPhase, + phase: PHASE_REGISTRATION, flows: null, }; }, @@ -308,58 +285,6 @@ module.exports = React.createClass({ }); }, - onFormValidationChange: function(fieldErrors) { - // `fieldErrors` is an object mapping field IDs to error codes when there is an - // error or `null` for no error, so the values array will be something like: - // `[ null, "RegistrationForm.ERR_PASSWORD_MISSING", null]` - // Find the first non-null error code and show that. - const errCode = Object.values(fieldErrors).find(value => !!value); - if (!errCode) { - this.setState({ - errorText: null, - }); - return; - } - - let errMsg; - switch (errCode) { - case "RegistrationForm.ERR_PASSWORD_MISSING": - errMsg = _t('Missing password.'); - break; - case "RegistrationForm.ERR_PASSWORD_MISMATCH": - errMsg = _t('Passwords don\'t match.'); - break; - case "RegistrationForm.ERR_PASSWORD_LENGTH": - errMsg = _t('Password too short (min %(MIN_PASSWORD_LENGTH)s).', {MIN_PASSWORD_LENGTH}); - break; - case "RegistrationForm.ERR_EMAIL_INVALID": - errMsg = _t('This doesn\'t look like a valid email address.'); - break; - case "RegistrationForm.ERR_PHONE_NUMBER_INVALID": - errMsg = _t('This doesn\'t look like a valid phone number.'); - break; - case "RegistrationForm.ERR_MISSING_EMAIL": - errMsg = _t('An email address is required to register on this homeserver.'); - break; - case "RegistrationForm.ERR_MISSING_PHONE_NUMBER": - errMsg = _t('A phone number is required to register on this homeserver.'); - break; - case "RegistrationForm.ERR_USERNAME_INVALID": - errMsg = _t("A username can only contain lower case letters, numbers and '=_-./'"); - break; - case "RegistrationForm.ERR_USERNAME_BLANK": - errMsg = _t('You need to enter a username.'); - break; - default: - console.error("Unknown error code: %s", errCode); - errMsg = _t('An unknown error occurred.'); - break; - } - this.setState({ - errorText: errMsg, - }); - }, - onLoginClick: function(ev) { ev.preventDefault(); ev.stopPropagation(); @@ -534,8 +459,6 @@ module.exports = React.createClass({ defaultPhoneCountry={this.state.formVals.phoneCountry} defaultPhoneNumber={this.state.formVals.phoneNumber} defaultPassword={this.state.formVals.password} - minPasswordLength={MIN_PASSWORD_LENGTH} - onValidationChange={this.onFormValidationChange} onRegisterClick={this.onFormSubmit} onEditServerDetailsClick={onEditServerDetailsClick} flows={this.state.flows} diff --git a/src/components/views/auth/RegistrationForm.js b/src/components/views/auth/RegistrationForm.js index 1784ab61c3..7c083ea270 100644 --- a/src/components/views/auth/RegistrationForm.js +++ b/src/components/views/auth/RegistrationForm.js @@ -25,6 +25,7 @@ import Modal from '../../../Modal'; import { _t } from '../../../languageHandler'; import SdkConfig from '../../../SdkConfig'; import { SAFE_LOCALPART_REGEX } from '../../../Registration'; +import withValidation from '../elements/Validation'; const FIELD_EMAIL = 'field_email'; const FIELD_PHONE_NUMBER = 'field_phone_number'; @@ -32,6 +33,8 @@ const FIELD_USERNAME = 'field_username'; const FIELD_PASSWORD = 'field_password'; const FIELD_PASSWORD_CONFIRM = 'field_password_confirm'; +const PASSWORD_MIN_SCORE = 3; // safely unguessable: moderate protection from offline slow-hash scenario. + /** * A pure UI component which displays a registration form. */ @@ -45,8 +48,6 @@ module.exports = React.createClass({ defaultPhoneNumber: PropTypes.string, defaultUsername: PropTypes.string, defaultPassword: PropTypes.string, - minPasswordLength: PropTypes.number, - onValidationChange: PropTypes.func, onRegisterClick: PropTypes.func.isRequired, // onRegisterClick(Object) => ?Promise onEditServerDetailsClick: PropTypes.func, flows: PropTypes.arrayOf(PropTypes.object).isRequired, @@ -59,7 +60,6 @@ module.exports = React.createClass({ getDefaultProps: function() { return { - minPasswordLength: 6, onValidationChange: console.error, }; }, @@ -67,7 +67,7 @@ module.exports = React.createClass({ getInitialState: function() { return { // Field error codes by field ID - fieldErrors: {}, + fieldValid: {}, // The ISO2 country code selected in the phone number entry phoneCountry: this.props.defaultPhoneCountry, username: "", @@ -75,44 +75,37 @@ module.exports = React.createClass({ phoneNumber: "", password: "", passwordConfirm: "", + passwordComplexity: null, }; }, - onSubmit: function(ev) { + onSubmit: async function(ev) { ev.preventDefault(); - // validate everything, in reverse order so - // the error that ends up being displayed - // is the one from the first invalid field. - // It's not super ideal that this just calls - // onValidationChange once for each invalid field. - this.validateField(FIELD_PHONE_NUMBER, ev.type); - this.validateField(FIELD_EMAIL, ev.type); - this.validateField(FIELD_PASSWORD_CONFIRM, ev.type); - this.validateField(FIELD_PASSWORD, ev.type); - this.validateField(FIELD_USERNAME, ev.type); + const allFieldsValid = await this.verifyFieldsBeforeSubmit(); + if (!allFieldsValid) { + return; + } const self = this; - if (this.allFieldsValid()) { - if (this.state.email == '') { - const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); - Modal.createTrackedDialog('If you don\'t specify an email address...', '', QuestionDialog, { - title: _t("Warning!"), - description: -
- { _t("If you don't specify an email address, you won't be able to reset your password. " + - "Are you sure?") } -
, - button: _t("Continue"), - onFinished: function(confirmed) { - if (confirmed) { - self._doSubmit(ev); - } - }, - }); - } else { - self._doSubmit(ev); - } + if (this.state.email == '') { + const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); + Modal.createTrackedDialog('If you don\'t specify an email address...', '', QuestionDialog, { + title: _t("Warning!"), + description: +
+ { _t("If you don't specify an email address, you won't be able to reset your password. " + + "Are you sure?") } +
, + button: _t("Continue"), + onFinished: function(confirmed) { + if (confirmed) { + self._doSubmit(ev); + } + }, + }); + } else { + self._doSubmit(ev); } }, @@ -134,118 +127,81 @@ module.exports = React.createClass({ } }, + async verifyFieldsBeforeSubmit() { + // Blur the active element if any, so we first run its blur validation, + // which is less strict than the pass we're about to do below for all fields. + const activeElement = document.activeElement; + if (activeElement) { + activeElement.blur(); + } + + const fieldIDsInDisplayOrder = [ + FIELD_USERNAME, + FIELD_PASSWORD, + FIELD_PASSWORD_CONFIRM, + FIELD_EMAIL, + FIELD_PHONE_NUMBER, + ]; + + // Run all fields with stricter validation that no longer allows empty + // values for required fields. + for (const fieldID of fieldIDsInDisplayOrder) { + const field = this[fieldID]; + if (!field) { + continue; + } + field.validate({ allowEmpty: false }); + } + + // Validation and state updates are async, so we need to wait for them to complete + // first. Queue a `setState` callback and wait for it to resolve. + await new Promise(resolve => this.setState({}, resolve)); + + if (this.allFieldsValid()) { + return true; + } + + const invalidField = this.findFirstInvalidField(fieldIDsInDisplayOrder); + + if (!invalidField) { + return true; + } + + // Focus the first invalid field and show feedback in the stricter mode + // that no longer allows empty values for required fields. + invalidField.focus(); + invalidField.validate({ allowEmpty: false, focused: true }); + return false; + }, + /** * @returns {boolean} true if all fields were valid last time they were validated. */ allFieldsValid: function() { - const keys = Object.keys(this.state.fieldErrors); + const keys = Object.keys(this.state.fieldValid); for (let i = 0; i < keys.length; ++i) { - if (this.state.fieldErrors[keys[i]]) { + if (!this.state.fieldValid[keys[i]]) { return false; } } return true; }, - validateField: function(fieldID, eventType) { - const pwd1 = this.state.password.trim(); - const pwd2 = this.state.passwordConfirm.trim(); - const allowEmpty = eventType === "blur"; - - switch (fieldID) { - case FIELD_EMAIL: { - const email = this.state.email; - const emailValid = email === '' || Email.looksValid(email); - if (this._authStepIsRequired('m.login.email.identity') && (!emailValid || email === '')) { - this.markFieldValid(fieldID, false, "RegistrationForm.ERR_MISSING_EMAIL"); - } else this.markFieldValid(fieldID, emailValid, "RegistrationForm.ERR_EMAIL_INVALID"); - break; + findFirstInvalidField(fieldIDs) { + for (const fieldID of fieldIDs) { + if (!this.state.fieldValid[fieldID] && this[fieldID]) { + return this[fieldID]; } - case FIELD_PHONE_NUMBER: { - const phoneNumber = this.state.phoneNumber; - const phoneNumberValid = phoneNumber === '' || phoneNumberLooksValid(phoneNumber); - if (this._authStepIsRequired('m.login.msisdn') && (!phoneNumberValid || phoneNumber === '')) { - this.markFieldValid(fieldID, false, "RegistrationForm.ERR_MISSING_PHONE_NUMBER"); - } else this.markFieldValid(fieldID, phoneNumberValid, "RegistrationForm.ERR_PHONE_NUMBER_INVALID"); - break; - } - case FIELD_USERNAME: { - const username = this.state.username; - if (allowEmpty && username === '') { - this.markFieldValid(fieldID, true); - } else if (!SAFE_LOCALPART_REGEX.test(username)) { - this.markFieldValid( - fieldID, - false, - "RegistrationForm.ERR_USERNAME_INVALID", - ); - } else if (username == '') { - this.markFieldValid( - fieldID, - false, - "RegistrationForm.ERR_USERNAME_BLANK", - ); - } else { - this.markFieldValid(fieldID, true); - } - break; - } - case FIELD_PASSWORD: - if (allowEmpty && pwd1 === "") { - this.markFieldValid(fieldID, true); - } else if (pwd1 == '') { - this.markFieldValid( - fieldID, - false, - "RegistrationForm.ERR_PASSWORD_MISSING", - ); - } else if (pwd1.length < this.props.minPasswordLength) { - this.markFieldValid( - fieldID, - false, - "RegistrationForm.ERR_PASSWORD_LENGTH", - ); - } else { - this.markFieldValid(fieldID, true); - } - break; - case FIELD_PASSWORD_CONFIRM: - if (allowEmpty && pwd2 === "") { - this.markFieldValid(fieldID, true); - } else { - this.markFieldValid( - fieldID, pwd1 == pwd2, - "RegistrationForm.ERR_PASSWORD_MISMATCH", - ); - } - break; } + return null; }, - markFieldValid: function(fieldID, valid, errorCode) { - const { fieldErrors } = this.state; - if (valid) { - fieldErrors[fieldID] = null; - } else { - fieldErrors[fieldID] = errorCode; - } + markFieldValid: function(fieldID, valid) { + const { fieldValid } = this.state; + fieldValid[fieldID] = valid; this.setState({ - fieldErrors, + fieldValid, }); - this.props.onValidationChange(fieldErrors); - }, - - _classForField: function(fieldID, ...baseClasses) { - let cls = baseClasses.join(' '); - if (this.state.fieldErrors[fieldID]) { - if (cls) cls += ' '; - cls += 'error'; - } - return cls; - }, - - onEmailBlur(ev) { - this.validateField(FIELD_EMAIL, ev.type); }, onEmailChange(ev) { @@ -254,26 +210,113 @@ module.exports = React.createClass({ }); }, - onPasswordBlur(ev) { - this.validateField(FIELD_PASSWORD, ev.type); + async onEmailValidate(fieldState) { + const result = await this.validateEmailRules(fieldState); + this.markFieldValid(FIELD_EMAIL, result.valid); + return result; }, + validateEmailRules: withValidation({ + description: () => _t("Use an email address to recover your account"), + rules: [ + { + key: "required", + test: function({ value, allowEmpty }) { + return allowEmpty || !this._authStepIsRequired('m.login.email.identity') || !!value; + }, + invalid: () => _t("Enter email address (required on this homeserver)"), + }, + { + key: "email", + test: ({ value }) => !value || Email.looksValid(value), + invalid: () => _t("Doesn't look like a valid email address"), + }, + ], + }), + onPasswordChange(ev) { this.setState({ password: ev.target.value, }); }, - onPasswordConfirmBlur(ev) { - this.validateField(FIELD_PASSWORD_CONFIRM, ev.type); + async onPasswordValidate(fieldState) { + const result = await this.validatePasswordRules(fieldState); + this.markFieldValid(FIELD_PASSWORD, result.valid); + return result; }, + validatePasswordRules: withValidation({ + description: function() { + const complexity = this.state.passwordComplexity; + const score = complexity ? complexity.score : 0; + return ; + }, + rules: [ + { + key: "required", + test: ({ value, allowEmpty }) => allowEmpty || !!value, + invalid: () => _t("Enter password"), + }, + { + key: "complexity", + test: async function({ value }) { + if (!value) { + return false; + } + const { scorePassword } = await import('../../../utils/PasswordScorer'); + const complexity = scorePassword(value); + this.setState({ + passwordComplexity: complexity, + }); + return complexity.score >= PASSWORD_MIN_SCORE; + }, + valid: () => _t("Nice, strong password!"), + invalid: function() { + const complexity = this.state.passwordComplexity; + if (!complexity) { + return null; + } + const { feedback } = complexity; + return feedback.warning || feedback.suggestions[0] || _t("Keep going..."); + }, + }, + ], + }), + onPasswordConfirmChange(ev) { this.setState({ passwordConfirm: ev.target.value, }); }, + async onPasswordConfirmValidate(fieldState) { + const result = await this.validatePasswordConfirmRules(fieldState); + this.markFieldValid(FIELD_PASSWORD_CONFIRM, result.valid); + return result; + }, + + validatePasswordConfirmRules: withValidation({ + rules: [ + { + key: "required", + test: ({ value, allowEmpty }) => allowEmpty || !!value, + invalid: () => _t("Confirm password"), + }, + { + key: "match", + test: function({ value }) { + return !value || value === this.state.password; + }, + invalid: () => _t("Passwords don't match"), + }, + ], + }), + onPhoneCountryChange(newVal) { this.setState({ phoneCountry: newVal.iso2, @@ -281,26 +324,64 @@ module.exports = React.createClass({ }); }, - onPhoneNumberBlur(ev) { - this.validateField(FIELD_PHONE_NUMBER, ev.type); - }, - onPhoneNumberChange(ev) { this.setState({ phoneNumber: ev.target.value, }); }, - onUsernameBlur(ev) { - this.validateField(FIELD_USERNAME, ev.type); + async onPhoneNumberValidate(fieldState) { + const result = await this.validatePhoneNumberRules(fieldState); + this.markFieldValid(FIELD_PHONE_NUMBER, result.valid); + return result; }, + validatePhoneNumberRules: withValidation({ + description: () => _t("Other users can invite you to rooms using your contact details"), + rules: [ + { + key: "required", + test: function({ value, allowEmpty }) { + return allowEmpty || !this._authStepIsRequired('m.login.msisdn') || !!value; + }, + invalid: () => _t("Enter phone number (required on this homeserver)"), + }, + { + key: "email", + test: ({ value }) => !value || phoneNumberLooksValid(value), + invalid: () => _t("Doesn't look like a valid phone number"), + }, + ], + }), + onUsernameChange(ev) { this.setState({ username: ev.target.value, }); }, + async onUsernameValidate(fieldState) { + const result = await this.validateUsernameRules(fieldState); + this.markFieldValid(FIELD_USERNAME, result.valid); + return result; + }, + + validateUsernameRules: withValidation({ + description: () => _t("Use letters, numbers, dashes and underscores only"), + rules: [ + { + key: "required", + test: ({ value, allowEmpty }) => allowEmpty || !!value, + invalid: () => _t("Enter username"), + }, + { + key: "safeLocalpart", + test: ({ value }) => !value || SAFE_LOCALPART_REGEX.test(value), + invalid: () => _t("Some characters not allowed"), + }, + ], + }), + /** * A step is required if all flows include that step. * @@ -325,9 +406,99 @@ module.exports = React.createClass({ }); }, - render: function() { + renderEmail() { + if (!this._authStepIsUsed('m.login.email.identity')) { + return null; + } const Field = sdk.getComponent('elements.Field'); + const emailPlaceholder = this._authStepIsRequired('m.login.email.identity') ? + _t("Email") : + _t("Email (optional)"); + return this[FIELD_EMAIL] = field} + type="text" + label={emailPlaceholder} + defaultValue={this.props.defaultEmail} + value={this.state.email} + onChange={this.onEmailChange} + onValidate={this.onEmailValidate} + />; + }, + renderPassword() { + const Field = sdk.getComponent('elements.Field'); + return this[FIELD_PASSWORD] = field} + type="password" + label={_t("Password")} + defaultValue={this.props.defaultPassword} + value={this.state.password} + onChange={this.onPasswordChange} + onValidate={this.onPasswordValidate} + />; + }, + + renderPasswordConfirm() { + const Field = sdk.getComponent('elements.Field'); + return this[FIELD_PASSWORD_CONFIRM] = field} + type="password" + label={_t("Confirm")} + defaultValue={this.props.defaultPassword} + value={this.state.passwordConfirm} + onChange={this.onPasswordConfirmChange} + onValidate={this.onPasswordConfirmValidate} + />; + }, + + renderPhoneNumber() { + const threePidLogin = !SdkConfig.get().disable_3pid_login; + if (!threePidLogin || !this._authStepIsUsed('m.login.msisdn')) { + return null; + } + const CountryDropdown = sdk.getComponent('views.auth.CountryDropdown'); + const Field = sdk.getComponent('elements.Field'); + const phoneLabel = this._authStepIsRequired('m.login.msisdn') ? + _t("Phone") : + _t("Phone (optional)"); + const phoneCountry = ; + return this[FIELD_PHONE_NUMBER] = field} + type="text" + label={phoneLabel} + defaultValue={this.props.defaultPhoneNumber} + value={this.state.phoneNumber} + prefix={phoneCountry} + onChange={this.onPhoneNumberChange} + onValidate={this.onPhoneNumberValidate} + />; + }, + + renderUsername() { + const Field = sdk.getComponent('elements.Field'); + return this[FIELD_USERNAME] = field} + type="text" + autoFocus={true} + label={_t("Username")} + defaultValue={this.props.defaultUsername} + value={this.state.username} + onChange={this.onUsernameChange} + onValidate={this.onUsernameValidate} + />; + }, + + render: function() { let yourMatrixAccountText = _t('Create your Matrix account'); if (this.props.hsName) { yourMatrixAccountText = _t('Create your Matrix account on %(serverName)s', { @@ -353,53 +524,6 @@ module.exports = React.createClass({ ; } - let emailSection; - if (this._authStepIsUsed('m.login.email.identity')) { - const emailPlaceholder = this._authStepIsRequired('m.login.email.identity') ? - _t("Email") : - _t("Email (optional)"); - - emailSection = ( - - ); - } - - const threePidLogin = !SdkConfig.get().disable_3pid_login; - const CountryDropdown = sdk.getComponent('views.auth.CountryDropdown'); - let phoneSection; - if (threePidLogin && this._authStepIsUsed('m.login.msisdn')) { - const phoneLabel = this._authStepIsRequired('m.login.msisdn') ? - _t("Phone") : - _t("Phone (optional)"); - const phoneCountry = ; - - phoneSection = ; - } - const registerButton = ( ); @@ -412,48 +536,18 @@ module.exports = React.createClass({
- + {this.renderUsername()}
- - + {this.renderPassword()} + {this.renderPasswordConfirm()}
- { emailSection } - { phoneSection } + {this.renderEmail()} + {this.renderPhoneNumber()}
- {_t( - "Use an email address to recover your account. Other users " + - "can invite you to rooms using your contact details.", - )} + {_t("Use an email address to recover your account.") + " "} + {_t("Other users can invite you to rooms using your contact details.")} { registerButton }
diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js index 504729f629..2e4611f7d0 100644 --- a/src/components/views/context_menus/MessageContextMenu.js +++ b/src/components/views/context_menus/MessageContextMenu.js @@ -27,6 +27,7 @@ import Modal from '../../../Modal'; import Resend from '../../../Resend'; import SettingsStore from '../../../settings/SettingsStore'; import { isUrlPermitted } from '../../../HtmlUtils'; +import { isContentActionable } from '../../../utils/EventUtils'; module.exports = React.createClass({ displayName: 'MessageContextMenu', @@ -201,14 +202,6 @@ module.exports = React.createClass({ this.closeMenu(); }, - onReplyClick: function() { - dis.dispatch({ - action: 'reply_to_event', - event: this.props.mxEvent, - }); - this.closeMenu(); - }, - onCollapseReplyThreadClick: function() { this.props.collapseReplyThread(); this.closeMenu(); @@ -226,7 +219,6 @@ module.exports = React.createClass({ let unhidePreviewButton; let externalURLButton; let quoteButton; - let replyButton; let collapseReplyThread; // status is SENT before remote-echo, null after @@ -256,28 +248,19 @@ module.exports = React.createClass({ ); } - if (isSent && mxEvent.getType() === 'm.room.message') { - const content = mxEvent.getContent(); - if (content.msgtype && content.msgtype !== 'm.bad.encrypted' && content.hasOwnProperty('body')) { - forwardButton = ( -
- { _t('Forward Message') } + if (isContentActionable(mxEvent)) { + forwardButton = ( +
+ { _t('Forward Message') } +
+ ); + + if (this.state.canPin) { + pinButton = ( +
+ { this._isPinned() ? _t('Unpin Message') : _t('Pin Message') }
); - - replyButton = ( -
- { _t('Reply') } -
- ); - - if (this.state.canPin) { - pinButton = ( -
- { this._isPinned() ? _t('Unpin Message') : _t('Pin Message') } -
- ); - } } } @@ -368,7 +351,6 @@ module.exports = React.createClass({ { unhidePreviewButton } { permalinkButton } { quoteButton } - { replyButton } { externalURLButton } { collapseReplyThread } { e2eInfo } diff --git a/src/components/views/dialogs/LogoutDialog.js b/src/components/views/dialogs/LogoutDialog.js index 617c455dfb..5241c14096 100644 --- a/src/components/views/dialogs/LogoutDialog.js +++ b/src/components/views/dialogs/LogoutDialog.js @@ -130,7 +130,7 @@ export default class LogoutDialog extends React.Component { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); let setupButtonCaption; if (this.state.backupInfo) { - setupButtonCaption = _t("Use Key Backup"); + setupButtonCaption = _t("Connect this device to Key Backup"); } else { // if there's an error fetching the backup info, we'll just assume there's // no backup for the purpose of the button caption diff --git a/src/components/views/dialogs/TimelineExplosionDialog.js b/src/components/views/dialogs/TimelineExplosionDialog.js deleted file mode 100644 index 6e810d0421..0000000000 --- a/src/components/views/dialogs/TimelineExplosionDialog.js +++ /dev/null @@ -1,130 +0,0 @@ -/* -Copyright 2019 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 sdk from '../../../index'; -import SdkConfig from '../../../SdkConfig'; -import { _t } from '../../../languageHandler'; - -// Dev note: this should be a temporary dialog while we work out what is -// actually going on. See https://github.com/vector-im/riot-web/issues/8593 -// for more details. This dialog is almost entirely a copy/paste job of -// BugReportDialog. -export default class TimelineExplosionDialog extends React.Component { - static propTypes = { - onFinished: React.PropTypes.func.isRequired, - }; - - constructor(props, context) { - super(props, context); - this.state = { - busy: false, - progress: null, - }; - } - - _onCancel() { - console.log("Reloading without sending logs for timeline explosion"); - window.location.reload(); - } - - _onSubmit = () => { - const userText = "Caught timeline explosion\n\nhttps://github.com/vector-im/riot-web/issues/8593"; - - this.setState({busy: true, progress: null}); - this._sendProgressCallback(_t("Preparing to send logs")); - - require(['../../../rageshake/submit-rageshake'], (s) => { - s(SdkConfig.get().bug_report_endpoint_url, { - userText, - sendLogs: true, - progressCallback: this._sendProgressCallback, - }).then(() => { - console.log("Logs sent for timeline explosion - reloading Riot"); - window.location.reload(); - }, (err) => { - console.error("Error sending logs for timeline explosion - reloading anyways.", err); - window.location.reload(); - }); - }); - }; - - _sendProgressCallback = (progress) => { - this.setState({progress: progress}); - }; - - render() { - const Loader = sdk.getComponent("elements.Spinner"); - const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); - const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); - - let progress = null; - if (this.state.busy) { - progress = ( -
- {this.state.progress} ... - -
- ); - } - - return ( - -
-

- {_t( - "Riot has run into a problem which makes it difficult to show you " + - "your messages right now. Nothing has been lost and reloading the app " + - "should fix this for you. In order to assist us in troubleshooting the " + - "problem, we'd like to take a look at your debug logs. You do not need " + - "to send your logs unless you want to, but we would really appreciate " + - "it if you did. We'd also like to apologize for having to show this " + - "message to you - we hope your debug logs are the key to solving the " + - "issue once and for all. If you'd like more information on the bug you've " + - "accidentally run into, please visit the issue.", - {}, - { - 'a': (sub) => { - return {sub}; - }, - }, - )} -

-

- {_t( - "Debug logs contain application usage data including your " + - "username, the IDs or aliases of the rooms or groups you " + - "have visited and the usernames of other users. They do " + - "not contain messages.", - )} -

- {progress} -
- -
- ); - } -} - diff --git a/src/components/views/elements/Field.js b/src/components/views/elements/Field.js index 12e20ad789..93bea70fc8 100644 --- a/src/components/views/elements/Field.js +++ b/src/components/views/elements/Field.js @@ -18,6 +18,10 @@ import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import sdk from '../../../index'; +import { throttle } from 'lodash'; + +// Invoke validation from user input (when typing, etc.) at most once every N ms. +const VALIDATION_THROTTLE_MS = 200; export default class Field extends React.PureComponent { static propTypes = { @@ -53,20 +57,73 @@ export default class Field extends React.PureComponent { }; } - onChange = (ev) => { - if (this.props.onValidate) { - const result = this.props.onValidate(ev.target.value); - this.setState({ - valid: result.valid, - feedback: result.feedback, - }); + onFocus = (ev) => { + this.validate({ + focused: true, + }); + // Parent component may have supplied its own `onFocus` as well + if (this.props.onFocus) { + this.props.onFocus(ev); } + }; + + onChange = (ev) => { + this.validateOnChange(); // Parent component may have supplied its own `onChange` as well if (this.props.onChange) { this.props.onChange(ev); } }; + onBlur = (ev) => { + this.validate({ + focused: false, + }); + // Parent component may have supplied its own `onBlur` as well + if (this.props.onBlur) { + this.props.onBlur(ev); + } + }; + + focus() { + this.input.focus(); + } + + async validate({ focused, allowEmpty = true }) { + if (!this.props.onValidate) { + return; + } + const value = this.input ? this.input.value : null; + const { valid, feedback } = await this.props.onValidate({ + value, + focused, + allowEmpty, + }); + + if (feedback) { + this.setState({ + valid, + feedback, + feedbackVisible: true, + }); + } else { + // When we receive null `feedback`, we want to hide the tooltip. + // We leave the previous `feedback` content in state without updating it, + // so that we can hide the tooltip containing the most recent feedback + // via CSS animation. + this.setState({ + valid, + feedbackVisible: false, + }); + } + } + + validateOnChange = throttle(() => { + this.validate({ + focused: true, + }); + }, VALIDATION_THROTTLE_MS); + render() { const { element, prefix, onValidate, children, ...inputProps } = this.props; @@ -74,10 +131,12 @@ export default class Field extends React.PureComponent { // Set some defaults for the element inputProps.type = inputProps.type || "text"; - inputProps.ref = "fieldInput"; + inputProps.ref = input => this.input = input; inputProps.placeholder = inputProps.placeholder || inputProps.label; + inputProps.onFocus = this.onFocus; inputProps.onChange = this.onChange; + inputProps.onBlur = this.onBlur; const fieldInput = React.createElement(inputElement, inputProps, children); @@ -95,12 +154,13 @@ export default class Field extends React.PureComponent { mx_Field_invalid: onValidate && this.state.valid === false, }); - // handle displaying feedback on validity + // Handle displaying feedback on validity const Tooltip = sdk.getComponent("elements.Tooltip"); - let feedback; + let tooltip; if (this.state.feedback) { - feedback = ; } @@ -109,7 +169,7 @@ export default class Field extends React.PureComponent { {prefixContainer} {fieldInput} - {feedback} + {tooltip}
; } } diff --git a/src/components/views/elements/Tooltip.js b/src/components/views/elements/Tooltip.js index 473aeb3bdc..1cc82978ed 100644 --- a/src/components/views/elements/Tooltip.js +++ b/src/components/views/elements/Tooltip.js @@ -31,10 +31,20 @@ module.exports = React.createClass({ className: React.PropTypes.string, // Class applied to the tooltip itself tooltipClassName: React.PropTypes.string, + // Whether the tooltip is visible or hidden. + // The hidden state allows animating the tooltip away via CSS. + // Defaults to visible if unset. + visible: React.PropTypes.bool, // the react element to put into the tooltip label: React.PropTypes.node, }, + getDefaultProps() { + return { + visible: true, + }; + }, + // Create a wrapper for the tooltip outside the parent and attach it to the body element componentDidMount: function() { this.tooltipContainer = document.createElement("div"); @@ -85,7 +95,10 @@ module.exports = React.createClass({ style = this._updatePosition(style); style.display = "block"; - const tooltipClasses = classNames("mx_Tooltip", this.props.tooltipClassName); + const tooltipClasses = classNames("mx_Tooltip", this.props.tooltipClassName, { + "mx_Tooltip_visible": this.props.visible, + "mx_Tooltip_invisible": !this.props.visible, + }); const tooltip = (
diff --git a/src/components/views/elements/Validation.js b/src/components/views/elements/Validation.js new file mode 100644 index 0000000000..31363b87c8 --- /dev/null +++ b/src/components/views/elements/Validation.js @@ -0,0 +1,131 @@ +/* +Copyright 2019 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. +*/ + +/* eslint-disable babel/no-invalid-this */ + +import classNames from 'classnames'; + +/** + * Creates a validation function from a set of rules describing what to validate. + * + * @param {Function} description + * Function that returns a string summary of the kind of value that will + * meet the validation rules. Shown at the top of the validation feedback. + * @param {Object} rules + * An array of rules describing how to check to input value. Each rule in an object + * and may have the following properties: + * - `key`: A unique ID for the rule. Required. + * - `test`: A function used to determine the rule's current validity. Required. + * - `valid`: Function returning text to show when the rule is valid. Only shown if set. + * - `invalid`: Function returning text to show when the rule is invalid. Only shown if set. + * @returns {Function} + * A validation function that takes in the current input value and returns + * the overall validity and a feedback UI that can be rendered for more detail. + */ +export default function withValidation({ description, rules }) { + return async function onValidate({ value, focused, allowEmpty = true }) { + if (!value && allowEmpty) { + return { + valid: null, + feedback: null, + }; + } + + const results = []; + let valid = true; + if (rules && rules.length) { + for (const rule of rules) { + if (!rule.key || !rule.test) { + continue; + } + // We're setting `this` to whichever component holds the validation + // function. That allows rules to access the state of the component. + const ruleValid = await rule.test.call(this, { value, allowEmpty }); + valid = valid && ruleValid; + if (ruleValid && rule.valid) { + // If the rule's result is valid and has text to show for + // the valid state, show it. + const text = rule.valid.call(this); + if (!text) { + continue; + } + results.push({ + key: rule.key, + valid: true, + text, + }); + } else if (!ruleValid && rule.invalid) { + // If the rule's result is invalid and has text to show for + // the invalid state, show it. + const text = rule.invalid.call(this); + if (!text) { + continue; + } + results.push({ + key: rule.key, + valid: false, + text, + }); + } + } + } + + // Hide feedback when not focused + if (!focused) { + return { + valid, + feedback: null, + }; + } + + let details; + if (results && results.length) { + details =
    + {results.map(result => { + const classes = classNames({ + "mx_Validation_detail": true, + "mx_Validation_valid": result.valid, + "mx_Validation_invalid": !result.valid, + }); + return
  • + {result.text} +
  • ; + })} +
; + } + + let summary; + if (description) { + // We're setting `this` to whichever component holds the validation + // function. That allows rules to access the state of the component. + const content = description.call(this); + summary =
{content}
; + } + + let feedback; + if (summary || details) { + feedback =
+ {summary} + {details} +
; + } + + return { + valid, + feedback, + }; + }; +} diff --git a/src/components/views/messages/MessageActionBar.js b/src/components/views/messages/MessageActionBar.js new file mode 100644 index 0000000000..74eb4165e9 --- /dev/null +++ b/src/components/views/messages/MessageActionBar.js @@ -0,0 +1,223 @@ +/* +Copyright 2019 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 classNames from 'classnames'; + +import { _t } from '../../../languageHandler'; +import sdk from '../../../index'; +import dis from '../../../dispatcher'; +import Modal from '../../../Modal'; +import { createMenu } from '../../structures/ContextualMenu'; +import SettingsStore from '../../../settings/SettingsStore'; +import { isContentActionable } from '../../../utils/EventUtils'; + +export default class MessageActionBar extends React.PureComponent { + static propTypes = { + mxEvent: PropTypes.object.isRequired, + permalinkCreator: PropTypes.object, + getTile: PropTypes.func, + getReplyThread: PropTypes.func, + onFocusChange: PropTypes.func, + }; + + constructor(props) { + super(props); + + this.state = { + agreeDimension: null, + likeDimension: null, + }; + } + + onFocusChange = (focused) => { + if (!this.props.onFocusChange) { + return; + } + this.props.onFocusChange(focused); + } + + onCryptoClicked = () => { + const event = this.props.mxEvent; + Modal.createTrackedDialogAsync('Encrypted Event Dialog', '', + import('../../../async-components/views/dialogs/EncryptedEventDialog'), + {event}, + ); + } + + onAgreeClick = (ev) => { + this.toggleDimensionValue("agreeDimension", "agree"); + } + + onDisagreeClick = (ev) => { + this.toggleDimensionValue("agreeDimension", "disagree"); + } + + onLikeClick = (ev) => { + this.toggleDimensionValue("likeDimension", "like"); + } + + onDislikeClick = (ev) => { + this.toggleDimensionValue("likeDimension", "dislike"); + } + + toggleDimensionValue(dimension, value) { + const state = this.state[dimension]; + const newState = state !== value ? value : null; + this.setState({ + [dimension]: newState, + }); + // TODO: Send the reaction event + } + + onReplyClick = (ev) => { + dis.dispatch({ + action: 'reply_to_event', + event: this.props.mxEvent, + }); + } + + onOptionsClick = (ev) => { + const MessageContextMenu = sdk.getComponent('context_menus.MessageContextMenu'); + const buttonRect = ev.target.getBoundingClientRect(); + + // The window X and Y offsets are to adjust position when zoomed in to page + const x = buttonRect.right + window.pageXOffset; + const y = (buttonRect.top + (buttonRect.height / 2) + window.pageYOffset) - 19; + + const { getTile, getReplyThread } = this.props; + const tile = getTile && getTile(); + const replyThread = getReplyThread && getReplyThread(); + + let e2eInfoCallback = null; + if (this.props.mxEvent.isEncrypted()) { + e2eInfoCallback = () => this.onCryptoClicked(); + } + + createMenu(MessageContextMenu, { + chevronOffset: 10, + mxEvent: this.props.mxEvent, + left: x, + top: y, + permalinkCreator: this.props.permalinkCreator, + eventTileOps: tile && tile.getEventTileOps ? tile.getEventTileOps() : undefined, + collapseReplyThread: replyThread && replyThread.canCollapse() ? replyThread.collapse : undefined, + e2eInfoCallback: e2eInfoCallback, + onFinished: () => { + this.onFocusChange(false); + }, + }); + + this.onFocusChange(true); + } + + isReactionsEnabled() { + return SettingsStore.isFeatureEnabled("feature_reactions"); + } + + renderAgreeDimension() { + if (!this.isReactionsEnabled()) { + return null; + } + + const state = this.state.agreeDimension; + const options = [ + { + key: "agree", + content: "👍", + onClick: this.onAgreeClick, + }, + { + key: "disagree", + content: "👎", + onClick: this.onDisagreeClick, + }, + ]; + + return + {this.renderReactionDimensionItems(state, options)} + ; + } + + renderLikeDimension() { + if (!this.isReactionsEnabled()) { + return null; + } + + const state = this.state.likeDimension; + const options = [ + { + key: "like", + content: "🙂", + onClick: this.onLikeClick, + }, + { + key: "dislike", + content: "😔", + onClick: this.onDislikeClick, + }, + ]; + + return + {this.renderReactionDimensionItems(state, options)} + ; + } + + renderReactionDimensionItems(state, options) { + return options.map(option => { + const disabled = state && state !== option.key; + const classes = classNames({ + mx_MessageActionBar_reactionDisabled: disabled, + }); + return + {option.content} + ; + }); + } + + render() { + let agreeDimensionReactionButtons; + let likeDimensionReactionButtons; + let replyButton; + + if (isContentActionable(this.props.mxEvent)) { + agreeDimensionReactionButtons = this.renderAgreeDimension(); + likeDimensionReactionButtons = this.renderLikeDimension(); + replyButton = ; + } + + return
+ {agreeDimensionReactionButtons} + {likeDimensionReactionButtons} + {replyButton} + +
; + } +} diff --git a/src/components/views/messages/ReactionsRow.js b/src/components/views/messages/ReactionsRow.js new file mode 100644 index 0000000000..a4299b9853 --- /dev/null +++ b/src/components/views/messages/ReactionsRow.js @@ -0,0 +1,65 @@ +/* +Copyright 2019 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 sdk from '../../../index'; +import { isContentActionable } from '../../../utils/EventUtils'; + +// TODO: Actually load reactions from the timeline +// Since we don't yet load reactions, let's inject some dummy data for testing the UI +// only. The UI assumes these are already sorted into the order we want to present, +// presumably highest vote first. +const SAMPLE_REACTIONS = { + "👍": 4, + "👎": 2, + "🙂": 1, +}; + +export default class ReactionsRow extends React.PureComponent { + static propTypes = { + // The event we're displaying reactions for + mxEvent: PropTypes.object.isRequired, + } + + render() { + const { mxEvent } = this.props; + + if (!isContentActionable(mxEvent)) { + return null; + } + + const content = mxEvent.getContent(); + // TODO: Remove this once we load real reactions + if (!content.body || content.body !== "reactions test") { + return null; + } + + const ReactionsRowButton = sdk.getComponent('messages.ReactionsRowButton'); + const items = Object.entries(SAMPLE_REACTIONS).map(([content, count]) => { + return ; + }); + + return
+ {items} +
; + } +} diff --git a/src/components/views/messages/ReactionsRowButton.js b/src/components/views/messages/ReactionsRowButton.js new file mode 100644 index 0000000000..985479a237 --- /dev/null +++ b/src/components/views/messages/ReactionsRowButton.js @@ -0,0 +1,65 @@ +/* +Copyright 2019 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 classNames from 'classnames'; + +export default class ReactionsRowButton extends React.PureComponent { + static propTypes = { + content: PropTypes.string.isRequired, + count: PropTypes.number.isRequired, + } + + constructor(props) { + super(props); + + // TODO: This should be derived from actual reactions you may have sent + // once we have some API to read them. + this.state = { + selected: false, + }; + } + + onClick = (ev) => { + const state = this.state.selected; + this.setState({ + selected: !state, + }); + // TODO: Send the reaction event + }; + + render() { + const { content, count } = this.props; + const { selected } = this.state; + + const classes = classNames({ + mx_ReactionsRowButton: true, + mx_ReactionsRowButton_selected: selected, + }); + + let adjustedCount = count; + if (selected) { + adjustedCount++; + } + + return + {content} {adjustedCount} + ; + } +} diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index d7c9f1e443..59025bf431 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -17,7 +17,6 @@ limitations under the License. 'use strict'; - import ReplyThread from "../elements/ReplyThread"; const React = require('react'); @@ -30,7 +29,6 @@ const sdk = require('../../../index'); const TextForEvent = require('../../../TextForEvent'); import withMatrixClient from '../../../wrappers/withMatrixClient'; -const ContextualMenu = require('../../structures/ContextualMenu'); import dis from '../../../dispatcher'; import SettingsStore from "../../../settings/SettingsStore"; import {EventStatus} from 'matrix-js-sdk'; @@ -172,8 +170,8 @@ module.exports = withMatrixClient(React.createClass({ getInitialState: function() { return { - // Whether the context menu is being displayed. - menu: false, + // Whether the action bar is focused. + actionBarFocused: false, // Whether all read receipts are being displayed. If not, only display // a truncation of them. allReadAvatars: false, @@ -309,36 +307,6 @@ module.exports = withMatrixClient(React.createClass({ return actions.tweaks.highlight; }, - onEditClicked: function(e) { - const MessageContextMenu = sdk.getComponent('context_menus.MessageContextMenu'); - const buttonRect = e.target.getBoundingClientRect(); - - // The window X and Y offsets are to adjust position when zoomed in to page - const x = buttonRect.right + window.pageXOffset; - const y = (buttonRect.top + (buttonRect.height / 2) + window.pageYOffset) - 19; - const self = this; - - const {tile, replyThread} = this.refs; - - let e2eInfoCallback = null; - if (this.props.mxEvent.isEncrypted()) e2eInfoCallback = () => this.onCryptoClicked(); - - ContextualMenu.createMenu(MessageContextMenu, { - chevronOffset: 10, - mxEvent: this.props.mxEvent, - left: x, - top: y, - permalinkCreator: this.props.permalinkCreator, - eventTileOps: tile && tile.getEventTileOps ? tile.getEventTileOps() : undefined, - collapseReplyThread: replyThread && replyThread.canCollapse() ? replyThread.collapse : undefined, - e2eInfoCallback: e2eInfoCallback, - onFinished: function() { - self.setState({menu: false}); - }, - }); - this.setState({menu: true}); - }, - toggleAllReadAvatars: function() { this.setState({ allReadAvatars: !this.state.allReadAvatars, @@ -490,6 +458,20 @@ module.exports = withMatrixClient(React.createClass({ return null; }, + onActionBarFocusChange(focused) { + this.setState({ + actionBarFocused: focused, + }); + }, + + getTile() { + return this.refs.tile; + }, + + getReplyThread() { + return this.refs.replyThread; + }, + render: function() { const MessageTimestamp = sdk.getComponent('messages.MessageTimestamp'); const SenderProfile = sdk.getComponent('messages.SenderProfile'); @@ -536,7 +518,7 @@ module.exports = withMatrixClient(React.createClass({ mx_EventTile_continuation: this.props.tileShape ? '' : this.props.continuation, mx_EventTile_last: this.props.last, mx_EventTile_contextual: this.props.contextual, - menu: this.state.menu, + mx_EventTile_actionBarFocused: this.state.actionBarFocused, mx_EventTile_verified: this.state.verified === true, mx_EventTile_unverified: this.state.verified === false, mx_EventTile_bad: isEncryptionFailure, @@ -602,9 +584,14 @@ module.exports = withMatrixClient(React.createClass({ } } - const editButton = ( - - ); + const MessageActionBar = sdk.getComponent('messages.MessageActionBar'); + const actionBar = ; const timestamp = this.props.mxEvent.getTs() ? : null; @@ -643,6 +630,14 @@ module.exports = withMatrixClient(React.createClass({
: null; + let reactions; + if (SettingsStore.isFeatureEnabled("feature_reactions")) { + const ReactionsRow = sdk.getComponent('messages.ReactionsRow'); + reactions = ; + } + switch (this.props.tileShape) { case 'notif': { const EmojiText = sdk.getComponent('elements.EmojiText'); @@ -755,7 +750,8 @@ module.exports = withMatrixClient(React.createClass({ showUrlPreview={this.props.showUrlPreview} onHeightChanged={this.props.onHeightChanged} /> { keyRequestInfo } - { editButton } + { reactions } + { actionBar } { // The avatar goes after the event tile as it's absolutly positioned to be over the diff --git a/src/components/views/rooms/RoomBreadcrumbs.js b/src/components/views/rooms/RoomBreadcrumbs.js index fff1fa7f3c..3e874c172e 100644 --- a/src/components/views/rooms/RoomBreadcrumbs.js +++ b/src/components/views/rooms/RoomBreadcrumbs.js @@ -117,6 +117,7 @@ export default class RoomBreadcrumbs extends React.Component { }; onRoomTimeline = (event, room) => { + if (!room) return; // Can be null for the notification timeline, etc. if (this.state.rooms.map(r => r.room.roomId).includes(room.roomId)) { this._calculateRoomBadges(room); } diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 55c39d3947..5d79463112 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -24,7 +24,6 @@ import MatrixClientPeg from '../../../MatrixClientPeg'; import dis from '../../../dispatcher'; import classNames from 'classnames'; import { _t } from '../../../languageHandler'; -import {getUserNameColorClass} from '../../../utils/FormattingUtils'; const MessageCase = Object.freeze({ NotLoggedIn: "NotLoggedIn", @@ -105,12 +104,6 @@ module.exports = React.createClass({ } }, - _onInviterClick(evt) { - evt.preventDefault(); - const member = this._getInviteMember(); - dis.dispatch({action: 'view_user_info', userId: member.userId}); - }, - _getMessageCase() { const isGuest = MatrixClientPeg.get().isGuest(); @@ -118,8 +111,7 @@ module.exports = React.createClass({ return MessageCase.NotLoggedIn; } - const myMember = this.props.room && - this.props.room.getMember(MatrixClientPeg.get().getUserId()); + const myMember = this._getMyMember(); if (myMember) { if (myMember.isKicked()) { @@ -158,9 +150,7 @@ module.exports = React.createClass({ }, _getKickOrBanInfo() { - const myMember = this.props.room ? - this.props.room.getMember(MatrixClientPeg.get().getUserId()) : - null; + const myMember = this._getMyMember(); if (!myMember) { return {}; } @@ -194,6 +184,13 @@ module.exports = React.createClass({ } }, + _getMyMember() { + return ( + this.props.room && + this.props.room.getMember(MatrixClientPeg.get().getUserId()) + ); + }, + _getInviteMember: function() { const {room} = this.props; if (!room) { @@ -208,6 +205,16 @@ module.exports = React.createClass({ return room.currentState.getMember(inviterUserId); }, + _isDMInvite() { + const myMember = this._getMyMember(); + if (!myMember) { + return false; + } + const memberEvent = myMember.events.member; + const memberContent = memberEvent.getContent(); + return memberContent.membership === "invite" && memberContent.is_direct; + }, + onLoginClick: function() { dis.dispatch({ action: 'start_login' }); }, @@ -279,7 +286,8 @@ module.exports = React.createClass({ break; } case MessageCase.OtherThreePIDError: { - title = _t("Something went wrong with your invite to this room"); + title = _t("Something went wrong with your invite to %(roomName)s", + {roomName: this._roomName()}); const joinRule = this._joinRule(); const errCodeMessage = _t("%(errcode)s was returned while trying to valide your invite. You could try to pass this information on to a room admin.", {errcode: this.state.threePidFetchError.errcode}, @@ -305,14 +313,19 @@ module.exports = React.createClass({ break; } case MessageCase.InvitedEmailMismatch: { - title = _t("The room invite wasn't sent to your account"); + title = _t("This invite to %(roomName)s wasn't sent to your account", + {roomName: this._roomName()}); const joinRule = this._joinRule(); if (joinRule === "public") { subTitle = _t("You can still join it because this is a public room."); primaryActionLabel = _t("Join the discussion"); primaryActionHandler = this.props.onJoinClick; } else { - subTitle = _t("Sign in with a different account, ask for another invite, or add the e-mail address %(email)s to this account.", {email: this.props.invitedEmail}); + subTitle = _t( + "Sign in with a different account, ask for another invite, or " + + "add the e-mail address %(email)s to this account.", + {email: this.props.invitedEmail}, + ); if (joinRule !== "invite") { primaryActionLabel = _t("Try to join anyway"); primaryActionHandler = this.props.onJoinClick; @@ -321,26 +334,29 @@ module.exports = React.createClass({ break; } case MessageCase.Invite: { + const RoomAvatar = sdk.getComponent("views.avatars.RoomAvatar"); + const avatar = ; + const inviteMember = this._getInviteMember(); - let avatar; let inviterElement; if (inviteMember) { - const MemberAvatar = sdk.getComponent("views.avatars.MemberAvatar"); - avatar = (); - const inviterClasses = [ - "mx_RoomPreviewBar_inviter", - getUserNameColorClass(inviteMember.userId), - ].join(" "); - inviterElement = ( - - {inviteMember.name} - - ); + inviterElement = + + {inviteMember.rawDisplayName} + ({inviteMember.userId}) + ; } else { inviterElement = ({this.props.inviterName}); } - title = _t("Do you want to join this room?"); + const isDM = this._isDMInvite(); + if (isDM) { + title = _t("Do you want to chat with %(user)s?", + { user: inviteMember.name }); + } else { + title = _t("Do you want to join %(roomName)s?", + { roomName: this._roomName() }); + } subTitle = [ avatar, _t(" invited you", {}, {userName: () => inviterElement}), @@ -354,7 +370,8 @@ module.exports = React.createClass({ } case MessageCase.ViewingRoom: { if (this.props.canPreview) { - title = _t("You're previewing this room. Want to join it?"); + title = _t("You're previewing %(roomName)s. Want to join it?", + {roomName: this._roomName()}); } else { title = _t("%(roomName)s can't be previewed. Do you want to join it?", {roomName: this._roomName(true)}); @@ -372,7 +389,10 @@ module.exports = React.createClass({ title = _t("%(roomName)s is not accessible at this time.", {roomName: this._roomName(true)}); subTitle = [ _t("Try again later, or ask a room admin to check if you have access."), - _t("%(errcode)s was returned while trying to access the room. If you think you're seeing this message in error, please submit a bug report.", + _t( + "%(errcode)s was returned while trying to access the room. " + + "If you think you're seeing this message in error, please " + + "submit a bug report.", { errcode: this.props.error.errcode }, { issueLink: label => { label } }, diff --git a/src/components/views/rooms/RoomRecoveryReminder.js b/src/components/views/rooms/RoomRecoveryReminder.js index 12fc78be4e..6b7366bc4f 100644 --- a/src/components/views/rooms/RoomRecoveryReminder.js +++ b/src/components/views/rooms/RoomRecoveryReminder.js @@ -119,7 +119,7 @@ export default class RoomRecoveryReminder extends React.PureComponent { let setupCaption; if (this.state.backupInfo) { - setupCaption = _t("Use Key Backup"); + setupCaption = _t("Connect this device to Key Backup"); } else { setupCaption = _t("Start using Key Backup"); } diff --git a/src/components/views/settings/Notifications.js b/src/components/views/settings/Notifications.js index f344f2c897..9b5688aa6a 100644 --- a/src/components/views/settings/Notifications.js +++ b/src/components/views/settings/Notifications.js @@ -507,6 +507,7 @@ module.exports = React.createClass({ //'.m.rule.member_event': 'vector', '.m.rule.call': 'vector', '.m.rule.suppress_notices': 'vector', + '.m.rule.tombstone': 'vector', // Others go to others }; @@ -562,6 +563,7 @@ module.exports = React.createClass({ //'im.vector.rule.member_event', '.m.rule.call', '.m.rule.suppress_notices', + '.m.rule.tombstone', ]; for (const i in vectorRuleIds) { const vectorRuleId = vectorRuleIds[i]; @@ -702,6 +704,10 @@ module.exports = React.createClass({ const rows = []; for (const i in this.state.vectorPushRules) { const rule = this.state.vectorPushRules[i]; + if (rule.rule === undefined && rule.vectorRuleId.startsWith(".m.")) { + console.warn(`Skipping render of rule ${rule.vectorRuleId} due to no underlying rule`); + continue; + } //console.log("rendering: " + rule.description + ", " + rule.vectorRuleId + ", " + rule.vectorState); rows.push(this.renderNotifRulesTableRow(rule.description, rule.vectorRuleId, rule.vectorState)); } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index feeff019c0..640f31c1a7 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -297,6 +297,7 @@ "Show recent room avatars above the room list": "Show recent room avatars above the room list", "Group & filter rooms by custom tags (refresh to apply changes)": "Group & filter rooms by custom tags (refresh to apply changes)", "Render simple counters in room header": "Render simple counters in room header", + "React to messages with emoji": "React to messages with emoji", "Enable Emoji suggestions while typing": "Enable Emoji suggestions while typing", "Use compact timeline layout": "Use compact timeline layout", "Show a placeholder for removed messages": "Show a placeholder for removed messages", @@ -342,6 +343,7 @@ "When I'm invited to a room": "When I'm invited to a room", "Call invitation": "Call invitation", "Messages sent by bot": "Messages sent by bot", + "When rooms are upgraded": "When rooms are upgraded", "Active call (%(roomName)s)": "Active call (%(roomName)s)", "unknown caller": "unknown caller", "Incoming voice call from %(name)s": "Incoming voice call from %(name)s", @@ -671,7 +673,6 @@ "%(senderName)s sent an image": "%(senderName)s sent an image", "%(senderName)s sent a video": "%(senderName)s sent a video", "%(senderName)s uploaded a file": "%(senderName)s uploaded a file", - "Options": "Options", "Your key share request has been sent - please check your other devices for key share requests.": "Your key share request has been sent - please check your other devices for key share requests.", "Key share requests are sent to your other devices automatically. If you rejected or dismissed the key share request on your other devices, click here to request the keys for this session again.": "Key share requests are sent to your other devices automatically. If you rejected or dismissed the key share request on your other devices, click here to request the keys for this session again.", "If your other devices do not have the key for this message you will not be able to decrypt them.": "If your other devices do not have the key for this message you will not be able to decrypt them.", @@ -727,20 +728,20 @@ "block-quote": "block-quote", "bulleted-list": "bulleted-list", "numbered-list": "numbered-list", - "Hangup": "Hangup", "Voice call": "Voice call", "Video call": "Video call", - "Upload file": "Upload file", + "Hangup": "Hangup", "Show Text Formatting Toolbar": "Show Text Formatting Toolbar", + "Upload file": "Upload file", "Send an encrypted reply…": "Send an encrypted reply…", "Send a reply (unencrypted)…": "Send a reply (unencrypted)…", "Send an encrypted message…": "Send an encrypted message…", "Send a message (unencrypted)…": "Send a message (unencrypted)…", + "Markdown is disabled": "Markdown is disabled", + "Hide Text Formatting Toolbar": "Hide Text Formatting Toolbar", "The conversation continues here.": "The conversation continues here.", "This room has been replaced and is no longer active.": "This room has been replaced and is no longer active.", "You do not have permission to post to this room": "You do not have permission to post to this room", - "Markdown is disabled": "Markdown is disabled", - "Hide Text Formatting Toolbar": "Hide Text Formatting Toolbar", "Server error": "Server error", "Server unavailable, overloaded, or something else went wrong.": "Server unavailable, overloaded, or something else went wrong.", "Command error": "Command error", @@ -804,25 +805,25 @@ "Forget this room": "Forget this room", "Re-join": "Re-join", "You were banned from %(roomName)s by %(memberName)s": "You were banned from %(roomName)s by %(memberName)s", - "Something went wrong with your invite to this room": "Something went wrong with your invite to this room", + "Something went wrong with your invite to %(roomName)s": "Something went wrong with your invite to %(roomName)s", "%(errcode)s was returned while trying to valide your invite. You could try to pass this information on to a room admin.": "%(errcode)s was returned while trying to valide your invite. You could try to pass this information on to a room admin.", "You can only join it with a working invite.": "You can only join it with a working invite.", "You can still join it because this is a public room.": "You can still join it because this is a public room.", "Join the discussion": "Join the discussion", "Try to join anyway": "Try to join anyway", - "The room invite wasn't sent to your account": "The room invite wasn't sent to your account", + "This invite to %(roomName)s wasn't sent to your account": "This invite to %(roomName)s wasn't sent to your account", "Sign in with a different account, ask for another invite, or add the e-mail address %(email)s to this account.": "Sign in with a different account, ask for another invite, or add the e-mail address %(email)s to this account.", - "Do you want to join this room?": "Do you want to join this room?", + "Do you want to chat with %(user)s?": "Do you want to chat with %(user)s?", + "Do you want to join %(roomName)s?": "Do you want to join %(roomName)s?", " invited you": " invited you", "Reject": "Reject", - "You're previewing this room. Want to join it?": "You're previewing this room. Want to join it?", + "You're previewing %(roomName)s. Want to join it?": "You're previewing %(roomName)s. Want to join it?", "%(roomName)s can't be previewed. Do you want to join it?": "%(roomName)s can't be previewed. Do you want to join it?", "%(roomName)s does not exist.": "%(roomName)s does not exist.", "This room doesn't exist. Are you sure you're at the right place?": "This room doesn't exist. Are you sure you're at the right place?", "%(roomName)s is not accessible at this time.": "%(roomName)s is not accessible at this time.", "Try again later, or ask a room admin to check if you have access.": "Try again later, or ask a room admin to check if you have access.", "%(errcode)s was returned while trying to access the room. If you think you're seeing this message in error, please submit a bug report.": "%(errcode)s was returned while trying to access the room. If you think you're seeing this message in error, please submit a bug report.", - "Use Key Backup": "Use Key Backup", "Never lose encrypted messages": "Never lose encrypted messages", "Messages in this room are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.": "Messages in this room are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.", "Securely back up your keys to avoid losing them. Learn more.": "Securely back up your keys to avoid losing them. Learn more.", @@ -890,6 +891,10 @@ "Today": "Today", "Yesterday": "Yesterday", "Error decrypting audio": "Error decrypting audio", + "Agree or Disagree": "Agree or Disagree", + "Like or Dislike": "Like or Dislike", + "Reply": "Reply", + "Options": "Options", "Attachment": "Attachment", "Error decrypting attachment": "Error decrypting attachment", "Decrypt %(text)s": "Decrypt %(text)s", @@ -1206,10 +1211,6 @@ "Missing session data": "Missing session data", "Some session data, including encrypted message keys, is missing. Sign out and sign in to fix this, restoring keys from backup.": "Some session data, including encrypted message keys, is missing. Sign out and sign in to fix this, restoring keys from backup.", "Your browser likely removed this data when running low on disk space.": "Your browser likely removed this data when running low on disk space.", - "Error showing you your room": "Error showing you your room", - "Riot has run into a problem which makes it difficult to show you your messages right now. Nothing has been lost and reloading the app should fix this for you. In order to assist us in troubleshooting the problem, we'd like to take a look at your debug logs. You do not need to send your logs unless you want to, but we would really appreciate it if you did. We'd also like to apologize for having to show this message to you - we hope your debug logs are the key to solving the issue once and for all. If you'd like more information on the bug you've accidentally run into, please visit the issue.": "Riot has run into a problem which makes it difficult to show you your messages right now. Nothing has been lost and reloading the app should fix this for you. In order to assist us in troubleshooting the problem, we'd like to take a look at your debug logs. You do not need to send your logs unless you want to, but we would really appreciate it if you did. We'd also like to apologize for having to show this message to you - we hope your debug logs are the key to solving the issue once and for all. If you'd like more information on the bug you've accidentally run into, please visit the issue.", - "Send debug logs and reload Riot": "Send debug logs and reload Riot", - "Reload Riot without sending logs": "Reload Riot without sending logs", "You are currently blacklisting unverified devices; to send messages to these devices you must verify them.": "You are currently blacklisting unverified devices; to send messages to these devices you must verify them.", "We recommend you go through the verification process for each device to confirm they belong to their legitimate owner, but you can resend the message without verifying if you prefer.": "We recommend you go through the verification process for each device to confirm they belong to their legitimate owner, but you can resend the message without verifying if you prefer.", "Room contains unknown devices": "Room contains unknown devices", @@ -1260,7 +1261,6 @@ "Resend": "Resend", "Cancel Sending": "Cancel Sending", "Forward Message": "Forward Message", - "Reply": "Reply", "Pin Message": "Pin Message", "View Source": "View Source", "View Decrypted Source": "View Decrypted Source", @@ -1323,12 +1323,26 @@ "Change": "Change", "Sign in with": "Sign in with", "If you don't specify an email address, you won't be able to reset your password. Are you sure?": "If you don't specify an email address, you won't be able to reset your password. Are you sure?", + "Use an email address to recover your account": "Use an email address to recover your account", + "Enter email address (required on this homeserver)": "Enter email address (required on this homeserver)", + "Doesn't look like a valid email address": "Doesn't look like a valid email address", + "Enter password": "Enter password", + "Nice, strong password!": "Nice, strong password!", + "Keep going...": "Keep going...", + "Passwords don't match": "Passwords don't match", + "Other users can invite you to rooms using your contact details": "Other users can invite you to rooms using your contact details", + "Enter phone number (required on this homeserver)": "Enter phone number (required on this homeserver)", + "Doesn't look like a valid phone number": "Doesn't look like a valid phone number", + "Use letters, numbers, dashes and underscores only": "Use letters, numbers, dashes and underscores only", + "Enter username": "Enter username", + "Some characters not allowed": "Some characters not allowed", + "Email (optional)": "Email (optional)", + "Confirm": "Confirm", + "Phone (optional)": "Phone (optional)", "Create your Matrix account": "Create your Matrix account", "Create your Matrix account on %(serverName)s": "Create your Matrix account on %(serverName)s", - "Email (optional)": "Email (optional)", - "Phone (optional)": "Phone (optional)", - "Confirm": "Confirm", - "Use an email address to recover your account. Other users can invite you to rooms using your contact details.": "Use an email address to recover your account. Other users can invite you to rooms using your contact details.", + "Use an email address to recover your account.": "Use an email address to recover your account.", + "Other users can invite you to rooms using your contact details.": "Other users can invite you to rooms using your contact details.", "Other servers": "Other servers", "Enter custom server URLs What does this mean?": "Enter custom server URLs What does this mean?", "Homeserver URL": "Homeserver URL", @@ -1516,15 +1530,6 @@ "Registration has been disabled on this homeserver.": "Registration has been disabled on this homeserver.", "Unable to query for supported registration methods.": "Unable to query for supported registration methods.", "This server does not support authentication with a phone number.": "This server does not support authentication with a phone number.", - "Missing password.": "Missing password.", - "Passwords don't match.": "Passwords don't match.", - "Password too short (min %(MIN_PASSWORD_LENGTH)s).": "Password too short (min %(MIN_PASSWORD_LENGTH)s).", - "This doesn't look like a valid email address.": "This doesn't look like a valid email address.", - "This doesn't look like a valid phone number.": "This doesn't look like a valid phone number.", - "An email address is required to register on this homeserver.": "An email address is required to register on this homeserver.", - "A phone number is required to register on this homeserver.": "A phone number is required to register on this homeserver.", - "You need to enter a username.": "You need to enter a username.", - "An unknown error occurred.": "An unknown error occurred.", "Create your account": "Create your account", "Commands": "Commands", "Results from DuckDuckGo": "Results from DuckDuckGo", @@ -1563,7 +1568,6 @@ "File to import": "File to import", "Import": "Import", "Great! This passphrase looks strong enough.": "Great! This passphrase looks strong enough.", - "Keep going...": "Keep going...", "We'll store an encrypted copy of your keys on our server. Protect your backup with a passphrase to keep it secure.": "We'll store an encrypted copy of your keys on our server. Protect your backup with a passphrase to keep it secure.", "For maximum security, this should be different from your account password.": "For maximum security, this should be different from your account password.", "Enter a passphrase...": "Enter a passphrase...", diff --git a/src/notifications/VectorPushRulesDefinitions.js b/src/notifications/VectorPushRulesDefinitions.js index 402a69e7a6..b15fb4ccd7 100644 --- a/src/notifications/VectorPushRulesDefinitions.js +++ b/src/notifications/VectorPushRulesDefinitions.js @@ -183,4 +183,15 @@ module.exports = { off: StandardActions.ACTION_DONT_NOTIFY, }, }), + + // Room upgrades (tombstones) + ".m.rule.tombstone": new VectorPushRuleDefinition({ + kind: "override", + description: _td("When rooms are upgraded"), // passed through _t() translation in src/components/views/settings/Notifications.js + vectorStateToActions: { // The actions for each vector state, or null to disable the rule. + on: StandardActions.ACTION_NOTIFY, + loud: StandardActions.ACTION_HIGHLIGHT, + off: StandardActions.ACTION_DISABLED, + }, + }), }; diff --git a/src/settings/Settings.js b/src/settings/Settings.js index b0014ae4b6..3ef2e8dd86 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -122,6 +122,9 @@ export const SETTINGS = { "feature_notification_sounds": { isFeature: true, displayName: _td("Custom Notification Sounds"), + "feature_reactions": { + isFeature: true, + displayName: _td("React to messages with emoji"), supportedLevels: LEVELS_FEATURE, default: false, }, diff --git a/src/utils/EventUtils.js b/src/utils/EventUtils.js new file mode 100644 index 0000000000..911257f95c --- /dev/null +++ b/src/utils/EventUtils.js @@ -0,0 +1,45 @@ +/* +Copyright 2019 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 { EventStatus } from 'matrix-js-sdk'; + +/** + * Returns whether an event should allow actions like reply, reactions, edit, etc. + * which effectively checks whether it's a regular message that has been sent and that we + * can display. + * + * @param {MatrixEvent} mxEvent The event to check + * @returns {boolean} true if actionable + */ +export function isContentActionable(mxEvent) { + const { status: eventStatus } = mxEvent; + + // status is SENT before remote-echo, null after + const isSent = !eventStatus || eventStatus === EventStatus.SENT; + + if (isSent && mxEvent.getType() === 'm.room.message') { + const content = mxEvent.getContent(); + if ( + content.msgtype && + content.msgtype !== 'm.bad.encrypted' && + content.hasOwnProperty('body') + ) { + return true; + } + } + + return false; +} diff --git a/src/utils/MegolmExportEncryption.js b/src/utils/MegolmExportEncryption.js index 01c521da0c..2f2fc4cca7 100644 --- a/src/utils/MegolmExportEncryption.js +++ b/src/utils/MegolmExportEncryption.js @@ -147,7 +147,7 @@ export async function encryptMegolmKeyFile(data, password, options) { // clear bit 63 of the IV to stop us hitting the 64-bit counter boundary // (which would mean we wouldn't be able to decrypt on Android). The loss // of a single bit of iv is a price we have to pay. - iv[9] &= 0x7f; + iv[8] &= 0x7f; const [aesKey, hmacKey] = await deriveKeys(salt, kdfRounds, password); const encodedData = new TextEncoder().encode(data); diff --git a/src/utils/PasswordScorer.js b/src/utils/PasswordScorer.js index 647436c131..3c366a73f8 100644 --- a/src/utils/PasswordScorer.js +++ b/src/utils/PasswordScorer.js @@ -67,7 +67,9 @@ export function scorePassword(password) { if (password.length === 0) return null; const userInputs = ZXCVBN_USER_INPUTS.slice(); - userInputs.push(MatrixClientPeg.get().getUserIdLocalpart()); + if (MatrixClientPeg.get()) { + userInputs.push(MatrixClientPeg.get().getUserIdLocalpart()); + } let zxcvbnResult = zxcvbn(password, userInputs); // Work around https://github.com/dropbox/zxcvbn/issues/216 diff --git a/yarn.lock b/yarn.lock index a2942fd1d3..22072971eb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,17 +10,17 @@ "@babel/highlight" "^7.0.0" "@babel/core@>=7.1.0": - version "7.4.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.4.3.tgz#198d6d3af4567be3989550d97e068de94503074f" - integrity sha512-oDpASqKFlbspQfzAE7yaeTmdljSH2ADIvBlb0RwbStltTuWa0+7CCI1fYVINNv9saHPa1W7oaKeuNuKj+RQCvA== + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.4.4.tgz#84055750b05fcd50f9915a826b44fa347a825250" + integrity sha512-lQgGX3FPRgbz2SKmhMtYgJvVzGZrmjaF4apZ2bLwofAKiSjxU0drPh4S/VasyYXwaTs+A1gvQ45BN8SQJzHsQQ== dependencies: "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.4.0" - "@babel/helpers" "^7.4.3" - "@babel/parser" "^7.4.3" - "@babel/template" "^7.4.0" - "@babel/traverse" "^7.4.3" - "@babel/types" "^7.4.0" + "@babel/generator" "^7.4.4" + "@babel/helpers" "^7.4.4" + "@babel/parser" "^7.4.4" + "@babel/template" "^7.4.4" + "@babel/traverse" "^7.4.4" + "@babel/types" "^7.4.4" convert-source-map "^1.1.0" debug "^4.1.0" json5 "^2.1.0" @@ -29,23 +29,12 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.3.4": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.4.tgz#9aa48c1989257877a9d971296e5b73bfe72e446e" - integrity sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg== +"@babel/generator@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.4.4.tgz#174a215eb843fc392c7edcaabeaa873de6e8f041" + integrity sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ== dependencies: - "@babel/types" "^7.3.4" - jsesc "^2.5.1" - lodash "^4.17.11" - source-map "^0.5.0" - trim-right "^1.0.1" - -"@babel/generator@^7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.4.0.tgz#c230e79589ae7a729fd4631b9ded4dc220418196" - integrity sha512-/v5I+a1jhGSKLgZDcmAUZ4K/VePi43eRkUs3yePW1HB1iANOD5tqJXwGSG4BZhSksP8J9ejSlwGeTiiOFZOrXQ== - dependencies: - "@babel/types" "^7.4.0" + "@babel/types" "^7.4.4" jsesc "^2.5.1" lodash "^4.17.11" source-map "^0.5.0" @@ -67,28 +56,21 @@ dependencies: "@babel/types" "^7.0.0" -"@babel/helper-split-export-declaration@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz#3aae285c0311c2ab095d997b8c9a94cad547d813" - integrity sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag== +"@babel/helper-split-export-declaration@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" + integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q== dependencies: - "@babel/types" "^7.0.0" + "@babel/types" "^7.4.4" -"@babel/helper-split-export-declaration@^7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.0.tgz#571bfd52701f492920d63b7f735030e9a3e10b55" - integrity sha512-7Cuc6JZiYShaZnybDmfwhY4UYHzI6rlqhWjaIqbsJGsIqPimEYy5uh3akSRLMg65LSdSEnJ8a8/bWQN6u2oMGw== +"@babel/helpers@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.4.4.tgz#868b0ef59c1dd4e78744562d5ce1b59c89f2f2a5" + integrity sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A== dependencies: - "@babel/types" "^7.4.0" - -"@babel/helpers@^7.4.3": - version "7.4.3" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.4.3.tgz#7b1d354363494b31cb9a2417ae86af32b7853a3b" - integrity sha512-BMh7X0oZqb36CfyhvtbSmcWc3GXocfxv3yNsAEuM0l+fAqSO22rQrUpijr3oE/10jCTrB6/0b9kzmG4VetCj8Q== - dependencies: - "@babel/template" "^7.4.0" - "@babel/traverse" "^7.4.3" - "@babel/types" "^7.4.0" + "@babel/template" "^7.4.4" + "@babel/traverse" "^7.4.4" + "@babel/types" "^7.4.4" "@babel/highlight@^7.0.0": version "7.0.0" @@ -99,96 +81,57 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.2.2", "@babel/parser@^7.3.4": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.4.tgz#a43357e4bbf4b92a437fb9e465c192848287f27c" - integrity sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ== - -"@babel/parser@^7.4.0", "@babel/parser@^7.4.3": - version "7.4.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.3.tgz#eb3ac80f64aa101c907d4ce5406360fe75b7895b" - integrity sha512-gxpEUhTS1sGA63EGQGuA+WESPR/6tz6ng7tSHFCmaTJK/cGK8y37cBTspX+U2xCAue2IQVvF6Z0oigmjwD8YGQ== +"@babel/parser@^7.0.0", "@babel/parser@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.4.tgz#5977129431b8fe33471730d255ce8654ae1250b6" + integrity sha512-5pCS4mOsL+ANsFZGdvNLybx4wtqAZJ0MJjMHxvzI3bvIsz6sQvzW8XX92EYIkiPtIvcfG3Aj+Ir5VNyjnZhP7w== "@babel/runtime@^7.1.2": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.4.tgz#73d12ba819e365fcf7fd152aed56d6df97d21c83" - integrity sha512-IvfvnMdSaLBateu0jfsYIpZTxAc2cKEXEMiezGGN75QcBcecDUKd3PgLAncT0oOgxKy8dd8hrJKj9MfzgfZd6g== + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.4.tgz#dc2e34982eb236803aa27a07fea6857af1b9171d" + integrity sha512-w0+uT71b6Yi7i5SE0co4NioIpSYS6lLiXvCzWzGSKvpK5vdQtCbICHMj+gbAKAOtxiV6HsVh/MBdaF9EQ6faSg== dependencies: - regenerator-runtime "^0.12.0" + regenerator-runtime "^0.13.2" -"@babel/template@^7.1.0": - version "7.2.2" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907" - integrity sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g== +"@babel/template@^7.1.0", "@babel/template@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237" + integrity sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw== dependencies: "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.2.2" - "@babel/types" "^7.2.2" + "@babel/parser" "^7.4.4" + "@babel/types" "^7.4.4" -"@babel/template@^7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.0.tgz#12474e9c077bae585c5d835a95c0b0b790c25c8b" - integrity sha512-SOWwxxClTTh5NdbbYZ0BmaBVzxzTh2tO/TeLTbF6MO6EzVhHTnff8CdBXx3mEtazFBoysmEM6GU/wF+SuSx4Fw== +"@babel/traverse@^7.0.0", "@babel/traverse@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.4.4.tgz#0776f038f6d78361860b6823887d4f3937133fe8" + integrity sha512-Gw6qqkw/e6AGzlyj9KnkabJX7VcubqPtkUQVAwkc0wUMldr3A/hezNB3Rc5eIvId95iSGkGIOe5hh1kMKf951A== dependencies: "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.4.0" - "@babel/types" "^7.4.0" - -"@babel/traverse@^7.0.0": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.3.4.tgz#1330aab72234f8dea091b08c4f8b9d05c7119e06" - integrity sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.3.4" + "@babel/generator" "^7.4.4" "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.0.0" - "@babel/parser" "^7.3.4" - "@babel/types" "^7.3.4" + "@babel/helper-split-export-declaration" "^7.4.4" + "@babel/parser" "^7.4.4" + "@babel/types" "^7.4.4" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.11" -"@babel/traverse@^7.4.3": - version "7.4.3" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.4.3.tgz#1a01f078fc575d589ff30c0f71bf3c3d9ccbad84" - integrity sha512-HmA01qrtaCwwJWpSKpA948cBvU5BrmviAief/b3AVw936DtcdsTexlbyzNuDnthwhOQ37xshn7hvQaEQk7ISYQ== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.4.0" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.0" - "@babel/parser" "^7.4.3" - "@babel/types" "^7.4.0" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.11" - -"@babel/types@^7.0.0", "@babel/types@^7.2.2", "@babel/types@^7.3.4": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.3.4.tgz#bf482eaeaffb367a28abbf9357a94963235d90ed" - integrity sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ== +"@babel/types@^7.0.0", "@babel/types@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.4.4.tgz#8db9e9a629bb7c29370009b4b779ed93fe57d5f0" + integrity sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ== dependencies: esutils "^2.0.2" lodash "^4.17.11" to-fast-properties "^2.0.0" -"@babel/types@^7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.4.0.tgz#670724f77d24cce6cc7d8cf64599d511d164894c" - integrity sha512-aPvkXyU2SPOnztlgo8n9cEiXW755mgyvueUPcpStqdzoSPm0fjO0vQBjLkt3JKJW7ufikfcnMTTPsN1xaTsBPA== - dependencies: - esutils "^2.0.2" - lodash "^4.17.11" - to-fast-properties "^2.0.0" - -"@jest/console@^24.3.0": - version "24.3.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.3.0.tgz#7bd920d250988ba0bf1352c4493a48e1cb97671e" - integrity sha512-NaCty/OOei6rSDcbPdMiCbYCI0KGFGPgGO6B09lwWt5QTxnkuhKYET9El5u5z1GAcSxkQmSMtM63e24YabCWqA== +"@jest/console@^24.7.1": + version "24.7.1" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.7.1.tgz#32a9e42535a97aedfe037e725bd67e954b459545" + integrity sha512-iNhtIy2M8bXlAOULWVTUxmnelTLFneTNEkHCgPmgd+zNwy9zVddJ6oS5rZ9iwoscNdT5mMwUd0C51v/fSlzItg== dependencies: "@jest/source-map" "^24.3.0" - "@types/node" "*" chalk "^2.0.1" slash "^2.0.0" @@ -201,21 +144,21 @@ graceful-fs "^4.1.15" source-map "^0.6.0" -"@jest/test-result@^24.3.0": - version "24.3.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.3.0.tgz#4c0b1c9716212111920f7cf8c4329c69bc81924a" - integrity sha512-j7UZ49T8C4CVipEY99nLttnczVTtLyVzFfN20OiBVn7awOs0U3endXSTq7ouPrLR5y4YjI5GDcbcvDUjgeamzg== +"@jest/test-result@^24.7.1": + version "24.7.1" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.7.1.tgz#19eacdb29a114300aed24db651e5d975f08b6bbe" + integrity sha512-3U7wITxstdEc2HMfBX7Yx3JZgiNBubwDqQMh+BXmZXHa3G13YWF3p6cK+5g0hGkN3iufg/vGPl3hLxQXD74Npg== dependencies: - "@jest/console" "^24.3.0" - "@jest/types" "^24.3.0" - "@types/istanbul-lib-coverage" "^1.1.0" + "@jest/console" "^24.7.1" + "@jest/types" "^24.7.0" + "@types/istanbul-lib-coverage" "^2.0.0" -"@jest/types@^24.3.0": - version "24.3.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.3.0.tgz#3f6e117e47248a9a6b5f1357ec645bd364f7ad23" - integrity sha512-VoO1F5tU2n/93QN/zaZ7Q8SeV/Rj+9JJOgbvKbBwy4lenvmdj1iDaQEPXGTKrO6OSvDeb2drTFipZJYxgo6kIQ== +"@jest/types@^24.7.0": + version "24.7.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.7.0.tgz#c4ec8d1828cdf23234d9b4ee31f5482a3f04f48b" + integrity sha512-ipJUa2rFWiKoBqMKP63Myb6h9+iT3FHRTF2M8OR6irxWzItisa8i4dcSg14IbvmXUnBlHBlUQPYUHWyX3UPpYA== dependencies: - "@types/istanbul-lib-coverage" "^1.1.0" + "@types/istanbul-lib-coverage" "^2.0.0" "@types/yargs" "^12.0.9" "@mrmlnc/readdir-enhanced@^2.2.1": @@ -254,9 +197,9 @@ "@sinonjs/samsam" "^3.1.0" "@sinonjs/samsam@^3.1.0": - version "3.3.0" - resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-3.3.0.tgz#9557ea89cd39dbc94ffbd093c8085281cac87416" - integrity sha512-beHeJM/RRAaLLsMJhsCvHK31rIqZuobfPLa/80yGH5hnD8PV1hyh9xJBJNFfNmO7yWqm+zomijHsXpI6iTQJfQ== + version "3.3.1" + resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-3.3.1.tgz#e88c53fbd9d91ad9f0f2b0140c16c7c107fe0d07" + integrity sha512-wRSfmyd81swH0hA1bxJZJ57xr22kC07a1N4zuIL47yTS04bDk6AoCkczcqHEjcRPmJ+FruGJ9WBQiJwMtIElFw== dependencies: "@sinonjs/commons" "^1.0.2" array-from "^2.1.1" @@ -281,10 +224,10 @@ "@types/minimatch" "*" "@types/node" "*" -"@types/istanbul-lib-coverage@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.0.tgz#2cc2ca41051498382b43157c8227fea60363f94a" - integrity sha512-ohkhb9LehJy+PA40rDtGAji61NCgdtKLAlFoYp4cnuuQEswwdK3vz9SOIkkyc3wrk8dzjphQApNs56yyXLStaQ== +"@types/istanbul-lib-coverage@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" + integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg== "@types/minimatch@*": version "3.0.3" @@ -292,9 +235,9 @@ integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== "@types/node@*": - version "11.11.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.0.tgz#070e9ce7c90e727aca0e0c14e470f9a93ffe9390" - integrity sha512-D5Rt+HXgEywr3RQJcGlZUCTCx1qVbCZpVk3/tOOA6spLNZdGm8BU+zRgdRYDoF1pO3RuXLxADzMrF903JlQXqg== + version "11.13.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-11.13.9.tgz#f80697caca7f7fb2526527a5c5a2743487f05ccc" + integrity sha512-NJ4yuEVw5podZbINp3tEqUIImMSAEHaCXRiWCf3KC32l6hIKf0iPJEh2uZdT0fELfRYk310yLmMXqy2leZQUbg== "@types/stack-utils@^1.0.1": version "1.0.1" @@ -324,9 +267,9 @@ "@types/vfile-message" "*" "@types/yargs@^12.0.9": - version "12.0.9" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.9.tgz#693e76a52f61a2f1e7fb48c0eef167b95ea4ffd0" - integrity sha512-sCZy4SxP9rN2w30Hlmg5dtdRwgYQfYRiLo9usw8X9cxlf+H4FqM1xX7+sNH7NNKVdbXMJWqva7iyy+fxh/V7fA== + version "12.0.12" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.12.tgz#45dd1d0638e8c8f153e87d296907659296873916" + integrity sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw== "@webassemblyjs/ast@1.8.5": version "1.8.5" @@ -490,12 +433,12 @@ abbrev@1: integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== accepts@~1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" - integrity sha1-63d99gEXI6OxTopywIBcjoZ0a9I= + version "1.3.7" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" + integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== dependencies: - mime-types "~2.1.18" - negotiator "0.6.1" + mime-types "~2.1.24" + negotiator "0.6.2" acorn-dynamic-import@^4.0.0: version "4.0.0" @@ -731,9 +674,9 @@ astral-regex@^1.0.0: integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== async-each@^1.0.0, async-each@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" - integrity sha1-GdOGodntxufByF04iu28xW0zYC0= + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== async-limiter@~1.0.0: version "1.0.0" @@ -1569,9 +1512,9 @@ big.js@^5.2.2: integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== binary-extensions@^1.0.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.0.tgz#9523e001306a32444b907423f1de2164222f6ab1" - integrity sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw== + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== blob@0.0.5: version "0.0.5" @@ -1579,9 +1522,9 @@ blob@0.0.5: integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig== bluebird@^3.3.0, bluebird@^3.5.0, bluebird@^3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" - integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw== + version "3.5.4" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.4.tgz#d6cc661595de30d5b3af5fcedd3c0b3ef6ec5714" + integrity sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw== blueimp-canvas-to-blob@^3.5.0: version "3.14.0" @@ -1594,20 +1537,20 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== body-parser@^1.16.1: - version "1.18.3" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" - integrity sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ= + version "1.19.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== dependencies: - bytes "3.0.0" + bytes "3.1.0" content-type "~1.0.4" debug "2.6.9" depd "~1.1.2" - http-errors "~1.6.3" - iconv-lite "0.4.23" + http-errors "1.7.2" + iconv-lite "0.4.24" on-finished "~2.3.0" - qs "6.5.2" - raw-body "2.3.3" - type-is "~1.6.16" + qs "6.7.0" + raw-body "2.4.0" + type-is "~1.6.17" brace-expansion@^1.1.7: version "1.1.11" @@ -1722,13 +1665,13 @@ browserify-zlib@^0.2.0: pako "~1.0.5" browserslist@^4.5.4: - version "4.5.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.5.4.tgz#166c4ecef3b51737a42436ea8002aeea466ea2c7" - integrity sha512-rAjx494LMjqKnMPhFkuLmLp8JWEX0o8ADTGeAbOqaF+XCvYLreZrG5uVjnPBlAQ8REZK4pzXGvp0bWgrFtKaag== + version "4.5.6" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.5.6.tgz#ea42e8581ca2513fa7f371d4dd66da763938163d" + integrity sha512-o/hPOtbU9oX507lIqon+UvPYqpx3mHc8cV3QemSBTXwkG8gSQSK6UKvXcE/DcleU3+A59XTUHyCvZ5qGy8xVAg== dependencies: - caniuse-lite "^1.0.30000955" - electron-to-chromium "^1.3.122" - node-releases "^1.1.13" + caniuse-lite "^1.0.30000963" + electron-to-chromium "^1.3.127" + node-releases "^1.1.17" bs58@^4.0.1: version "4.0.1" @@ -1779,10 +1722,10 @@ builtin-status-codes@^3.0.0: resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= +bytes@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" + integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== cacache@^11.0.2: version "11.3.2" @@ -1849,9 +1792,9 @@ callsites@^2.0.0: integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= callsites@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.0.0.tgz#fb7eb569b72ad7a45812f93fd9430a3e410b3dd3" - integrity sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw== + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== camelcase-keys@^4.0.0: version "4.2.0" @@ -1868,14 +1811,14 @@ camelcase@^4.1.0: integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= camelcase@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.2.0.tgz#e7522abda5ed94cc0489e1b8466610e88404cf45" - integrity sha512-IXFsBS2pC+X0j0N/GE7Dm7j3bsEBp+oTpb7F50dwEVX7rf3IgwO9XatnegTsDtniKCUtEJH4fSU6Asw7uoVLfQ== + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -caniuse-lite@^1.0.30000955, caniuse-lite@^1.0.30000957: - version "1.0.30000957" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000957.tgz#fb1026bf184d7d62c685205358c3b24b9e29f7b3" - integrity sha512-8wxNrjAzyiHcLXN/iunskqQnJquQQ6VX8JHfW5kLgAPRSiSuKZiNfmIkP5j7jgyXqAQBSoXyJxfnbCFS0ThSiQ== +caniuse-lite@^1.0.30000957, caniuse-lite@^1.0.30000963: + version "1.0.30000966" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000966.tgz#f3c6fefacfbfbfb981df6dfa68f2aae7bff41b64" + integrity sha512-qqLQ/uYrpZmFhPY96VuBkMEo8NhVFBZ9y/Bh+KnvGzGJ5I8hvpIaWlF2pw5gqe4PLAL+ZjsPgMOvoXSpX21Keg== caseless@~0.12.0: version "0.12.0" @@ -1949,9 +1892,9 @@ chokidar@^1.6.1: fsevents "^1.0.0" chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.2.tgz#9c23ea40b01638439e0513864d362aeacc5ad058" - integrity sha512-IwXUx0FXc5ibYmPC2XeEj5mpXoV66sR+t3jqu2NS2GYwCktt3KF1/Qqjws/NkegajBA4RbZ5+DDwlOiJsxDHEg== + version "2.1.5" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.5.tgz#0ae8434d962281a5f56c72869e79cb6d9d86ad4d" + integrity sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A== dependencies: anymatch "^2.0.0" async-each "^1.0.1" @@ -1963,7 +1906,7 @@ chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.1.2: normalize-path "^3.0.0" path-is-absolute "^1.0.0" readdirp "^2.2.1" - upath "^1.1.0" + upath "^1.1.1" optionalDependencies: fsevents "^1.2.7" @@ -2079,9 +2022,9 @@ commander@2.15.1: integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== commander@^2.11.0, commander@^2.19.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" - integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== + version "2.20.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" + integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== commondir@^1.0.1: version "1.0.1" @@ -2103,11 +2046,16 @@ component-bind@1.0.0: resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E= -component-emitter@1.2.1, component-emitter@^1.2.1: +component-emitter@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + component-inherit@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" @@ -2357,7 +2305,7 @@ date-now@^0.1.4: resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= -debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -2378,7 +2326,7 @@ debug@^3.1.0, debug@^3.2.6: dependencies: ms "^2.1.1" -debug@^4.0.0, debug@^4.0.1, debug@^4.1.0: +debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== @@ -2605,10 +2553,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.122: - version "1.3.124" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.124.tgz#861fc0148748a11b3e5ccebdf8b795ff513fa11f" - integrity sha512-glecGr/kFdfeXUHOHAWvGcXrxNU+1wSO/t5B23tT1dtlvYB26GY8aHzZSWD7HqhqC800Lr+w/hQul6C5AF542w== +electron-to-chromium@^1.3.127: + version "1.3.130" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.130.tgz#27f84e823bd80a5090e2baeca4fefbaf476cf7af" + integrity sha512-UY2DI+gsnqGtQJqO8wXN0DnpJY+29FwJafACj0h18ZShn5besKnrRq6+lXWUbKzdxw92QQcnTqRLgNByOKXcUg== elliptic@^6.0.0: version "6.4.1" @@ -2781,17 +2729,17 @@ eslint-plugin-flowtype@^2.30.0: lodash "^4.17.10" eslint-plugin-react@^7.7.0: - version "7.12.4" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.12.4.tgz#b1ecf26479d61aee650da612e425c53a99f48c8c" - integrity sha512-1puHJkXJY+oS1t467MjbqjvX53uQ05HXwjqDgdbGBqf5j9eeydI54G3KwiJmWciQ0HTBacIKw2jgwSBSH3yfgQ== + version "7.13.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.13.0.tgz#bc13fd7101de67996ea51b33873cd9dc2b7e5758" + integrity sha512-uA5LrHylu8lW/eAH3bEQe9YdzpPaFd9yAJTwTi/i/BKTD7j6aQMKVAdGM/ML72zD6womuSK7EiGtMKuK06lWjQ== dependencies: array-includes "^3.0.3" doctrine "^2.1.0" has "^1.0.3" - jsx-ast-utils "^2.0.1" + jsx-ast-utils "^2.1.0" object.fromentries "^2.0.0" - prop-types "^15.6.2" - resolve "^1.9.0" + prop-types "^15.7.2" + resolve "^1.10.1" eslint-rule-composer@^0.3.0: version "0.3.0" @@ -2806,10 +2754,10 @@ eslint-scope@3.7.1: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-scope@^4.0.0, eslint-scope@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.2.tgz#5f10cd6cabb1965bf479fa65745673439e21cb0e" - integrity sha512-5q1+B/ogmHl8+paxtOKx38Z8LtWkVGuNt3+GQNErqwLl6ViNp/gdJGMCjZNxZ8j/VYjDNZ2Fo+eQc1TAVPIzbg== +eslint-scope@^4.0.0, eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" @@ -2825,9 +2773,9 @@ eslint-visitor-keys@^1.0.0: integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== eslint@^5.12.0: - version "5.15.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.15.1.tgz#8266b089fd5391e0009a047050795b1d73664524" - integrity sha512-NTcm6vQ+PTgN3UBsALw5BMhgO6i5EpIjQF/Xb5tIh3sk9QhrFafujUOczGz4J24JBlzWclSB9Vmx8d+9Z6bFCg== + version "5.16.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" + integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.9.1" @@ -2835,7 +2783,7 @@ eslint@^5.12.0: cross-spawn "^6.0.5" debug "^4.0.1" doctrine "^3.0.0" - eslint-scope "^4.0.2" + eslint-scope "^4.0.3" eslint-utils "^1.3.1" eslint-visitor-keys "^1.0.0" espree "^5.0.1" @@ -2849,7 +2797,7 @@ eslint@^5.12.0: import-fresh "^3.0.0" imurmurhash "^0.1.4" inquirer "^6.2.2" - js-yaml "^3.12.0" + js-yaml "^3.13.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" lodash "^4.17.11" @@ -2915,9 +2863,9 @@ esutils@^2.0.2: integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= eventemitter3@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163" - integrity sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA== + version "3.1.2" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" + integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q== events@^3.0.0: version "3.0.0" @@ -3007,15 +2955,15 @@ expect@^1.20.2: tmatch "^2.0.1" expect@^24.1.0: - version "24.3.1" - resolved "https://registry.yarnpkg.com/expect/-/expect-24.3.1.tgz#7c42507da231a91a8099d065bc8dc9322dc85fc0" - integrity sha512-xnmobSlaqhg4FKqjb5REk4AobQzFMJoctDdREKfSGqrtzRfCWYbfqt3WmikAvQz/J8mCNQhORgYdEjPMJbMQPQ== + version "24.7.1" + resolved "https://registry.yarnpkg.com/expect/-/expect-24.7.1.tgz#d91defbab4e627470a152feaf35b3c31aa1c7c14" + integrity sha512-mGfvMTPduksV3xoI0xur56pQsg2vJjNf5+a+bXOjqCkiCBbmCayrBbHS/75y9K430cfqyocPr2ZjiNiRx4SRKw== dependencies: - "@jest/types" "^24.3.0" + "@jest/types" "^24.7.0" ansi-styles "^3.2.0" jest-get-type "^24.3.0" - jest-matcher-utils "^24.3.1" - jest-message-util "^24.3.0" + jest-matcher-utils "^24.7.0" + jest-message-util "^24.7.1" jest-regex-util "^24.3.0" extend-shallow@^2.0.1: @@ -3227,12 +3175,12 @@ find-cache-dir@^1.0.0: pkg-dir "^2.0.0" find-cache-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.0.0.tgz#4c1faed59f45184530fb9d7fa123a4d04a98472d" - integrity sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA== + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== dependencies: commondir "^1.0.1" - make-dir "^1.0.0" + make-dir "^2.0.0" pkg-dir "^3.0.0" find-up@^2.0.0, find-up@^2.1.0: @@ -3406,12 +3354,12 @@ fs.realpath@^1.0.0: integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@^1.0.0, fsevents@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.7.tgz#4851b664a3783e52003b3c66eb0eee1074933aa4" - integrity sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw== + version "1.2.9" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" + integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== dependencies: - nan "^2.9.2" - node-pre-gyp "^0.10.0" + nan "^2.12.1" + node-pre-gyp "^0.12.0" function-bind@^1.1.1: version "1.1.1" @@ -3592,9 +3540,9 @@ global-prefix@^3.0.0: which "^1.3.1" globals@^11.1.0, globals@^11.7.0: - version "11.11.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.11.0.tgz#dcf93757fa2de5486fbeed7118538adf789e9c2e" - integrity sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw== + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globals@^9.18.0: version "9.18.0" @@ -3806,15 +3754,16 @@ htmlparser2@^3.10.0: inherits "^2.0.1" readable-stream "^3.1.1" -http-errors@1.6.3, http-errors@~1.6.3: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= +http-errors@1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" + integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== dependencies: depd "~1.1.2" inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" http-proxy@^1.13.0: version "1.17.0" @@ -3839,14 +3788,7 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= -iconv-lite@0.4.23: - version "0.4.23" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" - integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -3854,9 +3796,9 @@ iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: safer-buffer ">= 2.1.2 < 3" ieee754@^1.1.4: - version "1.1.12" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" - integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA== + version "1.1.13" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" + integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== iferr@^0.1.5: version "0.1.5" @@ -3876,9 +3818,9 @@ ignore@^4.0.3, ignore@^4.0.6: integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== ignore@^5.0.4: - version "5.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.0.6.tgz#562dacc7ec27d672dde433aa683c543b24c17694" - integrity sha512-/+hp3kUf/Csa32ktIaj0OlRqQxrgs30n62M90UBpNd9k+ENEch5S+hmbW3DtcJGz3sYFTh4F3A6fQ0q7KWsp4w== + version "5.1.1" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.1.tgz#2fc6b8f518aff48fef65a7f348ed85632448e4a5" + integrity sha512-DWjnQIFLenVrwyRCKZT+7a7/U4Cqgar4WG8V++K3hw+lrW1hc/SIwdiGmtxKCVACmHULTuGeBbHJmbwW7/sAvA== immutable@^3.7.4: version "3.8.2" @@ -3958,9 +3900,9 @@ ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== inquirer@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.2.tgz#46941176f65c9eb20804627149b743a218f25406" - integrity sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA== + version "6.3.1" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.3.1.tgz#7a413b5e7950811013a3db491c61d1f3b776e8e7" + integrity sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA== dependencies: ansi-escapes "^3.2.0" chalk "^2.4.2" @@ -3973,7 +3915,7 @@ inquirer@^6.2.2: run-async "^2.2.0" rxjs "^6.4.0" string-width "^2.1.0" - strip-ansi "^5.0.0" + strip-ansi "^5.1.0" through "^2.3.6" interpret@^1.1.0: @@ -4206,9 +4148,9 @@ is-glob@^3.1.0: is-extglob "^2.1.0" is-glob@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" - integrity sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A= + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== dependencies: is-extglob "^2.1.1" @@ -4406,39 +4348,39 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -jest-diff@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.3.1.tgz#87952e5ea1548567da91df398fa7bf7977d3f96a" - integrity sha512-YRVzDguyzShP3Pb9wP/ykBkV7Z+O4wltrMZ2P4LBtNxrHNpxwI2DECrpD9XevxWubRy5jcE8sSkxyX3bS7W+rA== +jest-diff@^24.7.0: + version "24.7.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.7.0.tgz#5d862899be46249754806f66e5729c07fcb3580f" + integrity sha512-ULQZ5B1lWpH70O4xsANC4tf4Ko6RrpwhE3PtG6ERjMg1TiYTC2Wp4IntJVGro6a8HG9luYHhhmF4grF0Pltckg== dependencies: chalk "^2.0.1" diff-sequences "^24.3.0" jest-get-type "^24.3.0" - pretty-format "^24.3.1" + pretty-format "^24.7.0" jest-get-type@^24.3.0: version "24.3.0" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.3.0.tgz#582cfd1a4f91b5cdad1d43d2932f816d543c65da" integrity sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow== -jest-matcher-utils@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.3.1.tgz#025e1cd9c54a5fde68e74b12428775d06d123aa8" - integrity sha512-P5VIsUTJeI0FYvWVMwEHjxK1L83vEkDiKMV0XFPIrT2jzWaWPB2+dPCHkP2ID9z4eUKElaHqynZnJiOdNVHfXQ== +jest-matcher-utils@^24.7.0: + version "24.7.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.7.0.tgz#bbee1ff37bc8b2e4afcaabc91617c1526af4bcd4" + integrity sha512-158ieSgk3LNXeUhbVJYRXyTPSCqNgVXOp/GT7O94mYd3pk/8+odKTyR1JLtNOQSPzNi8NFYVONtvSWA/e1RDXg== dependencies: chalk "^2.0.1" - jest-diff "^24.3.1" + jest-diff "^24.7.0" jest-get-type "^24.3.0" - pretty-format "^24.3.1" + pretty-format "^24.7.0" -jest-message-util@^24.3.0: - version "24.3.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.3.0.tgz#e8f64b63ebc75b1a9c67ee35553752596e70d4a9" - integrity sha512-lXM0YgKYGqN5/eH1NGw4Ix+Pk2I9Y77beyRas7xM24n+XTTK3TbT0VkT3L/qiyS7WkW0YwyxoXnnAaGw4hsEDA== +jest-message-util@^24.7.1: + version "24.7.1" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.7.1.tgz#f1dc3a6c195647096a99d0f1dadbc447ae547018" + integrity sha512-dk0gqVtyqezCHbcbk60CdIf+8UHgD+lmRHifeH3JRcnAqh4nEyPytSc9/L1+cQyxC+ceaeP696N4ATe7L+omcg== dependencies: "@babel/code-frame" "^7.0.0" - "@jest/test-result" "^24.3.0" - "@jest/types" "^24.3.0" + "@jest/test-result" "^24.7.1" + "@jest/types" "^24.7.0" "@types/stack-utils" "^1.0.1" chalk "^2.0.1" micromatch "^3.1.10" @@ -4456,9 +4398,9 @@ jest-regex-util@^24.3.0: integrity sha512-tXQR1NEOyGlfylyEjg1ImtScwMq8Oh3iJbGTjN7p0J23EuVX1MA8rwU69K4sLbCmwzgCUbVkm0FkSF9TdzOhtg== jquery@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca" - integrity sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg== + version "3.4.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2" + integrity sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw== "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" @@ -4470,14 +4412,6 @@ js-tokens@^3.0.2: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= -js-yaml@^3.12.0: - version "3.12.2" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.2.tgz#ef1d067c5a9d9cb65bd72f285b5d8105c77f14fc" - integrity sha512-QHn/Lh/7HhZ/Twc7vJYQTkjuCa0kaCcDcjK5Zlk2rvnUpy7DxMJ23+Jc2dcyvltwQVg1nygAVlB2oRDFHoRS5Q== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - js-yaml@^3.13.0: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" @@ -4567,10 +4501,10 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" -jsx-ast-utils@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz#e801b1b39985e20fffc87b40e3748080e2dcac7f" - integrity sha1-6AGxs5mF4g//yHtA43SAgOLcrH8= +jsx-ast-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.1.0.tgz#0ee4e2c971fb9601c67b5641b71be80faecf0b36" + integrity sha512-yDGDG2DS4JcqhA6blsuYbtsT09xL8AoLuUR2Gb5exrw7UEM19sBcOTq+YBBhrNbl0PUC4R4LnFu+dHg2HKeVvA== dependencies: array-includes "^3.0.3" @@ -4594,14 +4528,6 @@ karma-cli@^1.0.1: dependencies: resolve "^1.1.6" -karma-junit-reporter@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/karma-junit-reporter/-/karma-junit-reporter-2.0.0.tgz#f84629e0e1ef28dd2977c96f346c33d5bf93e159" - integrity sha1-+EYp4OHvKN0pd8lvNGwz1b+T4Vk= - dependencies: - path-is-absolute "^1.0.0" - xmlbuilder "3.1.0" - karma-logcapture-reporter@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/karma-logcapture-reporter/-/karma-logcapture-reporter-0.0.1.tgz#bf1b0b1c915e0de295a15fe2f0179d4281bacddc" @@ -4646,9 +4572,9 @@ karma-webpack@^4.0.0-beta.0: webpack-dev-middleware "^3.2.0" karma@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/karma/-/karma-4.0.1.tgz#2581d6caa0d4cd28b65131561b47bad6d5478773" - integrity sha512-ind+4s03BqIXas7ZmraV3/kc5+mnqwCd+VDX1FndS6jxbt03kQKX2vXrWxNLuCjVYmhMwOZosAEKMM0a2q7w7A== + version "4.1.0" + resolved "https://registry.yarnpkg.com/karma/-/karma-4.1.0.tgz#d07387c9743a575b40faf73e8a3eb5421c2193e1" + integrity sha512-xckiDqyNi512U4dXGOOSyLKPwek6X/vUizSy2f3geYevbLj+UIdvNwbn7IwfUIL2g1GXEPWt/87qFD1fBbl/Uw== dependencies: bluebird "^3.3.0" body-parser "^1.16.1" @@ -4811,11 +4737,6 @@ lodash.mergewith@^4.6.1: resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927" integrity sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ== -lodash@^3.5.0: - version "3.10.1" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" - integrity sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y= - lodash@^4.1.1, lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.2.1: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" @@ -4829,15 +4750,15 @@ log-symbols@^2.0.0, log-symbols@^2.2.0: chalk "^2.0.1" log4js@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/log4js/-/log4js-4.0.2.tgz#0c73e623ca4448669653eb0e9f629beacc7fbbe3" - integrity sha512-KE7HjiieVDPPdveA3bJZSuu0n8chMkFl8mIoisBFxwEJ9FmXe4YzNuiqSwYUiR1K8q8/5/8Yd6AClENY1RA9ww== + version "4.1.0" + resolved "https://registry.yarnpkg.com/log4js/-/log4js-4.1.0.tgz#57983c6a443546a8c8607e9cb045d2a117c27644" + integrity sha512-eDa+zZPeVEeK6QGJAePyXM6pg4P3n3TO5rX9iZMVY48JshsTyLJZLIL5HipI1kQ2qLsSyOpUqNND/C5H4WhhiA== dependencies: date-format "^2.0.0" - debug "^3.1.0" + debug "^4.1.1" flatted "^2.0.0" rfdc "^1.1.2" - streamroller "^1.0.1" + streamroller "^1.0.4" loglevel@1.6.1: version "1.6.1" @@ -4896,6 +4817,14 @@ make-dir@^1.0.0: dependencies: pify "^3.0.0" +make-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + mamacro@^0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4" @@ -4950,10 +4879,10 @@ mathml-tag-names@^2.0.1: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.0.tgz#490b70e062ee24636536e3d9481e333733d00f2c" integrity sha512-3Zs9P/0zzwTob2pdgT0CHZuMbnSUSp8MB1bddfm+HDmnFWHGT4jvEZRf+2RuPoa+cjdn/z25SEt5gFTqdhvJAg== -matrix-js-sdk@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-1.0.4.tgz#dbfa8399f750a23b020c1ec8f037a2f5c36d4672" - integrity sha512-FPx7U1a0SmLbDXhXlR4XHlC+FVKTnK2/+ZBtyOWGLi3nxw4x8hCSSzJ82gzStya1qvhHvbf/y7eblYFVE1l7SQ== +matrix-js-sdk@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-1.1.0.tgz#f0db49de2aa0b0d50c1fe49da538beb4926ce59c" + integrity sha512-ECoMN6DkwPdKiMa/jSoMkSDngFCo6x7oH84rLd1NtD7lBPl3Ejj6ARa0iIELE7u0OUO6J0FzdWh7Hd0ZnVTmww== dependencies: another-json "^0.2.0" babel-runtime "^6.26.0" @@ -5010,12 +4939,12 @@ media-typer@0.3.0: integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= mem@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-4.1.0.tgz#aeb9be2d21f47e78af29e4ac5978e8afa2ca5b8a" - integrity sha512-I5u6Q1x7wxO0kdOpYBB28xueHADYps5uty/zg936CiG8NTe5sJL8EjrCuLneuDW3PlMdZBGDIn8BirEVdovZvg== + version "4.3.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" + integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w== dependencies: map-age-cleaner "^0.1.1" - mimic-fn "^1.0.0" + mimic-fn "^2.0.0" p-is-promise "^2.0.0" memoize-one@^3.0.1: @@ -5102,28 +5031,33 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@~1.38.0: - version "1.38.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.38.0.tgz#1a2aab16da9eb167b49c6e4df2d9c68d63d8e2ad" - integrity sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg== +mime-db@1.40.0: + version "1.40.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" + integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== -mime-types@^2.1.12, mime-types@~2.1.18, mime-types@~2.1.19: - version "2.1.22" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.22.tgz#fe6b355a190926ab7698c9a0556a11199b2199bd" - integrity sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog== +mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24: + version "2.1.24" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" + integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ== dependencies: - mime-db "~1.38.0" + mime-db "1.40.0" mime@^2.3.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.0.tgz#e051fd881358585f3279df333fe694da0bcffdd6" - integrity sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w== + version "2.4.2" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.2.tgz#ce5229a5e99ffc313abac806b482c10e7ba6ac78" + integrity sha512-zJBfZDkwRu+j3Pdd2aHsR5GfH2jIWhmL1ZzBoc+X+3JEti2hbArWcyJ+1laC1D2/U/W1a/+Cegj0/OnEU2ybjg== mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== +mimic-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -5259,10 +5193,10 @@ mute-stream@0.0.7: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= -nan@^2.9.2: - version "2.12.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" - integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== +nan@^2.12.1: + version "2.13.2" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7" + integrity sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw== nanomatch@^1.2.9: version "1.2.13" @@ -5287,18 +5221,18 @@ natural-compare@^1.4.0: integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= needle@^2.2.1: - version "2.2.4" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" - integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== + version "2.3.1" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.3.1.tgz#d272f2f4034afb9c4c9ab1379aabc17fc85c9388" + integrity sha512-CaLXV3W8Vnbps8ZANqDGz7j4x7Yj1LW4TWF/TQuDfj7Cfx4nAPTvw98qgTevtto1oHDrh3pQkaODbqupXlsWTg== dependencies: - debug "^2.1.2" + debug "^4.1.0" iconv-lite "^0.4.4" sax "^1.2.4" -negotiator@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" - integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk= +negotiator@0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" + integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== neo-async@^2.5.0: version "2.6.0" @@ -5358,10 +5292,10 @@ node-libs-browser@^2.0.0: util "^0.11.0" vm-browserify "0.0.4" -node-pre-gyp@^0.10.0: - version "0.10.3" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" - integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== +node-pre-gyp@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" + integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== dependencies: detect-libc "^1.0.2" mkdirp "^0.5.1" @@ -5374,10 +5308,10 @@ node-pre-gyp@^0.10.0: semver "^5.3.0" tar "^4" -node-releases@^1.1.13: - version "1.1.13" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.13.tgz#8c03296b5ae60c08e2ff4f8f22ae45bd2f210083" - integrity sha512-fKZGviSXR6YvVPyc011NHuJDSD8gFQvLPmc2d2V3BS4gr52ycyQ1Xzs7a8B+Ax3Ni/W+5h1h4SqmzeoA8WZRmA== +node-releases@^1.1.17: + version "1.1.17" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.17.tgz#71ea4631f0a97d5cd4f65f7d04ecf9072eac711a" + integrity sha512-/SCjetyta1m7YXLgtACZGDYJdCSIBAWorDWkGCGZlydP2Ll7J48l7j/JxNYZ+xsgSPbWfdulVS/aY+GdjUsQ7Q== dependencies: semver "^5.3.0" @@ -5496,9 +5430,9 @@ object-inspect@^1.1.0: integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== object-keys@^1.0.12, object-keys@^1.0.9: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.0.tgz#11bd22348dd2e096a045ab06f6c85bcc340fa032" - integrity sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg== + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object-visit@^1.0.0: version "1.0.1" @@ -5635,9 +5569,9 @@ p-finally@^1.0.0: integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= p-is-promise@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.0.0.tgz#7554e3d572109a87e1f3f53f6a7d85d1b194f4c5" - integrity sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg== + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" + integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== p-limit@^1.1.0: version "1.3.0" @@ -5673,9 +5607,9 @@ p-try@^1.0.0: integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= p-try@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" - integrity sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ== + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== pako@^1.0.5, pako@~1.0.5: version "1.0.10" @@ -5692,9 +5626,9 @@ parallel-transform@^1.1.0: readable-stream "^2.1.5" parent-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.0.tgz#df250bdc5391f4a085fb589dad761f5ad6b865b5" - integrity sha512-8Mf5juOMmiE4FcmzYc4IaiS9L3+9paz2KOiXzkRviCP6aDmN49Hz6EMWz0lGNp9pX80GvvAuLADtyGfW/Em3TA== + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" @@ -5760,9 +5694,9 @@ parseuri@0.0.5: better-assert "~1.0.0" parseurl@~1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" - integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M= + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== pascalcase@^0.1.1: version "0.1.1" @@ -5989,12 +5923,12 @@ preserve@^0.2.0: resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= -pretty-format@^24.3.1: - version "24.3.1" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.3.1.tgz#ae4a98e93d73d86913a8a7dd1a7c3c900f8fda59" - integrity sha512-NZGH1NWS6o4i9pvRWLsxIK00JB9pqOUzVrO7yWT6vjI2thdxwvxefBJO6O5T24UAhI8P5dMceZ7x5wphgVI7Mg== +pretty-format@^24.7.0: + version "24.7.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.7.0.tgz#d23106bc2edcd776079c2daa5da02bcb12ed0c10" + integrity sha512-apen5cjf/U4dj7tHetpC7UEFCvtAgnNZnBDkfPv3fokzIqyOJckAG9OlAPC1BlFALnqT/lGB2tl9EJjlK6eCsA== dependencies: - "@jest/types" "^24.3.0" + "@jest/types" "^24.7.0" ansi-regex "^4.0.0" ansi-styles "^3.2.0" react-is "^16.8.4" @@ -6031,7 +5965,7 @@ promise@^7.0.3, promise@^7.1.1: dependencies: asap "~2.0.3" -prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2: +prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -6124,16 +6058,16 @@ qrcode-react@^0.1.16: dependencies: qr.js "0.0.0" -qs@6.5.2, qs@~6.5.2: +qs@6.7.0, qs@^6.5.2, qs@^6.6.0: + version "6.7.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" + integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + +qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== -qs@^6.5.2, qs@^6.6.0: - version "6.6.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.6.0.tgz#a99c0f69a8d26bf7ef012f871cdabb0aee4424c2" - integrity sha512-KIJqT9jQJDQx5h5uAVPimw6yVg2SekOKu959OCtktD3FjzbpvaPr8i4zzg07DOMz+igA4W/aNM7OV8H37pFYfA== - querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" @@ -6190,14 +6124,14 @@ range-parser@^1.0.3, range-parser@^1.2.0: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= -raw-body@2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" - integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw== +raw-body@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" + integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== dependencies: - bytes "3.0.0" - http-errors "1.6.3" - iconv-lite "0.4.23" + bytes "3.1.0" + http-errors "1.7.2" + iconv-lite "0.4.24" unpipe "1.0.0" rc@^1.2.7: @@ -6247,14 +6181,14 @@ react-dom@^15.6.0, react-dom@^15.6.1: prop-types "^15.5.10" react-dom@^16.4.2: - version "16.8.4" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.4.tgz#1061a8e01a2b3b0c8160037441c3bf00a0e3bc48" - integrity sha512-Ob2wK7XG2tUDt7ps7LtLzGYYB6DXMCLj0G5fO6WeEICtT4/HdpOi7W/xLzZnR6RCG1tYza60nMdqtxzA8FaPJQ== + version "16.8.6" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f" + integrity sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.13.4" + scheduler "^0.13.6" "react-gemini-scrollbar@github:matrix-org/react-gemini-scrollbar#5e97aef": version "2.1.5" @@ -6268,9 +6202,9 @@ react-immutable-proptypes@^2.1.0: integrity sha1-Aj1vObsVyXwHHp5g0A0TbqxfoLQ= react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4: - version "16.8.4" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.4.tgz#90f336a68c3a29a096a3d648ab80e87ec61482a2" - integrity sha512-PVadd+WaUDOAciICm/J1waJaSvgq+4rHE/K70j0PFqKhkTBsPv/82UGQJNXAngz1fOQLLxI6z1sEDmJDQhCTAA== + version "16.8.6" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16" + integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA== react-lifecycles-compat@^3.0.0: version "3.0.4" @@ -6311,14 +6245,14 @@ react@^15.6.0, react@^15.6.1: prop-types "^15.5.10" react@^16.4.2: - version "16.8.4" - resolved "https://registry.yarnpkg.com/react/-/react-16.8.4.tgz#fdf7bd9ae53f03a9c4cd1a371432c206be1c4768" - integrity sha512-0GQ6gFXfUH7aZcjGVymlPOASTuSjlQL4ZtVC5YKH+3JL6bBLCVO21DknzmaPlI90LN253ojj02nsapy+j7wIjg== + version "16.8.6" + resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe" + integrity sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.13.4" + scheduler "^0.13.6" read-pkg-up@^3.0.0: version "3.0.0" @@ -6360,9 +6294,9 @@ read-pkg@^4.0.1: util-deprecate "~1.0.1" readable-stream@^3.1.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.2.0.tgz#de17f229864c120a9f56945756e4f32c4045245d" - integrity sha512-RV20kLjdmpZuTF1INEb9IA3L68Nmi+Ri7ppZqo78wj//Pn62fCoJyV9zalccNzDD/OuJpMG4f+pfMl8+L6QdGw== + version "3.3.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.3.0.tgz#cb8011aad002eb717bf040291feba8569c986fb9" + integrity sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" @@ -6415,10 +6349,10 @@ regenerator-runtime@^0.11.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== -regenerator-runtime@^0.12.0: - version "0.12.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" - integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== +regenerator-runtime@^0.13.2: + version "0.13.2" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz#32e59c9a6fb9b1a4aff09b4930ca2d4477343447" + integrity sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA== regenerator-transform@^0.10.0: version "0.10.1" @@ -6633,10 +6567,10 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.3.2, resolve@^1.9.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba" - integrity sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg== +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.3.2: + version "1.10.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.1.tgz#664842ac960795bbe758221cdccda61fb64b5f18" + integrity sha512-KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA== dependencies: path-parse "^1.0.6" @@ -6688,9 +6622,9 @@ run-queue@^1.0.0, run-queue@^1.0.3: aproba "^1.1.1" rxjs@^6.3.3, rxjs@^6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.4.0.tgz#f3bb0fe7bda7fb69deac0c16f17b50b0b8790504" - integrity sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw== + version "6.5.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.1.tgz#f7a005a9386361921b8524f38f54cbf80e5d08f4" + integrity sha512-y0j31WJc83wPu31vS1VlAFW5JGrnGC+j+TtGAa1fRQphy48+fDYiDmX8tjGloToEsMkxnouOg/1IzXGKkJnZMg== dependencies: tslib "^1.9.0" @@ -6717,9 +6651,9 @@ samsam@1.3.0: integrity sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg== sanitize-html@^1.18.4: - version "1.20.0" - resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.20.0.tgz#9a602beb1c9faf960fb31f9890f61911cc4d9156" - integrity sha512-BpxXkBoAG+uKCHjoXFmox6kCSYpnulABoGcZ/R3QyY9ndXbIM5S94eOr1IqnzTG8TnbmXaxWoDDzKC5eJv7fEQ== + version "1.20.1" + resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.20.1.tgz#f6effdf55dd398807171215a62bfc21811bacf85" + integrity sha512-txnH8TQjaQvg2Q0HY06G6CDJLVYCpbnxrdO0WN8gjCKaU5J0KbyGYhZxx5QJg3WLZ1lB7XU9kDkfrCXUozqptA== dependencies: chalk "^2.4.1" htmlparser2 "^3.10.0" @@ -6737,10 +6671,10 @@ sax@^1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -scheduler@^0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.4.tgz#8fef05e7a3580c76c0364d2df5e550e4c9140298" - integrity sha512-cvSOlRPxOHs5dAhP9yiS/6IDmVAVxmk33f0CtTJRkmUWcb1Us+t7b1wqdzoC0REw2muC9V5f1L/w5R5uKGaepA== +scheduler@^0.13.6: + version "0.13.6" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.6.tgz#466a4ec332467b31a91b9bf74e5347072e4cd889" + integrity sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -6759,20 +6693,15 @@ selection-is-backward@^1.0.0: resolved "https://registry.yarnpkg.com/selection-is-backward/-/selection-is-backward-1.0.0.tgz#97a54633188a511aba6419fc5c1fa91b467e6be1" integrity sha1-l6VGMxiKURq6ZBn8XB+pG0Z+a+E= -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.5.1: - version "5.6.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" - integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== - -semver@^5.4.1: +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: version "5.7.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== serialize-javascript@^1.4.0: - version "1.6.1" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.6.1.tgz#4d1f697ec49429a847ca6f442a2a755126c4d879" - integrity sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw== + version "1.7.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.7.0.tgz#d6e0dfb2a3832a8c94468e6eb1db97e55a192a65" + integrity sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA== set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" @@ -6804,10 +6733,10 @@ setimmediate@^1.0.4, setimmediate@^1.0.5: resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" @@ -6858,9 +6787,9 @@ slash@^2.0.0: integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== slate-base64-serializer@^0.2.69: - version "0.2.97" - resolved "https://registry.yarnpkg.com/slate-base64-serializer/-/slate-base64-serializer-0.2.97.tgz#232220da1320cdc918369834940f1c997b1e80f9" - integrity sha512-f8TnU8rPz8qzKsGaJJwEzPoR5JQ55kB03nO/aIeXRVg4PPY/Rp9VaEcBP6vmeimH51gf3vpe8S5RUITbW9pXHw== + version "0.2.102" + resolved "https://registry.yarnpkg.com/slate-base64-serializer/-/slate-base64-serializer-0.2.102.tgz#05cdb9149172944b55c8d0a0d14b4499a1c3b5a2" + integrity sha512-44BI/jEbSMDNjEpOd92dVtpKyoFEaQtS3YgDoD30gHsvJvuzdRd/EQjp01BAUhDLLgDINi9qIHZS3AkpqKOtow== dependencies: isomorphic-base64 "^1.0.2" @@ -6902,9 +6831,9 @@ slate-html-serializer@^0.6.1: resolved "https://codeload.github.com/matrix-org/slate-md-serializer/tar.gz/f7c4ad394f5af34d4c623de7909ce95ab78072d3" slate-plain-serializer@^0.6.8: - version "0.6.36" - resolved "https://registry.yarnpkg.com/slate-plain-serializer/-/slate-plain-serializer-0.6.36.tgz#19ac5c66f972f068654b226c9a628bdc29475764" - integrity sha512-StVNj0wyM9KNtjRPYsFxNVrkeKtILwRy0QHr33Ln/SH05mAF6Of7MkmeC7GrqrN99J01ntz0pA2VLewq8ErhDQ== + version "0.6.39" + resolved "https://registry.yarnpkg.com/slate-plain-serializer/-/slate-plain-serializer-0.6.39.tgz#5fb8d4dc530a2e7e0689548d48964ce242c4516a" + integrity sha512-EGl+Y+9Fw9IULtPg8sttydaeiAoaibJolMXNfqI79+5GWTQwJFIbg24keKvsTw+3f2RieaPu8fcrKyujKtZ7ZQ== slate-prop-types@^0.4.67: version "0.4.67" @@ -7061,9 +6990,9 @@ source-map-support@^0.4.15: source-map "^0.5.6" source-map-support@~0.5.10: - version "0.5.10" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.10.tgz#2214080bc9d51832511ee2bab96e3c2f9353120c" - integrity sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ== + version "0.5.12" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" + integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -7110,9 +7039,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz#81c0ce8f21474756148bbb5f3bfc0f36bf15d76e" - integrity sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g== + version "3.0.4" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz#75ecd1a88de8c184ef015eafb51b5b48bfd11bb1" + integrity sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA== specificity@^0.4.1: version "0.4.1" @@ -7184,7 +7113,7 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -"statuses@>= 1.4.0 < 2": +"statuses@>= 1.5.0 < 2": version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= @@ -7226,10 +7155,10 @@ stream-shift@^1.0.0: resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= -streamroller@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-1.0.3.tgz#cb51e7e382f799a9381a5d7490ce3053b325fba3" - integrity sha512-P7z9NwP51EltdZ81otaGAN3ob+/F88USJE546joNq7bqRNTe6jc74fTBDyynxP4qpIfKlt/CesEYicuMzI0yJg== +streamroller@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-1.0.4.tgz#d485c7624796d5e2eb34190c79afcbf006afb5e6" + integrity sha512-Wc2Gm5ygjSX8ZpW9J7Y9FwiSzTlKSvcl0FTTMd3rn7RoxDXpBW+xD9TY5sWL2n0UR61COB0LG1BQvN6nTUQbLQ== dependencies: async "^2.6.1" date-format "^2.0.0" @@ -7306,10 +7235,10 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^5.0.0, strip-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.1.0.tgz#55aaa54e33b4c0649a7338a43437b1887d153ec4" - integrity sha512-TjxrkPONqO2Z8QDCpeE2j6n0M6EwxzyDgzEeGp+FbdvaJAt//ClYi6W5my+3ROlC/hZX2KACUwDfK49Ka5eDvg== +strip-ansi@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== dependencies: ansi-regex "^4.1.0" @@ -7338,17 +7267,17 @@ style-search@^0.1.0: resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902" integrity sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI= -stylelint-config-recommended@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/stylelint-config-recommended/-/stylelint-config-recommended-2.1.0.tgz#f526d5c771c6811186d9eaedbed02195fee30858" - integrity sha512-ajMbivOD7JxdsnlS5945KYhvt7L/HwN6YeYF2BH6kE4UCLJR0YvXMf+2j7nQpJyYLZx9uZzU5G1ZOSBiWAc6yA== +stylelint-config-recommended@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/stylelint-config-recommended/-/stylelint-config-recommended-2.2.0.tgz#46ab139db4a0e7151fd5f94af155512886c96d3f" + integrity sha512-bZ+d4RiNEfmoR74KZtCKmsABdBJr4iXRiCso+6LtMJPw5rd/KnxUWTxht7TbafrTJK1YRjNgnN0iVZaJfc3xJA== stylelint-config-standard@^18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/stylelint-config-standard/-/stylelint-config-standard-18.2.0.tgz#6283149aba7f64f18731aef8f0abfb35cf619e06" - integrity sha512-07x0TaSIzvXlbOioUU4ORkCIM07kyIuojkbSVCyFWNVgXMXYHfhnQSCkqu+oHWJf3YADAnPGWzdJ53NxkoJ7RA== + version "18.3.0" + resolved "https://registry.yarnpkg.com/stylelint-config-standard/-/stylelint-config-standard-18.3.0.tgz#a2a1b788d2cf876c013feaff8ae276117a1befa7" + integrity sha512-Tdc/TFeddjjy64LvjPau9SsfVRexmTFqUhnMBrzz07J4p2dVQtmpncRF/o8yZn8ugA3Ut43E6o1GtjX80TFytw== dependencies: - stylelint-config-recommended "^2.1.0" + stylelint-config-recommended "^2.2.0" stylelint@^9.10.1: version "9.10.1" @@ -7469,9 +7398,9 @@ table@^5.0.0, table@^5.2.3: string-width "^3.0.0" tapable@^1.0.0, tapable@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.1.tgz#4d297923c5a72a42360de2ab52dadfaaec00018e" - integrity sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA== + version "1.1.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== tar@^4: version "4.4.8" @@ -7596,6 +7525,11 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" @@ -7668,13 +7602,13 @@ type-detect@4.0.8, type-detect@^4.0.8: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -type-is@~1.6.16: - version "1.6.16" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" - integrity sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q== +type-is@~1.6.17: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== dependencies: media-typer "0.3.0" - mime-types "~2.1.18" + mime-types "~2.1.24" type-of@^2.0.1: version "2.0.1" @@ -7808,7 +7742,7 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" -upath@^1.1.0: +upath@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068" integrity sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q== @@ -7965,9 +7899,9 @@ watchpack@^1.5.0: neo-async "^2.5.0" webpack-cli@^3.1.1: - version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.2.3.tgz#13653549adfd8ccd920ad7be1ef868bacc22e346" - integrity sha512-Ik3SjV6uJtWIAN5jp5ZuBMWEAaP5E4V78XJ2nI+paFPh8v4HPSwo/myN0r29Xc/6ZKnd2IdrAlpSgNOu2CDQ6Q== + version "3.3.1" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.1.tgz#98b0499c7138ba9ece8898bd99c4f007db59909d" + integrity sha512-c2inFU7SM0IttEgF7fK6AaUsbBnORRzminvbyRKS+NlbQHVZdCtzKBlavRL5359bFsywXGRAItA5di/IruC8mg== dependencies: chalk "^2.4.1" cross-spawn "^6.0.5" @@ -7979,12 +7913,12 @@ webpack-cli@^3.1.1: loader-utils "^1.1.0" supports-color "^5.5.0" v8-compile-cache "^2.0.2" - yargs "^12.0.4" + yargs "^12.0.5" webpack-dev-middleware@^3.2.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.6.1.tgz#91f2531218a633a99189f7de36045a331a4b9cd4" - integrity sha512-XQmemun8QJexMEvNFbD2BIg4eSKrmSIMrTfnl2nql2Sc6OGAYFyb8rwuYrCjl/IiEYYuyTEiimMscu7EXji/Dw== + version "3.6.2" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.6.2.tgz#f37a27ad7c09cd7dc67cd97655413abaa1f55942" + integrity sha512-A47I5SX60IkHrMmZUlB0ZKSWi29TZTcPz7cha1Z75yYOsgWh/1AcPmQEbC8ZIbU3A1ytSv1PMU0PyPz2Lmz2jg== dependencies: memory-fs "^0.4.1" mime "^2.3.1" @@ -8008,9 +7942,9 @@ webpack-sources@^1.1.0, webpack-sources@^1.3.0: source-map "~0.6.1" webpack@^4.20.2: - version "4.29.6" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.29.6.tgz#66bf0ec8beee4d469f8b598d3988ff9d8d90e955" - integrity sha512-MwBwpiE1BQpMDkbnUUaW6K8RFZjljJHArC6tWQJoFm0oQtfoSebtg4Y7/QHnJ/SddtjYLHaKGX64CFjG5rehJw== + version "4.30.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.30.0.tgz#aca76ef75630a22c49fcc235b39b4c57591d33a9" + integrity sha512-4hgvO2YbAFUhyTdlR4FNyt2+YaYBYHavyzjCMbZzgglo02rlKi/pcsEzwCuCpsn1ryzIl1cq/u8ArIKu8JBYMg== dependencies: "@webassemblyjs/ast" "1.8.5" "@webassemblyjs/helper-module-context" "1.8.5" @@ -8122,13 +8056,6 @@ x-is-string@^0.1.0: resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82" integrity sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI= -xmlbuilder@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-3.1.0.tgz#2c86888f2d4eade850fa38ca7f7223f7209516e1" - integrity sha1-LIaIjy1OrehQ+jjKf3Ij9yCVFuE= - dependencies: - lodash "^3.5.0" - xmlhttprequest-ssl@~1.5.4: version "1.5.5" resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e" @@ -8169,7 +8096,7 @@ yargs-parser@^11.1.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs@^12.0.1, yargs@^12.0.4: +yargs@^12.0.1, yargs@^12.0.5: version "12.0.5" resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==