Update custom emojis endpoint (#852)

* Update emoji endpoint

* Use React.memo on Markdown

* Support RC versions lower than 0.75.0

* Realm migration
This commit is contained in:
Diego Mello 2019-04-26 18:13:07 -03:00 committed by GitHub
parent c340829638
commit 5c1be71fa1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 164 additions and 124 deletions

View File

@ -14,98 +14,90 @@ const formatText = text => text.replace(
(match, url, title) => `[${ title }](${ url })` (match, url, title) => `[${ title }](${ url })`
); );
export default class Markdown extends React.Component { const Markdown = React.memo(({
shouldComponentUpdate(nextProps) { msg, customEmojis, style, rules, baseUrl, username, edited, numberOfLines
const { msg } = this.props; }) => {
return nextProps.msg !== msg; if (!msg) {
return null;
} }
let m = formatText(msg);
render() { if (m) {
const { m = emojify(m, { output: 'unicode' });
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 (
<MarkdownRenderer
rules={{
paragraph: (node, children) => (
// eslint-disable-next-line
<Text key={node.key} style={styles.paragraph} numberOfLines={numberOfLines}>
{children}
{edited ? <Text style={styles.edited}> (edited)</Text> : null}
</Text>
),
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 (
<Text style={mentionStyle} key={key}>
&nbsp;{content}&nbsp;
</Text>
);
},
hashtag: node => (
<Text key={node.key} style={styles.mention}>
&nbsp;#{node.content}&nbsp;
</Text>
),
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 <CustomEmoji key={node.key} baseUrl={baseUrl} style={styles.customEmoji} emoji={emoji} />;
}
return <Text key={node.key}>:{content}:</Text>;
}
return null;
},
hardbreak: () => null,
blocklink: () => null,
image: node => (
<Image key={node.key} style={styles.inlineImage} source={{ uri: node.attributes.src }} />
),
...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}
</MarkdownRenderer>
);
} }
} m = m.replace(/^\[([^\]]*)\]\(([^)]*)\)/, '').trim();
if (numberOfLines > 0) {
m = m.replace(/[\n]+/g, '\n').trim();
}
return (
<MarkdownRenderer
rules={{
paragraph: (node, children) => (
// eslint-disable-next-line
<Text key={node.key} style={styles.paragraph} numberOfLines={numberOfLines}>
{children}
{edited ? <Text style={styles.edited}> (edited)</Text> : null}
</Text>
),
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 (
<Text style={mentionStyle} key={key}>
&nbsp;{content}&nbsp;
</Text>
);
},
hashtag: node => (
<Text key={node.key} style={styles.mention}>
&nbsp;#{node.content}&nbsp;
</Text>
),
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 <CustomEmoji key={node.key} baseUrl={baseUrl} style={styles.customEmoji} emoji={emoji} />;
}
return <Text key={node.key}>:{content}:</Text>;
}
return null;
},
hardbreak: () => null,
blocklink: () => null,
image: node => (
<Image key={node.key} style={styles.inlineImage} source={{ uri: node.attributes.src }} />
),
...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}
</MarkdownRenderer>
);
}, (prevProps, nextProps) => prevProps.msg === nextProps.msg);
Markdown.propTypes = { Markdown.propTypes = {
msg: PropTypes.string, msg: PropTypes.string,
@ -117,3 +109,5 @@ Markdown.propTypes = {
edited: PropTypes.bool, edited: PropTypes.bool,
numberOfLines: PropTypes.number numberOfLines: PropTypes.number
}; };
export default Markdown;

View File

@ -1,39 +1,83 @@
import { InteractionManager } from 'react-native'; import { InteractionManager } from 'react-native';
import semver from 'semver';
import reduxStore from '../createStore'; import reduxStore from '../createStore';
import database from '../realm'; import database from '../realm';
import * as actions from '../../actions'; import * as actions from '../../actions';
import log from '../../utils/log'; import log from '../../utils/log';
const getLastMessage = () => { const getUpdatedSince = () => {
const setting = database.objects('customEmojis').sorted('_updatedAt', true)[0]; const emoji = database.objects('customEmojis').sorted('_updatedAt', true)[0];
return setting && setting._updatedAt; 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() { export default async function() {
try { try {
const lastMessage = getLastMessage(); const serverVersion = reduxStore.getState().server.version;
// RC 0.61.0 const updatedSince = getUpdatedSince();
const result = await this.sdk.get('emoji-custom');
let { emojis } = result; // if server version is lower than 0.75.0, fetches from old api
emojis = emojis.filter(emoji => !lastMessage || emoji._updatedAt > lastMessage); if (semver.lt(serverVersion, '0.75.0')) {
if (emojis.length === 0) { // RC 0.61.0
return; const result = await this.sdk.get('emoji-custom');
}
emojis = this._prepareEmojis(emojis); InteractionManager.runAfterInteractions(() => {
InteractionManager.runAfterInteractions(() => { let { emojis } = result;
database.write(() => { emojis = emojis.filter(emoji => !updatedSince || emoji._updatedAt > updatedSince);
emojis.forEach((emoji) => { database.write(() => {
try { create(emojis);
database.create('customEmojis', emoji, true);
} catch (e) {
log('create custom emojis', e);
}
}); });
reduxStore.dispatch(actions.setCustomEmojis(this.parseEmojis(result.emojis)));
}); });
}); } else {
reduxStore.dispatch(actions.setCustomEmojis(this.parseEmojis(emojis))); 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) { } catch (e) {
log('getCustomEmojis', e); log('getCustomEmojis', e);
} }

View File

@ -24,6 +24,9 @@ export const merge = (subscription, room) => {
subscription.archived = room.archived; subscription.archived = room.archived;
subscription.joinCodeRequired = room.joinCodeRequired; subscription.joinCodeRequired = room.joinCodeRequired;
subscription.broadcast = room.broadcast; subscription.broadcast = room.broadcast;
if (!subscription.roles || !subscription.roles.length) {
subscription.roles = [];
}
if (room.muted && room.muted.length) { if (room.muted && room.muted.length) {
subscription.muted = room.muted.filter(user => user).map(user => ({ value: user })); subscription.muted = room.muted.filter(user => user).map(user => ({ value: user }));

View File

@ -286,21 +286,13 @@ const frequentlyUsedEmojiSchema = {
} }
}; };
const customEmojiAliasesSchema = {
name: 'customEmojiAliases',
primaryKey: 'value',
properties: {
value: 'string'
}
};
const customEmojisSchema = { const customEmojisSchema = {
name: 'customEmojis', name: 'customEmojis',
primaryKey: '_id', primaryKey: '_id',
properties: { properties: {
_id: 'string', _id: 'string',
name: 'string', name: 'string',
aliases: { type: 'list', objectType: 'customEmojiAliases' }, aliases: 'string[]',
extension: 'string', extension: 'string',
_updatedAt: { type: 'date', optional: true } _updatedAt: { type: 'date', optional: true }
} }
@ -353,7 +345,6 @@ const schema = [
permissionsSchema, permissionsSchema,
url, url,
frequentlyUsedEmojiSchema, frequentlyUsedEmojiSchema,
customEmojiAliasesSchema,
customEmojisSchema, customEmojisSchema,
messagesReactionsSchema, messagesReactionsSchema,
messagesReactionsUsernamesSchema, messagesReactionsUsernamesSchema,
@ -428,7 +419,7 @@ class DB {
return this.databases.activeDB = new Realm({ return this.databases.activeDB = new Realm({
path: `${ path }.realm`, path: `${ path }.realm`,
schema, schema,
schemaVersion: 8, schemaVersion: 9,
migration: (oldRealm, newRealm) => { migration: (oldRealm, newRealm) => {
if (oldRealm.schemaVersion >= 3 && newRealm.schemaVersion <= 8) { if (oldRealm.schemaVersion >= 3 && newRealm.schemaVersion <= 8) {
const newSubs = newRealm.objects('subscriptions'); const newSubs = newRealm.objects('subscriptions');
@ -445,6 +436,14 @@ class DB {
const newThreadMessages = newRealm.objects('threadMessages'); const newThreadMessages = newRealm.objects('threadMessages');
newRealm.delete(newThreadMessages); 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);
}
} }
}); });
} }