39 KiB
Chat API Documentation
Обзор
Система чата является комплексным решением для обмена сообщениями в CRM системе, поддерживающим множественные провайдеры (WhatsApp, Telegram, Messenger и др.), персональные и групповые чаты, а также интеграцию с сущностями системы.
Архитектура
Компоненты системы
-
Backend (NestJS)
- REST API для управления чатами
- WebSocket для real-time сообщений
- Интеграция с внешними провайдерами
-
Frontend (React/TypeScript)
- Веб-интерфейс для управления чатами
- Модальные окна и встроенные компоненты
-
Android приложение
- Мобильный клиент для Android устройств
- Полная функциональность чата
-
База данных
- PostgreSQL с TypeORM
- Комплексная схема для чатов, сообщений, пользователей
Backend API
Детальная спецификация API
MultichatController (/chat)
Основной контроллер для общих операций с чатами.
@ApiTags('multichat')
@Controller('chat')
@JwtAuthorized()
export class MultichatController {
// Получение количества непрочитанных сообщений
@Get('unseen-count')
async getUnseenCount(): Promise<number>
// Обновление статуса сообщений для всех чатов
@Put('status/:status')
async updateMessagesStatus()
}
GET /chat/unseen-count
Описание: Получить общее количество непрочитанных сообщений для текущего пользователя.
Аутентификация: JWT токен обязательна
Параметры: Нет
Ответ:
{
"statusCode": 200,
"data": 5
}
PUT /chat/status/{status}
Описание: Обновить статус всех сообщений во всех чатах пользователя.
Аутентификация: JWT токен обязательна
Параметры пути:
status(string): Новый статус (received/seen)
Тело запроса:
{
"accountId": 1,
"user": {...},
"status": "seen"
}
Ответ:
{
"statusCode": 200,
"message": "Messages status updated"
}
ChatController (/chat/chats)
Контроллер для операций с конкретными чатами.
Создание чатов:
POST /personal- персональный чатPOST /group- групповой чатPOST /external- внешний чат
Получение чатов:
GET /- список чатов с пагинациейGET /find- простой поискGET /find/full- полный поиск с дополнительными даннымиGET /find/full/personal- поиск по имени пользователяGET /find/full/by-message-content- поиск по содержимому сообщенийGET /:chatId- получение конкретного чата
Управление чатами:
PATCH /group/:chatId- обновление группового чатаDELETE /:chatId- удаление чатаPUT /:chatId/pin/:messageId- закрепление сообщенияPUT /:chatId/unpin/:messageId- открепление сообщенияPUT /:chatId/status/:status- обновление статуса сообщений в чате
Дополнительные операции:
POST /:chatId/contact- создание контакта и лида
ChatMessageController (/chat/chats/:chatId/messages)
Контроллер для работы с сообщениями в чате.
Операции с сообщениями:
POST /- отправка сообщенияGET /- получение списка сообщенийGET /:messageId- получение конкретного сообщенияPUT /:messageId- редактирование сообщенияDELETE /:messageId- удаление сообщения
Статусы сообщений:
POST /status/:status- обновление статуса нескольких сообщенийPUT /:messageId/status/:status- обновление статуса одного сообщения
Реакции:
PUT /:messageId/react/:reaction- добавление реакцииPUT /:messageId/unreact/:reactionId- удаление реакции
ChatProviderController (/chat/providers)
Контроллер для работы с провайдерами чатов.
@ApiTags('multichat/providers')
@Controller('chat/providers')
@JwtAuthorized()
export class ChatProviderController {
@Get()
async findMany(): Promise<ChatProviderDto[]>
}
Модели данных
Chat (Чат)
export class ChatDto {
id: number; // ID чата
providerId: number; // ID провайдера
createdBy: number; // ID создателя
externalId: string | null; // Внешний ID
type: ChatType; // Тип чата (PERSONAL/GROUP)
title: string | null; // Название
entityId: number | null; // ID связанной сущности
createdAt: string; // Дата создания
users: ChatUserDto[]; // Пользователи чата
pinnedMessages: ChatMessageDto[]; // Закрепленные сообщения
lastMessage: ChatMessageDto | null; // Последнее сообщение
unseenCount: number; // Количество непрочитанных
updatedAt: string; // Дата обновления
entityInfo: EntityInfoDto | null; // Информация о сущности
hasAccess?: boolean | null; // Доступ пользователя
}
ChatMessage (Сообщение)
export class ChatMessageDto {
id: number; // ID сообщения
chatId: number; // ID чата
chatUserId: number; // ID пользователя чата
text: string | null; // Текст сообщения
replyToId: number | null; // ID сообщения-ответа
createdAt: string; // Дата создания
files: ChatMessageFileDto[]; // Прикрепленные файлы
reactions: ChatMessageReactionDto[]; // Реакции
status: ChatMessageStatus; // Статус для текущего пользователя
}
ChatUser (Пользователь чата)
export class ChatUserDto {
id: number; // ID в чате
chatId: number; // ID чата
userId: number | null; // ID пользователя системы
role: ChatUserRole; // Роль в чате
name: string | null; // Имя
avatarUrl: string | null; // URL аватара
}
ChatProvider (Провайдер)
export class ChatProviderDto {
id: number; // ID провайдера
type: ChatProviderType; // Тип провайдера
title: string; // Название
status: ChatProviderStatus; // Статус
transport: ChatProviderTransport; // Транспорт
unseenCount: number; // Непрочитанные сообщения
}
Статусы и типы
ChatType
export enum ChatType {
PERSONAL = 'personal', // Персональный чат между двумя пользователями
GROUP = 'group' // Групповой чат с множеством участников
}
ChatMessageStatus
export enum ChatMessageStatus {
RECEIVED = 'received', // Сообщение получено
SEEN = 'seen' // Сообщение просмотрено
}
ChatProviderType
export enum ChatProviderType {
Amwork = 'amwork', // Внутренняя система Amwork
Twilio = 'twilio', // Twilio WhatsApp
Facebook = 'facebook', // Facebook Messenger
Wazzup = 'wazzup' // Wazzup WhatsApp
}
ChatProviderTransport
export enum ChatProviderTransport {
Amwork = 'amwork', // Внутренняя система
Whatsapp = 'whatsapp', // WhatsApp
Messenger = 'messenger', // Facebook Messenger
Telegram = 'telegram', // Telegram
Instagram = 'instagram', // Instagram
Vk = 'vk', // VKontakte
Avito = 'avito' // Avito
}
ChatProviderStatus
export enum ChatProviderStatus {
Draft = 'draft', // Черновик настройки
Active = 'active', // Активен
Inactive = 'inactive', // Неактивен
Deleted = 'deleted' // Удален
}
ChatUserRole
export enum ChatUserRole {
OWNER = 'owner', // Владелец чата
ADMIN = 'admin', // Администратор
SUPERVISOR = 'supervisor', // Супервайзер
USER = 'user', // Обычный пользователь
EXTERNAL = 'external' // Внешний пользователь
}
DTOs для создания чатов
CreatePersonalChatDto
export class CreatePersonalChatDto {
@ApiProperty({ description: 'Provider ID' })
@IsNumber()
providerId: number;
@ApiProperty({ description: 'User ID of chat companion' })
@IsNumber()
companionId: number;
}
Пример запроса:
{
"providerId": 1,
"companionId": 123
}
CreateGroupChatDto
export class CreateGroupChatDto {
@ApiProperty({ description: 'Provider ID' })
@IsNumber()
providerId: number;
@ApiProperty({ description: 'Chat title' })
@IsString()
title: string;
@ApiProperty({ description: 'User IDs of chat participants', type: [Number] })
@IsArray()
participantIds: number[];
@ApiPropertyOptional({ description: 'Entity ID associated with the chat', nullable: true })
@IsOptional()
@IsNumber()
entityId?: number | null;
}
Пример запроса:
{
"providerId": 1,
"title": "Проект Alpha",
"participantIds": [123, 456, 789],
"entityId": 1001
}
DTOs для сообщений
SendChatMessageDto
export class SendChatMessageDto {
@ApiPropertyOptional()
@IsOptional()
@IsNumber()
replyToId?: number | null;
@ApiProperty()
@IsString()
text: string;
@ApiPropertyOptional({ nullable: true })
@IsOptional()
@IsArray()
fileIds?: string[] | null;
}
Пример запроса:
{
"text": "Привет, как дела?",
"replyToId": 123,
"fileIds": ["file_123", "file_456"]
}
База данных
Основные таблицы
chat
CREATE TABLE public.chat (
id integer NOT NULL,
provider_id integer NOT NULL,
created_by integer,
external_id character varying,
type character varying NOT NULL,
title character varying,
entity_id integer,
account_id integer NOT NULL,
created_at timestamp without time zone NOT NULL
);
chat_message
CREATE TABLE public.chat_message (
id integer NOT NULL,
chat_id integer NOT NULL,
chat_user_id integer NOT NULL,
external_id character varying,
text text,
account_id integer NOT NULL,
created_at timestamp without time zone NOT NULL,
reply_to_id integer
);
chat_user
CREATE TABLE public.chat_user (
id integer NOT NULL,
chat_id integer NOT NULL,
user_id integer,
role character varying NOT NULL,
account_id integer NOT NULL
);
chat_provider
CREATE TABLE public.chat_provider (
id integer NOT NULL,
created_by integer,
type character varying NOT NULL,
title character varying NOT NULL,
account_id integer NOT NULL,
created_at timestamp without time zone NOT NULL,
status character varying NOT NULL,
transport character varying NOT NULL
);
chat_message_reaction
CREATE TABLE public.chat_message_reaction (
id integer NOT NULL,
message_id integer NOT NULL,
chat_user_id integer NOT NULL,
reaction character varying NOT NULL,
account_id integer NOT NULL,
created_at timestamp without time zone NOT NULL
);
chat_message_user_status
CREATE TABLE public.chat_message_user_status (
chat_id integer NOT NULL,
message_id integer NOT NULL,
chat_user_id integer NOT NULL,
status character varying NOT NULL,
account_id integer NOT NULL,
created_at timestamp without time zone NOT NULL
);
Frontend
Архитектура компонентов
Система чата построена на базе React с использованием контекстов для управления состоянием и кастомных хуков для работы с API.
MultichatProvider
Контекст-провайдер для глобального управления состоянием чата в приложении.
Ключевые свойства:
interface MultichatContextValue {
// Видимость модальных окон
opened: boolean;
pageOpened: boolean;
hide: () => void;
toggle: () => void;
// Активный чат
activeChatId: number | null;
activeProviderId: number | null;
setActiveChatId: (id: number | null) => void;
setActiveProviderId: (id: number | null) => void;
// Управление сообщениями
editMessageId: number | null;
replyToId: number | null;
setEditMessageId: (id: number | null) => void;
setReplyToId: (id: number | null) => void;
// Навигация
show: (params: { activeChatId?: number; activeProviderId?: number }) => void;
openPage: (returnUrl?: string) => void;
closePage: () => void;
}
Использование:
const { show, opened, activeChatId } = useMultichatContext();
// Открыть чат
show({ activeChatId: 123, activeProviderId: 1 });
// Проверить видимость
if (opened) {
// Показать модальное окно
}
MultichatModal
Модальное окно для отображения интерфейса чата в модальном режиме.
Особенности:
- Перетаскиваемое и изменяемое по размеру
- Адаптивный дизайн
- Сохранение позиции и размера
- Интеграция с основным UI
Props:
interface MultichatModalProps {
children?: ReactNode;
modalBounds?: DraggableResizableControlBounds;
setModalBounds?: (bounds: DraggableResizableControlBounds) => void;
}
MultichatControl
Основной контейнер управления чатом с боковой панелью и областью сообщений.
Структура:
MultichatControl
├── MultichatControlHeader (при модальном просмотре)
├── ChatsSidebar
│ ├── ChatList
│ ├── CreateAmworkChatButton
│ └── ProviderSelector
└── ChatMessagesPanel
├── ChatMessagesPanelHeader
├── ChatMessagesList
└── SendChatMessageBlock
ChatMessagesPanel
Компонент для отображения и управления сообщениями в чате.
Ключевые функции:
- Ленивая загрузка сообщений
- Автоматическая прокрутка к новым сообщениям
- Отметка сообщений как прочитанные
- Обработка реакций и ответов
Props:
interface ChatMessagesPanelProps {
activeChatId: number;
mobileView?: boolean;
providers?: ChatProvider[];
activeProvider?: ChatProvider;
modalWidth?: string;
onBack?: () => void;
}
SendChatMessageBlock
Компонент для отправки сообщений с поддержкой различных типов контента.
Возможности:
- Текстовые сообщения
- Файловые вложения (drag & drop)
- Ответы на сообщения
- Редактирование сообщений
- Отправка через Enter или кнопку
Состояния:
- Обычное сообщение
- Ответ на сообщение
- Редактирование сообщения
- Отправка файла
Кастомные хуки
useGetChat
Получение данных о конкретном чате.
const { data: chat, isLoading, error } = useGetChat(chatId);
useGetChatMessages
Получение сообщений чата с пагинацией.
const {
data: messages,
hasNextPage,
fetchNextPage,
isLoading
} = useGetChatMessages(chatId);
useSendChatMessage
Отправка сообщений в чат.
const { mutateAsync: sendMessage, isPending } = useSendChatMessage({
chatId,
providerId
});
// Отправка
await sendMessage({
text: "Привет!",
fileIds: ["file_123"]
});
useCreateGroupChat
Создание группового чата.
const { mutateAsync: createChat } = useCreateGroupChat();
// Создание
const newChat = await createChat({
providerId: 1,
title: "Новый проект",
participantIds: [123, 456]
});
API интеграция
ChatApi
Основной API клиент для работы с чатами:
export const chatApi = {
// Получение чатов
getChats: (params: CursorPagingQuery) =>
api.get('/chat/chats', { params }),
getChat: (chatId: number) =>
api.get(`/chat/chats/${chatId}`),
// Создание чатов
createPersonalChat: (data: CreatePersonalChatDto) =>
api.post('/chat/chats/personal', data),
createGroupChat: (data: CreateGroupChatDto) =>
api.post('/chat/chats/group', data),
createExternalChat: (data: CreateExternalChatDto) =>
api.post('/chat/chats/external', data),
// Поиск чатов
findChats: (params: { filter: ChatFindFilterDto; paging: PagingQuery }) =>
api.get('/chat/chats/find', { params }),
findChatsFull: (params: { filter: ChatFindFilterDto; paging: PagingQuery }) =>
api.get('/chat/chats/find/full', { params }),
// Сообщения
getChatMessages: (chatId: number, params: ChatMessagesFilterDto & PagingQuery) =>
api.get(`/chat/chats/${chatId}/messages`, { params }),
sendMessage: (chatId: number, data: SendChatMessageDto) =>
api.post(`/chat/chats/${chatId}/messages`, data),
updateMessage: (chatId: number, messageId: number, data: SendChatMessageDto) =>
api.put(`/chat/chats/${chatId}/messages/${messageId}`, data),
deleteMessage: (chatId: number, messageId: number) =>
api.delete(`/chat/chats/${chatId}/messages/${messageId}`),
// Статусы
markAllChatMessagesAsRead: (chatId: number) =>
api.put(`/chat/chats/${chatId}/status/read`),
updateMessageStatus: (chatId: number, messageId: number, status: ChatMessageStatus) =>
api.put(`/chat/chats/${chatId}/messages/${messageId}/status/${status}`),
// Реакции
reactToMessage: (chatId: number, messageId: number, reaction: string) =>
api.put(`/chat/chats/${chatId}/messages/${messageId}/react/${reaction}`),
unreactToMessage: (chatId: number, messageId: number, reactionId: number) =>
api.put(`/chat/chats/${chatId}/messages/${messageId}/unreact/${reactionId}`),
// Управление чатами
updateGroupChat: (chatId: number, data: UpdateGroupChatDto) =>
api.patch(`/chat/chats/group/${chatId}`, data),
deleteChat: (chatId: number) =>
api.delete(`/chat/chats/${chatId}`),
pinMessage: (chatId: number, messageId: number) =>
api.put(`/chat/chats/${chatId}/pin/${messageId}`),
unpinMessage: (chatId: number, messageId: number) =>
api.put(`/chat/chats/${chatId}/unpin/${messageId}`),
// Провайдеры
getChatProviders: () =>
api.get('/chat/providers'),
// Счетчики
getUnseenCount: () =>
api.get('/chat/unseen-count'),
};
React Query интеграция
Система использует React Query для кеширования и синхронизации данных:
// Ключи запросов
export const MULTICHAT_QUERY_KEYS = {
chats: ['multichat', 'chats'] as const,
chat: (chatId: number) => ['multichat', 'chats', chatId] as const,
chatMessages: (chatId: number) => ['multichat', 'chats', chatId, 'messages'] as const,
chatProviders: ['multichat', 'providers'] as const,
unseenCount: ['multichat', 'unseen-count'] as const,
} as const;
// Инвалидация кеша
queryClient.invalidateQueries({ queryKey: MULTICHAT_QUERY_KEYS.chats });
Стилизация
Компоненты используют styled-components с поддержкой тем:
const Root = styled.div`
background-color: var(--graphite-graphite-20);
border-radius: 8px;
${p => p.$mobileView && css`
width: calc(100vw - var(--sidebar-width));
`}
`;
Обработка событий
Система поддерживает real-time обновления через WebSocket события:
// Обработчик событий чата
const chatEventHandler = {
subscribe: (context: MultichatContextValue) => {
// Подписка на события
},
unsubscribe: () => {
// Отписка от событий
}
};
Android приложение
Архитектура
Приложение построено на базе MVVM архитектуры с использованием Android Architecture Components:
- Activities/Fragments - представление данных
- ViewModels - бизнес-логика и управление состоянием
- Repositories - абстракция доступа к данным
- Retrofit - HTTP клиент для API
- Room - локальная база данных (опционально)
- WorkManager - фоновая синхронизация
Основные Activity
ChatActivity
Основная активность для отображения чата с полным жизненным циклом управления.
Жизненный цикл:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityChatBinding.inflate(layoutInflater)
setContentView(binding.root)
// Инициализация ViewModel
viewModel.initialize(serverUrl, token, apiKey, chatId)
// Настройка UI компонентов
setupViews()
observeViewModel()
observeAddressBook()
}
override fun onResume() {
super.onResume()
viewModel.setChatActive(true) // Активация чата
}
override fun onPause() {
super.onPause()
viewModel.setChatActive(false) // Деактивация чата
}
Основные функции:
- Отображение списка сообщений с
RecyclerView - Отправка текстовых сообщений
- Отправка файлов через
FilePicker - Ответы на сообщения с визуальным индикатором
- Автоматическая отметка сообщений как прочитанные при прокрутке
- Управление прикрепленными файлами
Ключевые компоненты:
MessageAdapter- адаптер дляRecyclerViewс поддержкой разных типов сообщенийChatViewModel- управление состоянием чата и бизнес-логикойNotificationHelper- обработка push-уведомленийBackgroundSyncWorker- фоновая синхронизация
MainActivity
Главная активность с навигацией и списком чатов.
Особенности:
BottomNavigationViewдля переключения разделовSwipeRefreshLayoutдля обновления списка чатовFloatingActionButtonдля создания новых чатов- Управление жизненным циклом всех чатов
CreateChatActivity
Активность для создания новых чатов с пошаговым мастером.
Этапы создания:
- Выбор типа чата (персональный/групповой)
- Выбор участников через
UserSelectionActivity - Настройка параметров чата
- Создание и переход к чату
ViewModels
ChatViewModel
Управляет состоянием конкретного чата и сообщениями.
Состояния:
sealed class ChatState {
object Loading : ChatState()
data class Success(val chat: Chat) : ChatState()
data class Error(val message: String) : ChatState()
}
sealed class MessagesState {
object Loading : MessagesState()
data class Success(val messages: List<ChatMessage>) : MessagesState()
data class Error(val message: String) : MessagesState()
}
sealed class SendMessageState {
object Loading : SendMessageState()
object Success : SendMessageState()
data class Error(val message: String) : SendMessageState()
}
Ключевые методы:
// Загрузка данных чата
fun refreshChat()
// Загрузка сообщений
fun refreshMessages()
// Отправка сообщения
fun sendMessage(text: String, replyToMessage: ChatMessage?, fileIds: List<String>? = null)
// Отправка файла
fun sendFileMessage(uri: Uri, contentResolver: ContentResolver)
// Отметка как прочитанное
fun markMessagesAsRead()
// Управление активностью чата
fun setChatActive(active: Boolean)
MainViewModel
Глобальная ViewModel для управления приложением.
Функции:
- Управление списком чатов
- Кеширование данных пользователей (адресная книга)
- Синхронизация состояния между активностями
- Управление подключением к серверу
Ключевые методы:
// Получение имени пользователя
fun getUserName(userId: Long): String
// Получение URL аватара
fun getUserAvatarUrl(userId: Long): String?
// Уведомление об обновлении чата
fun notifyChatUpdated(chatId: Long)
// Управление адресной книгой
fun refreshAddressBook()
Репозитории
ChatRepository
Репозиторий для работы с API чатов с поддержкой кеширования.
Основные методы:
suspend fun getChats(): Result<List<Chat>>
suspend fun getChat(chatId: Long): Result<Chat>
suspend fun getMessages(chatId: Long, limit: Int = 50, offset: Long? = null): Result<List<ChatMessage>>
suspend fun sendMessage(chatId: Long, message: SendChatMessageDto): Result<ChatMessage>
suspend fun uploadFile(uri: Uri, contentResolver: ContentResolver): Result<List<UploadedFile>>
suspend fun markAsRead(chatId: Long): Result<Unit>
suspend fun updateMessageStatus(chatId: Long, messageId: Long, status: ChatMessageStatus): Result<Unit>
Обработка ошибок:
sealed class Result<T> {
data class Success<T>(val data: T) : Result<T>()
data class Failure<T>(val exception: Throwable) : Result<T>()
}
Модели данных
ChatRequests.kt
DTO для запросов к API:
data class CreatePersonalChatRequest(
val providerId: Long,
val companionId: Long
)
data class CreateGroupChatRequest(
val providerId: Long,
val title: String,
val participantIds: List<Long>,
val entityId: Long? = null
)
data class UpdateGroupChatRequest(
val title: String? = null,
val participantIds: List<Long>? = null
)
ChatModels.kt
Основные модели данных приложения:
data class Chat(
val id: Long,
val providerId: Long,
val type: String,
val title: String?,
val users: List<ChatUserItem>,
val lastMessage: ChatMessage?,
val unseenCount: Int,
val createdAt: String
)
data class ChatMessage(
val id: Long,
val chatId: Long,
val chatUserId: Long,
val text: String?,
val replyToId: Long?,
val files: List<ChatMessageFile>,
val reactions: List<ChatMessageReaction>,
val status: ChatMessageStatus,
val createdAt: String
)
data class ChatUserItem(
val id: Long,
val userId: Long?,
val name: String?,
val avatarUrl: String?
)
UI Компоненты
MessageAdapter
Адаптер для отображения сообщений в RecyclerView.
Типы ViewHolder:
TextMessageViewHolder- текстовые сообщенияFileMessageViewHolder- сообщения с файламиReplyMessageViewHolder- ответы на сообщенияSystemMessageViewHolder- системные сообщения
Особенности:
- Поддержка разных типов сообщений через
getItemViewType() - Оптимизация производительности с
DiffUtil - Обработка кликов и долгого нажатия
- Анимации для новых сообщений
MessageAdapter.kt
class MessageAdapter(
private val getUserName: (Long) -> String,
private val chatUsers: List<ChatUserItem>?,
private val onScrollToMessage: (Long) -> Unit,
private val onReplyToMessage: (ChatMessage) -> Unit,
private val serverUrl: String,
private val token: String?,
private val apiKey: String?
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val messages = mutableListOf<ChatMessage>()
fun submitList(newMessages: List<ChatMessage>) {
val diffResult = DiffUtil.calculateDiff(MessageDiffCallback(messages, newMessages))
messages.clear()
messages.addAll(newMessages)
diffResult.dispatchUpdatesTo(this)
}
}
Background Sync
BackgroundSyncWorker
Worker для фоновой синхронизации данных.
Функции:
- Периодическая проверка новых сообщений
- Обновление уведомлений
- Синхронизация аватаров пользователей
- Обработка оффлайн режима
Конфигурация:
val syncWork = PeriodicWorkRequestBuilder<BackgroundSyncWorker>(
15, TimeUnit.MINUTES // Синхронизация каждые 15 минут
)
.addConstraints(
Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
)
.build()
Уведомления
NotificationHelper
Управление push-уведомлениями и локальными уведомлениями.
Функции:
- Создание уведомлений о новых сообщениях
- Группировка уведомлений по чатам
- Кастомные звуки и вибрация
- Deep linking в конкретные чаты
fun showMessageNotification(
chatId: Long,
message: ChatMessage,
senderName: String,
chatTitle: String
) {
val intent = Intent(context, ChatActivity::class.java).apply {
putExtra("chat_id", chatId)
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent = PendingIntent.getActivity(
context, chatId.toInt(), intent, PendingIntent.FLAG_IMMUTABLE
)
val notification = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_message)
.setContentTitle(chatTitle)
.setContentText("$senderName: ${message.text}")
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.build()
notificationManager.notify(chatId.toInt(), notification)
}
Работа с файлами
File Handling
Обработка загрузки и отображения файлов.
Поддерживаемые операции:
- Выбор файлов через
Intent.ACTION_GET_CONTENT - Загрузка файлов на сервер
- Отображение превью изображений
- Скачивание файлов
- Управление разрешениями на хранение
private fun uploadFileAndSendMessage(message: String) {
selectedFileUri?.let { uri ->
lifecycleScope.launch {
try {
val result = ChatRepository(apiClient).uploadFile(uri, contentResolver)
result.fold(
onSuccess = { files ->
viewModel.sendMessage(message, replyingToMessage, files.map { it.id })
clearFileSelection()
},
onFailure = { error ->
Toast.makeText(this@ChatActivity, "Upload failed: ${error.message}", Toast.LENGTH_SHORT).show()
}
)
} catch (e: Exception) {
Toast.makeText(this@ChatActivity, "Error: ${e.message}", Toast.LENGTH_SHORT).show()
}
}
}
}
Темизация и локализация
Поддержка тем:
- Светлая тема
- Темная тема
- Системная тема
Локализация:
- Русский язык
- Английский язык
- Поддержка RTL для арабского и иврита
Производительность
Оптимизации:
- ViewBinding вместо findViewById
- DiffUtil для RecyclerView
- Кеширование изображений с Glide
- Пейджинг для больших списков
- Background threading для тяжелых операций
Интеграция с внешними провайдерами
Поддерживаемые провайдеры
-
Facebook Messenger
- Требует:
page_id,page_access_token,user_access_token - Транспорт:
messenger
- Требует:
-
Telegram
- Интеграция через Telegram API
-
WhatsApp (Twilio)
- Требует:
account_sid,auth_token,phone_number - Транспорт:
whatsapp
- Требует:
-
Whazzup
- Требует:
api_key,channel_id,plain_id - Транспорт:
whatsapp
- Требует:
Настройка провайдеров
Провайдеры настраиваются через интерфейс интеграций в разделе "Settings > Integrations".
Безопасность
Аутентификация
- JWT токены для API запросов
- Проверка прав доступа на уровне аккаунта
- Валидация принадлежности пользователя к чату
Авторизация
- Проверка доступа к чатам
- Ролевая модель для групповых чатов
- Ограничение действий с сообщениями
Real-time обновления
WebSocket
- Автоматическое обновление сообщений
- Статусы прочтения в реальном времени
- Уведомления о новых сообщениях
Background Sync (Android)
BackgroundSyncWorkerдля синхронизации в фоне- Обновление уведомлений
- Синхронизация аватаров пользователей
Файловые вложения
Поддерживаемые форматы
- Изображения, документы, видео, аудио
- Максимальный размер файла настраивается
Загрузка файлов
- Backend: хранение в файловом хранилище
- Frontend: drag & drop, выбор файла
- Android: выбор из галереи/файлового менеджера
Безопасность файлов
- Валидация MIME типов
- Сканирование на вирусы (опционально)
- Ограничение доступа по ссылкам
Поиск и фильтрация
Поиск чатов
- По имени пользователя (персональные чаты)
- По содержимому сообщений
- По связанным сущностям
- Фильтрация по провайдеру
Полнотекстовый поиск
- Индексы в базе данных
- Поиск по тексту сообщений
- Поддержка регулярных выражений
Мониторинг и логирование
Метрики
- Количество активных чатов
- Статистика сообщений
- Производительность API
Логи
- Детальное логирование API запросов
- Ошибки интеграции с провайдерами
- Аудит действий пользователей
Расширение системы
Добавление нового провайдера
- Создать конфигурацию провайдера в базе данных
- Реализовать интеграцию в
ChatProviderService - Добавить DTO для настроек
- Создать миграцию для новой таблицы провайдера
- Обновить UI для настройки
Кастомизация UI
- Темизация компонентов
- Кастомные аватары
- Дополнительные поля в сообщениях
Заключение
Система чата предоставляет полнофункциональное решение для коммуникации в CRM, поддерживая множественные каналы связи, real-time обновления и интеграцию с бизнес-логикой системы. Архитектура обеспечивает масштабируемость, безопасность и гибкость для будущих расширений.