11 KiB
11 KiB
Веб-кабинет Ласточки
Обзор
Веб-кабинет мессенджера Ласточка предоставляет полный функционал для общения:
- 💬 Личные чаты — общение один на один
- 👥 Группы — групповые чаты с участниками
- 📢 Каналы — публикация контента подписчикам
- 🔍 Поиск — поиск пользователей и сообщений
- ⚙️ Настройки — управление профилем и настройками
Структура
src/
├── components/
│ ├── layout/
│ │ └── Sidebar.tsx # Боковая панель с навигацией
│ ├── chat/
│ │ ├── ChatHeader.tsx # Шапка чата
│ │ ├── ChatWindow.tsx # Окно чата
│ │ ├── MessagesList.tsx # Список сообщений
│ │ └── MessageInput.tsx # Ввод сообщений
│ ├── sidebar/
│ │ ├── ChatList.tsx # Список чатов
│ │ └── ChatItem.tsx # Элемент чата
│ └── ui/
│ ├── UserSearch.tsx # Поиск пользователей
│ ├── CreateGroupModal.tsx # Создание группы/канала
│ ├── MembersPanel.tsx # Панель участников
│ └── Avatar.tsx # Аватар
├── store/
│ ├── auth.ts # Аутентификация
│ ├── chat.ts # Чаты и сообщения
│ └── groups.ts # Группы и каналы
└── types/
└── index.ts # Типы данных
Компоненты
Sidebar.tsx
Боковая панель с переключением между чатами, группами и каналами.
Вкладки:
- Чаты — личные и групповые чаты
- Группы — управление группами
- Каналы — управление каналами
Функции:
- Поиск по чатам
- Счётчики непрочитанных
- Быстрое создание групп/каналов
ChatHeader.tsx
Шапка чата с информацией о собеседнике/группе.
Отображение:
- Аватар и имя
- Статус (онлайн/был недавно)
- Для групп: количество участников
- Для каналов: количество подписчиков
Действия:
- Поиск по сообщениям
- Показать/скрыть участников
- Меню действий
ChatWindow.tsx
Основное окно чата.
Режимы:
- Пустое состояние (чат не выбран)
- Активный чат с сообщениями
UserSearch.tsx
Поиск пользователей для добавления в чат или группу.
Props:
interface UserSearchProps {
onSelect?: (user: User) => void
onClose?: () => void
showStartChat?: boolean // Показать кнопку "Начать чат"
showAddToGroup?: boolean // Показать кнопку "Добавить в группу"
groupId?: string // ID группы для добавления
}
Функции:
- Debounced поиск (300ms)
- Отображение статуса онлайн
- Быстрое добавление в группу
CreateGroupModal.tsx
Модальное окно создания группы или канала.
Этапы:
- Информация — название, описание, тип доступа
- Участники — выбор пользователей
Props:
interface CreateGroupModalProps {
isOpen: boolean
onClose: () => void
mode: 'group' | 'channel'
}
Параметры создания:
- Название (обязательно)
- Описание (необязательно)
- Тип доступа (приватный/публичный)
- Участники (необязательно)
MembersPanel.tsx
Выезжающая панель участников группы/канала.
Props:
interface MembersPanelProps {
isOpen: boolean
onClose: () => void
groupId: string
canAddMembers?: boolean
canRemoveMembers?: boolean
}
Функции:
- Просмотр списка участников
- Добавление участников (если разрешено)
- Удаление участников (для владельца)
- Выход из группы/канала
Store
groups.ts
Управление группами и каналами.
Состояние:
interface GroupsStore {
groups: Group[] // Список групп
channels: Group[] // Список каналов
selectedGroup: Group | null // Выбранная группа
isLoading: boolean
error: string | null
}
Методы:
loadGroups()— загрузка списка группloadChannels()— загрузка списка каналовcreateGroup(params)— создание группыcreateChannel(params)— создание каналаselectGroup(groupId)— выбор группыaddMember(groupId, userId)— добавление участникаremoveMember(groupId, userId)— удаление участникаleaveGroup(groupId)— выход из группыdeleteGroup(groupId)— удаление группыupdateGroupInfo(groupId, name, description)— обновление информацииsearchUsersForInvite(query)— поиск пользователей
Типы данных
Group
interface Group {
id: string
name: string
description?: string
avatar?: string
owner: string
members: GroupMember[]
created: Date
isChannel: boolean
isPublic: boolean
membersCount: number
}
GroupMember
interface GroupMember {
userId: string
name: string
avatar?: string
role: 'owner' | 'admin' | 'member'
joined: Date
online?: boolean
}
CreateGroupParams
interface CreateGroupParams {
name: string
description?: string
isChannel: boolean
isPublic: boolean
members: string[] // user IDs
avatar?: string
}
Создание группы
import { useGroupsStore } from '@/store/groups'
const { createGroup } = useGroupsStore()
const group = await createGroup({
name: 'Моя группа',
description: 'Описание группы',
isChannel: false,
isPublic: false,
members: ['user1', 'user2'],
})
Создание канала
import { useGroupsStore } from '@/store/groups'
const { createChannel } = useGroupsStore()
const channel = await createChannel({
name: 'Мой канал',
description: 'Описание канала',
isPublic: true,
members: [], // Можно без участников
})
Поиск пользователей
import { useGroupsStore } from '@/store/groups'
const { searchUsersForInvite } = useGroupsStore()
const users = await searchUsersForInvite('Иван')
// [{ id: 'user1', name: 'Иван', online: true }, ...]
Добавление участника
import { useGroupsStore } from '@/store/groups'
const { addMember } = useGroupsStore()
await addMember('group-id', 'user-id')
Отличия групп и каналов
| Параметр | Группа | Канал |
|---|---|---|
| Цель | Общение | Публикация контента |
| Участники | Могут писать | Только читают (обычно) |
| Создатель | Владелец | Администратор |
| Доступ | Приватный/Публичный | Приватный/Публичный |
| Уведомления | Все сообщения | Только новые посты |
Типы доступа
Приватный
- Вход только по приглашению
- Не отображается в поиске
- Участники видны друг другу
Публичный
- Любой может вступить
- Отображается в поиске
- Можно пригласить ссылку
Интеграция с Tinode
Группы
Tinode использует topics с префиксом grp:
// Создание группы
const groupTopic = tn.getTopic('new')
await groupTopic.save({
desc: {
public: {
fn: 'Название',
note: 'Описание',
type: 'group',
},
},
subs: members.map(userId => ({
user: userId,
mode: 'RW', // Read-Write
})),
})
Каналы
// Создание канала
const channelTopic = tn.getTopic('new')
await channelTopic.save({
desc: {
public: {
fn: 'Название',
note: 'Описание',
type: 'channel',
},
},
subs: members.map(userId => ({
user: userId,
mode: 'R', // Read-only
})),
})
Роли участников
Owner (Владелец)
- Полный доступ
- Может удалять группу
- Назначать администраторов
- Добавлять/удалять участников
Admin (Администратор)
- Может добавлять участников
- Может удалять участников (не админов)
- Может редактировать информацию
Member (Участник)
- Может писать сообщения
- Может приглашать других (если разрешено)
- Может покинуть группу
Примеры использования
Создание публичного канала
const { createChannel } = useGroupsStore()
const channel = await createChannel({
name: 'Новости Ласточки',
description: 'Официальные новости мессенджера',
isPublic: true,
members: [],
})
// Переход в канал
const { setActiveChat } = useChatStore.getState()
await setActiveChat(channel.id)
Добавление участника из поиска
<UserSearch
showAddToGroup
groupId="group-id"
onSelect={(user) => {
console.log('Добавлен:', user)
}}
/>
Просмотр участников
const { selectGroup, selectedGroup } = useGroupsStore()
await selectGroup('group-id')
console.log(selectedGroup?.members)
// [{ userId: 'user1', name: 'Иван', role: 'owner', ... }]
Ласточка — народный мессенджер с открытым кодом 🕊️