forked from Ivasoft/mattermost-mobile
combine reactions by their first alias
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
|
||||
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import {getEmojiFirstAlias} from '@utils/emoji/helpers';
|
||||
import {safeParseJSON} from '@utils/helpers';
|
||||
|
||||
import type SystemModel from '@typings/database/models/servers/system';
|
||||
@@ -29,16 +30,17 @@ export const addRecentReaction = async (serverUrl: string, emojiNames: string[],
|
||||
|
||||
try {
|
||||
const recentEmojis = new Set(recent);
|
||||
for (const name of emojiNames) {
|
||||
if (recentEmojis.has(name)) {
|
||||
recentEmojis.delete(name);
|
||||
const aliases = emojiNames.map((e) => getEmojiFirstAlias(e));
|
||||
for (const alias of aliases) {
|
||||
if (recentEmojis.has(alias)) {
|
||||
recentEmojis.delete(alias);
|
||||
}
|
||||
}
|
||||
|
||||
recent = Array.from(recentEmojis);
|
||||
|
||||
for (const name of emojiNames) {
|
||||
recent.unshift(name);
|
||||
for (const alias of aliases) {
|
||||
recent.unshift(alias);
|
||||
}
|
||||
return operator.handleSystem({
|
||||
systems: [{
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {Model, Q} from '@nozbe/watermelondb';
|
||||
import {Model} from '@nozbe/watermelondb';
|
||||
|
||||
import {addRecentReaction} from '@actions/local/reactions';
|
||||
import {MM_TABLES} from '@constants/database';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import NetworkManager from '@init/network_manager';
|
||||
import {queryRecentPostsInChannel, queryRecentPostsInThread} from '@queries/servers/post';
|
||||
import {queryReaction} from '@queries/servers/reaction';
|
||||
import {queryCurrentChannelId, queryCurrentUserId} from '@queries/servers/system';
|
||||
import {getEmojiFirstAlias} from '@utils/emoji/helpers';
|
||||
|
||||
import {forceLogoutIfNecessary} from './session';
|
||||
|
||||
@@ -30,29 +31,41 @@ export const addReaction = async (serverUrl: string, postId: string, emojiName:
|
||||
|
||||
try {
|
||||
const currentUserId = await queryCurrentUserId(operator.database);
|
||||
const reaction = await client.addReaction(currentUserId, postId, emojiName);
|
||||
const models: Model[] = [];
|
||||
const emojiAlias = getEmojiFirstAlias(emojiName);
|
||||
const reacted = await queryReaction(operator.database, emojiAlias, postId, currentUserId).fetchCount() > 0;
|
||||
if (!reacted) {
|
||||
const reaction = await client.addReaction(currentUserId, postId, emojiAlias);
|
||||
const models: Model[] = [];
|
||||
|
||||
const reactions = await operator.handleReactions({
|
||||
postsReactions: [{
|
||||
const reactions = await operator.handleReactions({
|
||||
postsReactions: [{
|
||||
post_id: postId,
|
||||
reactions: [reaction],
|
||||
}],
|
||||
prepareRecordsOnly: true,
|
||||
skipSync: true, // this prevents the handler from deleting previous reactions
|
||||
});
|
||||
models.push(...reactions);
|
||||
|
||||
const recent = await addRecentReaction(serverUrl, [emojiName], true);
|
||||
if (Array.isArray(recent)) {
|
||||
models.push(...recent);
|
||||
}
|
||||
|
||||
if (models.length) {
|
||||
await operator.batchRecords(models);
|
||||
}
|
||||
|
||||
return {reaction};
|
||||
}
|
||||
return {
|
||||
reaction: {
|
||||
user_id: currentUserId,
|
||||
post_id: postId,
|
||||
reactions: [reaction],
|
||||
}],
|
||||
prepareRecordsOnly: true,
|
||||
skipSync: true, // this prevents the handler from deleting previous reactions
|
||||
});
|
||||
models.push(...reactions);
|
||||
|
||||
const recent = await addRecentReaction(serverUrl, [emojiName], true);
|
||||
if (Array.isArray(recent)) {
|
||||
models.push(...recent);
|
||||
}
|
||||
|
||||
if (models.length) {
|
||||
await operator.batchRecords(models);
|
||||
}
|
||||
|
||||
return {reaction};
|
||||
emoji_name: emojiAlias,
|
||||
create_at: Date.now(),
|
||||
} as Reaction,
|
||||
};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
return {error};
|
||||
@@ -74,14 +87,11 @@ export const removeReaction = async (serverUrl: string, postId: string, emojiNam
|
||||
|
||||
try {
|
||||
const currentUserId = await queryCurrentUserId(database);
|
||||
await client.removeReaction(currentUserId, postId, emojiName);
|
||||
const emojiAlias = getEmojiFirstAlias(emojiName);
|
||||
await client.removeReaction(currentUserId, postId, emojiAlias);
|
||||
|
||||
// should return one or no reaction
|
||||
const reaction = await database.get(MM_TABLES.SERVER.REACTION).query(
|
||||
Q.where('emoji_name', emojiName),
|
||||
Q.where('post_id', postId),
|
||||
Q.where('user_id', currentUserId),
|
||||
).fetch();
|
||||
const reaction = await queryReaction(database, emojiAlias, postId, currentUserId).fetch();
|
||||
|
||||
if (reaction.length) {
|
||||
await database.write(async () => {
|
||||
|
||||
@@ -10,6 +10,7 @@ import CompassIcon from '@components/compass_icon';
|
||||
import {MAX_ALLOWED_REACTIONS} from '@constants/emoji';
|
||||
import {useServerUrl} from '@context/server';
|
||||
import {showModal, showModalOverCurrentContext} from '@screens/navigation';
|
||||
import {getEmojiFirstAlias} from '@utils/emoji/helpers';
|
||||
import {preventDoubleTap} from '@utils/tap';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
|
||||
@@ -59,12 +60,12 @@ const Reactions = ({currentUserId, canAddReaction, canRemoveReaction, disabled,
|
||||
const intl = useIntl();
|
||||
const serverUrl = useServerUrl();
|
||||
const pressed = useRef(false);
|
||||
const [sortedReactions, setSortedReactions] = useState(new Set(reactions.map((r) => r.emojiName)));
|
||||
const [sortedReactions, setSortedReactions] = useState(new Set(reactions.map((r) => getEmojiFirstAlias(r.emojiName))));
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
useEffect(() => {
|
||||
// This helps keep the reactions in the same position at all times until unmounted
|
||||
const rs = reactions.map((r) => r.emojiName);
|
||||
const rs = reactions.map((r) => getEmojiFirstAlias(r.emojiName));
|
||||
const sorted = new Set([...sortedReactions]);
|
||||
const added = rs.filter((r) => !sorted.has(r));
|
||||
added.forEach(sorted.add, sorted);
|
||||
@@ -78,14 +79,20 @@ const Reactions = ({currentUserId, canAddReaction, canRemoveReaction, disabled,
|
||||
|
||||
const reactionsByName = reactions.reduce((acc, reaction) => {
|
||||
if (reaction) {
|
||||
if (acc.has(reaction.emojiName)) {
|
||||
acc.get(reaction.emojiName)!.push(reaction);
|
||||
const emojiAlias = getEmojiFirstAlias(reaction.emojiName);
|
||||
if (acc.has(emojiAlias)) {
|
||||
const rs = acc.get(emojiAlias);
|
||||
// eslint-disable-next-line max-nested-callbacks
|
||||
const present = rs!.findIndex((r) => r.userId === reaction.userId) > -1;
|
||||
if (!present) {
|
||||
rs!.push(reaction);
|
||||
}
|
||||
} else {
|
||||
acc.set(reaction.emojiName, [reaction]);
|
||||
acc.set(emojiAlias, [reaction]);
|
||||
}
|
||||
|
||||
if (reaction.userId === currentUserId) {
|
||||
highlightedReactions.push(reaction.emojiName);
|
||||
highlightedReactions.push(emojiAlias);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
15
app/queries/servers/reaction.ts
Normal file
15
app/queries/servers/reaction.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {Database, Q} from '@nozbe/watermelondb';
|
||||
|
||||
import {MM_TABLES} from '@constants/database';
|
||||
const {SERVER: {REACTION}} = MM_TABLES;
|
||||
|
||||
export const queryReaction = (database: Database, emojiName: string, postId: string, userId: string) => {
|
||||
return database.get(REACTION).query(
|
||||
Q.where('emoji_name', emojiName),
|
||||
Q.where('post_id', postId),
|
||||
Q.where('user_id', userId),
|
||||
);
|
||||
};
|
||||
@@ -193,6 +193,10 @@ export function doesMatchNamedEmoji(emojiName: string) {
|
||||
return false;
|
||||
}
|
||||
|
||||
export const getEmojiFirstAlias = (emoji: string) => {
|
||||
return getEmojiByName(emoji, [])?.short_names?.[0] || emoji;
|
||||
};
|
||||
|
||||
export function getEmojiByName(emojiName: string, customEmojis: CustomEmojiModel[]) {
|
||||
if (EmojiIndicesByAlias.has(emojiName)) {
|
||||
return Emojis[EmojiIndicesByAlias.get(emojiName)!];
|
||||
|
||||
Reference in New Issue
Block a user