Convert EmojiReaction to zod

This commit is contained in:
Alex Gleason 2023-05-02 19:11:17 -05:00
parent 0016aeacec
commit e3fcff55f9
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
10 changed files with 29 additions and 38 deletions

View File

@ -1,12 +1,10 @@
import userEvent from '@testing-library/user-event'; import userEvent from '@testing-library/user-event';
import React from 'react'; import React from 'react';
import { normalizeEmojiReaction } from 'soapbox/normalizers/emoji-reaction';
import { render, screen } from '../../../../jest/test-helpers'; import { render, screen } from '../../../../jest/test-helpers';
import ChatMessageReaction from '../chat-message-reaction'; import ChatMessageReaction from '../chat-message-reaction';
const emojiReaction = normalizeEmojiReaction({ const emojiReaction = ({
name: '👍', name: '👍',
count: 1, count: 1,
me: false, me: false,
@ -56,7 +54,7 @@ describe('<ChatMessageReaction />', () => {
render( render(
<ChatMessageReaction <ChatMessageReaction
emojiReaction={normalizeEmojiReaction({ emojiReaction={({
name: '👍', name: '👍',
count: 1, count: 1,
me: true, me: true,

View File

@ -312,7 +312,7 @@ const ChatMessage = (props: IChatMessage) => {
</Stack> </Stack>
</HStack> </HStack>
{(chatMessage.emoji_reactions?.size) ? ( {(chatMessage.emoji_reactions?.length) ? (
<div <div
className={clsx({ className={clsx({
'space-y-1': true, 'space-y-1': true,

View File

@ -6,8 +6,8 @@ import {
} from 'immutable'; } from 'immutable';
import { normalizeAttachment } from 'soapbox/normalizers/attachment'; import { normalizeAttachment } from 'soapbox/normalizers/attachment';
import { emojiReactionSchema } from 'soapbox/schemas';
import { normalizeEmojiReaction } from './emoji-reaction'; import { filteredArray } from 'soapbox/schemas/utils';
import type { Attachment, Card, Emoji, EmojiReaction } from 'soapbox/types/entities'; import type { Attachment, Card, Emoji, EmojiReaction } from 'soapbox/types/entities';
@ -20,7 +20,7 @@ export const ChatMessageRecord = ImmutableRecord({
created_at: '', created_at: '',
emojis: ImmutableList<Emoji>(), emojis: ImmutableList<Emoji>(),
expiration: null as number | null, expiration: null as number | null,
emoji_reactions: null as ImmutableList<EmojiReaction> | null, emoji_reactions: null as readonly EmojiReaction[] | null,
id: '', id: '',
unread: false, unread: false,
deleting: false, deleting: false,
@ -41,13 +41,8 @@ const normalizeMedia = (status: ImmutableMap<string, any>) => {
}; };
const normalizeChatMessageEmojiReaction = (chatMessage: ImmutableMap<string, any>) => { const normalizeChatMessageEmojiReaction = (chatMessage: ImmutableMap<string, any>) => {
const emojiReactions = chatMessage.get('emoji_reactions'); const emojiReactions = chatMessage.get('emoji_reactions') || ImmutableList();
return chatMessage.set('emoji_reactions', filteredArray(emojiReactionSchema).parse(emojiReactions.toJS()));
if (emojiReactions) {
return chatMessage.set('emoji_reactions', ImmutableList(emojiReactions.map(normalizeEmojiReaction)));
} else {
return chatMessage;
}
}; };
/** Rewrite `<p></p>` to empty string. */ /** Rewrite `<p></p>` to empty string. */

View File

@ -1,14 +0,0 @@
import { Map as ImmutableMap, Record as ImmutableRecord, fromJS } from 'immutable';
// https://docs.joinmastodon.org/entities/emoji/
export const EmojiReactionRecord = ImmutableRecord({
name: '',
count: null as number | null,
me: false,
});
export const normalizeEmojiReaction = (emojiReaction: Record<string, any>) => {
return EmojiReactionRecord(
ImmutableMap(fromJS(emojiReaction)),
);
};

View File

@ -7,7 +7,6 @@ export { AttachmentRecord, normalizeAttachment } from './attachment';
export { ChatRecord, normalizeChat } from './chat'; export { ChatRecord, normalizeChat } from './chat';
export { ChatMessageRecord, normalizeChatMessage } from './chat-message'; export { ChatMessageRecord, normalizeChatMessage } from './chat-message';
export { EmojiRecord, normalizeEmoji } from './emoji'; export { EmojiRecord, normalizeEmoji } from './emoji';
export { EmojiReactionRecord } from './emoji-reaction';
export { FilterRecord, normalizeFilter } from './filter'; export { FilterRecord, normalizeFilter } from './filter';
export { FilterKeywordRecord, normalizeFilterKeyword } from './filter-keyword'; export { FilterKeywordRecord, normalizeFilterKeyword } from './filter-keyword';
export { FilterStatusRecord, normalizeFilterStatus } from './filter-status'; export { FilterStatusRecord, normalizeFilterStatus } from './filter-status';

View File

@ -1,4 +1,4 @@
import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; import { Map as ImmutableMap } from 'immutable';
import sumBy from 'lodash/sumBy'; import sumBy from 'lodash/sumBy';
import { useEffect } from 'react'; import { useEffect } from 'react';
@ -6,7 +6,6 @@ import { __stub } from 'soapbox/api';
import { buildRelationship } from 'soapbox/jest/factory'; import { buildRelationship } from 'soapbox/jest/factory';
import { createTestStore, mockStore, queryClient, renderHook, rootState, waitFor } from 'soapbox/jest/test-helpers'; import { createTestStore, mockStore, queryClient, renderHook, rootState, waitFor } from 'soapbox/jest/test-helpers';
import { normalizeChatMessage } from 'soapbox/normalizers'; import { normalizeChatMessage } from 'soapbox/normalizers';
import { normalizeEmojiReaction } from 'soapbox/normalizers/emoji-reaction';
import { Store } from 'soapbox/store'; import { Store } from 'soapbox/store';
import { ChatMessage } from 'soapbox/types/entities'; import { ChatMessage } from 'soapbox/types/entities';
import { flattenPages } from 'soapbox/utils/queries'; import { flattenPages } from 'soapbox/utils/queries';
@ -426,11 +425,11 @@ describe('useChatActions', () => {
}); });
const updatedChatMessage = (queryClient.getQueryData(ChatKeys.chatMessages(chat.id)) as any).pages[0].result[0] as ChatMessage; const updatedChatMessage = (queryClient.getQueryData(ChatKeys.chatMessages(chat.id)) as any).pages[0].result[0] as ChatMessage;
expect(updatedChatMessage.emoji_reactions).toEqual(ImmutableList([normalizeEmojiReaction({ expect(updatedChatMessage.emoji_reactions).toEqual([{
name: '👍', name: '👍',
count: 1, count: 1,
me: true, me: true,
})])); }]);
}); });
}); });
}); });

View File

@ -0,0 +1,15 @@
import { z } from 'zod';
/** Validates the string as an emoji. */
const emojiSchema = z.string().refine((v) => /\p{Extended_Pictographic}/u.test(v));
/** Pleroma emoji reaction. */
const emojiReactionSchema = z.object({
name: emojiSchema,
count: z.number().nullable().catch(null),
me: z.boolean().catch(false),
});
type EmojiReaction = z.infer<typeof emojiReactionSchema>;
export { emojiReactionSchema, EmojiReaction };

View File

@ -1,6 +1,7 @@
export { accountSchema, type Account } from './account'; export { accountSchema, type Account } from './account';
export { cardSchema, type Card } from './card'; export { cardSchema, type Card } from './card';
export { customEmojiSchema, type CustomEmoji } from './custom-emoji'; export { customEmojiSchema, type CustomEmoji } from './custom-emoji';
export { emojiReactionSchema, type EmojiReaction } from './emoji-reaction';
export { groupSchema, type Group } from './group'; export { groupSchema, type Group } from './group';
export { groupMemberSchema, type GroupMember } from './group-member'; export { groupMemberSchema, type GroupMember } from './group-member';
export { groupRelationshipSchema, type GroupRelationship } from './group-relationship'; export { groupRelationshipSchema, type GroupRelationship } from './group-relationship';

View File

@ -8,7 +8,6 @@ import {
ChatRecord, ChatRecord,
ChatMessageRecord, ChatMessageRecord,
EmojiRecord, EmojiRecord,
EmojiReactionRecord,
FieldRecord, FieldRecord,
FilterRecord, FilterRecord,
FilterKeywordRecord, FilterKeywordRecord,
@ -38,7 +37,6 @@ type Attachment = ReturnType<typeof AttachmentRecord>;
type Chat = ReturnType<typeof ChatRecord>; type Chat = ReturnType<typeof ChatRecord>;
type ChatMessage = ReturnType<typeof ChatMessageRecord>; type ChatMessage = ReturnType<typeof ChatMessageRecord>;
type Emoji = ReturnType<typeof EmojiRecord>; type Emoji = ReturnType<typeof EmojiRecord>;
type EmojiReaction = ReturnType<typeof EmojiReactionRecord>;
type Field = ReturnType<typeof FieldRecord>; type Field = ReturnType<typeof FieldRecord>;
type Filter = ReturnType<typeof FilterRecord>; type Filter = ReturnType<typeof FilterRecord>;
type FilterKeyword = ReturnType<typeof FilterKeywordRecord>; type FilterKeyword = ReturnType<typeof FilterKeywordRecord>;
@ -81,7 +79,6 @@ export {
Chat, Chat,
ChatMessage, ChatMessage,
Emoji, Emoji,
EmojiReaction,
Field, Field,
Filter, Filter,
FilterKeyword, FilterKeyword,
@ -105,6 +102,7 @@ export {
export type { export type {
Card, Card,
EmojiReaction,
Group, Group,
GroupMember, GroupMember,
GroupRelationship, GroupRelationship,

View File

@ -254,7 +254,7 @@ const getInstanceFeatures = (instance: Instance) => {
/** /**
* Ability to add reactions to chat messages. * Ability to add reactions to chat messages.
*/ */
chatEmojiReactions: v.software === TRUTHSOCIAL && v.build === UNRELEASED, chatEmojiReactions: v.software === TRUTHSOCIAL,
/** /**
* Pleroma chats API. * Pleroma chats API.