diff options
28 files changed, 167 insertions, 184 deletions
diff --git a/webapp/components/access_history_modal.jsx b/webapp/components/access_history_modal.jsx index 94a10c97f..9c49c3879 100644 --- a/webapp/components/access_history_modal.jsx +++ b/webapp/components/access_history_modal.jsx @@ -2,7 +2,6 @@ // See License.txt for license information. import $ from 'jquery'; -import ReactDOM from 'react-dom'; import {Modal} from 'react-bootstrap'; import LoadingScreen from './loading_screen.jsx'; import AuditTable from './audit_table.jsx'; @@ -36,11 +35,8 @@ class AccessHistoryModal extends React.Component { } onShow() { AsyncClient.getAudits(); - - if ($(window).width() > 768) { - $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 200); - } else { - $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 150); + if (!Utils.isMobile()) { + $('.modal-body').perfectScrollbar(); } } onHide() { diff --git a/webapp/components/activity_log_modal.jsx b/webapp/components/activity_log_modal.jsx index 9a4ff3ef2..f1dd4a26a 100644 --- a/webapp/components/activity_log_modal.jsx +++ b/webapp/components/activity_log_modal.jsx @@ -2,7 +2,6 @@ // See License.txt for license information. import $ from 'jquery'; -import ReactDOM from 'react-dom'; import UserStore from 'stores/user_store.jsx'; import * as Client from 'utils/client.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; @@ -56,11 +55,8 @@ export default class ActivityLogModal extends React.Component { } onShow() { AsyncClient.getSessions(); - - if ($(window).width() > 768) { - $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 200); - } else { - $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 150); + if (!Utils.isMobile()) { + $('.modal-body').perfectScrollbar(); } } onHide() { diff --git a/webapp/components/channel_header.jsx b/webapp/components/channel_header.jsx index 7cd713942..369fa2dbb 100644 --- a/webapp/components/channel_header.jsx +++ b/webapp/components/channel_header.jsx @@ -80,6 +80,7 @@ export default class ChannelHeader extends React.Component { SearchStore.addSearchChangeListener(this.onListenerChange); PreferenceStore.addChangeListener(this.onListenerChange); UserStore.addChangeListener(this.onListenerChange); + $('.sidebar--left .dropdown-menu').perfectScrollbar(); } componentWillUnmount() { ChannelStore.removeChangeListener(this.onListenerChange); diff --git a/webapp/components/edit_post_modal.jsx b/webapp/components/edit_post_modal.jsx index 0a55b2968..caf9a0ee5 100644 --- a/webapp/components/edit_post_modal.jsx +++ b/webapp/components/edit_post_modal.jsx @@ -27,8 +27,8 @@ const holders = defineMessages({ import React from 'react'; class EditPostModal extends React.Component { - constructor() { - super(); + constructor(props) { + super(props); this.handleEdit = this.handleEdit.bind(this); this.handleEditInput = this.handleEditInput.bind(this); @@ -56,12 +56,13 @@ class EditPostModal extends React.Component { updatedPost.id = this.state.post_id; updatedPost.channel_id = this.state.channel_id; - Client.updatePost(updatedPost, - function success() { + Client.updatePost( + updatedPost, + () => { AsyncClient.getPosts(updatedPost.channel_id); window.scrollTo(0, 0); }, - function error(err) { + (err) => { AsyncClient.dispatchError(err, 'updatePost'); } ); @@ -106,11 +107,11 @@ class EditPostModal extends React.Component { componentDidMount() { var self = this; - $(ReactDOM.findDOMNode(this.refs.modal)).on('hidden.bs.modal', function onHidden() { + $(ReactDOM.findDOMNode(this.refs.modal)).on('hidden.bs.modal', () => { self.setState({editText: '', title: '', channel_id: '', post_id: '', comments: 0, refocusId: '', error: ''}); }); - $(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', function onShow(e) { + $(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', (e) => { var button = e.relatedTarget; if (!button) { return; @@ -118,12 +119,11 @@ class EditPostModal extends React.Component { self.setState({editText: $(button).attr('data-message'), title: $(button).attr('data-title'), channel_id: $(button).attr('data-channelid'), post_id: $(button).attr('data-postid'), comments: $(button).attr('data-comments'), refocusId: $(button).attr('data-refocusid')}); }); - $(ReactDOM.findDOMNode(this.refs.modal)).on('shown.bs.modal', function onShown() { - self.refs.editbox.resize(); - $('#edit_textbox').get(0).focus(); + $(ReactDOM.findDOMNode(this.refs.modal)).on('shown.bs.modal', () => { + self.refs.editbox.focus(); }); - $(ReactDOM.findDOMNode(this.refs.modal)).on('hide.bs.modal', function onShown() { + $(ReactDOM.findDOMNode(this.refs.modal)).on('hide.bs.modal', () => { if (self.state.refocusId !== '') { setTimeout(() => { $(self.state.refocusId).get(0).focus(); @@ -221,4 +221,4 @@ EditPostModal.propTypes = { intl: intlShape.isRequired }; -export default injectIntl(EditPostModal);
\ No newline at end of file +export default injectIntl(EditPostModal); diff --git a/webapp/components/invite_member_modal.jsx b/webapp/components/invite_member_modal.jsx index d567183ac..1f8fd6133 100644 --- a/webapp/components/invite_member_modal.jsx +++ b/webapp/components/invite_member_modal.jsx @@ -1,7 +1,6 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import $ from 'jquery'; import ReactDOM from 'react-dom'; import * as utils from 'utils/utils.jsx'; import Constants from 'utils/constants.jsx'; @@ -176,12 +175,6 @@ class InviteMemberModal extends React.Component { }); } - componentDidUpdate(prevProps, prevState) { - if (!prevState.show && this.state.show) { - $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 200); - } - } - addInviteFields() { var count = this.state.idCount + 1; var inviteIds = this.state.inviteIds; diff --git a/webapp/components/logged_in.jsx b/webapp/components/logged_in.jsx index 7ddb6b83d..c6f7b50b1 100644 --- a/webapp/components/logged_in.jsx +++ b/webapp/components/logged_in.jsx @@ -6,6 +6,7 @@ import * as AsyncClient from 'utils/async_client.jsx'; import * as GlobalActions from 'action_creators/global_actions.jsx'; import UserStore from 'stores/user_store.jsx'; import ChannelStore from 'stores/channel_store.jsx'; +import BrowserStore from 'stores/browser_store.jsx'; import PreferenceStore from 'stores/preference_store.jsx'; import * as Utils from 'utils/utils.jsx'; import Constants from 'utils/constants.jsx'; @@ -84,7 +85,7 @@ export default class LoggedIn extends React.Component { // when one tab on a browser logs out, it sets __logout__ in localStorage to trigger other tabs to log out if (e.originalEvent.key === '__logout__' && e.originalEvent.storageArea === localStorage && e.originalEvent.newValue) { // make sure it isn't this tab that is sending the logout signal (only necessary for IE11) - if (window.BrowserStore.isSignallingLogout(e.originalEvent.newValue)) { + if (BrowserStore.isSignallingLogout(e.originalEvent.newValue)) { return; } @@ -94,7 +95,7 @@ export default class LoggedIn extends React.Component { if (e.originalEvent.key === '__login__' && e.originalEvent.storageArea === localStorage && e.originalEvent.newValue) { // make sure it isn't this tab that is sending the logout signal (only necessary for IE11) - if (window.BrowserStore.isSignallingLogin(e.originalEvent.newValue)) { + if (BrowserStore.isSignallingLogin(e.originalEvent.newValue)) { return; } diff --git a/webapp/components/popover_list_members.jsx b/webapp/components/popover_list_members.jsx index 7d048019c..819c7f590 100644 --- a/webapp/components/popover_list_members.jsx +++ b/webapp/components/popover_list_members.jsx @@ -1,6 +1,8 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. +import $ from 'jquery'; + import UserStore from 'stores/user_store.jsx'; import {Popover, Overlay} from 'react-bootstrap'; import * as Utils from 'utils/utils.jsx'; @@ -20,6 +22,10 @@ export default class PopoverListMembers extends React.Component { this.closePopover = this.closePopover.bind(this); } + componentDidUpdate() { + $('.member-list__popover .popover-content').perfectScrollbar(); + } + componentWillMount() { this.setState({showPopover: false}); } diff --git a/webapp/components/rhs_thread.jsx b/webapp/components/rhs_thread.jsx index 2760765eb..f0324d7ce 100644 --- a/webapp/components/rhs_thread.jsx +++ b/webapp/components/rhs_thread.jsx @@ -46,6 +46,9 @@ export default class RhsThread extends React.Component { window.addEventListener('resize', this.handleResize); this.mounted = true; + if (!Utils.isMobile()) { + $('.sidebar--right .post-right__scroll').perfectScrollbar(); + } } componentDidUpdate() { if ($('.post-right__scroll')[0]) { diff --git a/webapp/components/search_results.jsx b/webapp/components/search_results.jsx index 7619e41cd..c5baf50ef 100644 --- a/webapp/components/search_results.jsx +++ b/webapp/components/search_results.jsx @@ -61,6 +61,9 @@ export default class SearchResults extends React.Component { UserStore.addChangeListener(this.onUserChange); this.resize(); window.addEventListener('resize', this.handleResize); + if (!Utils.isMobile()) { + $('.sidebar--right .search-items-container').perfectScrollbar(); + } } shouldComponentUpdate(nextProps, nextState) { diff --git a/webapp/components/sidebar.jsx b/webapp/components/sidebar.jsx index d8d825fd4..0e1b7dd0e 100644 --- a/webapp/components/sidebar.jsx +++ b/webapp/components/sidebar.jsx @@ -163,6 +163,9 @@ export default class Sidebar extends React.Component { componentDidUpdate() { this.updateTitle(); this.updateUnreadIndicators(); + if (!Utils.isMobile()) { + $('.sidebar--left .nav-pills__container').perfectScrollbar(); + } } componentWillUnmount() { window.removeEventListener('resize', this.handleResize); diff --git a/webapp/components/suggestion/suggestion_box.jsx b/webapp/components/suggestion/suggestion_box.jsx index e3ec63194..b7f0e3a36 100644 --- a/webapp/components/suggestion/suggestion_box.jsx +++ b/webapp/components/suggestion/suggestion_box.jsx @@ -3,11 +3,14 @@ import $ from 'jquery'; import ReactDOM from 'react-dom'; + import Constants from 'utils/constants.jsx'; import * as GlobalActions from 'action_creators/global_actions.jsx'; import SuggestionStore from 'stores/suggestion_store.jsx'; import * as Utils from 'utils/utils.jsx'; +import TextareaAutosize from 'react-textarea-autosize'; + const KeyCodes = Constants.KeyCodes; import React from 'react'; @@ -44,7 +47,13 @@ export default class SuggestionBox extends React.Component { getTextbox() { // this is to support old code that looks at the input/textarea DOM nodes - return ReactDOM.findDOMNode(this.refs.textbox); + let textbox = this.refs.textbox; + + if (!(textbox instanceof HTMLElement)) { + textbox = ReactDOM.findDOMNode(textbox); + } + + return textbox; } handleDocumentClick(e) { @@ -132,7 +141,8 @@ export default class SuggestionBox extends React.Component { ); } else if (this.props.type === 'textarea') { textbox = ( - <textarea + <TextareaAutosize + id={this.suggestionId} ref='textbox' {...newProps} /> @@ -163,5 +173,6 @@ SuggestionBox.propTypes = { // explicitly name any input event handlers we override and need to manually call onChange: React.PropTypes.func, - onKeyDown: React.PropTypes.func + onKeyDown: React.PropTypes.func, + onHeightChange: React.PropTypes.func }; diff --git a/webapp/components/team_settings_modal.jsx b/webapp/components/team_settings_modal.jsx index 7dbbd680a..c19787993 100644 --- a/webapp/components/team_settings_modal.jsx +++ b/webapp/components/team_settings_modal.jsx @@ -5,6 +5,7 @@ import $ from 'jquery'; import ReactDOM from 'react-dom'; import SettingsSidebar from './settings_sidebar.jsx'; import TeamSettings from './team_settings.jsx'; +import * as Utils from 'utils/utils.jsx'; import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'react-intl'; @@ -49,9 +50,16 @@ class TeamSettingsModal extends React.Component { $('.modal-dialog.display--content').removeClass('display--content'); }, 500); }); + + if (!Utils.isMobile()) { + $('.settings-modal .settings-content').perfectScrollbar(); + } } updateTab(tab) { this.setState({activeTab: tab, activeSection: ''}); + if (!Utils.isMobile()) { + $('.settings-modal .modal-body').scrollTop(0).perfectScrollbar('update'); + } } updateSection(section) { this.setState({activeSection: section}); diff --git a/webapp/components/textbox.jsx b/webapp/components/textbox.jsx index 1a395072e..371c581e5 100644 --- a/webapp/components/textbox.jsx +++ b/webapp/components/textbox.jsx @@ -2,7 +2,6 @@ // See License.txt for license information. import $ from 'jquery'; -import ReactDOM from 'react-dom'; import AtMentionProvider from './suggestion/at_mention_provider.jsx'; import CommandProvider from './suggestion/command_provider.jsx'; import EmoticonProvider from './suggestion/emoticon_provider.jsx'; @@ -29,7 +28,7 @@ export default class Textbox extends React.Component { this.onRecievedError = this.onRecievedError.bind(this); this.handleKeyPress = this.handleKeyPress.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this); - this.resize = this.resize.bind(this); + this.handleHeightChange = this.handleHeightChange.bind(this); this.showPreview = this.showPreview.bind(this); this.state = { @@ -54,8 +53,6 @@ export default class Textbox extends React.Component { componentDidMount() { ErrorStore.addChangeListener(this.onRecievedError); - - this.resize(); } componentWillUnmount() { @@ -72,10 +69,6 @@ export default class Textbox extends React.Component { } } - componentDidUpdate() { - this.resize(); - } - handleKeyPress(e) { this.props.onKeyPress(e); } @@ -86,50 +79,28 @@ export default class Textbox extends React.Component { } } - focus() { - this.refs.message.getTextbox().focus(); - } + handleHeightChange(height) { + const textbox = $(this.refs.message.getTextbox()); + const wrapper = $(this.refs.wrapper); - resize() { - const textbox = this.refs.message.getTextbox(); - const $textbox = $(textbox); - const $wrapper = $(ReactDOM.findDOMNode(this.refs.wrapper)); + const maxHeight = parseInt(textbox.css('max-height'), 10); - const padding = parseInt($textbox.css('padding-bottom'), 10) + parseInt($textbox.css('padding-top'), 10); - const borders = parseInt($textbox.css('border-bottom-width'), 10) + parseInt($textbox.css('border-top-width'), 10); - const maxHeight = parseInt($textbox.css('max-height'), 10) - borders; - - // set the height to auto and remove the scrollbar so we can get the actual size of the contents - $textbox.css('height', 'auto').css('overflow-y', 'hidden'); - - let height = textbox.scrollHeight - padding; - - if (height + padding > maxHeight) { - height = maxHeight - padding; - - // turn scrollbar on and move over attachment icon to compensate for that - $textbox.css('overflow-y', 'scroll'); - $wrapper.closest('.post-body__cell').addClass('scroll'); + // move over attachment icon to compensate for the scrollbar + if (height > maxHeight) { + wrapper.closest('.post-body__cell').addClass('scroll'); } else { - $wrapper.closest('.post-body__cell').removeClass('scroll'); + wrapper.closest('.post-body__cell').removeClass('scroll'); } + } - // set the textarea to be the proper height - $textbox.height(height); - - // set the wrapper height to match the height of the textbox including padding and borders - $wrapper.height(height + padding + borders); - - if (this.state.preview) { - $(ReactDOM.findDOMNode(this.refs.preview)).height(height + borders); - } + focus() { + this.refs.message.getTextbox().focus(); } showPreview(e) { e.preventDefault(); e.target.blur(); this.setState({preview: !this.state.preview}); - this.resize(); } render() { @@ -157,7 +128,7 @@ export default class Textbox extends React.Component { ); } - let helpText = ( + const helpText = ( <div style={{visibility: hasText ? 'visible' : 'hidden', opacity: hasText ? '0.5' : '0'}} className='help_format_text' @@ -174,12 +145,16 @@ export default class Textbox extends React.Component { defaultMessage='_italic_' /> </i> - <span>~~<strike> - <FormattedMessage - id='textbox.strike' - defaultMessage='strike' - /> - </strike>~~ </span> + <span> + {'~~'} + <strike> + <FormattedMessage + id='textbox.strike' + defaultMessage='strike' + /> + </strike> + {'~~ '} + </span> <code> <FormattedMessage id='textbox.inlinecode' @@ -214,16 +189,17 @@ export default class Textbox extends React.Component { spellCheck='true' autoComplete='off' autoCorrect='off' - rows='1' maxLength={Constants.MAX_POST_LEN} placeholder={this.props.createMessage} value={this.props.messageText} onUserInput={this.props.onUserInput} onKeyPress={this.handleKeyPress} onKeyDown={this.handleKeyDown} + onHeightChange={this.handleHeightChange} style={{visibility: this.state.preview ? 'hidden' : 'visible'}} listComponent={SuggestionList} providers={this.suggestionProviders} + channelId={this.props.channelId} /> <div ref='preview' diff --git a/webapp/components/user_list.jsx b/webapp/components/user_list.jsx index b5d42decc..3652723be 100644 --- a/webapp/components/user_list.jsx +++ b/webapp/components/user_list.jsx @@ -24,11 +24,16 @@ export default class UserList extends React.Component { }); } else { content = ( - <div key='no-users-found'> - <FormattedMessage - id='user_list.notFound' - defaultMessage='No users found :(' - /> + <div + key='no-users-found' + className='no-channel-message' + > + <p className='primary-message'> + <FormattedMessage + id='user_list.notFound' + defaultMessage='No users found :(' + /> + </p> </div> ); } diff --git a/webapp/components/user_settings/user_settings_modal.jsx b/webapp/components/user_settings/user_settings_modal.jsx index bd1df6ea5..d1c1f0fe2 100644 --- a/webapp/components/user_settings/user_settings_modal.jsx +++ b/webapp/components/user_settings/user_settings_modal.jsx @@ -64,7 +64,6 @@ class UserSettingsModal extends React.Component { constructor(props) { super(props); - this.handleShow = this.handleShow.bind(this); this.handleHide = this.handleHide.bind(this); this.handleHidden = this.handleHidden.bind(this); this.handleCollapse = this.handleCollapse.bind(this); @@ -95,24 +94,13 @@ class UserSettingsModal extends React.Component { } componentDidMount() { - if (this.props.show) { - this.handleShow(); - } UserStore.addChangeListener(this.onUserChanged); } - componentDidUpdate(prevProps) { - if (this.props.show && !prevProps.show) { - this.handleShow(); - } + componentDidUpdate() { UserStore.removeChangeListener(this.onUserChanged); - } - - handleShow() { - if ($(window).width() > 768) { - $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 200); - } else { - $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 50); + if (!Utils.isMobile()) { + $('.settings-modal .modal-body').perfectScrollbar(); } } @@ -222,6 +210,10 @@ class UserSettingsModal extends React.Component { active_section: '' }); } + + if (!Utils.isMobile()) { + $('.settings-modal .modal-body').scrollTop(0).perfectScrollbar('update'); + } } updateSection(section, skipConfirm) { diff --git a/webapp/package.json b/webapp/package.json index cdfba8ef0..6f50962a4 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -24,6 +24,7 @@ "react-dom": "0.14.7", "react-intl": "2.0.0-rc-1", "react-router": "2.0.1", + "react-textarea-autosize": "3.3.0", "twemoji": "1.4.1", "velocity-animate": "1.2.3" }, @@ -53,8 +54,8 @@ "webpack": "webpack/webpack#master" }, "scripts": { - "check": "eslint --ext \".jsx\" --ignore-pattern node_modules --quiet .", - "build": "webpack", - "run": "webpack --progress --watch" + "check": "eslint --ext \".jsx\" --ignore-pattern node_modules --quiet .", + "build": "webpack", + "run": "webpack --progress --watch" } } diff --git a/webapp/root.jsx b/webapp/root.jsx index bb5f506c1..f4d9a0e47 100644 --- a/webapp/root.jsx +++ b/webapp/root.jsx @@ -2,6 +2,7 @@ // See License.txt for license information. import $ from 'jquery'; +require('perfect-scrollbar/jquery')($); import 'bootstrap/dist/css/bootstrap.css'; import 'jasny-bootstrap/dist/css/jasny-bootstrap.css'; diff --git a/webapp/sass/components/_modal.scss b/webapp/sass/components/_modal.scss index 94378aabe..4e2049857 100644 --- a/webapp/sass/components/_modal.scss +++ b/webapp/sass/components/_modal.scss @@ -9,6 +9,7 @@ } .modal-body { + max-height: calc(90vh - 62px); overflow: auto; padding: 20px 15px; diff --git a/webapp/sass/components/_suggestion-list.scss b/webapp/sass/components/_suggestion-list.scss index 0100026ca..39269642d 100644 --- a/webapp/sass/components/_suggestion-list.scss +++ b/webapp/sass/components/_suggestion-list.scss @@ -8,6 +8,7 @@ .suggestion-list--top { position: absolute; + bottom: 100%; } .suggestion-list__content { diff --git a/webapp/sass/layout/_headers.scss b/webapp/sass/layout/_headers.scss index 9b631d00f..e75d2556b 100644 --- a/webapp/sass/layout/_headers.scss +++ b/webapp/sass/layout/_headers.scss @@ -134,6 +134,10 @@ @include alpha-property(background, $black, .1); } + a { + text-decoration: none; + } + .user__name { color: $white; } diff --git a/webapp/sass/layout/_navigation.scss b/webapp/sass/layout/_navigation.scss index 87e4b4d27..3daf6e56b 100644 --- a/webapp/sass/layout/_navigation.scss +++ b/webapp/sass/layout/_navigation.scss @@ -89,7 +89,7 @@ &.info-popover { @include background-size(100% 100%); - background: url('../images/info__icon.png'); + background-image: url('../images/info__icon.png'); cursor: pointer; height: 19px; position: relative; diff --git a/webapp/sass/layout/_post.scss b/webapp/sass/layout/_post.scss index 9d5be239a..4170483db 100644 --- a/webapp/sass/layout/_post.scss +++ b/webapp/sass/layout/_post.scss @@ -7,9 +7,7 @@ line-height: 20px; min-height: 36px; overflow-x: hidden; - position: absolute; resize: none; - top: 0px; white-space: pre-wrap; word-wrap: break-word; diff --git a/webapp/sass/layout/_sidebar-left.scss b/webapp/sass/layout/_sidebar-left.scss index 4c65d0a65..3a5e74570 100644 --- a/webapp/sass/layout/_sidebar-left.scss +++ b/webapp/sass/layout/_sidebar-left.scss @@ -1,7 +1,6 @@ @charset 'UTF-8'; .sidebar--left { - background: #fafafa; border-right: $border-gray; height: 100%; left: 0; diff --git a/webapp/sass/routes/_admin-console.scss b/webapp/sass/routes/_admin-console.scss index 0b47e5ab6..7e53713c0 100644 --- a/webapp/sass/routes/_admin-console.scss +++ b/webapp/sass/routes/_admin-console.scss @@ -10,12 +10,8 @@ width: 100%; } - .row { - margin: 0; - } - h3 { - border-bottom: 1px solid #ddd; + border-bottom: 1px solid alpha-color($black, .1); font-weight: 600; margin: 1em 0; padding-bottom: .5em; @@ -75,11 +71,18 @@ width: 17px; } + &.divider { + @include alpha-property(background, $black, .1); + } + > a { &:hover, - &.active, &:focus { - background-color: #eaeaea; + @include alpha-property(background, $black, .1); + } + + &.active { + background-color: transparent; } } diff --git a/webapp/stores/browser_store.jsx b/webapp/stores/browser_store.jsx index 66190f6a2..bba146e38 100644 --- a/webapp/stores/browser_store.jsx +++ b/webapp/stores/browser_store.jsx @@ -8,6 +8,8 @@ function getPrefix() { return global.window.mm_current_user_id + '_'; } + console.log('BrowserStore tried to operate without user present'); //eslint-disable-line no-console + return 'unknown_'; } @@ -34,46 +36,35 @@ class BrowserStoreClass { } checkVersion() { - var currentVersion = sessionStorage.getItem('storage_version'); + var currentVersion = this.getGlobalItem('storage_version'); if (currentVersion !== global.window.mm_config.Version) { - sessionStorage.clear(); + this.clearAll(); try { - sessionStorage.setItem('storage_version', global.window.mm_config.Version); + this.setGlobalItem('storage_version', global.window.mm_config.Version); } catch (e) { // Do nothing } } } - getItem(name, defaultValue) { - var result = null; - try { - result = JSON.parse(sessionStorage.getItem(getPrefix() + name)); - } catch (err) { - result = null; - } - - if (result === null && typeof defaultValue !== 'undefined') { - result = defaultValue; - } - - return result; + setItem(name, value) { + this.setGlobalItem(getPrefix() + name, value); } - setItem(name, value) { - sessionStorage.setItem(getPrefix() + name, JSON.stringify(value)); + getItem(name, defaultValue) { + return this.getGlobalItem(getPrefix() + name, defaultValue); } removeItem(name) { - sessionStorage.removeItem(getPrefix() + name); + this.removeGlobalItem(getPrefix() + name); } setGlobalItem(name, value) { try { if (this.isLocalStorageSupported()) { - localStorage.setItem(getPrefix() + name, JSON.stringify(value)); + localStorage.setItem(name, JSON.stringify(value)); } else { - sessionStorage.setItem(getPrefix() + name, JSON.stringify(value)); + sessionStorage.setItem(name, JSON.stringify(value)); } } catch (err) { console.log('An error occurred while setting local storage, clearing all props'); //eslint-disable-line no-console @@ -87,9 +78,9 @@ class BrowserStoreClass { var result = null; try { if (this.isLocalStorageSupported()) { - result = JSON.parse(localStorage.getItem(getPrefix() + name)); + result = JSON.parse(localStorage.getItem(name)); } else { - result = JSON.parse(sessionStorage.getItem(getPrefix() + name)); + result = JSON.parse(sessionStorage.getItem(name)); } } catch (err) { result = null; @@ -104,18 +95,18 @@ class BrowserStoreClass { removeGlobalItem(name) { if (this.isLocalStorageSupported()) { - localStorage.removeItem(getPrefix() + name); + localStorage.removeItem(name); } else { - sessionStorage.removeItem(getPrefix() + name); + sessionStorage.removeItem(name); } } getLastServerVersion() { - return sessionStorage.getItem('last_server_version'); + return this.getGlobalItem('last_server_version'); } setLastServerVersion(version) { - sessionStorage.setItem('last_server_version', version); + this.setGlobalItem('last_server_version', version); } signalLogout() { @@ -185,6 +176,7 @@ class BrowserStoreClass { const logoutId = sessionStorage.getItem('__logout__'); sessionStorage.clear(); + localStorage.clear(); if (logoutId) { sessionStorage.setItem('__logout__', logoutId); @@ -222,4 +214,3 @@ class BrowserStoreClass { var BrowserStore = new BrowserStoreClass(); export default BrowserStore; -window.BrowserStore = BrowserStore; diff --git a/webapp/stores/error_store.jsx b/webapp/stores/error_store.jsx index 776375a82..7c695a335 100644 --- a/webapp/stores/error_store.jsx +++ b/webapp/stores/error_store.jsx @@ -35,15 +35,15 @@ class ErrorStoreClass extends EventEmitter { } getLastError() { - return BrowserStore.getItem('last_error'); + return BrowserStore.getGlobalItem('last_error'); } storeLastError(error) { - BrowserStore.setItem('last_error', error); + BrowserStore.setGlobalItem('last_error', error); } getConnectionErrorCount() { - var count = BrowserStore.getItem('last_error_conn'); + var count = BrowserStore.getGlobalItem('last_error_conn'); if (count == null) { return 0; @@ -53,12 +53,12 @@ class ErrorStoreClass extends EventEmitter { } setConnectionErrorCount(count) { - BrowserStore.setItem('last_error_conn', count); + BrowserStore.setGlobalItem('last_error_conn', count); } clearLastError() { - BrowserStore.removeItem('last_error'); - BrowserStore.removeItem('last_error_conn'); + BrowserStore.removeGlobalItem('last_error'); + BrowserStore.removeGlobalItem('last_error_conn'); } } diff --git a/webapp/stores/user_store.jsx b/webapp/stores/user_store.jsx index 98cc2f3f1..4213e6e8c 100644 --- a/webapp/stores/user_store.jsx +++ b/webapp/stores/user_store.jsx @@ -16,7 +16,10 @@ const CHANGE_EVENT_STATUSES = 'change_statuses'; class UserStoreClass extends EventEmitter { constructor() { super(); - this.profileCache = null; + this.profiles = {}; + this.statuses = {}; + this.sessions = {}; + this.audits = {}; this.currentUserId = ''; } @@ -135,11 +138,7 @@ class UserStoreClass extends EventEmitter { } getProfiles() { - if (this.profileCache !== null) { - return this.profileCache; - } - - return BrowserStore.getItem('profiles', {}); + return this.profiles; } getActiveOnlyProfiles(skipCurrent) { @@ -171,47 +170,38 @@ class UserStoreClass extends EventEmitter { } saveProfile(profile) { - var ps = this.getProfiles(); - ps[profile.id] = profile; - this.profileCache = ps; - BrowserStore.setItem('profiles', ps); + this.profiles[profile.id] = profile; } saveProfiles(profiles) { const currentId = this.getCurrentId(); - if (this.profileCache) { - const currentUser = this.profileCache[currentId]; - if (currentUser) { - if (currentId in profiles) { - delete profiles[currentId]; - } - - this.profileCache = profiles; - this.profileCache[currentId] = currentUser; - } else { - this.profileCache = profiles; + const currentUser = this.profiles[currentId]; + if (currentUser) { + if (currentId in this.profiles) { + delete this.profiles[currentId]; } + + this.profiles = profiles; + this.profiles[currentId] = currentUser; } else { - this.profileCache = profiles; + this.profiles = profiles; } - - BrowserStore.setItem('profiles', profiles); } setSessions(sessions) { - BrowserStore.setItem('sessions', sessions); + this.sessions = sessions; } getSessions() { - return BrowserStore.getItem('sessions', {loading: true}); + return this.sessions; } setAudits(audits) { - BrowserStore.setItem('audits', audits); + this.audits = audits; } getAudits() { - return BrowserStore.getItem('audits', {loading: true}); + return this.audits; } getCurrentMentionKeys() { @@ -252,7 +242,7 @@ class UserStoreClass extends EventEmitter { } pSetStatuses(statuses) { - BrowserStore.setItem('statuses', statuses); + this.statuses = statuses; } setStatus(userId, status) { @@ -263,7 +253,7 @@ class UserStoreClass extends EventEmitter { } getStatuses() { - return BrowserStore.getItem('statuses', {}); + return this.statuses; } getStatus(id) { diff --git a/webapp/utils/utils.jsx b/webapp/utils/utils.jsx index 5f16baf1f..1379455ca 100644 --- a/webapp/utils/utils.jsx +++ b/webapp/utils/utils.jsx @@ -687,7 +687,7 @@ export function applyTheme(theme) { } if (theme.centerChannelBg) { - changeCss('.app__content, .markdown__table, .markdown__table tbody tr, .suggestion-list__content, .modal .modal-content, .modal .modal-back', 'background:' + theme.centerChannelBg, 1); + changeCss('.app__content, .markdown__table, .markdown__table tbody tr, .suggestion-list__content, .modal .modal-content', 'background:' + theme.centerChannelBg, 1); changeCss('#post-list .post-list-holder-by-time', 'background:' + theme.centerChannelBg, 1); changeCss('#post-create', 'background:' + theme.centerChannelBg, 1); changeCss('.date-separator .separator__text, .new-separator .separator__text', 'background:' + theme.centerChannelBg, 1); |