From ca8d57c4dbfe839db28b583caa7d599c0cfc023a Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Fri, 23 Jun 2017 12:09:56 -0400 Subject: PLT-6890 Fix various scrolling issues (#6727) * Fix various scrolling issues * Move reaction scrolling to reaction list * Handle scrolling when RHS opens * Only run scroll update code when posts change --- webapp/actions/global_actions.jsx | 7 + webapp/components/post_view/post_image.jsx | 5 + webapp/components/post_view/post_list.jsx | 33 +++-- .../post_view/reaction_list/reaction_list.jsx | 8 + webapp/components/rhs_thread/rhs_thread.jsx | 4 +- webapp/components/sidebar_right/sidebar_right.jsx | 9 +- .../non_npm_dependencies/key-mirror/keyMirror.js | 51 ------- webapp/package.json | 1 + webapp/stores/scroll_store.jsx | 24 --- webapp/utils/constants.jsx | 2 +- webapp/utils/event_types.jsx | 8 + webapp/utils/global_event_emitter.jsx | 27 ++++ webapp/utils/markdown.jsx | 7 +- webapp/yarn.lock | 164 ++++++++++----------- 14 files changed, 171 insertions(+), 179 deletions(-) delete mode 100644 webapp/non_npm_dependencies/key-mirror/keyMirror.js delete mode 100644 webapp/stores/scroll_store.jsx create mode 100644 webapp/utils/event_types.jsx create mode 100644 webapp/utils/global_event_emitter.jsx (limited to 'webapp') diff --git a/webapp/actions/global_actions.jsx b/webapp/actions/global_actions.jsx index 9fb856081..ca38ec9f1 100644 --- a/webapp/actions/global_actions.jsx +++ b/webapp/actions/global_actions.jsx @@ -19,6 +19,7 @@ import {trackEvent} from 'actions/diagnostics_actions.jsx'; import Constants from 'utils/constants.jsx'; const ActionTypes = Constants.ActionTypes; +import EventTypes from 'utils/event_types.jsx'; import Client from 'client/web_client.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; @@ -560,3 +561,9 @@ export function requestOpenGraphMetadata(url) { ); } } + +export function postListScrollChange() { + AppDispatcher.handleViewAction({ + type: EventTypes.POST_LIST_SCROLL_CHANGE + }); +} diff --git a/webapp/components/post_view/post_image.jsx b/webapp/components/post_view/post_image.jsx index 5feb01db4..322742305 100644 --- a/webapp/components/post_view/post_image.jsx +++ b/webapp/components/post_view/post_image.jsx @@ -4,6 +4,8 @@ import React from 'react'; import PropTypes from 'prop-types'; +import {postListScrollChange} from 'actions/global_actions.jsx'; + export default class PostImageEmbed extends React.PureComponent { static propTypes = { @@ -66,6 +68,9 @@ export default class PostImageEmbed extends React.PureComponent { loaded: true, errored: false }); + + postListScrollChange(); + if (this.props.onLinkLoaded) { this.props.onLinkLoaded(); } diff --git a/webapp/components/post_view/post_list.jsx b/webapp/components/post_view/post_list.jsx index bf0ee079d..3ae768b5c 100644 --- a/webapp/components/post_view/post_list.jsx +++ b/webapp/components/post_view/post_list.jsx @@ -12,6 +12,8 @@ import * as Utils from 'utils/utils.jsx'; import Constants from 'utils/constants.jsx'; import {createChannelIntroMessage} from 'utils/channel_intro_messages.jsx'; import DelayedAction from 'utils/delayed_action.jsx'; +import EventTypes from 'utils/event_types.jsx'; +import GlobalEventEmitter from 'utils/global_event_emitter.jsx'; import {FormattedDate, FormattedMessage} from 'react-intl'; @@ -113,11 +115,13 @@ export default class PostList extends React.PureComponent { componentDidMount() { this.loadPosts(this.props.channel.id, this.props.focusedPostId); + GlobalEventEmitter.addListener(EventTypes.POST_LIST_SCROLL_CHANGE, this.handleResize); window.addEventListener('resize', this.handleResize); } componentWillUnmount() { + GlobalEventEmitter.removeListener(EventTypes.POST_LIST_SCROLL_CHANGE, this.handleResize); window.removeEventListener('resize', this.handleResize); } @@ -171,14 +175,25 @@ export default class PostList extends React.PureComponent { } componentDidUpdate(prevProps) { + // Do not update scrolling unless posts change + if (this.props.posts === prevProps.posts) { + return; + } + + const prevPosts = prevProps.posts; + const posts = this.props.posts; + const postList = this.refs.postlist; + // Scroll to focused post on first load const focusedPost = this.refs[this.props.focusedPostId]; - if (focusedPost) { - if (!this.hasScrolledToFocusedPost && this.props.posts) { + if (focusedPost && this.props.posts) { + if (!this.hasScrolledToFocusedPost) { const element = ReactDOM.findDOMNode(focusedPost); const rect = element.getBoundingClientRect(); - const listHeight = this.refs.postlist.clientHeight / 2; - this.refs.postlist.scrollTop = this.refs.postlist.scrollTop + (rect.top - listHeight); + const listHeight = postList.clientHeight / 2; + postList.scrollTop += postList.scrollTop + (rect.top - listHeight); + } else if (this.previousScrollHeight !== postList.scrollHeight && posts[0].id === prevPosts[0].id) { + postList.scrollTop = this.previousScrollTop + (postList.scrollHeight - this.previousScrollHeight); } return; } @@ -190,14 +205,10 @@ export default class PostList extends React.PureComponent { element.scrollIntoView(); return; } else if (this.refs.postlist && !this.hasScrolledToNewMessageSeparator) { - this.refs.postlist.scrollTop = this.refs.postlist.scrollHeight; + postList.scrollTop = postList.scrollHeight; return; } - const prevPosts = prevProps.posts; - const posts = this.props.posts; - const postList = this.refs.postlist; - if (postList && prevPosts && posts && posts[0] && prevPosts[0]) { // A new message was posted, so scroll to bottom if it was from current user // or if user was already scrolled close to bottom @@ -225,8 +236,8 @@ export default class PostList extends React.PureComponent { } // New posts added at the top, maintain scroll position - if (this.previousScrollHeight !== this.refs.postlist.scrollHeight && posts[0].id === prevPosts[0].id) { - this.refs.postlist.scrollTop = this.previousScrollTop + (this.refs.postlist.scrollHeight - this.previousScrollHeight); + if (this.previousScrollHeight !== postList.scrollHeight && posts[0].id === prevPosts[0].id) { + postList.scrollTop = this.previousScrollTop + (postList.scrollHeight - this.previousScrollHeight); } } } diff --git a/webapp/components/post_view/reaction_list/reaction_list.jsx b/webapp/components/post_view/reaction_list/reaction_list.jsx index 516f5332f..4d2f3a5fc 100644 --- a/webapp/components/post_view/reaction_list/reaction_list.jsx +++ b/webapp/components/post_view/reaction_list/reaction_list.jsx @@ -4,6 +4,8 @@ import React from 'react'; import PropTypes from 'prop-types'; +import {postListScrollChange} from 'actions/global_actions.jsx'; + import Reaction from 'components/post_view/reaction'; export default class ReactionListView extends React.PureComponent { @@ -38,6 +40,12 @@ export default class ReactionListView extends React.PureComponent { } } + componentDidUpdate(prevProps) { + if (this.props.reactions !== prevProps.reactions) { + postListScrollChange(); + } + } + render() { if (!this.props.post.has_reactions || (this.props.reactions && this.props.reactions.length === 0)) { return null; diff --git a/webapp/components/rhs_thread/rhs_thread.jsx b/webapp/components/rhs_thread/rhs_thread.jsx index f4e7b33fa..50f5f0aa3 100644 --- a/webapp/components/rhs_thread/rhs_thread.jsx +++ b/webapp/components/rhs_thread/rhs_thread.jsx @@ -124,8 +124,8 @@ export default class RhsThread extends React.Component { this.mounted = false; } - componentDidUpdate(prevProps, prevState) { - const prevPostsArray = prevState.postsArray || []; + componentDidUpdate(prevProps) { + const prevPostsArray = prevProps.posts || []; const curPostsArray = this.props.posts || []; if (prevPostsArray.length >= curPostsArray.length) { diff --git a/webapp/components/sidebar_right/sidebar_right.jsx b/webapp/components/sidebar_right/sidebar_right.jsx index 00a7d2d25..f48bcaa56 100644 --- a/webapp/components/sidebar_right/sidebar_right.jsx +++ b/webapp/components/sidebar_right/sidebar_right.jsx @@ -15,6 +15,7 @@ import WebrtcStore from 'stores/webrtc_store.jsx'; import {getFlaggedPosts, getPinnedPosts} from 'actions/post_actions.jsx'; import {trackEvent} from 'actions/diagnostics_actions.jsx'; +import {postListScrollChange} from 'actions/global_actions.jsx'; import * as Utils from 'utils/utils.jsx'; import Constants from 'utils/constants.jsx'; @@ -120,10 +121,16 @@ export default class SidebarRight extends React.Component { return null; } - componentDidUpdate() { + componentDidUpdate(prevProps, prevState) { const isOpen = this.state.searchVisible || this.props.postRightVisible; WebrtcStore.emitRhsChanged(isOpen); this.doStrangeThings(); + + const wasOpen = prevState.searchVisible || prevProps.postRightVisible; + + if (isOpen && !wasOpen) { + postListScrollChange(); + } } onPreferenceChange() { diff --git a/webapp/non_npm_dependencies/key-mirror/keyMirror.js b/webapp/non_npm_dependencies/key-mirror/keyMirror.js deleted file mode 100644 index 3bd4cff33..000000000 --- a/webapp/non_npm_dependencies/key-mirror/keyMirror.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2013-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule keyMirror - * @typechecks static-only - */ - -'use strict'; - -var invariant = require('invariant'); - -/** - * Constructs an enumeration with keys equal to their value. - * - * For example: - * - * var COLORS = keyMirror({blue: null, red: null}); - * var myColor = COLORS.blue; - * var isColorValid = !!COLORS[myColor]; - * - * The last line could not be performed if the values of the generated enum were - * not equal to their keys. - * - * Input: {key1: val1, key2: val2} - * Output: {key1: key1, key2: key2} - * - * @param {object} obj - * @return {object} - */ -var keyMirror = function(obj) { - var ret = {}; - var key; - invariant( - obj instanceof Object && !Array.isArray(obj), - 'keyMirror(...): Argument must be an object.' - ); - for (key in obj) { - if (!obj.hasOwnProperty(key)) { - continue; - } - ret[key] = key; - } - return ret; -}; - -module.exports = keyMirror; \ No newline at end of file diff --git a/webapp/package.json b/webapp/package.json index 3cf427d07..a028d19e8 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -20,6 +20,7 @@ "intl": "1.2.5", "jasny-bootstrap": "3.1.3", "jquery": "3.2.1", + "key-mirror": "1.0.1", "localforage": "1.5.0", "marked": "mattermost/marked#8f5902fff9bad793cd6c66e0c44002c9e79e1317", "match-at": "0.1.0", diff --git a/webapp/stores/scroll_store.jsx b/webapp/stores/scroll_store.jsx deleted file mode 100644 index 4f5abd64a..000000000 --- a/webapp/stores/scroll_store.jsx +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import EventEmitter from 'events'; - -const UPDATE_POST_SCROLL_EVENT = 'update_post_scroll'; - -class ScrollStoreClass extends EventEmitter { - emitPostScroll() { - this.emit(UPDATE_POST_SCROLL_EVENT); - } - - addPostScrollListener(callback) { - this.on(UPDATE_POST_SCROLL_EVENT, callback); - } - - removePostScrollListener(callback) { - this.removeListener(UPDATE_POST_SCROLL_EVENT, callback); - } -} - -var ScrollStore = new ScrollStoreClass(); -export default ScrollStore; - diff --git a/webapp/utils/constants.jsx b/webapp/utils/constants.jsx index 9b18b52f9..9dbc43f60 100644 --- a/webapp/utils/constants.jsx +++ b/webapp/utils/constants.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import keyMirror from 'key-mirror/keyMirror.js'; +import keyMirror from 'key-mirror'; import audioIcon from 'images/icons/audio.png'; import videoIcon from 'images/icons/video.png'; diff --git a/webapp/utils/event_types.jsx b/webapp/utils/event_types.jsx new file mode 100644 index 000000000..1d43f4290 --- /dev/null +++ b/webapp/utils/event_types.jsx @@ -0,0 +1,8 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import keyMirror from 'key-mirror'; + +export default keyMirror({ + POST_LIST_SCROLL_CHANGE: null +}); diff --git a/webapp/utils/global_event_emitter.jsx b/webapp/utils/global_event_emitter.jsx new file mode 100644 index 000000000..0d231d2a2 --- /dev/null +++ b/webapp/utils/global_event_emitter.jsx @@ -0,0 +1,27 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import AppDispatcher from 'dispatcher/app_dispatcher.jsx'; +import EventEmitter from 'events'; + +import EventTypes from 'utils/event_types.jsx'; + +class GlobalEventEmitterClass extends EventEmitter { + constructor() { + super(); + this.dispatchToken = AppDispatcher.register(this.handleEventPayload); + } + + handleEventPayload = (payload) => { + const {type, value, ...args} = payload.action; //eslint-disable-line no-use-before-define + + switch (type) { + case EventTypes.POST_LIST_SCROLL_CHANGE: + this.emit(type, value, args); + break; + } + } +} + +const GlobalEventEmitter = new GlobalEventEmitterClass(); +export default GlobalEventEmitter; diff --git a/webapp/utils/markdown.jsx b/webapp/utils/markdown.jsx index f47c45d10..60ccbd246 100644 --- a/webapp/utils/markdown.jsx +++ b/webapp/utils/markdown.jsx @@ -4,11 +4,11 @@ import * as TextFormatting from './text_formatting.jsx'; import * as SyntaxHighlighting from './syntax_highlighting.jsx'; +import {postListScrollChange} from 'actions/global_actions.jsx'; + import marked from 'marked'; import katex from 'katex'; -import ScrollStore from 'stores/scroll_store.jsx'; - function markdownImageLoaded(image) { if (image.hasAttribute('height') && image.attributes.height.value !== 'auto') { const maxHeight = parseInt(global.getComputedStyle(image).maxHeight, 10); @@ -22,7 +22,8 @@ function markdownImageLoaded(image) { } else { image.style.height = 'auto'; } - ScrollStore.emitPostScroll(); + + postListScrollChange(); } global.markdownImageLoaded = markdownImageLoaded; diff --git a/webapp/yarn.lock b/webapp/yarn.lock index 16474c136..8691a824a 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -330,20 +330,20 @@ babel-code-frame@^6.11.0, babel-code-frame@^6.16.0, babel-code-frame@^6.22.0: esutils "^2.0.2" js-tokens "^3.0.0" -babel-core@^6.0.0, babel-core@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.24.1.tgz#8c428564dce1e1f41fb337ec34f4c3b022b5ad83" +babel-core@6.25.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.25.0.tgz#7dd42b0463c742e9d5296deb3ec67a9322dad729" dependencies: babel-code-frame "^6.22.0" - babel-generator "^6.24.1" + babel-generator "^6.25.0" babel-helpers "^6.24.1" babel-messages "^6.23.0" babel-register "^6.24.1" babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - babylon "^6.11.0" + babel-template "^6.25.0" + babel-traverse "^6.25.0" + babel-types "^6.25.0" + babylon "^6.17.2" convert-source-map "^1.1.0" debug "^2.1.1" json5 "^0.5.0" @@ -354,20 +354,20 @@ babel-core@^6.0.0, babel-core@^6.24.1: slash "^1.0.0" source-map "^0.5.0" -babel-core@^6.25.0: - version "6.25.0" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.25.0.tgz#7dd42b0463c742e9d5296deb3ec67a9322dad729" +babel-core@^6.0.0, babel-core@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.24.1.tgz#8c428564dce1e1f41fb337ec34f4c3b022b5ad83" dependencies: babel-code-frame "^6.22.0" - babel-generator "^6.25.0" + babel-generator "^6.24.1" babel-helpers "^6.24.1" babel-messages "^6.23.0" babel-register "^6.24.1" babel-runtime "^6.22.0" - babel-template "^6.25.0" - babel-traverse "^6.25.0" - babel-types "^6.25.0" - babylon "^6.17.2" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + babylon "^6.11.0" convert-source-map "^1.1.0" debug "^2.1.1" json5 "^0.5.0" @@ -548,7 +548,7 @@ babel-jest@20.0.3, babel-jest@^20.0.3: babel-plugin-istanbul "^4.0.0" babel-preset-jest "^20.0.3" -babel-loader@^7.1.0: +babel-loader@7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.0.tgz#3fbf2581f085774bd9642dca9990e6d6c1491144" dependencies: @@ -1268,7 +1268,7 @@ boom@2.x.x: dependencies: hoek "2.x.x" -bootstrap-colorpicker@^2.5.1: +bootstrap-colorpicker@2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/bootstrap-colorpicker/-/bootstrap-colorpicker-2.5.1.tgz#fdf70646956f51e640b031f43f22dd868592ef4c" dependencies: @@ -1859,15 +1859,7 @@ create-hmac@^1.1.0, create-hmac@^1.1.2: create-hash "^1.1.0" inherits "^2.0.1" -create-react-class@^15.5.2: - version "15.5.3" - resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.5.3.tgz#fb0f7cae79339e9a179e194ef466efa3923820fe" - dependencies: - fbjs "^0.8.9" - loose-envify "^1.3.1" - object-assign "^4.1.1" - -create-react-class@^15.5.3, create-react-class@^15.6.0: +create-react-class@^15.5.2, create-react-class@^15.5.3, create-react-class@^15.6.0: version "15.6.0" resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.0.tgz#ab448497c26566e1e29413e883207d57cfe7bed4" dependencies: @@ -1875,7 +1867,7 @@ create-react-class@^15.5.3, create-react-class@^15.6.0: loose-envify "^1.3.1" object-assign "^4.1.1" -cross-env@^5.0.1: +cross-env@5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.0.1.tgz#ff4e72ea43b47da2486b43a7f2043b2609e44913" dependencies: @@ -1929,7 +1921,7 @@ css-color-names@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" -css-loader@^0.28.4: +css-loader@0.28.4: version "0.28.4" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.4.tgz#6cf3579192ce355e8b38d5f42dd7a1f2ec898d0f" dependencies: @@ -2147,7 +2139,7 @@ decompress@^3.0.0: vinyl-assign "^1.0.1" vinyl-fs "^2.2.0" -deep-equal@1.0.1: +deep-equal@1.0.1, deep-equal@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" @@ -2812,7 +2804,7 @@ extglob@^0.3.1: dependencies: is-extglob "^1.0.0" -extract-text-webpack-plugin@^2.1.2: +extract-text-webpack-plugin@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-2.1.2.tgz#756ef4efa8155c3681833fbc34da53b941746d6c" dependencies: @@ -2907,7 +2899,7 @@ file-entry-cache@^2.0.0: flat-cache "^1.2.1" object-assign "^4.0.1" -file-loader@^0.11.2: +file-loader@0.11.2: version "0.11.2" resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-0.11.2.tgz#4ff1df28af38719a6098093b88c82c71d1794a34" dependencies: @@ -3459,19 +3451,18 @@ he@1.1.x: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" -highlight.js@^9.12.0: +highlight.js@9.12.0: version "9.12.0" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e" -history@^4.6.0: - version "4.6.3" - resolved "https://registry.yarnpkg.com/history/-/history-4.6.3.tgz#6d723a8712c581d6bef37e8c26f4aedc6eb86967" +history@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/history/-/history-2.1.2.tgz#4aa2de897a0e4867e4539843be6ecdb2986bfdec" dependencies: - invariant "^2.2.1" - loose-envify "^1.2.0" - resolve-pathname "^2.0.0" - value-equal "^0.2.0" - warning "^3.0.0" + deep-equal "^1.0.0" + invariant "^2.0.0" + query-string "^3.0.0" + warning "^2.0.0" hmac-drbg@^1.0.0: version "1.0.1" @@ -3533,7 +3524,7 @@ html-minifier@^3.0.1, html-minifier@^3.2.3: relateurl "0.2.x" uglify-js "~2.8.22" -html-to-react@^1.2.11: +html-to-react@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/html-to-react/-/html-to-react-1.2.11.tgz#fd05600ca26e5cf3eadac94bdfb43ddda623d7b4" dependencies: @@ -3818,7 +3809,7 @@ intl@1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/intl/-/intl-1.2.5.tgz#82244a2190c4e419f8371f5aa34daa3420e2abde" -invariant@^2.0.0, invariant@^2.1.0, invariant@^2.1.1, invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2: +invariant@^2.0.0, invariant@^2.1.0, invariant@^2.1.1, invariant@^2.2.0, invariant@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" dependencies: @@ -4205,7 +4196,7 @@ jest-changed-files@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-20.0.3.tgz#9394d5cc65c438406149bef1bf4d52b68e03e3f8" -jest-cli@^20.0.4: +jest-cli@20.0.4, jest-cli@^20.0.4: version "20.0.4" resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-20.0.4.tgz#e532b19d88ae5bc6c417e8b0593a6fe954b1dc93" dependencies: @@ -4406,7 +4397,7 @@ jest-validate@^20.0.3: leven "^2.1.0" pretty-format "^20.0.3" -jest@^20.0.4: +jest@20.0.4: version "20.0.4" resolved "https://registry.yarnpkg.com/jest/-/jest-20.0.4.tgz#3dd260c2989d6dad678b1e9cc4d91944f6d602ac" dependencies: @@ -4473,7 +4464,7 @@ jsdom-global@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/jsdom-global/-/jsdom-global-3.0.2.tgz#6bd299c13b0c4626b2da2c0393cd4385d606acb9" -jsdom@^11.0.0: +jsdom@11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.0.0.tgz#1ee507cb2c0b16c875002476b1a8557d951353e5" dependencies: @@ -4619,6 +4610,10 @@ jws@^3.1.4: jwa "^1.1.4" safe-buffer "^5.0.1" +key-mirror@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/key-mirror/-/key-mirror-1.0.1.tgz#0a132d5c8a82a3a4fcd7df732ff9510d04ab366b" + keycode@^2.1.2: version "2.1.8" resolved "https://registry.yarnpkg.com/keycode/-/keycode-2.1.8.tgz#94d2b7098215eff0e8f9a8931d5a59076c4532fb" @@ -5048,11 +5043,12 @@ math-expression-evaluator@^1.2.14: mattermost-redux@mattermost/mattermost-redux#webapp-master: version "0.0.1" - resolved "https://codeload.github.com/mattermost/mattermost-redux/tar.gz/713e134e945a97dd92f4217301231b8a7af20216" + resolved "https://codeload.github.com/mattermost/mattermost-redux/tar.gz/de4fb87089a0cfb68af04ac0b16cc96481710d88" dependencies: deep-equal "1.0.1" harmony-reflect "1.5.1" isomorphic-fetch "2.2.1" + key-mirror "1.0.1" mime-db "1.27.0" redux "3.6.0" redux-action-buffer "1.0.1" @@ -5715,12 +5711,6 @@ path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" -path-to-regexp@^1.5.3: - version "1.7.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" - dependencies: - isarray "0.0.1" - path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -5735,7 +5725,7 @@ pbkdf2@^3.0.3: dependencies: create-hmac "^1.1.2" -pdfjs-dist@^1.8.474: +pdfjs-dist@1.8.474: version "1.8.474" resolved "https://registry.yarnpkg.com/pdfjs-dist/-/pdfjs-dist-1.8.474.tgz#a34c0d79748b15087957d52698337db7a2ff2546" dependencies: @@ -5746,7 +5736,7 @@ pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" -perfect-scrollbar@^0.7.1: +perfect-scrollbar@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/perfect-scrollbar/-/perfect-scrollbar-0.7.1.tgz#0c256fb9c5cee401d60a299687a3f9a61487e0d5" @@ -6144,6 +6134,12 @@ qs@6.4.0, qs@^6.1.0, qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" +query-string@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-3.0.3.tgz#ae2e14b4d05071d4e9b9eb4873c35b0dcd42e638" + dependencies: + strict-uri-encode "^1.0.0" + query-string@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" @@ -6205,14 +6201,14 @@ rc@^1.1.2, rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -react-addons-pure-render-mixin@^15.6.0: +react-addons-pure-render-mixin@15.6.0: version "15.6.0" resolved "https://registry.yarnpkg.com/react-addons-pure-render-mixin/-/react-addons-pure-render-mixin-15.6.0.tgz#84ba028630cdf89239d16f1bb4d98fe865651813" dependencies: fbjs "^0.8.4" object-assign "^4.1.0" -react-addons-test-utils@^15.6.0: +react-addons-test-utils@15.6.0: version "15.6.0" resolved "https://registry.yarnpkg.com/react-addons-test-utils/-/react-addons-test-utils-15.6.0.tgz#062d36117fe8d18f3ba5e06eb33383b0b85ea5b9" @@ -6231,7 +6227,7 @@ react-bootstrap@0.31.0: uncontrollable "^4.1.0" warning "^3.0.0" -react-color@^2.12.1: +react-color@2.12.1: version "2.12.1" resolved "https://registry.yarnpkg.com/react-color/-/react-color-2.12.1.tgz#ef5a4dc4260ed7d1642047d5b6693d68939b19f7" dependencies: @@ -6249,7 +6245,7 @@ react-custom-scrollbars@4.1.2: prop-types "^15.5.10" raf "^3.1.0" -react-dom@^15.6.1: +react-dom@15.6.1: version "15.6.1" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.6.1.tgz#2cb0ed4191038e53c209eb3a79a23e2a4cf99470" dependencies: @@ -6290,7 +6286,7 @@ react-prop-types@^0.4.0: dependencies: warning "^3.0.0" -react-redux@^5.0.5: +react-redux@5.0.5: version "5.0.5" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.5.tgz#f8e8c7b239422576e52d6b7db06439469be9846a" dependencies: @@ -6302,19 +6298,17 @@ react-redux@^5.0.5: loose-envify "^1.1.0" prop-types "^15.5.10" -react-router@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.1.1.tgz#d448f3b7c1b429a6fbb03395099949c606b1fe95" +react-router@2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-2.8.1.tgz#73e9491f6ceb316d0f779829081863e378ee4ed7" dependencies: - history "^4.6.0" + history "^2.1.2" hoist-non-react-statics "^1.2.0" - invariant "^2.2.2" - loose-envify "^1.3.1" - path-to-regexp "^1.5.3" - prop-types "^15.5.4" + invariant "^2.2.1" + loose-envify "^1.2.0" warning "^3.0.0" -react-select@^1.0.0-rc.5: +react-select@1.0.0-rc.5: version "1.0.0-rc.5" resolved "https://registry.yarnpkg.com/react-select/-/react-select-1.0.0-rc.5.tgz#9d316f252b1adc372ddb5cdf1f119c6b7cfdb5d6" dependencies: @@ -6323,7 +6317,7 @@ react-select@^1.0.0-rc.5: prop-types "^15.5.8" react-input-autosize "^1.1.3" -react@^15.6.1: +react@15.6.1: version "15.6.1" resolved "https://registry.yarnpkg.com/react/-/react-15.6.1.tgz#baa8434ec6780bde997cdc380b79cd33b96393df" dependencies: @@ -6474,7 +6468,7 @@ redux-devtools-instrument@^1.3.3: dependencies: redux-persist "^4.5.0" -redux-persist-transform-filter@^0.0.13: +redux-persist-transform-filter@0.0.13: version "0.0.13" resolved "https://registry.yarnpkg.com/redux-persist-transform-filter/-/redux-persist-transform-filter-0.0.13.tgz#b22573ac8571b8e15c5826b80398825d1b1178cb" dependencies: @@ -6575,7 +6569,7 @@ remote-redux-devtools-on-debugger@0.7.1: minimist "^1.2.0" remotedev-server "^0.2.2" -remote-redux-devtools@^0.5.12: +remote-redux-devtools@0.5.12: version "0.5.12" resolved "https://registry.yarnpkg.com/remote-redux-devtools/-/remote-redux-devtools-0.5.12.tgz#42cb95dfa9e54c1d9671317c5e7bba41e68caec2" dependencies: @@ -6716,10 +6710,6 @@ resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" -resolve-pathname@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.1.0.tgz#e8358801b86b83b17560d4e3c382d7aef2100944" - resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" @@ -6805,7 +6795,7 @@ sass-graph@^2.1.1: lodash "^4.0.0" yargs "^4.7.1" -sass-loader@^6.0.6: +sass-loader@6.0.6: version "6.0.6" resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-6.0.6.tgz#e9d5e6c1f155faa32a4b26d7a9b7107c225e40f9" dependencies: @@ -7310,7 +7300,7 @@ strip-outer@^1.0.0: dependencies: escape-string-regexp "^1.0.2" -style-loader@^0.18.2: +style-loader@0.18.2: version "0.18.2" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.18.2.tgz#cc31459afbcd6d80b7220ee54b291a9fd66ff5eb" dependencies: @@ -7577,7 +7567,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" -twemoji@^2.3.0: +twemoji@2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/twemoji/-/twemoji-2.3.0.tgz#45b4af4292d42f2fdf2d8ec5b86d5a8a996bc018" @@ -7704,7 +7694,7 @@ upper-case@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" -url-loader@^0.5.9: +url-loader@0.5.9: version "0.5.9" resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-0.5.9.tgz#cc8fea82c7b906e7777019250869e569e995c295" dependencies: @@ -7791,10 +7781,6 @@ validate-npm-package-license@^3.0.1: spdx-correct "~1.0.0" spdx-expression-parse "~1.0.0" -value-equal@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.2.1.tgz#c220a304361fce6994dbbedaa3c7e1a1b895871d" - vary@^1, vary@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37" @@ -7883,6 +7869,12 @@ ware@^1.2.0: dependencies: wrap-fn "^0.1.0" +warning@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/warning/-/warning-2.1.0.tgz#21220d9c63afc77a8c92111e011af705ce0c6901" + dependencies: + loose-envify "^1.0.0" + warning@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c" @@ -7920,7 +7912,7 @@ webpack-sources@^1.0.1: source-list-map "^2.0.0" source-map "~0.5.3" -webpack@^3.0.0: +webpack@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.0.0.tgz#ee9bcebf21247f7153cb410168cab45e3a59d4d7" dependencies: @@ -7947,7 +7939,7 @@ webpack@^3.0.0: webpack-sources "^1.0.1" yargs "^6.0.0" -webrtc-adapter@^4.0.2: +webrtc-adapter@4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webrtc-adapter/-/webrtc-adapter-4.0.2.tgz#f9d1d0604d7937766fb4b672ba235af70feada2b" dependencies: -- cgit v1.2.3-1-g7c22