Prosemirror integrate (#86)

Comment Editor
This commit is contained in:
Ilya Y 2023-01-26 09:59:43 +03:00 committed by GitHub
parent f22d6c60c5
commit 87a99d9e8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 421 additions and 68 deletions

View File

@ -122,12 +122,31 @@
@include font-size(1.5rem);
line-height: 1.47;
blockquote {
margin-left: 0;
padding-left: 10px;
font-style: italic;
font-weight: 400;
color: #9fa1a7;
border-left: 2px solid #696969;
p,
.paragraph {
margin-bottom: 0;
}
}
}
.commentAuthor,
.commentDate,
.commentRating {
@include font-size(1.2rem);
}
.articleAuthor {
color: #2638d9;
font-size: 12px;
margin-right: 12px;
}
.commentDate {
color: rgb(0 0 0 / 30%);
flex: 1;

View File

@ -13,18 +13,20 @@ import stylesHeader from '../Nav/Header.module.scss'
import Userpic from '../Author/Userpic'
import { useSession } from '../../context/session'
import { ReactionKind } from '../../graphql/types.gen'
import GrowingTextarea from '../_shared/GrowingTextarea'
import CommentEditor from '../_shared/CommentEditor'
import { ShowOnlyOnClient } from '../_shared/ShowOnlyOnClient'
type Props = {
comment: Reaction
compact?: boolean
reactions?: Reaction[]
isArticleAuthor?: boolean
}
const Comment = (props: Props) => {
const [isReplyVisible, setIsReplyVisible] = createSignal(false)
const [loading, setLoading] = createSignal(false)
const [errorMessage, setErrorMessage] = createSignal<string | null>(null)
const [loading, setLoading] = createSignal<boolean>(false)
const [submitted, setSubmitted] = createSignal<boolean>(false)
const { session } = useSession()
const canEdit = createMemo(() => props.comment.createdBy?.slug === session()?.user?.slug)
@ -58,12 +60,13 @@ const Comment = (props: Props) => {
}
)
setIsReplyVisible(false)
setSubmitted(true)
setLoading(false)
} catch (error) {
console.error('[handleCreate reaction]:', error)
setErrorMessage(t('Something went wrong, please try again'))
}
}
const formattedDate = createMemo(() =>
formatDate(new Date(comment()?.createdAt), { hour: 'numeric', minute: 'numeric' })
)
@ -94,6 +97,10 @@ const Comment = (props: Props) => {
/>
</div>
<Show when={props.isArticleAuthor}>
<div class={styles.articleAuthor}>{t('Author')}</div>
</Show>
<div class={styles.commentDate}>{formattedDate()}</div>
<div
class={styles.commentRating}
@ -164,14 +171,13 @@ const Comment = (props: Props) => {
</div>
<Show when={isReplyVisible()}>
<GrowingTextarea
placeholder={t('Write comment')}
submitButtonText={t('Send')}
cancelButtonText={t('cancel')}
submit={(value) => handleCreate(value)}
loading={loading()}
errorMessage={errorMessage()}
/>
<ShowOnlyOnClient>
<CommentEditor
initialValue={''}
clear={submitted()}
onSubmit={(value) => handleCreate(value)}
/>
</ShowOnlyOnClient>
</Show>
</Show>
</div>
@ -179,7 +185,13 @@ const Comment = (props: Props) => {
<Show when={props.reactions}>
<ul>
<For each={props.reactions.filter((r) => r.replyTo === props.comment.id)}>
{(reaction) => <Comment reactions={props.reactions} comment={reaction} />}
{(reaction) => (
<Comment
isArticleAuthor={props.isArticleAuthor}
reactions={props.reactions}
comment={reaction}
/>
)}
</For>
</ul>
</Show>

View File

@ -7,14 +7,21 @@ import type { Reaction } from '../../graphql/types.gen'
import { clsx } from 'clsx'
import { byCreated, byStat } from '../../utils/sortby'
import { Loading } from '../Loading'
import GrowingTextarea from '../_shared/GrowingTextarea'
import { ReactionKind } from '../../graphql/types.gen'
import { Author, ReactionKind } from '../../graphql/types.gen'
import { useSession } from '../../context/session'
import CommentEditor from '../_shared/CommentEditor'
import { ShowOnlyOnClient } from '../_shared/ShowOnlyOnClient'
const ARTICLE_COMMENTS_PAGE_SIZE = 50
const MAX_COMMENT_LEVEL = 6
export const CommentsTree = (props: { shoutSlug: string; shoutId: number }) => {
type Props = {
commentAuthors: Author[]
shoutSlug: string
shoutId: number
}
export const CommentsTree = (props: Props) => {
const [getCommentsPage, setCommentsPage] = createSignal(0)
const [commentsOrder, setCommentsOrder] = createSignal<'rating' | 'createdAt'>('createdAt')
const [isCommentsLoading, setIsCommentsLoading] = createSignal(false)
@ -47,11 +54,9 @@ export const CommentsTree = (props: { shoutSlug: string; shoutId: number }) => {
}
onMount(async () => await loadMore())
const [loading, setLoading] = createSignal<boolean>(false)
const [errorMessage, setErrorMessage] = createSignal<string | null>(null)
const [submitted, setSubmitted] = createSignal<boolean>(false)
const handleSubmitComment = async (value) => {
try {
setLoading(true)
await createReaction(
{
kind: ReactionKind.Comment,
@ -64,12 +69,12 @@ export const CommentsTree = (props: { shoutSlug: string; shoutId: number }) => {
slug: session().user.slug
}
)
setLoading(false)
setSubmitted(true)
} catch (error) {
setErrorMessage(t('Something went wrong, please try again'))
console.error('[handleCreate reaction]:', error)
}
}
return (
<div>
<Show when={!isCommentsLoading()} fallback={<Loading />}>
@ -109,20 +114,25 @@ export const CommentsTree = (props: { shoutSlug: string; shoutId: number }) => {
.reverse()
.filter((r) => !r.replyTo)}
>
{(reaction) => <Comment reactions={reactions()} comment={reaction} />}
{(reaction) => (
<Comment
isArticleAuthor={Boolean(props.commentAuthors.some((a) => a.slug === session()?.user.slug))}
reactions={reactions()}
comment={reaction}
/>
)}
</For>
</ul>
<Show when={isLoadMoreButtonVisible()}>
<button onClick={loadMore}>{t('Load more')}</button>
</Show>
<GrowingTextarea
placeholder={t('Write comment')}
submitButtonText={t('Send')}
cancelButtonText={t('cancel')}
submit={(value) => handleSubmitComment(value)}
loading={loading()}
errorMessage={errorMessage()}
/>
<ShowOnlyOnClient>
<CommentEditor
initialValue={t('Write a comment...')}
clear={submitted()}
onSubmit={(value) => handleSubmitComment(value)}
/>
</ShowOnlyOnClient>
</Show>
</div>
)

View File

@ -224,7 +224,11 @@ export const FullArticle = (props: ArticleProps) => {
)}
</For>
</div>
<CommentsTree shoutSlug={props.article?.slug} shoutId={props.article?.id} />
<CommentsTree
shoutId={props.article?.id}
shoutSlug={props.article?.slug}
commentAuthors={props.article?.authors}
/>
</div>
</div>
)

View File

@ -35,7 +35,7 @@ const CreateModalContent = (props: Props) => {
})
})
if (usersId().length > 1 && theme().length === 1) {
setTheme(t('group_chat'))
setTheme(t('Group Chat'))
}
})

