From 38cc1485749c60c32ee9ef8a01da74140588cc3a Mon Sep 17 00:00:00 2001 From: Asaad Mahmood Date: Tue, 22 Sep 2015 11:21:28 +0500 Subject: UI Modifications for multiple tickets --- web/react/utils/utils.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'web/react/utils') diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index 074591489..6e660286b 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -955,7 +955,8 @@ export function getTeamURLFromAddressBar() { export function getShortenedTeamURL() { const teamURL = getTeamURLFromAddressBar(); - if (teamURL.length > 24) { + if (teamURL.length > 35) { return teamURL.substring(0, 10) + '...' + teamURL.substring(teamURL.length - 12, teamURL.length) + '/'; } + return teamURL + '/'; } -- cgit v1.2.3-1-g7c22 From ffe34aa1544172b42658cd628cdcc4036d6ff403 Mon Sep 17 00:00:00 2001 From: hmhealey Date: Tue, 22 Sep 2015 13:53:43 -0400 Subject: Restored changes which remove emojify and switch to our own version --- web/react/utils/emoticons.jsx | 159 ++++++++++++++++++++++++++++++++++++ web/react/utils/text_formatting.jsx | 6 ++ 2 files changed, 165 insertions(+) create mode 100644 web/react/utils/emoticons.jsx (limited to 'web/react/utils') diff --git a/web/react/utils/emoticons.jsx b/web/react/utils/emoticons.jsx new file mode 100644 index 000000000..7210201ff --- /dev/null +++ b/web/react/utils/emoticons.jsx @@ -0,0 +1,159 @@ +// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. +// See License.txt for license information. + +const emoticonPatterns = { + smile: /:-?\)/g, // :) + open_mouth: /:o/gi, // :o + scream: /:-o/gi, // :-o + smirk: /[:;]-?]/g, // :] + grinning: /[:;]-?d/gi, // :D + stuck_out_tongue_closed_eyes: /x-d/gi, // x-d + stuck_out_tongue_winking_eye: /[:;]-?p/gi, // ;p + rage: /:-?[\[@]/g, // :@ + frowning: /:-?\(/g, // :( + sob: /:['’]-?\(|:'\(/g, // :`( + kissing_heart: /:-?\*/g, // :* + wink: /;-?\)/g, // ;) + pensive: /:-?\//g, // :/ + confounded: /:-?s/gi, // :s + flushed: /:-?\|/g, // :| + relaxed: /:-?\$/g, // :$ + mask: /:-x/gi, // :-x + heart: /<3|<3/g, // <3 + broken_heart: /<\/3|</3/g, // `, + originalText: match + }); + + return alias; + } + + return match; + } + + output = output.replace(/:([a-zA-Z0-9_-]+):/g, replaceEmoticonWithToken); + + $.each(emoticonPatterns, (name, pattern) => { + // this might look a bit funny, but since the name isn't contained in the actual match + // like with the named emoticons, we need to add it in manually + output = output.replace(pattern, (match) => replaceEmoticonWithToken(match, name)); + }); + + return output; +} + +function getImagePathForEmoticon(name) { + return `/static/images/emoji/${name}.png`; +} diff --git a/web/react/utils/text_formatting.jsx b/web/react/utils/text_formatting.jsx index 4e390f708..be82f7b9c 100644 --- a/web/react/utils/text_formatting.jsx +++ b/web/react/utils/text_formatting.jsx @@ -3,6 +3,7 @@ const Autolinker = require('autolinker'); const Constants = require('./constants.jsx'); +const Emoticons = require('./emoticons.jsx'); const Markdown = require('./markdown.jsx'); const UserStore = require('../stores/user_store.jsx'); const Utils = require('./utils.jsx'); @@ -17,6 +18,7 @@ const markdownRenderer = new Markdown.MattermostMarkdownRenderer(); // - searchTerm - If specified, this word is highlighted in the resulting html. Defaults to nothing. // - mentionHighlight - Specifies whether or not to highlight mentions of the current user. Defaults to true. // - singleline - Specifies whether or not to remove newlines. Defaults to false. +// - emoticons - Enables emoticon parsing. Defaults to true. // - markdown - Enables markdown parsing. Defaults to true. export function formatText(text, options = {}) { if (!('markdown' in options)) { @@ -34,6 +36,10 @@ export function formatText(text, options = {}) { const tokens = new Map(); // replace important words and phrases with tokens + if (!('emoticons' in options) || options.emoticon) { + output = Emoticons.handleEmoticons(output, tokens); + } + output = autolinkUrls(output, tokens, !!options.markdown); output = autolinkAtMentions(output, tokens); output = autolinkHashtags(output, tokens); -- cgit v1.2.3-1-g7c22 From 1709532ae6f48df0c152afb6a58597cd07d6df49 Mon Sep 17 00:00:00 2001 From: hmhealey Date: Tue, 22 Sep 2015 14:14:54 -0400 Subject: Moved emoticon parsing to happen after url parsing so that we don't have smilies accidentally occuring in urls --- web/react/utils/text_formatting.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'web/react/utils') diff --git a/web/react/utils/text_formatting.jsx b/web/react/utils/text_formatting.jsx index be82f7b9c..940bd0485 100644 --- a/web/react/utils/text_formatting.jsx +++ b/web/react/utils/text_formatting.jsx @@ -36,14 +36,14 @@ export function formatText(text, options = {}) { const tokens = new Map(); // replace important words and phrases with tokens - if (!('emoticons' in options) || options.emoticon) { - output = Emoticons.handleEmoticons(output, tokens); - } - output = autolinkUrls(output, tokens, !!options.markdown); output = autolinkAtMentions(output, tokens); output = autolinkHashtags(output, tokens); + if (!('emoticons' in options) || options.emoticon) { + output = Emoticons.handleEmoticons(output, tokens); + } + if (options.searchTerm) { output = highlightSearchTerm(output, tokens, options.searchTerm); } -- cgit v1.2.3-1-g7c22 From d025da5da9b6b6bf3c0003191f07a8184e545f8a Mon Sep 17 00:00:00 2001 From: hmhealey Date: Tue, 22 Sep 2015 14:28:43 -0400 Subject: Changed hashtag regex to only accept hashtags that begin with a letter --- web/react/utils/text_formatting.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'web/react/utils') diff --git a/web/react/utils/text_formatting.jsx b/web/react/utils/text_formatting.jsx index 940bd0485..089fdd4f9 100644 --- a/web/react/utils/text_formatting.jsx +++ b/web/react/utils/text_formatting.jsx @@ -247,7 +247,7 @@ function autolinkHashtags(text, tokens) { return prefix + alias; } - return output.replace(/(^|\W)(#[a-zA-Z0-9.\-_]+)\b/g, replaceHashtagWithToken); + return output.replace(/(^|\W)(#[a-zA-Z][a-zA-Z0-9.\-_]*)\b/g, replaceHashtagWithToken); } function highlightSearchTerm(text, tokens, searchTerm) { -- cgit v1.2.3-1-g7c22 From 1afa1d37c77b9508a4256e32c4e1fea27113033f Mon Sep 17 00:00:00 2001 From: hmhealey Date: Tue, 22 Sep 2015 14:30:50 -0400 Subject: Moved text formatting code to only occur inside of markdown text nodes --- web/react/utils/markdown.jsx | 13 +++++++++++++ web/react/utils/text_formatting.jsx | 39 +++++++++++++++++++------------------ 2 files changed, 33 insertions(+), 19 deletions(-) (limited to 'web/react/utils') diff --git a/web/react/utils/markdown.jsx b/web/react/utils/markdown.jsx index 96da54217..0a876a3e3 100644 --- a/web/react/utils/markdown.jsx +++ b/web/react/utils/markdown.jsx @@ -1,9 +1,18 @@ // Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. // See License.txt for license information. +const TextFormatting = require('./text_formatting.jsx'); + const marked = require('marked'); export class MattermostMarkdownRenderer extends marked.Renderer { + constructor(options, formattingOptions = {}) { + super(options); + + this.text = this.text.bind(this); + + this.formattingOptions = formattingOptions; + } link(href, title, text) { let outHref = href; @@ -19,4 +28,8 @@ export class MattermostMarkdownRenderer extends marked.Renderer { return output; } + + text(text) { + return TextFormatting.doFormatText(text, this.formattingOptions); + } } diff --git a/web/react/utils/text_formatting.jsx b/web/react/utils/text_formatting.jsx index 089fdd4f9..41dc98084 100644 --- a/web/react/utils/text_formatting.jsx +++ b/web/react/utils/text_formatting.jsx @@ -10,8 +10,6 @@ const Utils = require('./utils.jsx'); const marked = require('marked'); -const markdownRenderer = new Markdown.MattermostMarkdownRenderer(); - // Performs formatting of user posts including highlighting mentions and search terms and converting urls, hashtags, and // @mentions to links by taking a user's message and returning a string of formatted html. Also takes a number of options // as part of the second parameter: @@ -25,14 +23,30 @@ export function formatText(text, options = {}) { options.markdown = true; } - // wait until marked can sanitize the html so that we don't break markdown block quotes let output; - if (!options.markdown) { - output = sanitizeHtml(text); + + if (options.markdown) { + // the markdown renderer will call doFormatText as necessary so just call marked + output = marked(text, { + renderer: new Markdown.MattermostMarkdownRenderer(null, options), + sanitize: true + }); } else { - output = text; + output = sanitizeHtml(text); + output = doFormatText(output, options); } + // replace newlines with spaces if necessary + if (options.singleline) { + output = replaceNewlines(output); + } + + return output; +} + +export function doFormatText(text, options) { + let output = text; + const tokens = new Map(); // replace important words and phrases with tokens @@ -52,22 +66,9 @@ export function formatText(text, options = {}) { output = highlightCurrentMentions(output, tokens); } - // perform markdown parsing while we have an html-free input string - if (options.markdown) { - output = marked(output, { - renderer: markdownRenderer, - sanitize: true - }); - } - // reinsert tokens with formatted versions of the important words and phrases output = replaceTokens(output, tokens); - // replace newlines with html line breaks - if (options.singleline) { - output = replaceNewlines(output); - } - return output; } -- cgit v1.2.3-1-g7c22 From 55f11ba8719d133103bc1d4779bb8cb66d591b58 Mon Sep 17 00:00:00 2001 From: hmhealey Date: Tue, 22 Sep 2015 14:34:59 -0400 Subject: Removed extra handling of markdown links when doing autolinking --- web/react/utils/text_formatting.jsx | 36 +++++------------------------------- 1 file changed, 5 insertions(+), 31 deletions(-) (limited to 'web/react/utils') diff --git a/web/react/utils/text_formatting.jsx b/web/react/utils/text_formatting.jsx index 41dc98084..56bf49c3f 100644 --- a/web/react/utils/text_formatting.jsx +++ b/web/react/utils/text_formatting.jsx @@ -19,13 +19,9 @@ const marked = require('marked'); // - emoticons - Enables emoticon parsing. Defaults to true. // - markdown - Enables markdown parsing. Defaults to true. export function formatText(text, options = {}) { - if (!('markdown' in options)) { - options.markdown = true; - } - let output; - if (options.markdown) { + if (!('markdown' in options) || options.markdown) { // the markdown renderer will call doFormatText as necessary so just call marked output = marked(text, { renderer: new Markdown.MattermostMarkdownRenderer(null, options), @@ -44,13 +40,14 @@ export function formatText(text, options = {}) { return output; } +// Performs most of the actual formatting work for formatText. Not intended to be called normally. export function doFormatText(text, options) { let output = text; const tokens = new Map(); // replace important words and phrases with tokens - output = autolinkUrls(output, tokens, !!options.markdown); + output = autolinkUrls(output, tokens); output = autolinkAtMentions(output, tokens); output = autolinkHashtags(output, tokens); @@ -85,7 +82,7 @@ export function sanitizeHtml(text) { return output; } -function autolinkUrls(text, tokens, markdown) { +function autolinkUrls(text, tokens) { function replaceUrlWithToken(autolinker, match) { const linkText = match.getMatchedText(); let url = linkText; @@ -115,30 +112,7 @@ function autolinkUrls(text, tokens, markdown) { replaceFn: replaceUrlWithToken }); - let output = text; - - // temporarily replace markdown links if markdown is enabled so that we don't accidentally parse them twice - const markdownLinkTokens = new Map(); - if (markdown) { - function replaceMarkdownLinkWithToken(markdownLink) { - const index = markdownLinkTokens.size; - const alias = `MM_MARKDOWNLINK${index}`; - - markdownLinkTokens.set(alias, {value: markdownLink}); - - return alias; - } - - output = output.replace(/\]\([^\)]*\)/g, replaceMarkdownLinkWithToken); - } - - output = autolinker.link(output); - - if (markdown) { - output = replaceTokens(output, markdownLinkTokens); - } - - return output; + return autolinker.link(text); } function autolinkAtMentions(text, tokens) { -- cgit v1.2.3-1-g7c22 From 018b036e5ddfc4632c5b1f9f255bc338173bcf03 Mon Sep 17 00:00:00 2001 From: hmhealey Date: Tue, 22 Sep 2015 15:23:39 -0400 Subject: Added CSS classes to markdown headings, links, and tables --- web/react/utils/markdown.jsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'web/react/utils') diff --git a/web/react/utils/markdown.jsx b/web/react/utils/markdown.jsx index 0a876a3e3..347024e1a 100644 --- a/web/react/utils/markdown.jsx +++ b/web/react/utils/markdown.jsx @@ -9,10 +9,17 @@ export class MattermostMarkdownRenderer extends marked.Renderer { constructor(options, formattingOptions = {}) { super(options); + this.heading = this.heading.bind(this); this.text = this.text.bind(this); this.formattingOptions = formattingOptions; } + + heading(text, level, raw) { + const id = `${this.options.headerPrefix}${raw.toLowerCase().replace(/[^\w]+/g, '-')}`; + return `${text}`; + } + link(href, title, text) { let outHref = href; @@ -20,7 +27,7 @@ export class MattermostMarkdownRenderer extends marked.Renderer { outHref = `http://${outHref}`; } - let output = '${header}${body}`; + } + text(text) { return TextFormatting.doFormatText(text, this.formattingOptions); } -- cgit v1.2.3-1-g7c22 From e4a15076f458be1416de25b2c45578975b914de5 Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Wed, 23 Sep 2015 10:12:40 -0400 Subject: Implement UI theme colors. --- web/react/utils/constants.jsx | 139 ++++++++++++++++++++++++++++++- web/react/utils/utils.jsx | 188 ++++++++++++++++++++++++++++++++---------- 2 files changed, 282 insertions(+), 45 deletions(-) (limited to 'web/react/utils') diff --git a/web/react/utils/constants.jsx b/web/react/utils/constants.jsx index 03e4635b5..41e9e9ca6 100644 --- a/web/react/utils/constants.jsx +++ b/web/react/utils/constants.jsx @@ -36,7 +36,9 @@ module.exports = { RECIEVED_CONFIG: null, - RECIEVED_LOGS: null + RECIEVED_LOGS: null, + + TOGGLE_IMPORT_THEME_MODAL: null }), PayloadSources: keyMirror({ @@ -110,5 +112,138 @@ module.exports = { ONLINE_ICON_SVG: "", OFFLINE_ICON_SVG: "", MENU_ICON: " ", - COMMENT_ICON: " " + COMMENT_ICON: " ", + THEMES: { + default: { + type: 'Mattermost', + sidebarBg: '#fafafa', + sidebarText: '#999999', + sidebarUnreadText: '#333333', + sidebarTextHoverBg: '#e6f2fa', + sidebarTextHoverColor: '#999999', + sidebarTextActiveBg: '#e1e1e1', + sidebarTextActiveColor: '#111111', + sidebarHeaderBg: '#2389d7', + sidebarHeaderTextColor: '#ffffff', + onlineIndicator: '#7DBE00', + mentionBj: '#2389d7', + mentionColor: '#ffffff', + centerChannelBg: '#ffffff', + centerChannelColor: '#333333', + linkColor: '#2389d7', + buttonBg: '#2389d7', + buttonColor: '#FFFFFF' + }, + slack: { + type: 'Slack', + sidebarBg: '#4D394B', + sidebarText: '#ab9ba9', + sidebarUnreadText: '#FFFFFF', + sidebarTextHoverBg: '#3e313c', + sidebarTextHoverColor: '#ab9ba9', + sidebarTextActiveBg: '#4c9689', + sidebarTextActiveColor: '#FFFFFF', + sidebarHeaderBg: '#4D394B', + sidebarHeaderTextColor: '#FFFFFF', + onlineIndicator: '#4c9689', + mentionBj: '#eb4d5c', + mentionColor: '#FFFFFF', + centerChannelBg: '#FFFFFF', + centerChannelColor: '#333333', + linkColor: '#2389d7', + buttonBg: '#26a970', + buttonColor: '#FFFFFF' + }, + dark: { + type: 'Dark', + sidebarBg: '#1B2C3E', + sidebarText: '#bbbbbb', + sidebarUnreadText: '#fff', + sidebarTextHoverBg: '#4A5664', + sidebarTextHoverColor: '#bbbbbb', + sidebarTextActiveBg: '#39769C', + sidebarTextActiveColor: '#FFFFFF', + sidebarHeaderBg: '#1B2C3E', + sidebarHeaderTextColor: '#FFFFFF', + onlineIndicator: '#4c9689', + mentionBj: '#B74A4A', + mentionColor: '#FFFFFF', + centerChannelBg: '#2F3E4E', + centerChannelColor: '#DDDDDD', + linkColor: '#A4FFEB', + buttonBg: '#2B9C99', + buttonColor: '#FFFFFF' + } + }, + THEME_ELEMENTS: [ + { + id: 'sidebarBg', + uiName: 'Sidebar BG' + }, + { + id: 'sidebarText', + uiName: 'Sidebar text color' + }, + { + id: 'sidebarHeaderBg', + uiName: 'Sidebar Header BG' + }, + { + id: 'sidebarHeaderTextColor', + uiName: 'Sidebar Header text color' + }, + { + id: 'sidebarUnreadText', + uiName: 'Sidebar unread text color' + }, + { + id: 'sidebarTextHoverBg', + uiName: 'Sidebar text hover BG' + }, + { + id: 'sidebarTextHoverColor', + uiName: 'Sidebar text hover color' + }, + { + id: 'sidebarTextActiveBg', + uiName: 'Sidebar text active BG' + }, + { + id: 'sidebarTextActiveColor', + uiName: 'Sidebar text active color' + }, + { + id: 'onlineIndicator', + uiName: 'Online indicator' + }, + { + id: 'mentionBj', + uiName: 'Mention jewel BG' + }, + { + id: 'mentionColor', + uiName: 'Mention jewel text color' + }, + { + id: 'centerChannelBg', + uiName: 'Center channel BG' + }, + { + id: 'centerChannelColor', + uiName: 'Center channel text color' + }, + { + id: 'linkColor', + uiName: 'Link color' + }, + { + id: 'buttonBg', + uiName: 'Button BG' + }, + + { + id: 'buttonColor', + uiName: 'Button Color' + } + ] }; diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index 074591489..a8860eb94 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -542,7 +542,119 @@ export function toTitleCase(str) { return str.replace(/\w\S*/g, doTitleCase); } -export function changeCss(className, classValue) { +export function applyTheme(theme) { + if (theme.sidebarBg) { + changeCss('.sidebar--left', 'background:' + theme.sidebarBg, 1); + changeCss('@media(max-width: 768px){.search-bar__container', 'background:' + theme.sidebarBg, 1); + } + + if (theme.sidebarText) { + changeCss('.sidebar--left .nav li>a, .sidebar--right', 'color:' + theme.sidebarText, 1); + changeCss('.sidebar--left .nav li>h4, .sidebar--left .add-channel-btn', 'color:' + changeOpacity(theme.sidebarText, 0.8), 1); + changeCss('.sidebar--left .add-channel-btn:hover, .sidebar--left .add-channel-btn:focus', 'color:' + theme.sidebarText, 1); + changeCss('.sidebar--left, .sidebar--right .sidebar--right__header', 'border-color:' + changeOpacity(theme.sidebarText, 0.2), 1); + changeCss('.sidebar--right .sidebar-right__body', 'border-color:' + changeOpacity(theme.sidebarText, 0.2), 2); + changeCss('.sidebar--left .status path', 'fill:' + changeOpacity(theme.sidebarText, 0.5), 1); + } + + if (theme.sidebarUnreadText) { + changeCss('.sidebar--left .nav li>a.unread-title', 'color:' + theme.sidebarUnreadText + '!important;', 1); + } + + if (theme.sidebarTextHoverBg) { + changeCss('.sidebar--left .nav li>a:hover, .sidebar--left .nav li>a:focus', 'background:' + theme.sidebarTextHoverBg, 1); + } + + if (theme.sidebarTextHoverColor) { + changeCss('.sidebar--left .nav li>a:hover, .sidebar--left .nav li>a:focus', 'color:' + theme.sidebarTextHoverColor, 2); + } + + if (theme.sidebarTextActiveBg) { + changeCss('.sidebar--left .nav li.active a, .sidebar--left .nav li.active a:hover, .sidebar--left .nav li.active a:focus', 'background:' + theme.sidebarTextActiveBg, 1); + } + + if (theme.sidebarTextActiveColor) { + changeCss('.sidebar--left .nav li.active a, .sidebar--left .nav li.active a:hover, .sidebar--left .nav li.active a:focus', 'color:' + theme.sidebarTextActiveColor, 2); + } + + if (theme.sidebarHeaderBg) { + changeCss('.sidebar--left .team__header, .sidebar--menu .team__header', 'background:' + theme.sidebarHeaderBg, 1); + changeCss('.modal .modal-header', 'background:' + theme.sidebarHeaderBg, 1); + changeCss('#navbar .navbar-default', 'background:' + theme.sidebarHeaderBg, 1); + } + + if (theme.sidebarHeaderTextColor) { + changeCss('.sidebar--left .team__header .header__info, .sidebar--menu .team__header .header__info', 'color:' + theme.sidebarHeaderTextColor, 1); + changeCss('.sidebar--left .team__header .user__name, .sidebar--menu .team__header .user__name', 'color:' + changeOpacity(theme.sidebarHeaderTextColor, 0.8), 1); + changeCss('.sidebar--left .team__header:hover .user__name, .sidebar--menu .team__header:hover .user__name', 'color:' + theme.sidebarHeaderTextColor, 1); + changeCss('.modal .modal-header .modal-title, .modal .modal-header .modal-title .name, .modal .modal-header button.close', 'color:' + theme.sidebarHeaderTextColor, 1); + changeCss('#navbar .navbar-default .navbar-brand .heading, ', 'color:' + theme.sidebarHeaderTextColor, 1); + changeCss('#navbar .navbar-default .navbar-toggle .icon-bar, ', 'background:' + theme.sidebarHeaderTextColor, 1); + } + + if (theme.onlineIndicator) { + changeCss('.sidebar--left .status .online--icon', 'fill:' + theme.onlineIndicator, 1); + } + + if (theme.mentionBj) { + changeCss('.sidebar--left .nav-pills__unread-indicator', 'background:' + theme.mentionBj, 1); + changeCss('.sidebar--left .badge', 'background:' + theme.mentionBj, 1); + } + + if (theme.mentionColor) { + changeCss('.sidebar--left .nav-pills__unread-indicator', 'color:' + theme.mentionColor, 2); + changeCss('.sidebar--left .badge', 'color:' + theme.mentionColor, 2); + } + + if (theme.centerChannelBg) { + changeCss('.app__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('.search-bar__container .search__form .search-bar', 'background:' + theme.centerChannelBg, 1); + changeCss('.date-separator .separator__text, .new-separator .separator__text', 'background:' + theme.centerChannelBg, 1); + changeCss('.sidebar--right', 'background:' + theme.centerChannelBg, 1); + } + + if (theme.centerChannelColor) { + changeCss('.app__content', 'color:' + theme.centerChannelColor, 2); + changeCss('#post-create', 'color:' + theme.centerChannelColor, 2); + changeCss('.channel-header .heading', 'color:' + theme.centerChannelColor, 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', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2) + '!important; color: ' + theme.centerChannelColor, 1); + changeCss('.search-bar__container .search__form .search-bar', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2) + '; color: ' + theme.centerChannelColor, 2); + changeCss('.search-bar__container .search__form', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1); + changeCss('.channel-intro .channel-intro__content', 'background:' + changeOpacity(theme.centerChannelColor, 0.05), 1); + changeCss('.date-separator .separator__text, .new-separator .separator__text', 'color:' + theme.centerChannelColor, 2); + changeCss('.date-separator .separator__hr, .new-separator .separator__hr, .post-right__container .post.post--root hr, .search-item-container', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1); + changeCss('.channel-intro', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1); + changeCss('.post.current--user .post-body, .post.post--comment.other--root.current--user .post-comment', 'background:' + changeOpacity(theme.centerChannelColor, 0.07), 1); + changeCss('.post.current--user .post-body, .post.post--comment.other--root.current--user .post-comment', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.07), 2); + changeCss('@media(max-width: 1440px){.post.same--root', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.07), 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, .sidebar--right .sidebar--right__header', 'background:' + changeOpacity(theme.centerChannelColor, 0.07), 1); + changeCss('.date-separator.hovered--before:after, .new-separator.hovered--before:after', 'background:' + changeOpacity(theme.centerChannelColor, 0.07), 1); + changeCss('.date-separator.hovered--after:before, .new-separator.hovered--after:before', 'background:' + changeOpacity(theme.centerChannelColor, 0.07), 1); + changeCss('.post.current--user:hover .post-body ', 'background: none;', 1); + changeCss('.sidebar--right', 'color:' + theme.centerChannelColor, 2); + } + + if (theme.linkColor) { + changeCss('a, a:focus, a:hover', 'color:' + theme.linkColor, 1); + changeCss('.post .comment-icon__container', 'fill:' + theme.linkColor, 1); + } + + if (theme.buttonBg) { + changeCss('.btn.btn-primary', 'background:' + theme.buttonBg, 1); + changeCss('.btn.btn-primary:hover, .btn.btn-primary:active, .btn.btn-primary:focus', 'background:' + changeColor(theme.buttonBg, -0.25), 1); + } + + if (theme.buttonColor) { + changeCss('.btn.btn-primary', 'color:' + theme.buttonColor, 2); + } +} + +export function changeCss(className, classValue, classRepeat) { // we need invisible container to store additional css definitions var cssMainContainer = $('#css-modifier-container'); if (cssMainContainer.length === 0) { @@ -552,9 +664,9 @@ export function changeCss(className, classValue) { } // and we need one div for each class - var classContainer = cssMainContainer.find('div[data-class="' + className + '"]'); + var classContainer = cssMainContainer.find('div[data-class="' + className + classRepeat + '"]'); if (classContainer.length === 0) { - classContainer = $('
'); + classContainer = $('
'); classContainer.appendTo(cssMainContainer); } @@ -760,57 +872,47 @@ Image.prototype.load = function imageLoad(url, progressCallback) { Image.prototype.completedPercentage = 0; export function changeColor(colourIn, amt) { - var usePound = false; - var col = colourIn; + var hex = colourIn; + var lum = amt; - if (col[0] === '#') { - col = col.slice(1); - usePound = true; + // validate hex string + hex = String(hex).replace(/[^0-9a-f]/gi, ''); + if (hex.length < 6) { + hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; } + lum = lum || 0; - var num = parseInt(col, 16); - - var r = (num >> 16) + amt; - - if (r > 255) { - r = 255; - } else if (r < 0) { - r = 0; - } - - var b = ((num >> 8) & 0x00FF) + amt; - - if (b > 255) { - b = 255; - } else if (b < 0) { - b = 0; + // convert to decimal and change luminosity + var rgb = '#'; + var c; + var i; + for (i = 0; i < 3; i++) { + c = parseInt(hex.substr(i * 2, 2), 16); + c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16); + rgb += ('00' + c).substr(c.length); } - var g = (num & 0x0000FF) + amt; - - if (g > 255) { - g = 255; - } else if (g < 0) { - g = 0; - } + return rgb; +} - var pound = '#'; - if (!usePound) { - pound = ''; +export function changeOpacity(oldColor, opacity) { + var color = oldColor; + if (color[0] === '#') { + color = color.slice(1); } - return pound + String('000000' + (g | (b << 8) | (r << 16)).toString(16)).slice(-6); -} + if (color.length === 3) { + const tempColor = color; + color = ''; -export function changeOpacity(oldColor, opacity) { - var col = oldColor; - if (col[0] === '#') { - col = col.slice(1); + color += tempColor[0] + tempColor[0]; + color += tempColor[1] + tempColor[1]; + color += tempColor[2] + tempColor[2]; } - var r = parseInt(col.substring(0, 2), 16); - var g = parseInt(col.substring(2, 4), 16); - var b = parseInt(col.substring(4, 6), 16); + var r = parseInt(color.substring(0, 2), 16); + var g = parseInt(color.substring(2, 4), 16); + var b = parseInt(color.substring(4, 6), 16); return 'rgba(' + r + ',' + g + ',' + b + ',' + opacity + ')'; } -- cgit v1.2.3-1-g7c22