Chats in store

This commit is contained in:
ilya-bkv 2022-11-30 18:25:02 +03:00
parent a319404851
commit 4e889a2c67
7 changed files with 65 additions and 44 deletions

View File

@ -13,7 +13,7 @@ type Props = {
const CreateModalContent = (props: Props) => { const CreateModalContent = (props: Props) => {
const inviteUsers: inviteUser[] = props.users.map((user) => ({ ...user, selected: false })) const inviteUsers: inviteUser[] = props.users.map((user) => ({ ...user, selected: false }))
const [theme, setTheme] = createSignal<string>('') const [theme, setTheme] = createSignal<string>(' ')
const [slugs, setSlugs] = createSignal<string[]>([]) const [slugs, setSlugs] = createSignal<string[]>([])
const [collectionToInvite, setCollectionToInvite] = createSignal<inviteUser[]>(inviteUsers) const [collectionToInvite, setCollectionToInvite] = createSignal<inviteUser[]>(inviteUsers)
let textInput: HTMLInputElement let textInput: HTMLInputElement
@ -34,7 +34,8 @@ const CreateModalContent = (props: Props) => {
return user['slug'] return user['slug']
}) })
}) })
if (slugs().length > 2 && theme().length === 0) {
if (slugs().length > 1 && theme().length === 1) {
setTheme(t('group_chat')) setTheme(t('group_chat'))
} }
}) })
@ -51,13 +52,14 @@ const CreateModalContent = (props: Props) => {
}) })
} }
const { chatEntities, actions } = useInbox() const { actions } = useInbox()
const handleCreate = async () => { const handleCreate = async () => {
try { try {
const initChat = await actions.createChat(slugs(), theme()) const initChat = await actions.createChat(slugs(), theme())
console.debug('[initChat]', initChat) console.debug('[initChat]', initChat)
hideModal() hideModal()
await actions.loadChats()
} catch (error) { } catch (error) {
console.error(error) console.error(error)
} }
@ -66,7 +68,7 @@ const CreateModalContent = (props: Props) => {
return ( return (
<div class={styles.CreateModalContent}> <div class={styles.CreateModalContent}>
<h4>{t('create_chat')}</h4> <h4>{t('create_chat')}</h4>
{slugs().length > 2 && ( {slugs().length > 1 && (
<input <input
ref={textInput} ref={textInput}
onInput={handleSetTheme} onInput={handleSetTheme}
@ -95,7 +97,7 @@ const CreateModalContent = (props: Props) => {
onClick={handleCreate} onClick={handleCreate}
disabled={slugs().length === 0} disabled={slugs().length === 0}
> >
{slugs().length > 2 ? t('create_group') : t('create_chat')} {slugs().length > 1 ? t('create_group') : t('create_chat')}
</button> </button>
</div> </div>
</div> </div>

View File

@ -10,12 +10,14 @@ type DialogProps = {
title?: string title?: string
ownSlug: string ownSlug: string
members: ChatMember[] members: ChatMember[]
onClick: () => void
} }
const DialogCard = (props: DialogProps) => { const DialogCard = (props: DialogProps) => {
if (!props.members) return
const companions = props.members.filter((member) => member.slug !== props.ownSlug) const companions = props.members.filter((member) => member.slug !== props.ownSlug)
return ( return (
<div class={styles.DialogCard}> <div class={styles.DialogCard} onClick={props.onClick}>
<div class={styles.avatar}> <div class={styles.avatar}>
{companions.length > 2 ? ( {companions.length > 2 ? (
<GroupDialogAvatar users={companions} /> <GroupDialogAvatar users={companions} />

View File

@ -8,13 +8,14 @@ import Search from '../Inbox/Search'
import { useSession } from '../../context/session' import { useSession } from '../../context/session'
import { createClient } from '@urql/core' import { createClient } from '@urql/core'
import Message from '../Inbox/Message' import Message from '../Inbox/Message'
import { loadRecipients, loadChats } from '../../stores/inbox' import { loadRecipients, loadMessages } from '../../stores/inbox'
import { t } from '../../utils/intl' import { t } from '../../utils/intl'
import { Modal } from '../Nav/Modal' import { Modal } from '../Nav/Modal'
import { showModal } from '../../stores/ui' import { showModal } from '../../stores/ui'
import CreateModalContent from '../Inbox/CreateModalContent' import CreateModalContent from '../Inbox/CreateModalContent'
import { clsx } from 'clsx' import { clsx } from 'clsx'
import '../../styles/Inbox.scss' import '../../styles/Inbox.scss'
import { useInbox } from '../../context/inbox'
const OWNER_ID = '501' const OWNER_ID = '501'
const client = createClient({ const client = createClient({
@ -58,9 +59,12 @@ const postMessage = async (msg: string) => {
} }
export const InboxView = () => { export const InboxView = () => {
const {
chats,
actions: { loadChats }
} = useInbox()
const [messages, setMessages] = createSignal([]) const [messages, setMessages] = createSignal([])
const [recipients, setRecipients] = createSignal<Author[]>([]) const [recipients, setRecipients] = createSignal<Author[]>([])
const [chats, setChats] = createSignal<Chat[]>([])
const [cashedRecipients, setCashedRecipients] = createSignal<Author[]>([]) const [cashedRecipients, setCashedRecipients] = createSignal<Author[]>([])
const [postMessageText, setPostMessageText] = createSignal('') const [postMessageText, setPostMessageText] = createSignal('')
const [loading, setLoading] = createSignal<boolean>(false) const [loading, setLoading] = createSignal<boolean>(false)
@ -79,29 +83,21 @@ export const InboxView = () => {
} }
} }
const fetchMessages = async (query) => {
const response = await client
.query(query, {
options: { slice: { start: 0, end: 3 } }
})
.toPromise()
if (response.error) console.debug('getMessages', response.error)
setMessages(response.data.comments.data)
}
let chatWindow let chatWindow
onMount(async () => { const handleOpenChat = async (chatId) => {
setLoading(true) setLoading(true)
try { try {
await fetchMessages(messageQuery) await loadMessages({ chat: chatId })
} catch (error) { } catch (error) {
setLoading(false) setLoading(false)
console.error([fetchMessages], error) console.error('[loadMessages]', error)
} finally { } finally {
setLoading(false) setLoading(false)
chatWindow.scrollTop = chatWindow.scrollHeight chatWindow.scrollTop = chatWindow.scrollHeight
} }
}
onMount(async () => {
setLoading(true)
try { try {
const response = await loadRecipients({ days: 365 }) const response = await loadRecipients({ days: 365 })
setRecipients(response as unknown as Author[]) setRecipients(response as unknown as Author[])
@ -110,12 +106,8 @@ export const InboxView = () => {
console.log(error) console.log(error)
} }
try { await loadChats()
const response = await loadChats() console.log('!!! chats:', chats())
setChats(response as unknown as Chat[])
} catch (error) {
console.log(error)
}
}) })
const handleSubmit = async () => { const handleSubmit = async () => {
@ -198,7 +190,14 @@ export const InboxView = () => {
: chats() : chats()
} }
> >
{(chat) => <DialogCard title={chat.title} members={chat.members} ownSlug={currentSlug()} />} {(chat) => (
<DialogCard
onClick={() => handleOpenChat(chat.id)}
title={chat.title}
members={chat.members}
ownSlug={currentSlug()}
/>
)}
</For> </For>
</div> </div>
</div> </div>

View File

@ -1,13 +1,14 @@
import type { JSX } from 'solid-js' import type { Accessor, JSX } from 'solid-js'
import { createContext, useContext } from 'solid-js' import { createContext, createSignal, useContext } from 'solid-js'
import type { Message } from '../graphql/types.gen' import type { Chat } from '../graphql/types.gen'
import { apiClient } from '../utils/apiClient' import { apiClient } from '../utils/apiClient'
import { createStore } from 'solid-js/store' import { createStore } from 'solid-js/store'
type InboxContextType = { type InboxContextType = {
chatEntities: { [chatId: string]: Message[] } chats: Accessor<Chat[]>
actions: { actions: {
createChat: (members: string[], title: string) => Promise<void> createChat: (members: string[], title: string) => Promise<void>
loadChats: () => Promise<void>
} }
} }
@ -18,20 +19,33 @@ export function useInbox() {
} }
export const InboxProvider = (props: { children: JSX.Element }) => { export const InboxProvider = (props: { children: JSX.Element }) => {
const [chatEntities, setChatEntities] = createStore({}) const [chats, setChats] = createSignal<Chat[]>([])
const loadChats = async () => {
try {
const chats = await apiClient.getChats({ limit: 50, offset: 0 })
setChats(
chats.sort((x, y) => {
return x.updatedAt < y.updatedAt ? 1 : -1
})
)
} catch (error) {
console.log(error)
}
}
const createChat = async (members: string[], title: string) => { const createChat = async (members: string[], title: string) => {
const chat = await apiClient.createChat({ members, title }) const chat = await apiClient.createChat({ members, title })
setChatEntities((s) => { setChats((prevChats) => {
s[chat.id] = chat return [chat, ...prevChats]
}) })
return chat return chat
} }
const actions = { const actions = {
createChat createChat,
loadChats
} }
const value: InboxContextType = { chatEntities, actions } const value: InboxContextType = { chats, actions }
return <InboxContext.Provider value={value}>{props.children}</InboxContext.Provider> return <InboxContext.Provider value={value}>{props.children}</InboxContext.Provider>
} }

View File

@ -8,8 +8,8 @@ export default gql`
author author
body body
createdAt createdAt
id
updatedAt updatedAt
seen
} }
} }
} }

View File

@ -1,9 +1,10 @@
import { apiClient } from '../utils/apiClient' import { apiClient } from '../utils/apiClient'
import type { MessagesBy } from '../graphql/types.gen'
export const loadRecipients = async (by = {}): Promise<void> => { export const loadRecipients = async (by = {}): Promise<void> => {
return await apiClient.getRecipients(by) return await apiClient.getRecipients(by)
} }
export const loadChats = async (): Promise<void> => { export const loadMessages = async (by: MessagesBy): Promise<void> => {
return await apiClient.getChats({ limit: 50, offset: 0 }) return await apiClient.getChatMessages({ by, limit: 50, offset: 0 })
} }

View File

@ -10,7 +10,8 @@ import type {
QueryLoadMessagesByArgs, QueryLoadMessagesByArgs,
MutationCreateChatArgs, MutationCreateChatArgs,
MutationCreateMessageArgs, MutationCreateMessageArgs,
QueryLoadRecipientsArgs QueryLoadRecipientsArgs,
Chat
} from '../graphql/types.gen' } from '../graphql/types.gen'
import { publicGraphQLClient } from '../graphql/publicGraphQLClient' import { publicGraphQLClient } from '../graphql/publicGraphQLClient'
import { getToken, privateGraphQLClient } from '../graphql/privateGraphQLClient' import { getToken, privateGraphQLClient } from '../graphql/privateGraphQLClient'
@ -270,7 +271,7 @@ export const apiClient = {
}, },
// inbox // inbox
getChats: async (options: QueryLoadChatsArgs) => { getChats: async (options: QueryLoadChatsArgs): Promise<Chat[]> => {
const resp = await privateGraphQLClient.query(myChats, options).toPromise() const resp = await privateGraphQLClient.query(myChats, options).toPromise()
return resp.data.loadChats.chats return resp.data.loadChats.chats
}, },
@ -287,8 +288,10 @@ export const apiClient = {
getChatMessages: async (options: QueryLoadMessagesByArgs) => { getChatMessages: async (options: QueryLoadMessagesByArgs) => {
const resp = await privateGraphQLClient.query(chatMessagesLoadBy, options).toPromise() const resp = await privateGraphQLClient.query(chatMessagesLoadBy, options).toPromise()
return resp.data.loadChat console.log('!!! resp:', resp)
// return resp.data.loadChat
}, },
getRecipients: async (options: QueryLoadRecipientsArgs) => { getRecipients: async (options: QueryLoadRecipientsArgs) => {
const resp = await privateGraphQLClient.query(loadRecipients, options).toPromise() const resp = await privateGraphQLClient.query(loadRecipients, options).toPromise()
return resp.data.loadRecipients.members return resp.data.loadRecipients.members