diff --git a/app/containers/message/Markdown.js b/app/containers/message/Markdown.js index 11dba2055..5b3a59a34 100644 --- a/app/containers/message/Markdown.js +++ b/app/containers/message/Markdown.js @@ -14,98 +14,90 @@ const formatText = text => text.replace( (match, url, title) => `[${ title }](${ url })` ); -export default class Markdown extends React.Component { - shouldComponentUpdate(nextProps) { - const { msg } = this.props; - return nextProps.msg !== msg; +const Markdown = React.memo(({ + msg, customEmojis, style, rules, baseUrl, username, edited, numberOfLines +}) => { + if (!msg) { + return null; } - - render() { - const { - msg, customEmojis, style, rules, baseUrl, username, edited, numberOfLines - } = this.props; - if (!msg) { - return null; - } - let m = formatText(msg); - if (m) { - m = emojify(m, { output: 'unicode' }); - } - m = m.replace(/^\[([^\]]*)\]\(([^)]*)\)/, '').trim(); - if (numberOfLines > 0) { - m = m.replace(/[\n]+/g, '\n').trim(); - } - return ( - ( - // eslint-disable-next-line - - {children} - {edited ? (edited) : null} - - ), - mention: (node) => { - const { content, key } = node; - let mentionStyle = styles.mention; - if (content === 'all' || content === 'here') { - mentionStyle = { - ...mentionStyle, - ...styles.mentionAll - }; - } else if (content === username) { - mentionStyle = { - ...mentionStyle, - ...styles.mentionLoggedUser - }; - } - return ( - -  {content}  - - ); - }, - hashtag: node => ( - -  #{node.content}  - - ), - emoji: (node) => { - if (node.children && node.children.length && node.children[0].content) { - const { content } = node.children[0]; - const emojiExtension = customEmojis[content]; - if (emojiExtension) { - const emoji = { extension: emojiExtension, content }; - return ; - } - return :{content}:; - } - return null; - }, - hardbreak: () => null, - blocklink: () => null, - image: node => ( - - ), - ...rules - }} - style={{ - paragraph: styles.paragraph, - text: styles.text, - codeInline: styles.codeInline, - codeBlock: styles.codeBlock, - link: styles.link, - ...style - }} - plugins={[ - new PluginContainer(MarkdownFlowdock), - new PluginContainer(MarkdownEmojiPlugin) - ]} - >{m} - - ); + let m = formatText(msg); + if (m) { + m = emojify(m, { output: 'unicode' }); } -} + m = m.replace(/^\[([^\]]*)\]\(([^)]*)\)/, '').trim(); + if (numberOfLines > 0) { + m = m.replace(/[\n]+/g, '\n').trim(); + } + return ( + ( + // eslint-disable-next-line + + {children} + {edited ? (edited) : null} + + ), + mention: (node) => { + const { content, key } = node; + let mentionStyle = styles.mention; + if (content === 'all' || content === 'here') { + mentionStyle = { + ...mentionStyle, + ...styles.mentionAll + }; + } else if (content === username) { + mentionStyle = { + ...mentionStyle, + ...styles.mentionLoggedUser + }; + } + return ( + +  {content}  + + ); + }, + hashtag: node => ( + +  #{node.content}  + + ), + emoji: (node) => { + if (node.children && node.children.length && node.children[0].content) { + const { content } = node.children[0]; + const emojiExtension = customEmojis[content]; + if (emojiExtension) { + const emoji = { extension: emojiExtension, content }; + return ; + } + return :{content}:; + } + return null; + }, + hardbreak: () => null, + blocklink: () => null, + image: node => ( + + ), + ...rules + }} + style={{ + paragraph: styles.paragraph, + text: styles.text, + codeInline: styles.codeInline, + codeBlock: styles.codeBlock, + link: styles.link, + ...style + }} + plugins={[ + new PluginContainer(MarkdownFlowdock), + new PluginContainer(MarkdownEmojiPlugin) + ]} + >{m} + + ); +}, (prevProps, nextProps) => prevProps.msg === nextProps.msg); Markdown.propTypes = { msg: PropTypes.string, @@ -117,3 +109,5 @@ Markdown.propTypes = { edited: PropTypes.bool, numberOfLines: PropTypes.number }; + +export default Markdown; diff --git a/app/lib/methods/getCustomEmojis.js b/app/lib/methods/getCustomEmojis.js index adcb2e83c..207ef446c 100644 --- a/app/lib/methods/getCustomEmojis.js +++ b/app/lib/methods/getCustomEmojis.js @@ -1,39 +1,83 @@ import { InteractionManager } from 'react-native'; +import semver from 'semver'; import reduxStore from '../createStore'; import database from '../realm'; import * as actions from '../../actions'; import log from '../../utils/log'; -const getLastMessage = () => { - const setting = database.objects('customEmojis').sorted('_updatedAt', true)[0]; - return setting && setting._updatedAt; +const getUpdatedSince = () => { + const emoji = database.objects('customEmojis').sorted('_updatedAt', true)[0]; + return emoji && emoji._updatedAt.toISOString(); }; -// TODO: fix api (get emojis by date/version....) +const create = (customEmojis) => { + if (customEmojis && customEmojis.length) { + customEmojis.forEach((emoji) => { + try { + database.create('customEmojis', emoji, true); + } catch (e) { + log('getEmojis create', e); + } + }); + } +}; + + export default async function() { try { - const lastMessage = getLastMessage(); - // RC 0.61.0 - const result = await this.sdk.get('emoji-custom'); - let { emojis } = result; - emojis = emojis.filter(emoji => !lastMessage || emoji._updatedAt > lastMessage); - if (emojis.length === 0) { - return; - } - emojis = this._prepareEmojis(emojis); - InteractionManager.runAfterInteractions(() => { - database.write(() => { - emojis.forEach((emoji) => { - try { - database.create('customEmojis', emoji, true); - } catch (e) { - log('create custom emojis', e); - } + const serverVersion = reduxStore.getState().server.version; + const updatedSince = getUpdatedSince(); + + // if server version is lower than 0.75.0, fetches from old api + if (semver.lt(serverVersion, '0.75.0')) { + // RC 0.61.0 + const result = await this.sdk.get('emoji-custom'); + + InteractionManager.runAfterInteractions(() => { + let { emojis } = result; + emojis = emojis.filter(emoji => !updatedSince || emoji._updatedAt > updatedSince); + database.write(() => { + create(emojis); }); + reduxStore.dispatch(actions.setCustomEmojis(this.parseEmojis(result.emojis))); }); - }); - reduxStore.dispatch(actions.setCustomEmojis(this.parseEmojis(emojis))); + } else { + const params = {}; + if (updatedSince) { + params.updatedSince = updatedSince; + } + + // RC 0.75.0 + const result = await this.sdk.get('emoji-custom.list', params); + + if (!result.success) { + return; + } + + InteractionManager.runAfterInteractions( + () => database.write(() => { + const { emojis } = result; + create(emojis.update); + + if (emojis.delete && emojis.delete.length) { + emojis.delete.forEach((emoji) => { + try { + const emojiRecord = database.objectForPrimaryKey('customEmojis', emoji._id); + if (emojiRecord) { + database.delete(emojiRecord); + } + } catch (e) { + log('getEmojis delete', e); + } + }); + } + + const allEmojis = database.objects('customEmojis'); + reduxStore.dispatch(actions.setCustomEmojis(this.parseEmojis(allEmojis))); + }) + ); + } } catch (e) { log('getCustomEmojis', e); } diff --git a/app/lib/methods/helpers/mergeSubscriptionsRooms.js b/app/lib/methods/helpers/mergeSubscriptionsRooms.js index c09caed51..7983cac08 100644 --- a/app/lib/methods/helpers/mergeSubscriptionsRooms.js +++ b/app/lib/methods/helpers/mergeSubscriptionsRooms.js @@ -24,6 +24,9 @@ export const merge = (subscription, room) => { subscription.archived = room.archived; subscription.joinCodeRequired = room.joinCodeRequired; subscription.broadcast = room.broadcast; + if (!subscription.roles || !subscription.roles.length) { + subscription.roles = []; + } if (room.muted && room.muted.length) { subscription.muted = room.muted.filter(user => user).map(user => ({ value: user })); diff --git a/app/lib/realm.js b/app/lib/realm.js index 8c2bbc547..a36327349 100644 --- a/app/lib/realm.js +++ b/app/lib/realm.js @@ -286,21 +286,13 @@ const frequentlyUsedEmojiSchema = { } }; -const customEmojiAliasesSchema = { - name: 'customEmojiAliases', - primaryKey: 'value', - properties: { - value: 'string' - } -}; - const customEmojisSchema = { name: 'customEmojis', primaryKey: '_id', properties: { _id: 'string', name: 'string', - aliases: { type: 'list', objectType: 'customEmojiAliases' }, + aliases: 'string[]', extension: 'string', _updatedAt: { type: 'date', optional: true } } @@ -353,7 +345,6 @@ const schema = [ permissionsSchema, url, frequentlyUsedEmojiSchema, - customEmojiAliasesSchema, customEmojisSchema, messagesReactionsSchema, messagesReactionsUsernamesSchema, @@ -428,7 +419,7 @@ class DB { return this.databases.activeDB = new Realm({ path: `${ path }.realm`, schema, - schemaVersion: 8, + schemaVersion: 9, migration: (oldRealm, newRealm) => { if (oldRealm.schemaVersion >= 3 && newRealm.schemaVersion <= 8) { const newSubs = newRealm.objects('subscriptions'); @@ -445,6 +436,14 @@ class DB { const newThreadMessages = newRealm.objects('threadMessages'); newRealm.delete(newThreadMessages); } + if (newRealm.schemaVersion === 9) { + const newSubs = newRealm.objects('subscriptions'); + newRealm.delete(newSubs); + const newEmojis = newRealm.objects('customEmojis'); + newRealm.delete(newEmojis); + const newSettings = newRealm.objects('settings'); + newRealm.delete(newSettings); + } } }); }