diff options
Diffstat (limited to 'web/react')
26 files changed, 166 insertions, 205 deletions
diff --git a/web/react/components/admin_console/license_settings.jsx b/web/react/components/admin_console/license_settings.jsx index fdbe912ef..d4dfa13f2 100644 --- a/web/react/components/admin_console/license_settings.jsx +++ b/web/react/components/admin_console/license_settings.jsx @@ -120,8 +120,7 @@ class LicenseSettings extends React.Component { expires: Utils.displayDate(parseInt(global.window.mm_license.ExpiresAt, 10)), ldap: global.window.mm_license.LDAP }} - defaultMessage='<div><p>This compiled release of Mattermost platform is provided under a <a href="http://mattermost.com" target="_blank">commercial license</a> - from Mattermost, Inc. based on your subscription level and is subject to the <a href="{terms}" target="_blank">Terms of Service.</a></p> + defaultMessage='<div><p>This compiled release of Mattermost platform is provided under a <a href="http://mattermost.com" target="_blank">commercial license</a> from Mattermost, Inc. based on your subscription level and is subject to the <a href="{terms}" target="_blank">Terms of Service.</a></p> <p>Your subscription details are as follows:</p> Name: {name}<br /> Company or organization name: {company}<br/> @@ -152,9 +151,7 @@ class LicenseSettings extends React.Component { <p className='help-text'> <FormattedHTMLMessage id='admin.licence.keyMigration' - defaultMessage='If you’re migrating servers you may need to remove your license key from this server in order to install it on a new server. To start, - <a href="http://mattermost.com" target="_blank">disable all Enterprise Edition features on this server</a>. - This will enable the ability to remove the license key and downgrade this server from Enterprise Edition to Team Edition.' + defaultMessage='If you’re migrating servers you may need to remove your license key from this server in order to install it on a new server. To start, <a href="http://mattermost.com" target="_blank">disable all Enterprise Edition features on this server</a>. This will enable the ability to remove the license key and downgrade this server from Enterprise Edition to Team Edition.' /> </p> </div> diff --git a/web/react/components/channel_members_modal.jsx b/web/react/components/channel_members_modal.jsx index 688ab7dd2..dc8e3baaf 100644 --- a/web/react/components/channel_members_modal.jsx +++ b/web/react/components/channel_members_modal.jsx @@ -44,6 +44,7 @@ export default class ChannelMembersModal extends React.Component { } getStateFromStores() { const extraInfo = ChannelStore.getCurrentExtraInfo(); + const profiles = UserStore.getActiveOnlyProfiles(); if (extraInfo.member_count !== extraInfo.members.length) { AsyncClient.getChannelExtraInfo(this.props.channel.id, -1); @@ -53,9 +54,8 @@ export default class ChannelMembersModal extends React.Component { }; } - // clone the member list since we mutate it later on const memberList = extraInfo.members.map((member) => { - return Object.assign({}, member); + return profiles[member.id]; }); function compareByUsername(a, b) { @@ -130,8 +130,8 @@ export default class ChannelMembersModal extends React.Component { onClick={this.handleRemove.bind(this, user)} > <FormattedMessage - id='channel_members_modal.removeMember' - defaultMessage='Remove Member' + id='channel_members_modal.remove' + defaultMessage='Remove' /> </button> ); @@ -178,7 +178,6 @@ export default class ChannelMembersModal extends React.Component { this.props.onModalDismissed(); }} > - <i className='glyphicon glyphicon-envelope'/> <FormattedMessage id='channel_members_modal.addNew' defaultMessage=' Add New Members' diff --git a/web/react/components/create_post.jsx b/web/react/components/create_post.jsx index 9d7a19554..62319b1a7 100644 --- a/web/react/components/create_post.jsx +++ b/web/react/components/create_post.jsx @@ -130,7 +130,7 @@ class CreatePost extends React.Component { post.message, false, (data) => { - PostStore.storeDraft(data.channel_id, null); + PostStore.storeDraft(this.state.channelId, null); this.setState({messageText: '', submitting: false, postError: null, previews: [], serverError: null}); if (data.goto_location && data.goto_location.length > 0) { @@ -262,9 +262,7 @@ class CreatePost extends React.Component { message = err.message; } - if (clientId === -1) { - this.setState({serverError: message}); - } else { + if (clientId !== -1) { const draft = PostStore.getDraft(this.state.channelId); const index = draft.uploadsInProgress.indexOf(clientId); @@ -274,8 +272,10 @@ class CreatePost extends React.Component { PostStore.storeDraft(this.state.channelId, draft); - this.setState({uploadsInProgress: draft.uploadsInProgress, serverError: message}); + this.setState({uploadsInProgress: draft.uploadsInProgress}); } + + this.setState({serverError: message}); } removePreview(id) { const previews = Object.assign([], this.state.previews); diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx index 810f90b13..6aeae638f 100644 --- a/web/react/components/file_attachment.jsx +++ b/web/react/components/file_attachment.jsx @@ -19,12 +19,10 @@ class FileAttachment extends React.Component { super(props); this.loadFiles = this.loadFiles.bind(this); - this.playGif = this.playGif.bind(this); - this.stopGif = this.stopGif.bind(this); this.addBackgroundImage = this.addBackgroundImage.bind(this); this.canSetState = false; - this.state = {fileSize: -1, mime: '', playing: false, loading: false, format: ''}; + this.state = {fileSize: -1}; } componentDidMount() { this.loadFiles(); @@ -95,42 +93,6 @@ class FileAttachment extends React.Component { return true; } - playGif(e, filename) { - var img = new Image(); - var fileUrl = utils.getFileUrl(filename); - - this.setState({loading: true}); - img.load(fileUrl); - img.onload = () => { - var state = {playing: true, loading: false}; - - switch (true) { - case img.width > img.height: - state.format = 'landscape'; - break; - case img.height > img.width: - state.format = 'portrait'; - break; - default: - state.format = 'quadrat'; - break; - } - - this.setState(state); - - // keep displaying background image for a short moment while browser is - // loading gif, to prevent white background flashing through - setTimeout(() => this.removeBackgroundImage.bind(this)(filename), 100); - }; - img.onError = () => this.setState({loading: false}); - - e.stopPropagation(); - } - stopGif(e, filename) { - this.setState({playing: false}); - this.addBackgroundImage(filename); - e.stopPropagation(); - } getFileInfoFromName(name) { var fileInfo = utils.splitFileLocation(name); @@ -164,74 +126,18 @@ class FileAttachment extends React.Component { var filename = this.props.filename; var fileInfo = utils.splitFileLocation(filename); - var fileUrl = utils.getFileUrl(filename); + var fileUrl = utils.getFileUrl(filename, true); var type = utils.getFileType(fileInfo.ext); - var playbackControls = ''; - var loadedFile = ''; - var loadingIndicator = ''; - if (this.state.mime === 'image/gif') { - playbackControls = ( - <div - className='file-playback-controls play' - onClick={(e) => this.playGif(e, filename)} - > - {"►"} - </div> - ); - } - if (this.state.playing) { - loadedFile = ( - <img - className={'file__loaded ' + this.state.format} - src={fileUrl} - /> - ); - playbackControls = ( + var thumbnail; + if (type === 'image') { + thumbnail = ( <div - className='file-playback-controls stop' - onClick={(e) => this.stopGif(e, filename)} - > - {"■"} - </div> - ); - } - if (this.state.loading) { - loadingIndicator = ( - <img - className='spinner file__loading' - src='/static/images/load.gif' + ref={filename} + className='post__load' + style={{backgroundImage: 'url(/static/images/load.gif)'}} /> ); - playbackControls = ''; - } - - var thumbnail; - if (type === 'image') { - if (this.state.playing) { - thumbnail = ( - <div - ref={filename} - className='post__load' - style={{backgroundImage: 'url(/static/images/load.gif)'}} - > - {playbackControls} - {loadedFile} - </div> - ); - } else { - thumbnail = ( - <div - ref={filename} - className='post__load' - style={{backgroundImage: 'url(/static/images/load.gif)'}} - > - {loadingIndicator} - {playbackControls} - {loadedFile} - </div> - ); - } } else { thumbnail = <div className={'file-icon ' + utils.getIconClassName(type)}/>; } @@ -242,7 +148,7 @@ class FileAttachment extends React.Component { filename, function success(data) { if (this.canSetState) { - this.setState({fileSize: parseInt(data.size, 10), mime: data.mime}); + this.setState({fileSize: parseInt(data.size, 10)}); } }.bind(this), function error() { diff --git a/web/react/components/file_upload.jsx b/web/react/components/file_upload.jsx index cb8ede51b..f8965e13e 100644 --- a/web/react/components/file_upload.jsx +++ b/web/react/components/file_upload.jsx @@ -108,12 +108,12 @@ class FileUpload extends React.Component { } } - handleChange() { - var element = $(ReactDOM.findDOMNode(this.refs.fileInput)); + handleChange(e) { + if (e.target.files.length > 0) { + this.uploadFiles(e.target.files); - this.uploadFiles(element.prop('files')); - - Utils.clearFileInput(element[0]); + Utils.clearFileInput(e.target); + } } handleDrop(e) { diff --git a/web/react/components/get_link_modal.jsx b/web/react/components/get_link_modal.jsx index 6a5c3b588..3309d690c 100644 --- a/web/react/components/get_link_modal.jsx +++ b/web/react/components/get_link_modal.jsx @@ -41,8 +41,6 @@ export default class GetLinkModal extends React.Component { } render() { - const userCreationEnabled = global.window.mm_config.EnableUserCreation === 'true'; - let helpText = null; if (this.props.helpText) { helpText = ( @@ -55,7 +53,7 @@ export default class GetLinkModal extends React.Component { } let copyLink = null; - if (userCreationEnabled && document.queryCommandSupported('copy')) { + if (document.queryCommandSupported('copy')) { copyLink = ( <button data-copy-btn='true' @@ -71,17 +69,14 @@ export default class GetLinkModal extends React.Component { ); } - let linkText = null; - if (userCreationEnabled) { - linkText = ( - <textarea - className='form-control no-resize min-height' - readOnly='true' - ref='textarea' - value={this.props.link} - /> - ); - } + const linkText = ( + <textarea + className='form-control no-resize min-height' + readOnly='true' + ref='textarea' + value={this.props.link} + /> + ); var copyLinkConfirm = null; if (this.state.copiedLink) { diff --git a/web/react/components/invite_member_modal.jsx b/web/react/components/invite_member_modal.jsx index 0c0330c40..184ba1357 100644 --- a/web/react/components/invite_member_modal.jsx +++ b/web/react/components/invite_member_modal.jsx @@ -495,7 +495,7 @@ class InviteMemberModal extends React.Component { <ConfirmModal title={formatMessage(holders.modalTitle)} message={formatMessage(holders.modalMessage)} - confirm_button={formatMessage(holders.modalButton)} + confirmButton={formatMessage(holders.modalButton)} show={this.state.showConfirmModal} onConfirm={this.handleHide.bind(this, false)} onCancel={() => this.setState({showConfirmModal: false})} @@ -512,4 +512,4 @@ InviteMemberModal.propTypes = { intl: intlShape.isRequired }; -export default injectIntl(InviteMemberModal);
\ No newline at end of file +export default injectIntl(InviteMemberModal); diff --git a/web/react/components/navbar_dropdown.jsx b/web/react/components/navbar_dropdown.jsx index e9df03c33..0ddd6ff4f 100644 --- a/web/react/components/navbar_dropdown.jsx +++ b/web/react/components/navbar_dropdown.jsx @@ -107,7 +107,7 @@ export default class NavbarDropdown extends React.Component { </li> ); - if (this.props.teamType === Constants.OPEN_TEAM) { + if (this.props.teamType === Constants.OPEN_TEAM && global.window.mm_config.EnableUserCreation === 'true') { teamLink = ( <li> <a diff --git a/web/react/components/settings_sidebar.jsx b/web/react/components/settings_sidebar.jsx index 90c0e8435..da8001f6f 100644 --- a/web/react/components/settings_sidebar.jsx +++ b/web/react/components/settings_sidebar.jsx @@ -4,10 +4,6 @@ import * as Utils from '../utils/utils.jsx'; export default class SettingsSidebar extends React.Component { - componentDidUpdate() { - $('.settings-modal').find('.modal-body').scrollTop(0); - $('.settings-modal').find('.modal-body').perfectScrollbar('update'); - } constructor(props) { super(props); diff --git a/web/react/components/suggestion/search_suggestion_list.jsx b/web/react/components/suggestion/search_suggestion_list.jsx index 40f5d8777..60a5562fa 100644 --- a/web/react/components/suggestion/search_suggestion_list.jsx +++ b/web/react/components/suggestion/search_suggestion_list.jsx @@ -30,7 +30,7 @@ export default class SearchSuggestionList extends SuggestionList { text = ( <FormattedMessage id='suggestion.search.private' - defaultMessage='Public Groups' + defaultMessage='Private Groups' /> ); } diff --git a/web/react/components/team_general_tab.jsx b/web/react/components/team_general_tab.jsx index c1b2a2e7f..ef7410b2f 100644 --- a/web/react/components/team_general_tab.jsx +++ b/web/react/components/team_general_tab.jsx @@ -611,7 +611,9 @@ class GeneralTab extends React.Component { className='modal-title' ref='title' > - <i className='modal-back'></i> + <div className='modal-back'> + <i className='fa fa-angle-left'></i> + </div> <FormattedMessage id='general_tab.title' defaultMessage='General Settings' diff --git a/web/react/components/team_import_tab.jsx b/web/react/components/team_import_tab.jsx index 828e9fc4e..c9a8afe6c 100644 --- a/web/react/components/team_import_tab.jsx +++ b/web/react/components/team_import_tab.jsx @@ -131,7 +131,10 @@ class TeamImportTab extends React.Component { <h4 className='modal-title' ref='title' - ><i className='modal-back'></i> + > + <div className='modal-back'> + <i className='fa fa-angle-left'></i> + </div> <FormattedMessage id='team_import_tab.import' defaultMessage='Import' diff --git a/web/react/components/team_members_dropdown.jsx b/web/react/components/team_members_dropdown.jsx index 8aacba8ca..cd7585d94 100644 --- a/web/react/components/team_members_dropdown.jsx +++ b/web/react/components/team_members_dropdown.jsx @@ -308,8 +308,8 @@ export default class TeamMembersDropdown extends React.Component { data-toggle='dropdown' aria-expanded='true' > - <span className='fa fa-pencil'></span> <span>{currentRoles} </span> + <span className='fa fa-chevron-down'></span> </a> <ul className='dropdown-menu member-menu' diff --git a/web/react/components/team_settings_modal.jsx b/web/react/components/team_settings_modal.jsx index d517f92fb..bef3ebf24 100644 --- a/web/react/components/team_settings_modal.jsx +++ b/web/react/components/team_settings_modal.jsx @@ -91,7 +91,7 @@ class TeamSettingsModal extends React.Component { /> </h4> </div> - <div className='modal-body'> + <div className='modal-body settings-modal__body'> <div className='settings-table'> <div className='settings-links'> <SettingsSidebar diff --git a/web/react/components/textbox.jsx b/web/react/components/textbox.jsx index 23ecfb57b..46900e436 100644 --- a/web/react/components/textbox.jsx +++ b/web/react/components/textbox.jsx @@ -129,12 +129,12 @@ export default class Textbox extends React.Component { } render() { + const hasText = this.props.messageText.length > 0; + let previewLink = null; if (Utils.isFeatureEnabled(PreReleaseFeatures.MARKDOWN_PREVIEW)) { - const previewLinkVisible = this.props.messageText.length > 0; previewLink = ( <a - style={{visibility: previewLinkVisible ? 'visible' : 'hidden'}} onClick={this.showPreview} className='textbox-preview-link' > @@ -153,6 +153,51 @@ export default class Textbox extends React.Component { ); } + let helpText = ( + <div + style={{visibility: hasText ? 'visible' : 'hidden', opacity: hasText ? '0.5' : '0'}} + className='help_format_text' + > + <b> + <FormattedMessage + id='textbox.bold' + defaultMessage='**bold**' + /> + </b> + <i> + <FormattedMessage + id='textbox.italic' + defaultMessage='_italic_' + /> + </i> + <span>~~<strike> + <FormattedMessage + id='textbox.strike' + defaultMessage='strike' + /> + </strike>~~ </span> + <code> + <FormattedMessage + id='textbox.inlinecode' + defaultMessage='`inline code`' + /> + </code> + <code> + <FormattedMessage + id='textbox.preformatted' + defaultMessage='```preformatted```' + /> + </code> + <span> + <FormattedMessage + id='textbox.quote' + defaultMessage='>quote' + /> + </span> + {previewLink} + </div> + ); + return ( <div ref='wrapper' @@ -184,7 +229,7 @@ export default class Textbox extends React.Component { dangerouslySetInnerHTML={{__html: this.state.preview ? TextFormatting.formatText(this.props.messageText) : ''}} > </div> - {previewLink} + {helpText} <a target='_blank' href='http://docs.mattermost.com/help/getting-started/messaging-basics.html' diff --git a/web/react/components/user_list_row.jsx b/web/react/components/user_list_row.jsx index 2aeca7d47..d75078619 100644 --- a/web/react/components/user_list_row.jsx +++ b/web/react/components/user_list_row.jsx @@ -10,9 +10,9 @@ export default function UserListRow({user, actions}) { let name = user.username; if (user.nickname && nameFormat === Constants.Preferences.DISPLAY_PREFER_NICKNAME) { - name = `${user.nickname} (${user.username})`; + name = `${user.nickname} (@${user.username})`; } else if ((user.first_name || user.last_name) && (nameFormat === Constants.Preferences.DISPLAY_PREFER_NICKNAME || nameFormat === Constants.Preferences.DISPLAY_PREFER_FULL_NAME)) { - name = `${Utils.getFullName(user)} (${user.username})`; + name = `${Utils.getFullName(user)} (@${user.username})`; } const buttons = actions.map((Action, index) => { diff --git a/web/react/components/user_settings/user_settings_advanced.jsx b/web/react/components/user_settings/user_settings_advanced.jsx index efaf63ada..cdaa5fd8a 100644 --- a/web/react/components/user_settings/user_settings_advanced.jsx +++ b/web/react/components/user_settings/user_settings_advanced.jsx @@ -300,10 +300,12 @@ class AdvancedSettingsDisplay extends React.Component { className='modal-title' ref='title' > - <i - className='modal-back' - onClick={this.props.collapseModal} - /> + <div className='modal-back'> + <i + className='fa fa-angle-left' + onClick={this.props.collapseModal} + /> + </div> <FormattedMessage id='user.settings.advance.title' defaultMessage='Advanced Settings' diff --git a/web/react/components/user_settings/user_settings_developer.jsx b/web/react/components/user_settings/user_settings_developer.jsx index 5868e0ad3..0acfd4a16 100644 --- a/web/react/components/user_settings/user_settings_developer.jsx +++ b/web/react/components/user_settings/user_settings_developer.jsx @@ -94,10 +94,12 @@ class DeveloperTab extends React.Component { className='modal-title' ref='title' > - <i - className='modal-back' - onClick={this.props.collapseModal} - /> + <div className='modal-back'> + <i + className='fa fa-angle-left' + onClick={this.props.collapseModal} + /> + </div> <FormattedMessage id='user.settings.developer.title' defaultMessage='Developer Settings' diff --git a/web/react/components/user_settings/user_settings_display.jsx b/web/react/components/user_settings/user_settings_display.jsx index 3e468e08f..b0e64b0aa 100644 --- a/web/react/components/user_settings/user_settings_display.jsx +++ b/web/react/components/user_settings/user_settings_display.jsx @@ -444,10 +444,12 @@ export default class UserSettingsDisplay extends React.Component { className='modal-title' ref='title' > - <i - className='modal-back' - onClick={this.props.collapseModal} - /> + <div className='modal-back'> + <i + className='fa fa-angle-left' + onClick={this.props.collapseModal} + /> + </div> <FormattedMessage id='user.settings.display.title' defaultMessage='Display Settings' diff --git a/web/react/components/user_settings/user_settings_general.jsx b/web/react/components/user_settings/user_settings_general.jsx index 2f2116c2a..b0b1c414e 100644 --- a/web/react/components/user_settings/user_settings_general.jsx +++ b/web/react/components/user_settings/user_settings_general.jsx @@ -759,10 +759,12 @@ class UserSettingsGeneralTab extends React.Component { className='modal-title' ref='title' > - <i - className='modal-back' - onClick={this.props.collapseModal} - /> + <div className='modal-back'> + <i + className='fa fa-angle-left' + onClick={this.props.collapseModal} + /> + </div> <FormattedMessage id='user.settings.general.title' defaultMessage='General Settings' diff --git a/web/react/components/user_settings/user_settings_integrations.jsx b/web/react/components/user_settings/user_settings_integrations.jsx index e4f460a6d..7633b2f95 100644 --- a/web/react/components/user_settings/user_settings_integrations.jsx +++ b/web/react/components/user_settings/user_settings_integrations.jsx @@ -163,10 +163,12 @@ class UserSettingsIntegrationsTab extends React.Component { className='modal-title' ref='title' > - <i - className='modal-back' - onClick={this.props.collapseModal} - /> + <div className='modal-back'> + <i + className='fa fa-angle-left' + onClick={this.props.collapseModal} + /> + </div> <FormattedMessage id='user.settings.integrations.title' defaultMessage='Integration Settings' diff --git a/web/react/components/user_settings/user_settings_modal.jsx b/web/react/components/user_settings/user_settings_modal.jsx index 80d03d88e..5d9951b72 100644 --- a/web/react/components/user_settings/user_settings_modal.jsx +++ b/web/react/components/user_settings/user_settings_modal.jsx @@ -277,7 +277,7 @@ class UserSettingsModal extends React.Component { /> </Modal.Title> </Modal.Header> - <Modal.Body ref='modalBody'> + <Modal.Body bsClass='settings-modal__body modal' ref='modalBody'> <div className='settings-table'> <div className='settings-links'> <SettingsSidebar @@ -309,7 +309,7 @@ class UserSettingsModal extends React.Component { <ConfirmModal title={formatMessage(holders.confirmTitle)} message={formatMessage(holders.confirmMsg)} - confirm_button={formatMessage(holders.confirmBtns)} + confirmButton={formatMessage(holders.confirmBtns)} show={this.state.showConfirmModal} onConfirm={this.handleConfirm} onCancel={this.handleCancelConfirmation} diff --git a/web/react/components/user_settings/user_settings_notifications.jsx b/web/react/components/user_settings/user_settings_notifications.jsx index ee9febb8e..3ef6435f1 100644 --- a/web/react/components/user_settings/user_settings_notifications.jsx +++ b/web/react/components/user_settings/user_settings_notifications.jsx @@ -774,10 +774,12 @@ class NotificationsTab extends React.Component { className='modal-title' ref='title' > - <i - className='modal-back' - onClick={this.props.collapseModal} - /> + <div className='modal-back'> + <i + className='fa fa-angle-left' + onClick={this.props.collapseModal} + /> + </div> <FormattedMessage id='user.settings.notifications.title' defaultMessage='Notification Settings' diff --git a/web/react/components/user_settings/user_settings_security.jsx b/web/react/components/user_settings/user_settings_security.jsx index 53d79906f..cba7ffdea 100644 --- a/web/react/components/user_settings/user_settings_security.jsx +++ b/web/react/components/user_settings/user_settings_security.jsx @@ -389,10 +389,12 @@ class SecurityTab extends React.Component { className='modal-title' ref='title' > - <i - className='modal-back' - onClick={this.props.collapseModal} - /> + <div className='modal-back'> + <i + className='fa fa-angle-left' + onClick={this.props.collapseModal} + /> + </div> <FormattedMessage id='user.settings.security.title' defaultMessage='Security Settings' diff --git a/web/react/utils/text_formatting.jsx b/web/react/utils/text_formatting.jsx index dae2252a6..a930e9ece 100644 --- a/web/react/utils/text_formatting.jsx +++ b/web/react/utils/text_formatting.jsx @@ -123,14 +123,13 @@ function autolinkAtMentions(text, tokens) { return (Constants.SPECIAL_MENTIONS.indexOf(u) !== -1 || UserStore.getProfileByUsername(u)); } - function addToken(username, mention, extraText) { + function addToken(username, mention) { const index = tokens.size; const alias = `MM_ATMENTION${index}`; tokens.set(alias, { value: `<a class='mention-link' href='#' data-mention='${username}'>${mention}</a>`, - originalText: mention, - extraText + originalText: mention }); return alias; } @@ -152,9 +151,9 @@ function autolinkAtMentions(text, tokens) { usernameLower = usernameLower.substring(0, c - 1); if (mentionExists(usernameLower)) { - const extraText = originalUsername.substr(c - 1); - const alias = addToken(usernameLower, '@' + usernameLower, extraText); - return alias; + const suffix = originalUsername.substr(c - 1); + const alias = addToken(usernameLower, '@' + usernameLower); + return alias + suffix; } } else { // If the last character is not punctuation, no point in going any further @@ -188,7 +187,7 @@ function highlightCurrentMentions(text, tokens) { const newAlias = `MM_SELFMENTION${index}`; newTokens.set(newAlias, { - value: `<span class='mention-highlight'>${alias}</span>` + (token.extraText || ''), + value: `<span class='mention-highlight'>${alias}</span>`, originalText: token.originalText }); output = output.replace(alias, newAlias); diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index 6ab2f64d4..6942a8e08 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -606,16 +606,17 @@ export function toTitleCase(str) { export function applyTheme(theme) { if (theme.sidebarBg) { - changeCss('.sidebar--left, .settings-modal .settings-table .settings-links, .sidebar--menu', 'background:' + theme.sidebarBg, 1); + changeCss('.sidebar--left, .modal .settings-modal .settings-table .settings-links, .sidebar--menu', 'background:' + theme.sidebarBg, 1); + changeCss('body', 'scrollbar-face-color:' + theme.sidebarBg, 3); } if (theme.sidebarText) { - changeCss('.sidebar--left .nav-pills__container li>a, .sidebar--right, .settings-modal .nav-pills>li a, .sidebar--menu', 'color:' + changeOpacity(theme.sidebarText, 0.6), 1); - changeCss('@media(max-width: 768px){.settings-modal .settings-table .nav>li>a', 'color:' + theme.sidebarText, 1); + changeCss('.sidebar--left .nav-pills__container li>a, .sidebar--right, .modal .settings-modal .nav-pills>li a, .sidebar--menu', 'color:' + changeOpacity(theme.sidebarText, 0.6), 1); + changeCss('@media(max-width: 768px){.modal .settings-modal .settings-table .nav>li>a', 'color:' + theme.sidebarText, 1); changeCss('.sidebar--left .nav-pills__container li>h4, .sidebar--left .add-channel-btn', 'color:' + changeOpacity(theme.sidebarText, 0.6), 1); changeCss('.sidebar--left .add-channel-btn:hover, .sidebar--left .add-channel-btn:focus', 'color:' + theme.sidebarText, 1); changeCss('.sidebar--left .status .offline--icon, .sidebar--left .status .offline--icon', 'fill:' + theme.sidebarText, 1); - changeCss('@media(max-width: 768px){.settings-modal .settings-table .nav>li>a', 'border-color:' + changeOpacity(theme.sidebarText, 0.2), 2); + changeCss('@media(max-width: 768px){.modal .settings-modal .settings-table .nav>li>a', 'border-color:' + changeOpacity(theme.sidebarText, 0.2), 2); } if (theme.sidebarUnreadText) { @@ -623,16 +624,16 @@ export function applyTheme(theme) { } if (theme.sidebarTextHoverBg) { - changeCss('.sidebar--left .nav-pills__container li>a:hover, .sidebar--left .nav-pills__container li>a:focus, .settings-modal .nav-pills>li:hover a, .settings-modal .nav-pills>li:focus a', 'background:' + theme.sidebarTextHoverBg, 1); - changeCss('@media(max-width: 768px){.settings-modal .settings-table .nav>li:hover a', 'background:' + theme.sidebarTextHoverBg, 1); + changeCss('.sidebar--left .nav-pills__container li>a:hover, .sidebar--left .nav-pills__container li>a:focus, .modal .settings-modal .nav-pills>li:hover a, .modal .settings-modal .nav-pills>li:focus a', 'background:' + theme.sidebarTextHoverBg, 1); + changeCss('@media(max-width: 768px){.modal .settings-modal .settings-table .nav>li:hover a', 'background:' + theme.sidebarTextHoverBg, 1); } if (theme.sidebarTextActiveBorder) { - changeCss('.sidebar--left .nav li.active a:before, .settings-modal .nav-pills>li.active a:before', 'background:' + theme.sidebarTextActiveBorder, 1); + changeCss('.sidebar--left .nav li.active a:before, .modal .settings-modal .nav-pills>li.active a:before', 'background:' + theme.sidebarTextActiveBorder, 1); } if (theme.sidebarTextActiveColor) { - changeCss('.sidebar--left .nav-pills__container li.active a, .sidebar--left .nav-pills__container li.active a:hover, .sidebar--left .nav-pills__container li.active a:focus, .settings-modal .nav-pills>li.active a, .settings-modal .nav-pills>li.active a:hover, .settings-modal .nav-pills>li.active a:active', 'color:' + theme.sidebarTextActiveColor, 2); + changeCss('.sidebar--left .nav-pills__container li.active a, .sidebar--left .nav-pills__container li.active a:hover, .sidebar--left .nav-pills__container li.active a:focus, .modal .settings-modal .nav-pills>li.active a, .modal .settings-modal .nav-pills>li.active a:hover, .modal .settings-modal .nav-pills>li.active a:active', 'color:' + theme.sidebarTextActiveColor, 2); changeCss('.sidebar--left .nav li.active a, .sidebar--left .nav li.active a:hover, .sidebar--left .nav li.active a:focus', 'background:' + changeOpacity(theme.sidebarTextActiveColor, 0.1), 1); } @@ -665,12 +666,12 @@ export function applyTheme(theme) { if (theme.mentionBj) { changeCss('.sidebar--left .nav-pills__unread-indicator', 'background:' + theme.mentionBj, 1); - changeCss('.sidebar--left .badge', 'background:' + theme.mentionBj, 1); + changeCss('.sidebar--left .badge', 'background:' + theme.mentionBj + '!important;', 1); } if (theme.mentionColor) { changeCss('.sidebar--left .nav-pills__unread-indicator', 'color:' + theme.mentionColor, 2); - changeCss('.sidebar--left .badge', 'color:' + theme.mentionColor, 2); + changeCss('.sidebar--left .badge', 'color:' + theme.mentionColor + '!important;', 2); } if (theme.centerChannelBg) { @@ -686,6 +687,8 @@ export function applyTheme(theme) { changeCss('.popover.top>.arrow:after, .tip-overlay.tip-overlay--chat .arrow', 'border-top-color:' + theme.centerChannelBg, 1); changeCss('@media(min-width: 768px){.search-bar__container .search__form .search-bar, .form-control', 'background:' + theme.centerChannelBg, 1); changeCss('.attachment__content', 'background:' + theme.centerChannelBg, 1); + changeCss('body', 'scrollbar-face-color:' + theme.centerChannelBg, 2); + changeCss('body', 'scrollbar-track-color:' + theme.centerChannelBg, 2); } if (theme.centerChannelColor) { @@ -705,7 +708,7 @@ export function applyTheme(theme) { changeCss('.markdown__table tbody tr:nth-child(2n)', 'background:' + changeOpacity(theme.centerChannelColor, 0.07), 1); changeCss('.channel-header__info>div.dropdown .header-dropdown__icon', 'color:' + changeOpacity(theme.centerChannelColor, 0.8), 1); changeCss('.channel-header #member_popover', 'color:' + changeOpacity(theme.centerChannelColor, 0.8), 1); - changeCss('.custom-textarea, .custom-textarea:focus, .preview-container .preview-div, .post-image__column .post-image__details, .sidebar--right .sidebar-right__body, .markdown__table th, .markdown__table td, .suggestion-content, .modal .modal-content, .settings-modal .settings-table .settings-content .divider-light, .webhooks__container, .dropdown-menu, .modal .modal-header, .popover', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1); + changeCss('.custom-textarea, .custom-textarea:focus, .preview-container .preview-div, .post-image__column .post-image__details, .sidebar--right .sidebar-right__body, .markdown__table th, .markdown__table td, .suggestion-content, .modal .modal-content, .modal .settings-modal .settings-table .settings-content .divider-light, .webhooks__container, .dropdown-menu, .modal .modal-header, .popover', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1); changeCss('.popover.bottom>.arrow', 'border-bottom-color:' + changeOpacity(theme.centerChannelColor, 0.25), 1); changeCss('.search-help-popover .search-autocomplete__divider span', 'color:' + changeOpacity(theme.centerChannelColor, 0.7), 1); changeCss('.popover.right>.arrow', 'border-right-color:' + changeOpacity(theme.centerChannelColor, 0.25), 1); @@ -726,18 +729,20 @@ export function applyTheme(theme) { changeCss('.date-separator .separator__hr, .modal-footer, .modal .custom-textarea', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1); changeCss('.search-item-container, .post-right__container .post.post--root', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.1), 1); changeCss('.modal .custom-textarea:focus', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.3), 1); - changeCss('.channel-intro, .settings-modal .settings-table .settings-content .divider-dark, hr, .settings-modal .settings-table .settings-links, .settings-modal .settings-table .settings-content .appearance-section .theme-elements__header', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1); + changeCss('.channel-intro, .modal .settings-modal .settings-table .settings-content .divider-dark, hr, .modal .settings-modal .settings-table .settings-links, .modal .settings-modal .settings-table .settings-content .appearance-section .theme-elements__header', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1); changeCss('.post.current--user .post__body, .post.post--comment.other--root.current--user .post-comment, pre, .post-right__container .post.post--root', 'background:' + changeOpacity(theme.centerChannelColor, 0.07), 1); changeCss('.post.current--user .post__body, .post.post--comment.other--root.current--user .post-comment, .post.same--root.post--comment .post__body, .modal .more-table tbody>tr td, .member-div:first-child, .member-div, .access-history__table .access__report, .activity-log__table', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.1), 2); changeCss('@media(max-width: 1800px){.inner__wrap.move--left .post.post--comment.same--root', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.07), 2); - changeCss('.post:hover, .modal .more-table tbody>tr:hover td, .settings-modal .settings-table .settings-content .section-min:hover', 'background:' + changeOpacity(theme.centerChannelColor, 0.07), 1); + changeCss('.post:hover, .modal .more-table tbody>tr:hover td, .modal .settings-modal .settings-table .settings-content .section-min:hover', 'background:' + changeOpacity(theme.centerChannelColor, 0.07), 1); changeCss('.date-separator.hovered--before:after, .date-separator.hovered--after:before, .new-separator.hovered--after:before, .new-separator.hovered--before:after', 'background:' + changeOpacity(theme.centerChannelColor, 0.07), 1); changeCss('.command-name:hover, .mentions-name:hover, .suggestion--selected, .dropdown-menu>li>a:focus, .dropdown-menu>li>a:hover, .bot-indicator', 'background:' + changeOpacity(theme.centerChannelColor, 0.15), 1); changeCss('code, .form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control', 'background:' + changeOpacity(theme.centerChannelColor, 0.1), 1); changeCss('@media(min-width: 960px){.post.current--user:hover .post__body ', 'background: none;', 1); changeCss('.sidebar--right', 'color:' + theme.centerChannelColor, 2); - changeCss('.search-help-popover .search-autocomplete__item:hover, .settings-modal .settings-table .settings-content .appearance-section .theme-elements__body', 'background:' + changeOpacity(theme.centerChannelColor, 0.05), 1); + changeCss('.search-help-popover .search-autocomplete__item:hover, .modal .settings-modal .settings-table .settings-content .appearance-section .theme-elements__body', 'background:' + changeOpacity(theme.centerChannelColor, 0.05), 1); changeCss('.search-help-popover .search-autocomplete__item.selected', 'background:' + changeOpacity(theme.centerChannelColor, 0.15), 1); + changeCss('::-webkit-scrollbar-thumb', 'background:' + changeOpacity(theme.centerChannelColor, 0.4), 1); + changeCss('body', 'scrollbar-arrow-color:' + theme.centerChannelColor, 4); } if (theme.newMessageSeparator) { |