diff options
Diffstat (limited to 'webapp/utils')
-rw-r--r-- | webapp/utils/async_client.jsx | 32 | ||||
-rw-r--r-- | webapp/utils/channel_intro_messages.jsx | 2 | ||||
-rw-r--r-- | webapp/utils/constants.jsx | 118 | ||||
-rw-r--r-- | webapp/utils/emoticons.jsx | 18 | ||||
-rw-r--r-- | webapp/utils/markdown.jsx | 357 | ||||
-rw-r--r-- | webapp/utils/text_formatting.jsx | 2 | ||||
-rw-r--r-- | webapp/utils/utils.jsx | 50 | ||||
-rw-r--r-- | webapp/utils/web_client.jsx | 21 |
8 files changed, 175 insertions, 425 deletions
diff --git a/webapp/utils/async_client.jsx b/webapp/utils/async_client.jsx index 6535c024d..6f5f8a2cd 100644 --- a/webapp/utils/async_client.jsx +++ b/webapp/utils/async_client.jsx @@ -3,7 +3,7 @@ import $ from 'jquery'; import Client from './web_client.jsx'; -import * as GlobalActions from 'action_creators/global_actions.jsx'; +import * as GlobalActions from 'actions/global_actions.jsx'; import AppDispatcher from '../dispatcher/app_dispatcher.jsx'; import BrowserStore from 'stores/browser_store.jsx'; import ChannelStore from 'stores/channel_store.jsx'; @@ -47,7 +47,21 @@ function isCallInProgress(callName) { return true; } -export function getChannels(checkVersion) { +export function checkVersion() { + var serverVersion = Client.getServerVersion(); + + if (serverVersion !== BrowserStore.getLastServerVersion()) { + if (!BrowserStore.getLastServerVersion() || BrowserStore.getLastServerVersion() === '') { + BrowserStore.setLastServerVersion(serverVersion); + } else { + BrowserStore.setLastServerVersion(serverVersion); + window.location.reload(true); + console.log('Detected version update refreshing the page'); //eslint-disable-line no-console + } + } +} + +export function getChannels(doVersionCheck) { if (isCallInProgress('getChannels')) { return null; } @@ -58,18 +72,8 @@ export function getChannels(checkVersion) { (data) => { callTracker.getChannels = 0; - if (checkVersion) { - var serverVersion = Client.getServerVersion(); - - if (serverVersion !== BrowserStore.getLastServerVersion()) { - if (!BrowserStore.getLastServerVersion() || BrowserStore.getLastServerVersion() === '') { - BrowserStore.setLastServerVersion(serverVersion); - } else { - BrowserStore.setLastServerVersion(serverVersion); - window.location.reload(true); - console.log('Detected version update refreshing the page'); //eslint-disable-line no-console - } - } + if (doVersionCheck) { + checkVersion(); } AppDispatcher.handleServerAction({ diff --git a/webapp/utils/channel_intro_messages.jsx b/webapp/utils/channel_intro_messages.jsx index 1d18e26ba..c9dd30712 100644 --- a/webapp/utils/channel_intro_messages.jsx +++ b/webapp/utils/channel_intro_messages.jsx @@ -8,7 +8,7 @@ import ToggleModalButton from 'components/toggle_modal_button.jsx'; import UserProfile from 'components/user_profile.jsx'; import ChannelStore from 'stores/channel_store.jsx'; import Constants from 'utils/constants.jsx'; -import * as GlobalActions from 'action_creators/global_actions.jsx'; +import * as GlobalActions from 'actions/global_actions.jsx'; import Client from 'utils/web_client.jsx'; import React from 'react'; diff --git a/webapp/utils/constants.jsx b/webapp/utils/constants.jsx index 109291d1f..0e2ae07ea 100644 --- a/webapp/utils/constants.jsx +++ b/webapp/utils/constants.jsx @@ -88,6 +88,7 @@ export default { RECEIVED_MSG: null, RECEIVED_MY_TEAM: null, + CREATED_TEAM: null, RECEIVED_CONFIG: null, RECEIVED_LOGS: null, @@ -249,7 +250,8 @@ export default { RESERVED_USERNAMES: [ 'valet', 'all', - 'channel' + 'channel', + 'here' ], MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], MAX_DMS: 20, @@ -304,7 +306,7 @@ export default { sidebarTextHoverBg: '#e6f2fa', sidebarTextActiveBorder: '#378FD2', sidebarTextActiveColor: '#111111', - sidebarHeaderBg: '#2389d7', + sidebarHeaderBg: '#3481B9', sidebarHeaderTextColor: '#ffffff', onlineIndicator: '#7DBE00', awayIndicator: '#DCBD4E', @@ -314,7 +316,7 @@ export default { centerChannelColor: '#333333', newMessageSeparator: '#FF8800', linkColor: '#2389d7', - buttonBg: '#2389d7', + buttonBg: '#23A2FF', buttonColor: '#FFFFFF', mentionHighlightBg: '#fff2bb', mentionHighlightLink: '#2f81b7', @@ -530,7 +532,11 @@ export default { CHANNEL_DISPLAY_MODE: 'channel_display_mode', CHANNEL_DISPLAY_MODE_CENTERED: 'centered', CHANNEL_DISPLAY_MODE_FULL_SCREEN: 'full', - CHANNEL_DISPLAY_MODE_DEFAULT: 'centered' + CHANNEL_DISPLAY_MODE_DEFAULT: 'centered', + MESSAGE_DISPLAY: 'message_display', + MESSAGE_DISPLAY_CLEAN: 'clean', + MESSAGE_DISPLAY_COMPACT: 'compact', + MESSAGE_DISPLAY_DEFAULT: 'clean' }, TutorialSteps: { INTRO_SCREENS: 0, @@ -539,16 +545,101 @@ export default { MENU_POPOVER: 3 }, KeyCodes: { - UP: 38, - DOWN: 40, - LEFT: 37, - RIGHT: 39, BACKSPACE: 8, + TAB: 9, ENTER: 13, + SHIFT: 16, + CTRL: 17, + ALT: 18, + CAPS_LOCK: 20, ESCAPE: 27, SPACE: 32, - TAB: 9, - U: 85 + PAGE_UP: 33, + PAGE_DOWN: 34, + END: 35, + HOME: 36, + LEFT: 37, + UP: 38, + RIGHT: 39, + DOWN: 40, + INSERT: 45, + DELETE: 46, + ZERO: 48, + ONE: 49, + TWO: 50, + THREE: 51, + FOUR: 52, + FIVE: 53, + SIX: 54, + SEVEN: 55, + EIGHT: 56, + NINE: 57, + A: 65, + B: 66, + C: 67, + D: 68, + E: 69, + F: 70, + G: 71, + H: 72, + I: 73, + J: 74, + K: 75, + L: 76, + M: 77, + N: 78, + O: 79, + P: 80, + Q: 81, + R: 82, + S: 83, + T: 84, + U: 85, + V: 86, + W: 87, + X: 88, + Y: 89, + Z: 90, + CMD: 91, + MENU: 93, + NUMPAD_0: 96, + NUMPAD_1: 97, + NUMPAD_2: 98, + NUMPAD_3: 99, + NUMPAD_4: 100, + NUMPAD_5: 101, + NUMPAD_6: 102, + NUMPAD_7: 103, + NUMPAD_8: 104, + NUMPAD_9: 105, + MULTIPLY: 106, + ADD: 107, + SUBTRACT: 109, + DECIMAL: 110, + DIVIDE: 111, + F1: 112, + F2: 113, + F3: 114, + F4: 115, + F5: 116, + F6: 117, + F7: 118, + F8: 119, + F9: 120, + F10: 121, + F11: 122, + F12: 123, + NUM_LOCK: 144, + SEMICOLON: 186, + EQUAL: 187, + COMMA: 188, + DASH: 189, + PERIOD: 190, + FORWARD_SLASH: 191, + TILDE: 192, + OPEN_BRACKET: 219, + BACK_SLASH: 220, + CLOSE_BRACKET: 221 }, CODE_PREVIEW_MAX_FILE_SIZE: 500000, // 500 KB HighlightedLanguages: { @@ -633,14 +724,19 @@ export default { } }, OVERLAY_TIME_DELAY: 400, + MIN_TEAMNAME_LENGTH: 4, + MAX_TEAMNAME_LENGTH: 15, MIN_USERNAME_LENGTH: 3, MAX_USERNAME_LENGTH: 22, MIN_PASSWORD_LENGTH: 5, MAX_PASSWORD_LENGTH: 50, + MIN_TRIGGER_LENGTH: 1, + MAX_TRIGGER_LENGTH: 128, TIME_SINCE_UPDATE_INTERVAL: 30000, MIN_HASHTAG_LINK_LENGTH: 3, EMOJI_PATH: '/static/emoji', DEFAULT_WEBHOOK_LOGO: logoWebhook, MHPNS: 'https://push.mattermost.com', - MTPNS: 'http://push-test.mattermost.com' + MTPNS: 'http://push-test.mattermost.com', + BOT_NAME: 'BOT' }; diff --git a/webapp/utils/emoticons.jsx b/webapp/utils/emoticons.jsx index 505e10c19..35c7dba04 100644 --- a/webapp/utils/emoticons.jsx +++ b/webapp/utils/emoticons.jsx @@ -1,8 +1,6 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import $ from 'jquery'; - import Constants from './constants.jsx'; import emojis from './emoji.json'; @@ -134,7 +132,7 @@ export function getEmoticonsByCodePoint() { export function handleEmoticons(text, tokens) { let output = text; - function replaceEmoticonWithToken(fullMatch, prefix, matchText, name) { + function replaceEmoticonWithToken(fullMatch, matchText, name) { if (getEmoticonsByName().has(name)) { const index = tokens.size; const alias = `MM_EMOTICON${index}`; @@ -145,19 +143,23 @@ export function handleEmoticons(text, tokens) { originalText: fullMatch }); - return prefix + alias; + return alias; } return fullMatch; } - output = output.replace(/(^|\s)(:([a-zA-Z0-9_-]+):)(?=$|\s)/g, (fullMatch, prefix, matchText, name) => replaceEmoticonWithToken(fullMatch, prefix, matchText, name)); + // match named emoticons like :goat: + output = output.replace(/(:([a-zA-Z0-9_-]+):)/g, (fullMatch, matchText, name) => replaceEmoticonWithToken(fullMatch, matchText, name)); + + // match text smilies like :D + for (const name of Object.keys(emoticonPatterns)) { + const pattern = emoticonPatterns[name]; - $.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, (fullMatch, prefix, matchText) => replaceEmoticonWithToken(fullMatch, prefix, matchText, name)); - }); + output = output.replace(pattern, (fullMatch, matchText) => replaceEmoticonWithToken(fullMatch, matchText, name)); + } return output; } diff --git a/webapp/utils/markdown.jsx b/webapp/utils/markdown.jsx index 2ddd3fe11..809ecc526 100644 --- a/webapp/utils/markdown.jsx +++ b/webapp/utils/markdown.jsx @@ -13,40 +13,6 @@ function markdownImageLoaded(image) { } window.markdownImageLoaded = markdownImageLoaded; -class MattermostInlineLexer extends marked.InlineLexer { - constructor(links, options) { - super(links, options); - - this.rules = Object.assign({}, this.rules); - - // modified version of the regex that allows for links starting with www and those surrounded by parentheses - // the original is /^[\s\S]+?(?=[\\<!\[_*`~]|https?:\/\/| {2,}\n|$)/ - this.rules.text = /^[\s\S]+?(?=[\\<!\[_*`~]|https?:\/\/|www\.|\(| {2,}\n|$)/; - - // modified version of the regex that allows links starting with www and those surrounded by parentheses - // the original is /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/ - this.rules.url = /^(\(?(?:https?:\/\/|www\.)[^\s<.][^\s<]*[^<.,:;"'\]\s])/; - - // modified version of the regex that allows <links> starting with www. - // the original is /^<([^ >]+(@|:\/)[^ >]+)>/ - this.rules.autolink = /^<((?:[^ >]+(@|:\/)|www\.)[^ >]+)>/; - } -} - -class MattermostParser extends marked.Parser { - parse(src) { - this.inline = new MattermostInlineLexer(src.links, this.options, this.renderer); - this.tokens = src.reverse(); - - var out = ''; - while (this.next()) { - out += this.tok(); - } - - return out; - } -} - class MattermostMarkdownRenderer extends marked.Renderer { constructor(options, formattingOptions = {}) { super(options); @@ -109,18 +75,6 @@ class MattermostMarkdownRenderer extends marked.Renderer { link(href, title, text) { let outHref = href; - let outText = text; - let prefix = ''; - let suffix = ''; - - // some links like https://en.wikipedia.org/wiki/Rendering_(computer_graphics) contain brackets - // and we try our best to differentiate those from ones just wrapped in brackets when autolinking - if (outHref.startsWith('(') && outHref.endsWith(')') && text === outHref) { - prefix = '('; - suffix = ')'; - outText = text.substring(1, text.length - 1); - outHref = outHref.substring(1, outHref.length - 1); - } try { const unescaped = decodeURIComponent(unescape(href)).replace(/[^\w:]/g, '').toLowerCase(); @@ -149,9 +103,9 @@ class MattermostMarkdownRenderer extends marked.Renderer { output += ' title="' + title + '"'; } - output += '>' + outText + '</a>'; + output += '>' + text + '</a>'; - return prefix + output + suffix; + return output; } paragraph(text) { @@ -166,13 +120,19 @@ class MattermostMarkdownRenderer extends marked.Renderer { return `<div class="table-responsive"><table class="markdown__table"><thead>${header}</thead><tbody>${body}</tbody></table></div>`; } - listitem(text) { + listitem(text, bullet) { const taskListReg = /^\[([ |xX])\] /; const isTaskList = taskListReg.exec(text); if (isTaskList) { return `<li class="list-item--task-list">${'<input type="checkbox" disabled="disabled" ' + (isTaskList[1] === ' ' ? '' : 'checked="checked" ') + '/> '}${text.replace(taskListReg, '')}</li>`; } + + if (/^\d+.$/.test(bullet)) { + // this is a numbered list item so override the numbering + return `<li value="${parseInt(bullet, 10)}">${text}</li>`; + } + return `<li>${text}</li>`; } @@ -181,301 +141,6 @@ class MattermostMarkdownRenderer extends marked.Renderer { } } -class MattermostLexer extends marked.Lexer { - token(originalSrc, top, bq) { - let src = originalSrc.replace(/^ +$/gm, ''); - - while (src) { - // newline - let cap = this.rules.newline.exec(src); - if (cap) { - src = src.substring(cap[0].length); - if (cap[0].length > 1) { - this.tokens.push({ - type: 'space' - }); - } - } - - // code - cap = this.rules.code.exec(src); - if (cap) { - src = src.substring(cap[0].length); - cap = cap[0].replace(/^ {4}/gm, ''); - this.tokens.push({ - type: 'code', - text: this.options.pedantic ? cap : cap.replace(/\n+$/, '') - }); - continue; - } - - // fences (gfm) - cap = this.rules.fences.exec(src); - if (cap) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'code', - lang: cap[2], - text: cap[3] || '' - }); - continue; - } - - // heading - cap = this.rules.heading.exec(src); - if (cap) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'heading', - depth: cap[1].length, - text: cap[2] - }); - continue; - } - - // table no leading pipe (gfm) - cap = this.rules.nptable.exec(src); - if (top && cap) { - src = src.substring(cap[0].length); - - const item = { - type: 'table', - header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), - align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), - cells: cap[3].replace(/\n$/, '').split('\n') - }; - - for (let i = 0; i < item.align.length; i++) { - if (/^ *-+: *$/.test(item.align[i])) { - item.align[i] = 'right'; - } else if (/^ *:-+: *$/.test(item.align[i])) { - item.align[i] = 'center'; - } else if (/^ *:-+ *$/.test(item.align[i])) { - item.align[i] = 'left'; - } else { - item.align[i] = null; - } - } - - for (let i = 0; i < item.cells.length; i++) { - item.cells[i] = item.cells[i].split(/ *\| */); - } - - this.tokens.push(item); - - continue; - } - - // lheading - cap = this.rules.lheading.exec(src); - if (cap) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'heading', - depth: cap[2] === '=' ? 1 : 2, - text: cap[1] - }); - continue; - } - - // hr - cap = this.rules.hr.exec(src); - if (cap) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'hr' - }); - continue; - } - - // blockquote - cap = this.rules.blockquote.exec(src); - if (cap) { - src = src.substring(cap[0].length); - - this.tokens.push({ - type: 'blockquote_start' - }); - - cap = cap[0].replace(/^ *> ?/gm, ''); - - // Pass `top` to keep the current - // "toplevel" state. This is exactly - // how markdown.pl works. - this.token(cap, top, true); - - this.tokens.push({ - type: 'blockquote_end' - }); - - continue; - } - - // list - cap = this.rules.list.exec(src); - if (cap) { - src = src.substring(cap[0].length); - const bull = cap[2]; - - this.tokens.push({ - type: 'list_start', - ordered: bull.length > 1 - }); - - // Get each top-level item. - cap = cap[0].match(this.rules.item); - - let next = false; - const l = cap.length; - let i = 0; - - for (; i < l; i++) { - let item = cap[i]; - - // Remove the list item's bullet - // so it is seen as the next token. - let space = item.length; - item = item.replace(/^ *([*+-]|\d+\.) +/, ''); - - // Outdent whatever the - // list item contains. Hacky. - if (~item.indexOf('\n ')) { - space -= item.length; - item = this.options.pedantic ? - item.replace(/^ {1,4}/gm, '') : - item.replace(new RegExp('^ {1,' + space + '}', 'gm'), ''); - } - - // Determine whether the next list item belongs here. - // Backpedal if it does not belong in this list. - if (this.options.smartLists && i !== l - 1) { - const b = this.rules.bullet.exec(cap[i + 1])[0]; - if (bull !== b && !(bull.length > 1 && b.length > 1)) { - src = cap.slice(i + 1).join('\n') + src; - i = l - 1; - } - } - - // Determine whether item is loose or not. - // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/ - // for discount behavior. - let loose = next || (/\n\n(?!\s*$)/).test(item); - if (i !== l - 1) { - next = item.charAt(item.length - 1) === '\n'; - if (!loose) { - loose = next; - } - } - - this.tokens.push({ - type: loose ? - 'loose_item_start' : - 'list_item_start' - }); - - // Recurse. - this.token(item, false, bq); - - this.tokens.push({ - type: 'list_item_end' - }); - } - - this.tokens.push({ - type: 'list_end' - }); - - continue; - } - - // html - cap = this.rules.html.exec(src); - if (cap) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: this.options.sanitize ? 'paragraph' : 'html', - pre: !this.options.sanitizer && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'), - text: cap[0] - }); - continue; - } - - // def - cap = this.rules.def.exec(src); - if ((!bq && top) && cap) { - src = src.substring(cap[0].length); - this.tokens.links[cap[1].toLowerCase()] = { - href: cap[2], - title: cap[3] - }; - continue; - } - - // table (gfm) - cap = this.rules.table.exec(src); - if (top && cap) { - src = src.substring(cap[0].length); - - const item = { - type: 'table', - header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), - align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), - cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') - }; - - for (let i = 0; i < item.align.length; i++) { - if (/^ *-+: *$/.test(item.align[i])) { - item.align[i] = 'right'; - } else if (/^ *:-+: *$/.test(item.align[i])) { - item.align[i] = 'center'; - } else if (/^ *:-+ *$/.test(item.align[i])) { - item.align[i] = 'left'; - } else { - item.align[i] = null; - } - } - - for (let i = 0; i < item.cells.length; i++) { - item.cells[i] = item.cells[i].replace(/^ *\| *| *\| *$/g, '').split(/ *\| */); - } - - this.tokens.push(item); - - continue; - } - - // top-level paragraph - cap = this.rules.paragraph.exec(src); - if (top && cap) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'paragraph', - text: cap[1].charAt(cap[1].length - 1) === '\n' ? cap[1].slice(0, -1) : cap[1] - }); - continue; - } - - // text - cap = this.rules.text.exec(src); - if (cap) { - // Top-level should never reach here. - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'text', - text: cap[0] - }); - continue; - } - - if (src) { - throw new Error('Infinite loop on byte: ' + src.charCodeAt(0)); - } - } - - return this.tokens; - } -} - export function format(text, options) { const markdownOptions = { renderer: new MattermostMarkdownRenderer(null, options), @@ -484,9 +149,7 @@ export function format(text, options) { tables: true }; - const tokens = new MattermostLexer(markdownOptions).lex(text); - - return new MattermostParser(markdownOptions).parse(tokens); + return marked(text, markdownOptions); } // Marked helper functions that should probably just be exported diff --git a/webapp/utils/text_formatting.jsx b/webapp/utils/text_formatting.jsx index 96b51d632..623fe0660 100644 --- a/webapp/utils/text_formatting.jsx +++ b/webapp/utils/text_formatting.jsx @@ -318,7 +318,7 @@ function parseSearchTerms(searchTerm) { termString = termString.substring(captured[0].length); // break the text up into words based on how the server splits them in SqlPostStore.SearchPosts and then discard empty terms - terms.push(...captured[0].split(/[ <>+\-\(\)\~\@]/).filter((term) => !!term)); + terms.push(...captured[0].split(/[ <>+\-\(\)~@]/).filter((term) => !!term)); continue; } diff --git a/webapp/utils/utils.jsx b/webapp/utils/utils.jsx index 2f728226c..978f231df 100644 --- a/webapp/utils/utils.jsx +++ b/webapp/utils/utils.jsx @@ -34,38 +34,6 @@ export function cleanUpUrlable(input) { return cleaned; } -export function isTestDomain() { - if ((/^localhost/).test(window.location.hostname)) { - return true; - } - - if ((/^dockerhost/).test(window.location.hostname)) { - return true; - } - - if ((/^test/).test(window.location.hostname)) { - return true; - } - - if ((/^127.0./).test(window.location.hostname)) { - return true; - } - - if ((/^192.168./).test(window.location.hostname)) { - return true; - } - - if ((/^10./).test(window.location.hostname)) { - return true; - } - - if ((/^176./).test(window.location.hostname)) { - return true; - } - - return false; -} - export function isChrome() { if (navigator.userAgent.indexOf('Chrome') > -1) { return true; @@ -457,7 +425,7 @@ export function replaceHtmlEntities(text) { }; var newtext = text; for (var tag in tagsToReplace) { - if ({}.hasOwnProperty.call(tagsToReplace, tag)) { + if (Reflect.apply({}.hasOwnProperty, this, [tagsToReplace, tag])) { var regex = new RegExp(tag, 'g'); newtext = newtext.replace(regex, tagsToReplace[tag]); } @@ -473,7 +441,7 @@ export function insertHtmlEntities(text) { }; var newtext = text; for (var tag in tagsToReplace) { - if ({}.hasOwnProperty.call(tagsToReplace, tag)) { + if (Reflect.apply({}.hasOwnProperty, this, [tagsToReplace, tag])) { var regex = new RegExp(tag, 'g'); newtext = newtext.replace(regex, tagsToReplace[tag]); } @@ -682,7 +650,7 @@ export function applyTheme(theme) { changeCss('.app__body .post-list__arrows', 'fill:' + changeOpacity(theme.centerChannelColor, 0.3), 1); changeCss('.app__body .sidebar--left, .app__body .sidebar--right .sidebar--right__header, .app__body .suggestion-list__content .command', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1); changeCss('.app__body .app__content, .app__body .post-create__container .post-create-body .btn-file, .app__body .post-create__container .post-create-footer .msg-typing, .app__body .suggestion-list__content .command, .app__body .modal .modal-content, .app__body .dropdown-menu, .app__body .popover, .app__body .mentions__name, .app__body .tip-overlay', 'color:' + theme.centerChannelColor, 1); - changeCss('.app__body #archive-link-home', 'background:' + changeOpacity(theme.centerChannelColor, 0.15), 1); + changeCss('.app__body #archive-link-home, .video-div .video-thumbnail__error', 'background:' + changeOpacity(theme.centerChannelColor, 0.15), 1); changeCss('.app__body #post-create', 'color:' + theme.centerChannelColor, 2); changeCss('.app__body .mentions--top, .app__body .suggestion-list', 'box-shadow:' + changeOpacity(theme.centerChannelColor, 0.2) + ' 1px -3px 12px', 3); changeCss('.app__body .mentions--top, .app__body .suggestion-list', '-webkit-box-shadow:' + changeOpacity(theme.centerChannelColor, 0.2) + ' 1px -3px 12px', 2); @@ -734,7 +702,7 @@ export function applyTheme(theme) { changeCss('.app__body .scrollbar--horizontal, .app__body .scrollbar--vertical', 'background:' + changeOpacity(theme.centerChannelColor, 0.5), 2); changeCss('.app__body .post-list__new-messages-below', 'background:' + changeColor(theme.centerChannelColor, 0.5), 2); changeCss('.app__body .post.post--comment .post__body', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1); - changeCss('.app__body .post.post--comment.current--user .post__body', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.13), 1); + changeCss('.app__body .post.post--comment.current--user .post__body', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1); } if (theme.newMessageSeparator) { @@ -924,7 +892,7 @@ export function isValidUsername(name) { error = 'This field is required'; } else if (name.length < Constants.MIN_USERNAME_LENGTH || name.length > Constants.MAX_USERNAME_LENGTH) { error = 'Must be between ' + Constants.MIN_USERNAME_LENGTH + ' and ' + Constants.MAX_USERNAME_LENGTH + ' characters'; - } else if (!(/^[a-z0-9\.\-\_]+$/).test(name)) { + } else if (!(/^[a-z0-9\.\-_]+$/).test(name)) { error = "Must contain only letters, numbers, and the symbols '.', '-', and '_'."; } else if (!(/[a-z]/).test(name.charAt(0))) { //eslint-disable-line no-negated-condition error = 'First character must be a letter.'; @@ -977,7 +945,7 @@ Image.prototype.load = function imageLoad(url, progressCallback) { xmlHTTP.responseType = 'arraybuffer'; xmlHTTP.onload = function onLoad() { var h = xmlHTTP.getAllResponseHeaders(); - var m = h.match(/^Content-Type\:\s*(.*?)$/mi); + var m = h.match(/^Content-Type:\s*(.*?)$/mi); var mimeType = m[1] || 'image/png'; var blob = new Blob([this.response], {type: mimeType}); @@ -1142,7 +1110,7 @@ export function generateId() { // implementation taken from http://stackoverflow.com/a/2117523 var id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'; - id = id.replace(/[xy]/g, function replaceRandom(c) { + id = id.replace(/[xy]/g, (c) => { var r = Math.floor(Math.random() * 16); var v; @@ -1408,6 +1376,10 @@ export function localizeMessage(id, defaultMessage) { return id; } +export function mod(a, b) { + return ((a % b) + b) % b; +} + export function getProfilePicSrcForPost(post, timestamp) { let src = Client.getUsersRoute() + '/' + post.user_id + '/image?time=' + timestamp; if (post.props && post.props.from_webhook && global.window.mm_config.EnablePostIconOverride === 'true') { diff --git a/webapp/utils/web_client.jsx b/webapp/utils/web_client.jsx index 642e523b7..b974ad31f 100644 --- a/webapp/utils/web_client.jsx +++ b/webapp/utils/web_client.jsx @@ -1,10 +1,12 @@ // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import Client from '../client/client.jsx'; +import Client from 'mattermost/client.jsx'; import TeamStore from '../stores/team_store.jsx'; import BrowserStore from '../stores/browser_store.jsx'; -import * as GlobalActions from 'action_creators/global_actions.jsx'; +import * as GlobalActions from 'actions/global_actions.jsx'; + +import request from 'superagent'; const HTTP_UNAUTHORIZED = 401; @@ -53,7 +55,7 @@ class WebClientClass extends Client { } }, (err) => { - this.track('api', 'api_users_login_fail', name, 'login_id', loginId); + this.track('api', 'api_users_login_fail', '', 'login_id', loginId); if (error) { error(err); } @@ -75,13 +77,24 @@ class WebClientClass extends Client { } }, (err) => { - this.track('api', 'api_users_login_fail', name, 'login_id', loginId); + this.track('api', 'api_users_login_fail', '', 'login_id', loginId); if (error) { error(err); } } ); } + + getYoutubeVideoInfo(googleKey, videoId, success, error) { + request.get('https://www.googleapis.com/youtube/v3/videos'). + query({part: 'snippet', id: videoId, key: googleKey}). + end((err, res) => { + if (err) { + return error(err); + } + return success(res.body); + }); + } } var WebClient = new WebClientClass(); |