View File

@ -5,12 +5,12 @@ import GroupDialogAvatar from './GroupDialogAvatar'
import formattedTime from '../../utils/formatDateTime'
import { clsx } from 'clsx'
import styles from './DialogCard.module.scss'
import { t } from '../../utils/intl'
type DialogProps = {
online?: boolean
message?: string
counter?: number
title?: string
ownId: number
members: ChatMember[]
onClick?: () => void
@ -23,6 +23,7 @@ const DialogCard = (props: DialogProps) => {
const companions = createMemo(
() => props.members && props.members.filter((member) => member.id !== props.ownId)
)
const names = createMemo(() =>
companions()
?.map((companion) => companion.name)
@ -40,14 +41,16 @@ const DialogCard = (props: DialogProps) => {
onClick={props.onClick}
>
<div class={styles.avatar}>
<Switch fallback={<DialogAvatar name={props.members[0].name} url={props.members[0].userpic} />}>
<Switch fallback={<DialogAvatar name={props.members[0].slug} url={props.members[0].userpic} />}>
<Match when={props.members.length >= 3}>
<GroupDialogAvatar users={props.members} />
</Match>
</Switch>
</div>
<div class={styles.row}>
<div class={styles.name}>{props.title}</div>
<div class={styles.name}>
{companions()?.length > 1 ? t('Group Chat') : companions()[0]?.name}
</div>
<div class={styles.message}>
<Switch>
<Match when={props.message && !props.isChatHeader}>{props.message}</Match>

View File

@ -9,7 +9,7 @@ import MessagesFallback from '../Inbox/MessagesFallback'
import QuotedMessage from '../Inbox/QuotedMessage'
import { Icon } from '../_shared/Icon'
import { useSession } from '../../context/session'
import { loadMessages, loadRecipients } from '../../stores/inbox'
import { loadRecipients } from '../../stores/inbox'
import { t } from '../../utils/intl'
import { Modal } from '../Nav/Modal'
import { showModal } from '../../stores/ui'
@ -155,7 +155,7 @@ export const InboxView = () => {
return messages().find((message) => message.id === messageId)
}
const handleKeyDown = (event) => {
const handleKeyDown = async (event) => {
if (event.keyCode === 13 && event.shiftKey) return
if (event.keyCode === 13 && !event.shiftKey && postMessageText().trim().length > 0) {
event.preventDefault()
@ -217,7 +217,6 @@ export const InboxView = () => {
<DialogCard
onClick={() => handleOpenChat(chat)}
isOpened={chat.id === currentDialog()?.id}
title={chat.title || chat.members[0].name}
members={chat.members}
ownId={currentUserId()}
lastUpdate={chat.updatedAt}

View File

@ -0,0 +1,91 @@
import styles from './styles/CommentEditor.module.scss'
import './styles/ProseMirrorOverrides.scss'
import { clsx } from 'clsx'
import Button from '../Button'
import { createEffect, createMemo, onMount } from 'solid-js'
import { t } from '../../../utils/intl'
//ProseMirror deps
import { schema } from './schema'
import { EditorState } from 'prosemirror-state'
import { EditorView } from 'prosemirror-view'
import { DOMSerializer } from 'prosemirror-model'
import { renderGrouped } from 'prosemirror-menu'
import { buildMenuItems } from './menu'
import { keymap } from 'prosemirror-keymap'
import { baseKeymap } from 'prosemirror-commands'
import { customKeymap } from '../../EditorNew/prosemirror/plugins/customKeymap'
import { placeholder } from '../../EditorNew/prosemirror/plugins/placeholder'
import { undo, redo, history } from 'prosemirror-history'
type Props = {
initialValue: string
onSubmit: (value: string) => void
clear?: boolean
}
const htmlContainer = typeof document === 'undefined' ? null : document.createElement('div')
const getHtml = (state: EditorState) => {
const fragment = DOMSerializer.fromSchema(schema).serializeFragment(state.doc.content)
htmlContainer.replaceChildren(fragment)
return htmlContainer.innerHTML
}
const CommentEditor = (props: Props) => {
const editorElRef: { current: HTMLDivElement } = { current: null }
const menuElRef: { current: HTMLDivElement } = { current: null }
const editorViewRef: { current: EditorView } = { current: null }
const initEditor = () => {
editorViewRef.current = new EditorView(editorElRef.current, {
state: EditorState.create({
schema,
plugins: [
history(),
customKeymap(),
placeholder(props.initialValue),
keymap({ 'Mod-z': undo, 'Mod-y': redo }),
keymap(baseKeymap)
]
})
})
}
onMount(() => {
initEditor()
const { dom } = renderGrouped(editorViewRef.current, buildMenuItems(schema))
menuElRef.current.appendChild(dom)
})
const handleSubmitButtonClick = () => {
props.onSubmit(getHtml(editorViewRef.current.state))
}
const clearEditor = () => {
editorViewRef.current.destroy()
initEditor()
}
createEffect(() => {
if (props.clear) clearEditor()
})
return (
<>
<div class={styles.commentEditor}>
<div
class={clsx('ProseMirrorOverrides', styles.textarea)}
ref={(el) => (editorElRef.current = el)}
/>
<div class={styles.actions}>
<div class={styles.menu} ref={(el) => (menuElRef.current = el)} />
<div class={styles.buttons}>
<Button value={t('Send')} variant="primary" onClick={handleSubmitButtonClick} />
<Button value="Cancel" variant="secondary" onClick={clearEditor} />
</div>
</div>
</div>
<div class={styles.helpText}>{'"Cmd-Z": Undo, "Cmd-Y": Redo'}</div>
</>
)
}
export default CommentEditor

View File

@ -0,0 +1 @@
export { default } from './CommentEditor'

View File

@ -0,0 +1,72 @@
import { blockTypeItem, icons, MenuItem, wrapItem } from 'prosemirror-menu'
import { toggleMark } from 'prosemirror-commands'
const markActive = (state, type) => {
const { from, $from, to, empty } = state.selection
if (empty) return type.isInSet(state.storedMarks || $from.marks())
return state.doc.rangeHasMark(from, to, type)
}
const cmdItem = (cmd, options) => {
const passedOptions = {
label: options.title,
run: cmd
}
for (const prop in options) passedOptions[prop] = options[prop]
if ((!options.enable || options.enable === true) && !options.select) {
passedOptions[options.enable ? 'enable' : 'select'] = (state) => cmd(state)
}
return new MenuItem(passedOptions)
}
const markItem = (markType, options) => {
const passedOptions = {
active(state) {
return markActive(state, markType)
},
enable: true
}
for (const prop in options) passedOptions[prop] = options[prop]
return cmdItem(toggleMark(markType), passedOptions)
}
//TODO: вывести тип для схемы
export const buildMenuItems = (schema) => {
const toggleStrong = markItem(schema.marks.strong, {
title: 'Toggle strong style',
icon: {
width: 14,
height: 16,
path: 'M9.82857 7.76C10.9371 6.99429 11.7143 5.73714 11.7143 4.57143C11.7143 1.98857 9.71428 0 7.14286 0H0V16H8.04571C10.4343 16 12.2857 14.0571 12.2857 11.6686C12.2857 9.93143 11.3029 8.44571 9.82857 7.76ZM3.42799 2.85708H6.85656C7.80513 2.85708 8.57085 3.6228 8.57085 4.57137C8.57085 5.51994 7.80513 6.28565 6.85656 6.28565H3.42799V2.85708ZM3.42799 13.1429H7.42799C8.37656 13.1429 9.14228 12.3772 9.14228 11.4286C9.14228 10.4801 8.37656 9.71434 7.42799 9.71434H3.42799V13.1429Z'
}
})
const toggleEm = markItem(schema.marks.em, {
title: 'Toggle emphasis',
icon: {
width: 14,
height: 16,
path: 'M4.39216 0V3.42857H6.81882L3.06353 12.5714H0V16H8.78431V12.5714H6.35765L10.1129 3.42857H13.1765V0H4.39216Z'
}
})
// const toggleLink = linkItem(schema.marks.link)
// const insertImage = insertImageItem(schema.nodes.image)
const wrapBlockQuote = wrapItem(schema.nodes.blockquote, {
title: 'Wrap in block quote',
icon: icons.blockquote
})
const inlineMenu = [toggleStrong, toggleEm, wrapBlockQuote]
return [inlineMenu]
}

View File

@ -0,0 +1,21 @@
import { Plugin } from 'prosemirror-state'
import { DecorationSet, Decoration } from 'prosemirror-view'
export const placeholder = (text: string): Plugin =>
new Plugin({
props: {
decorations(state) {
const { doc } = state
if (doc.childCount > 1 || !doc.firstChild.isTextblock || doc.firstChild.content.size > 0) {
return
}
const div = document.createElement('div')
div.setAttribute('contenteditable', 'false')
div.textContent = text
return DecorationSet.create(doc, [Decoration.widget(1, div)])
}
}
})

View File

@ -0,0 +1,43 @@
import { Schema } from 'prosemirror-model'
export const schema = new Schema({
nodes: {
doc: {
content: 'block+'
},
text: {
group: 'inline',
inline: true
},
paragraph: {
content: 'inline*',
group: 'block',
toDOM: function toDOM(node) {
return ['p', { class: 'paragraph' }, 0]
}
},
blockquote: {
content: 'block+',
group: 'block',
defining: true,
parseDOM: [{ tag: 'blockquote' }],
toDOM() {
return ['blockquote', 0]
}
}
},
marks: {
strong: {
toDOM() {
return ['strong', 0]
},
parseDOM: [{ tag: 'strong' }, { tag: 'b' }, { style: 'font-weight=bold' }]
},
em: {
toDOM() {
return ['em', 0]
},
parseDOM: [{ tag: 'em' }, { tag: 'i' }, { style: 'font-style=italic' }]
}
}
})

View File

@ -0,0 +1,32 @@
.commentEditor {
border: 2px solid #e8e8e8;
border-radius: 8px;
padding: 0 16px 16px;
.textarea {
min-height: 1em;
overflow: hidden;
}
.actions {
display: flex;
flex-direction: row;
justify-content: space-between;
.menu,
.buttons {
display: flex;
flex-direction: row;
}
.buttons {
gap: 10px;
}
}
}
.helpText {
font-size: 12px;
color: #696969;
margin: 12px 0;
font-style: italic;
}

View File

@ -0,0 +1,14 @@
.ProseMirrorOverrides > .ProseMirror {
.paragraph {
font-size: 15px;
line-height: 1.1em;
}
blockquote {
padding-left: 10px;
font-style: italic;
font-weight: 400;
color: #9fa1a7;
border-left: 2px solid #696969;
}
}

View File

@ -1 +0,0 @@
export { default } from './GrowingTextarea'

View File

@ -1,4 +1,4 @@
import { createContext, createSignal, useContext } from 'solid-js'
import { createContext, createEffect, createSignal, useContext } from 'solid-js'
import type { Accessor, JSX } from 'solid-js'
// import { createChatClient } from '../graphql/privateGraphQLClient'
import type { Chat, Message, MutationCreateMessageArgs } from '../graphql/types.gen'

View File

@ -6,6 +6,10 @@ export default gql`
error
chat {
id
members {
id
slug
}
}
}
}

View File

@ -9,6 +9,7 @@ export default gql`
id
slug
userpic
online
}
error
}

View File

@ -84,14 +84,6 @@ export type ChatMember = {
userpic?: Maybe<Scalars['String']>
}
export type Collab = {
authors: Array<Maybe<Scalars['String']>>
chat?: Maybe<Chat>
createdAt: Scalars['Int']
invites?: Maybe<Array<Maybe<Scalars['String']>>>
shout?: Maybe<Shout>
}
export type Collection = {
amount?: Maybe<Scalars['Int']>
createdAt: Scalars['DateTime']
@ -113,6 +105,30 @@ export type Community = {
slug: Scalars['String']
}
export type DraftCollab = {
authors: Array<Maybe<Scalars['Int']>>
body?: Maybe<Scalars['String']>
chat?: Maybe<Chat>
cover?: Maybe<Scalars['String']>
createdAt: Scalars['Int']
layout?: Maybe<Scalars['String']>
slug?: Maybe<Scalars['String']>
subtitle?: Maybe<Scalars['String']>
title?: Maybe<Scalars['String']>
topics?: Maybe<Array<Maybe<Scalars['String']>>>
updatedAt?: Maybe<Scalars['Int']>
}
export type DraftInput = {
authors?: InputMaybe<Array<InputMaybe<Scalars['Int']>>>
body?: InputMaybe<Scalars['String']>
cover?: InputMaybe<Scalars['String']>
slug?: InputMaybe<Scalars['String']>
subtitle?: InputMaybe<Scalars['String']>
title?: InputMaybe<Scalars['String']>
topics?: InputMaybe<Array<InputMaybe<Scalars['Int']>>>
}
export enum FollowingEntity {
Author = 'AUTHOR',
Community = 'COMMUNITY',
@ -167,28 +183,30 @@ export type MessagesBy = {
}
export type Mutation = {
acceptCoauthor: Result
confirmEmail: AuthResult
createChat: Result
createDraft: Result
createMessage: Result
createReaction: Result
createShout: Result
createTopic: Result
deleteChat: Result
deleteDraft: Result
deleteMessage: Result
deleteReaction: Result
deleteShout: Result
destroyTopic: Result
follow: Result
getSession: AuthResult
inviteCoauthor: Result
inviteAccept: Result
inviteAuthor: Result
markAsRead: Result
rateUser: Result
registerUser: AuthResult
removeCoauthor: Result
sendLink: Result
unfollow: Result
updateChat: Result
updateDraft: Result
updateMessage: Result
updateOnlineStatus: Result
updateProfile: Result
@ -197,10 +215,6 @@ export type Mutation = {
updateTopic: Result
}
export type MutationAcceptCoauthorArgs = {
shout: Scalars['Int']
}
export type MutationConfirmEmailArgs = {
token: Scalars['String']
}
@ -210,6 +224,10 @@ export type MutationCreateChatArgs = {
title?: InputMaybe<Scalars['String']>
}
export type MutationCreateDraftArgs = {
draft: DraftInput
}
export type MutationCreateMessageArgs = {
body: Scalars['String']
chat: Scalars['String']
@ -232,6 +250,10 @@ export type MutationDeleteChatArgs = {
chatId: Scalars['String']
}
export type MutationDeleteDraftArgs = {
draft: Scalars['Int']
}
export type MutationDeleteMessageArgs = {
chatId: Scalars['String']
id: Scalars['Int']
@ -254,9 +276,13 @@ export type MutationFollowArgs = {
what: FollowingEntity
}
export type MutationInviteCoauthorArgs = {
author: Scalars['String']
shout: Scalars['Int']
export type MutationInviteAcceptArgs = {
draft: Scalars['Int']
}
export type MutationInviteAuthorArgs = {
author: Scalars['Int']
draft: Scalars['Int']
}
export type MutationMarkAsReadArgs = {
@ -275,11 +301,6 @@ export type MutationRegisterUserArgs = {
password?: InputMaybe<Scalars['String']>
}
export type MutationRemoveCoauthorArgs = {
author: Scalars['String']
shout: Scalars['Int']
}
export type MutationSendLinkArgs = {
email: Scalars['String']
lang?: InputMaybe<Scalars['String']>
@ -295,6 +316,10 @@ export type MutationUpdateChatArgs = {
chat: ChatInput
}
export type MutationUpdateDraftArgs = {
draft: DraftInput
}
export type MutationUpdateMessageArgs = {
body: Scalars['String']
chatId: Scalars['String']
@ -345,11 +370,11 @@ export type ProfileInput = {
export type Query = {
authorsAll: Array<Maybe<Author>>
getAuthor?: Maybe<User>
getCollabs: Array<Maybe<Collab>>
getTopic?: Maybe<Topic>
isEmailUsed: Scalars['Boolean']
loadAuthorsBy: Array<Maybe<Author>>
loadChats: Result
loadDrafts: Array<Maybe<DraftCollab>>
loadMessagesBy: Result
loadReactionsBy: Array<Maybe<Reaction>>
loadRecipients: Result
@ -545,6 +570,7 @@ export type Result = {
chats?: Maybe<Array<Maybe<Chat>>>
communities?: Maybe<Array<Maybe<Community>>>
community?: Maybe<Community>
drafts?: Maybe<Array<Maybe<DraftCollab>>>
error?: Maybe<Scalars['String']>
members?: Maybe<Array<Maybe<ChatMember>>>
message?: Maybe<Message>

View File

@ -166,6 +166,7 @@
"actions": "действия",
"all topics": "все темы",
"author": "автор",
"Author": "Автор",
"authors": "авторы",
"collections": "коллекции",
"community": "сообщество",
@ -192,7 +193,7 @@
"discourse_theme": "Тема дискурса",
"cancel": "Отмена",
"Send": "Отправить",
"group_chat": "Общий чат",
"Group Chat": "Общий чат",
"Choose who you want to write to": "Выберите кому хотите написать",
"Start conversation": "Начать беседу",
"Profile settings": "Настройки профиля",
@ -218,6 +219,7 @@
"It does not look like url": "Это не похоже на ссылку",
"Something went wrong, please try again": "Что-то пошло не так, попробуйте еще раз",
"To write a comment, you must": "Чтобы написать комментарий, необходимо",
"Write a comment...": "Написать комментарий..."
"Add comment": "Комментировать",
"My subscriptions": "Подписки"
}

View File

@ -1,4 +1,4 @@
import type { Reaction, ReactionInput, User } from '../../graphql/types.gen'
import type { Reaction, ReactionInput } from '../../graphql/types.gen'
import { apiClient } from '../../utils/apiClient'
import { createSignal } from 'solid-js'
// TODO: import { roomConnect } from '../../utils/p2p'

View File

@ -296,12 +296,12 @@ export const apiClient = {
createMessage: async (options: MutationCreateMessageArgs) => {
const resp = await privateGraphQLClient.mutation(createMessage, options).toPromise()
return resp.data.createMessage
return resp.data.createMessage.message
},
getChatMessages: async (options: QueryLoadMessagesByArgs) => {
const resp = await privateGraphQLClient.query(chatMessagesLoadBy, options).toPromise()
return resp.data.loadChat
return resp.data.loadMessagesBy.messages
},
getRecipients: async (options: QueryLoadRecipientsArgs) => {
const resp = await privateGraphQLClient.query(loadRecipients, options).toPromise()