chats
This commit is contained in:
Vendored
+1
@@ -9,6 +9,7 @@ declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
Button: typeof import('primevue/button')['default']
|
||||
Card: typeof import('primevue/card')['default']
|
||||
ChatCard: typeof import('./src/components/ChatCard.vue')['default']
|
||||
ChatComponent: typeof import('./src/components/ChatComponent.vue')['default']
|
||||
ChatSubscribeWebPush: typeof import('./src/components/ChatSubscribeWebPush.vue')['default']
|
||||
Checkbox: typeof import('primevue/checkbox')['default']
|
||||
|
||||
@@ -19,6 +19,7 @@ export const getLocalDb = <T extends BaseDocument>(dbName: DB_NAMES) => new Pouc
|
||||
export const qrCodeDbRemote = getRemoteDb<QRCodeDocument>(DB_NAMES.QR)
|
||||
export const qrCodeDbLocal = getLocalDb<QRCodeDocument>(DB_NAMES.QR)
|
||||
export const messagesDbLocal = getLocalDb<MessageDocument>(DB_NAMES.MESSAGES)
|
||||
export const chatsDbLocal = getLocalDb<ChatDocument>(DB_NAMES.CHATS)
|
||||
export const chatsDbRemote = getRemoteDb<ChatDocument>(DB_NAMES.CHATS)
|
||||
export const webPushSubscriptionsDbRemote = getRemoteDb<
|
||||
WebPushSubscriptionDocument<PushSubscriptionJSON>
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<RouterLink :to="route" class="p-4 rounded-lg bg-white shadow-md" v-if="chatDoc.qr_code_uri">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<div class="flex items-center">
|
||||
<h2 class="text-lg font-semibold">{{ chatDoc.name }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-gray-500">
|
||||
<span class="text-nowrap">{{ formatedCreatedAt }}</span>
|
||||
</div>
|
||||
</RouterLink>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import type { ChatDocument } from '@hereconnect/types'
|
||||
import { ROUTE_NAMES } from '@/constants/routes'
|
||||
|
||||
const props = defineProps<{
|
||||
chatDoc: ChatDocument
|
||||
}>()
|
||||
|
||||
const formatDate = (date: string) => {
|
||||
// Форматирование даты
|
||||
const options: Intl.DateTimeFormatOptions = {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
}
|
||||
return new Date(date).toLocaleDateString(['ru-RU'], options)
|
||||
}
|
||||
|
||||
const route = computed(() => {
|
||||
return {
|
||||
name:
|
||||
props.chatDoc.role === 'owner' ? ROUTE_NAMES.MANAGE_QR_CODE_CHAT : ROUTE_NAMES.PUBLIC_CHAT,
|
||||
params: { qr_code_uri: props.chatDoc.qr_code_uri, chat: props.chatDoc.chat },
|
||||
}
|
||||
})
|
||||
|
||||
const formatedCreatedAt = computed(() => formatDate(props.chatDoc.created_at))
|
||||
</script>
|
||||
@@ -52,8 +52,13 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, useTemplateRef, watch, nextTick } from 'vue'
|
||||
import { messagesDbLocal as db, messagesDbRemote as remoteDb } from '@/api/dbs'
|
||||
import { type MessageDocument } from '@hereconnect/types'
|
||||
import {
|
||||
chatsDbLocal,
|
||||
chatsDbRemote,
|
||||
messagesDbLocal as db,
|
||||
messagesDbRemote as remoteDb,
|
||||
} from '@/api/dbs'
|
||||
import { type ChatDocument, type MessageDocument } from '@hereconnect/types'
|
||||
import { getBrowserUuid } from '@/utils/getBrowserUuid'
|
||||
import { getUserUuid } from '@/utils/getUserUuid'
|
||||
|
||||
@@ -70,7 +75,8 @@ const { qr_code_uri, chat, userRole } = defineProps<{
|
||||
const messages = ref<MessageDocument[]>([])
|
||||
const newMessage = ref('')
|
||||
let changesSubscription: PouchDB.Core.Changes<MessageDocument> | null = null
|
||||
let syncHandler: PouchDB.Replication.Sync<MessageDocument> | null = null
|
||||
let syncMessages: PouchDB.Replication.Sync<MessageDocument> | null = null
|
||||
// let syncChats: PouchDB.Replication.Sync<ChatDocument> | null = null
|
||||
|
||||
// Селектор для фильтрации сообщений
|
||||
const messageSelector = {
|
||||
@@ -95,6 +101,7 @@ async function loadMessages() {
|
||||
// Отправка нового сообщения
|
||||
async function sendMessage() {
|
||||
const created_at = new Date().toISOString()
|
||||
const user_uuid = getUserUuid()
|
||||
const message: MessageDocument = {
|
||||
_id: `message:${qr_code_uri}:${chat}:${created_at}`,
|
||||
type: 'message',
|
||||
@@ -103,13 +110,22 @@ async function sendMessage() {
|
||||
from: userRole,
|
||||
body: newMessage.value.trim(),
|
||||
browser_uuid: getBrowserUuid(),
|
||||
user_uuid: getUserUuid(),
|
||||
user_uuid,
|
||||
created_at,
|
||||
}
|
||||
|
||||
try {
|
||||
await db.put(message)
|
||||
newMessage.value = ''
|
||||
|
||||
// await chatsDbLocal.upsert(`chat:${user_uuid}:${userRole}:${qr_code_uri}:${chat}`, (chatDoc) => {
|
||||
// if (chatDoc.last_message_at && chatDoc.last_message_at < created_at) {
|
||||
// chatDoc.last_message_at = created_at
|
||||
// return chatDoc
|
||||
// } else {
|
||||
// return false
|
||||
// }
|
||||
// })
|
||||
} catch (error) {
|
||||
console.error('Ошибка отправки сообщения:', error)
|
||||
}
|
||||
@@ -145,22 +161,35 @@ function watchChanges() {
|
||||
|
||||
// Настройка синхронизации
|
||||
function setupSync() {
|
||||
syncHandler = db.sync(remoteDb, {
|
||||
syncMessages = db.sync(remoteDb, {
|
||||
live: true,
|
||||
retry: true,
|
||||
selector: messageSelector,
|
||||
})
|
||||
syncHandler.on('error', (err) => {
|
||||
syncMessages.on('error', (err) => {
|
||||
console.error('Ошибка синхронизации:', err)
|
||||
})
|
||||
// syncChats = chatsDbLocal.sync(chatsDbRemote, {
|
||||
// live: true,
|
||||
// retry: true,
|
||||
// selector: {
|
||||
// type: 'chat',
|
||||
// qr_code_uri,
|
||||
// chat,
|
||||
// },
|
||||
// })
|
||||
}
|
||||
|
||||
// Остановка синхронизации
|
||||
function stopSync() {
|
||||
if (syncHandler) {
|
||||
syncHandler.cancel()
|
||||
syncHandler = null
|
||||
if (syncMessages) {
|
||||
syncMessages.cancel()
|
||||
syncMessages = null
|
||||
}
|
||||
// if (syncChats) {
|
||||
// syncChats.cancel()
|
||||
// syncChats = null
|
||||
// }
|
||||
}
|
||||
|
||||
// Отписка от изменений
|
||||
|
||||
@@ -80,9 +80,12 @@ async function sendMessage(content: string) {
|
||||
type: 'chat',
|
||||
qr_code_uri: doc.uri,
|
||||
role: 'guest',
|
||||
// unread_messages_count: 0,
|
||||
chat,
|
||||
created_at,
|
||||
user_uuid,
|
||||
to_user_uuid: doc.user_uuid,
|
||||
created_at,
|
||||
// last_message_at: created_at,
|
||||
}
|
||||
|
||||
const chatOwnerDoc: ChatDocument = {
|
||||
@@ -91,8 +94,11 @@ async function sendMessage(content: string) {
|
||||
qr_code_uri: doc.uri,
|
||||
role: 'owner',
|
||||
chat,
|
||||
created_at,
|
||||
// unread_messages_count: 1,
|
||||
user_uuid: doc.user_uuid,
|
||||
to_user_uuid: user_uuid,
|
||||
created_at,
|
||||
// last_message_at: created_at,
|
||||
}
|
||||
|
||||
const message: MessageDocument = {
|
||||
@@ -109,6 +115,7 @@ async function sendMessage(content: string) {
|
||||
|
||||
await Promise.all([
|
||||
chatsDbRemote.bulkDocs([chatGuestDoc, chatOwnerDoc]),
|
||||
|
||||
// Сохраняем сообщение в локальную базу данных
|
||||
db.put(message),
|
||||
])
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
<template #default="{ data }">
|
||||
<div
|
||||
v-if="data.rows.length > 0"
|
||||
class="flex flex-col gap-5 my-4 grid grid-cols-1 sm:grid-cols-3 gap-4"
|
||||
class="justify-self-start align-baseline-start flex flex-col gap-4"
|
||||
>
|
||||
<ChatCard
|
||||
v-for="{ doc: chatDoc } in data.rows.filter((row) => !!row.doc)"
|
||||
:key="`${chatDoc!._id}`"
|
||||
:chatDoc="chatDoc!"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-else class="place-self-center">
|
||||
<h1 class="text-2xl font-bold mb-4 text-gray-500">Чаты в разработке</h1>
|
||||
<h1 class="text-2xl font-bold mb-4 text-gray-500">У вас пока нет чатов</h1>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -38,11 +44,19 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useQuery } from '@tanstack/vue-query'
|
||||
import { chatsDbRemote } from '@/api/dbs'
|
||||
import { getUserUuid } from '@/utils/getUserUuid'
|
||||
|
||||
const query = useQuery({
|
||||
queryKey: ['qrCodes'],
|
||||
queryFn: async () => {
|
||||
return { rows: [] } as const
|
||||
queryFn: () => {
|
||||
const user_uuid = getUserUuid()
|
||||
return chatsDbRemote.allDocs({
|
||||
startkey: `chat:${user_uuid}:`,
|
||||
endkey: `chat:${user_uuid}:\uffff`,
|
||||
limit: Number.MAX_SAFE_INTEGER,
|
||||
include_docs: true,
|
||||
})
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -6,6 +6,9 @@ import type { Role } from "./Role";
|
||||
* Используется для хранения чатов, отправленных через QR‑код.
|
||||
*/
|
||||
export interface ChatDocument extends BaseDocument {
|
||||
/** Идентификатор документа */
|
||||
_id: string;
|
||||
|
||||
/** Тип документа, всегда 'chat' */
|
||||
type: "chat";
|
||||
|
||||
@@ -20,4 +23,13 @@ export interface ChatDocument extends BaseDocument {
|
||||
|
||||
/** Идентификатор пользователя, которому принадлежит чат */
|
||||
user_uuid: string;
|
||||
|
||||
// /** Количество непрочитанных сообщений в чате */
|
||||
// unread_messages_count: number;
|
||||
|
||||
// /** Дата последнего сообщения в чате */
|
||||
// last_message_at: string;
|
||||
|
||||
/** Идентификатор пользователя, которому адресован чат */
|
||||
to_user_uuid: string;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user