mirror of
https://github.com/dev993848/lastochka-messenger.git
synced 2026-05-23 13:45:50 +00:00
🕊️ Ласточка — Веб-кабинет
Веб-кабинет — браузерная версия мессенджера Ласточка.
📋 Содержание
🚀 Быстрый старт
cd D:\Projects\Messenger\dev\lastochka-ui
# Установка
npm install
# Запуск
npm run dev
# Сборка
npm run build
Адрес: http://localhost:5173
📁 Структура
src/
├── components/
│ ├── admin/ # Админ-панель
│ │ ├── AdminPanel.tsx
│ │ ├── Dashboard.tsx
│ │ ├── Users.tsx
│ │ ├── Settings.tsx
│ │ └── Logs.tsx
│ ├── auth/ # Аутентификация
│ │ ├── LoginScreen.tsx
│ │ ├── RegisterForm.tsx
│ │ └── EmailVerification.tsx
│ ├── chat/ # Чат
│ │ ├── ChatWindow.tsx
│ │ ├── ChatHeader.tsx
│ │ ├── MessagesList.tsx
│ │ └── MessageInput.tsx
│ ├── layout/ # Layout
│ │ └── Sidebar.tsx
│ ├── sidebar/ # Боковая панель
│ │ ├── ChatList.tsx
│ │ └── ChatItem.tsx
│ └── ui/ # UI компоненты
│ ├── Avatar.tsx
│ ├── UserSearch.tsx
│ ├── CreateGroupModal.tsx
│ ├── MembersPanel.tsx
│ └── ProfileSettings.tsx
├── lib/ # Утилиты
│ ├── email-auth.ts
│ ├── sms-auth.ts
│ ├── phone-utils.ts
│ └── tinode-client.ts
├── store/ # Zustand store
│ ├── auth.ts
│ ├── chat.ts
│ ├── groups.ts
│ └── admin.ts
├── types/ # TypeScript типы
│ ├── index.ts
│ └── admin.ts
├── App.tsx
├── main.tsx
└── tinode.d.ts
🔐 Аутентификация
Регистрация
Поля:
- Логин (3-32 символа, буквы/цифры/подчёркивание)
- Email (валидный формат)
- Телефон (+7 XXX XXX-XX-XX)
- Пароль (минимум 6 символов)
- Подтверждение пароля
- Отображаемое имя (необязательно)
Проверки:
// Проверка логина на дубликат
const result = await checkLoginAvailability(login)
if (!result.available) {
setError('Этот логин уже занят')
}
// Проверка телефона на дубликат
const result = await checkPhoneAvailability(phone)
if (!result.available) {
setError('Этот номер уже зарегистрирован')
}
Вход
import { useAuthStore } from '@/store/auth'
const { login } = useAuthStore()
await login('username', 'password')
Настройки профиля
Вкладка Профиль:
- Аватар (загрузка файла, макс 5MB)
- Отображаемое имя
- Био/о себе
Вкладка Безопасность:
- Текущий пароль
- Новый пароль
- Подтверждение пароля
💬 Чаты
Типы чатов
| Тип | Описание | Макс. участников |
|---|---|---|
| P2P | Личная переписка | 2 |
| Группа | Групповой чат | 200 000 |
| Канал | Публикация контента | Неограниченно |
Отправка сообщений
import { useChatStore } from '@/store/chat'
const { sendMessage } = useChatStore()
await sendMessage('Привет, мир!')
Поиск пользователей
import UserSearch from '@/components/ui/UserSearch'
<UserSearch
showStartChat
onSelect={(user) => {
console.log('Выбран пользователь:', user)
}}
/>
👥 Группы и каналы
Создание группы
import { useGroupsStore } from '@/store/groups'
const { createGroup } = useGroupsStore()
const group = await createGroup({
name: 'Моя группа',
description: 'Описание',
isChannel: false,
isPublic: false,
members: ['user1', 'user2'],
})
Создание канала
const { createChannel } = useGroupsStore()
const channel = await createChannel({
name: 'Мой канал',
description: 'Новости проекта',
isPublic: true,
members: [],
})
Управление участниками
const { addMember, removeMember, leaveGroup } = useGroupsStore()
// Добавить участника
await addMember('group-id', 'user-id')
// Удалить участника
await removeMember('group-id', 'user-id')
// Покинуть группу
await leaveGroup('group-id')
🛡️ Админ-панель
Доступ
Только для пользователей с ролью admin или superadmin.
Кнопка в Sidebar:
<button onClick={() => onOpenAdmin?.()}>
<Shield size={20} />
</button>
Дашборд
Метрики:
- Пользователи (всего, активные, новые)
- Сообщения (всего, сегодня)
- Группы/каналы
- Хранилище
- API запросы
- Ошибки
Графики:
- Активность (день/неделя/месяц)
- Прогресс-бары ресурсов (CPU, RAM, Disk)
Пользователи
Функции:
- Поиск по имени/email/телефону
- Фильтры (роль, статус, сортировка)
- Изменение роли
- Блокировка/разблокировка
- Удаление
- Экспорт (CSV/JSON)
Роли:
user— обычный пользовательmoderator— модераторadmin— администраторsuperadmin— супер-админ
Статусы:
active— активенbanned— заблокированpending— ожиданиеdeleted— удалён
Логи
Фильтры:
- Поиск по пользователю/действию/цели
- Тип действия (14 типов)
- Период дат
- Сортировка
Экспорт:
const handleExport = () => {
const data = JSON.stringify(filteredLogs, null, 2)
const blob = new Blob([data], { type: 'application/json' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = `logs-${new Date().toISOString().split('T')[0]}.json`
a.click()
}
⚙️ Настройки
Общие
- Режим обслуживания
- Регистрация включена/выключена
- Сообщение о техобслуживании
Пользователи
- Требовать подтверждение email
- Требовать подтверждение телефона
- Разрешить несколько сессий
- Минимальная длина пароля
- Таймаут сессии
Контент
- Макс. размер файла (50MB)
- Макс. длина сообщения (4096 символов)
- Макс. групп на пользователя (50)
- Макс. каналов на пользователя (100)
- Разрешённые типы файлов
Безопасность
- Rate limiting (60 запросов/мин)
- Защита от перебора (5 попыток)
- Длительность блокировки (15 мин)
Уведомления
- Email уведомления
- Push уведомления
- SMTP настройки
Модерация
- Автомодерация
- Запрещённые слова
- Порог жалоб (10)
🎨 UI компоненты
Avatar
import Avatar from '@/components/ui/Avatar'
<Avatar name="Иван Петров" size="md" online={true} />
UserSearch
import UserSearch from '@/components/ui/UserSearch'
<UserSearch
showStartChat
showAddToGroup
groupId="grp123"
onSelect={(user) => console.log(user)}
/>
CreateGroupModal
import CreateGroupModal from '@/components/ui/CreateGroupModal'
<CreateGroupModal
isOpen={showModal}
onClose={() => setShowModal(false)}
mode="group"
/>
MembersPanel
import MembersPanel from '@/components/ui/MembersPanel'
<MembersPanel
isOpen={showPanel}
onClose={() => setShowPanel(false)}
groupId="grp123"
canAddMembers
canRemoveMembers
/>
📡 API клиент
Tinode Client
import { getTinode } from '@/lib/tinode-client'
const tn = getTinode()
// Подключение
await tn.connect()
// Вход
await tn.loginBasic('username', 'password')
// Получение темы
const topic = tn.getTopic('grp123')
// Подписка
await topic.subscribe(query)
// Отправка сообщения
const draft = topic.createMessage('Привет!', false)
await topic.publishMessage(draft)
Store
import { useAuthStore } from '@/store/auth'
import { useChatStore } from '@/store/chat'
import { useGroupsStore } from '@/store/groups'
import { useAdminStore } from '@/store/admin'
🔧 Конфигурация
Переменные окружения
Создайте файл .env в корне проекта:
VITE_TINODE_HOST=localhost:6060
VITE_TINODE_API_KEY=AQEAAAABAAD_rAp4DJh05a1HAwFT3A6K
VITE_TINODE_SECURE=false
VITE_APP_NAME=Ласточка
TypeScript
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"jsx": "react-jsx",
"strict": false,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}
📦 Сборка
Development
npm run dev
Production
npm run build
npm run preview
Docker
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 4173
CMD ["npm", "run", "preview"]
🤝 Вклад
Как помочь
- Форкните репозиторий
- Создайте ветку (
git checkout -b feature/amazing-feature) - Закоммитьте изменения (
git commit -m 'Add amazing feature') - Запушьте (
git push origin feature/amazing-feature) - Создайте Pull Request
Стандарты кода
- TypeScript: strict mode выключен для совместимости
- Именование: camelCase для переменных, PascalCase для компонентов
- Импорты: сначала npm пакеты, потом локальные файлы
Ласточка — народный мессенджер с открытым кодом 🕊️
Сделано с ❤️ для свободного общения